/** * This function creates a module constructor function to create the * map from function keys to function names. This function will be * automatically called when the module is loaded. * * The code was generated by using clang on a test file. The test * file looked like (foo.cc): * __attribute__((constructor)) * static void init() * { * } * * Then, run: * 1. clang -S -emit-llvm -c foo.cc * 2. llc -march=cpp foo.bc -o foo.lc * The output foo.lc provides code for generating a ctor using LLVM. * */ void BytesFlops::initializeKeyMap(Module& module) { if ( module.getFunction("func_key_map_ctor") ) return; LLVMContext& ctx = module.getContext(); // Type Definitions std::vector<Type*>StructTy_1_fields; StructTy_1_fields.push_back(IntegerType::get(ctx, 32)); std::vector<Type*>FuncTy_3_args; FunctionType* FuncTy_3 = FunctionType::get( /*Result=*/ Type::getVoidTy(ctx), /*Params=*/ FuncTy_3_args, /*isVarArg=*/ false); PointerType* PointerTy_2 = PointerType::get(FuncTy_3, 0); StructTy_1_fields.push_back(PointerTy_2); StructType * StructTy_1 = StructType::get(ctx, StructTy_1_fields, /*isPacked=*/false); ArrayType* ArrayTy_0 = NULL; // Function Declarations func_map_ctor = Function::Create( /*Type=*/FuncTy_3, /*Linkage=*/GlobalValue::InternalLinkage, /*Name=*/"func_key_map_ctor", &module); func_map_ctor->setCallingConv(CallingConv::C); AttributeSet func__ZL4initv_PAL; SmallVector<AttributeSet, 4> Attrs; AttributeSet PAS; AttrBuilder B; B.addAttribute(Attribute::NoUnwind); B.addAttribute(Attribute::UWTable); PAS = AttributeSet::get(ctx, ~0U, B); Attrs.push_back(PAS); func__ZL4initv_PAL = AttributeSet::get(ctx, Attrs); func_map_ctor->setAttributes(func__ZL4initv_PAL); // Global Variable Declarations // Constant Definitions std::vector<Constant*> ctor_elems; std::vector<Constant*> const_struct_8_fields; ConstantInt* const_int32_9 = ConstantInt::get(ctx, APInt(32, StringRef("65535"), 10)); const_struct_8_fields.push_back(const_int32_9); const_struct_8_fields.push_back(func_map_ctor); Constant* const_struct_8 = ConstantStruct::get(StructTy_1, const_struct_8_fields); ctor_elems.push_back(const_struct_8); GlobalVariable* llvm_global_ctors; /** * Add our constructor to the list of global constructors for the * module. It's possible that a module already contains a ctor. */ GlobalVariable* current_ctors = module.getGlobalVariable("llvm.global_ctors"); if ( !current_ctors ) { ArrayTy_0 = ArrayType::get(StructTy_1, 1); } else { // there are existing ctors, and the initializer points to them. // add ours to the initializer list (actually, we create a new // initializer list and add the existing ones to it). Constant * initializer = current_ctors->getInitializer(); ConstantArray * ar = llvm::dyn_cast<ConstantArray>(initializer); assert( ar ); int cnt = 0; Constant * elt = ar->getAggregateElement(cnt); // add existing ctors to new initializer list, and get rid // of the old one. while ( elt ) { assert( llvm::dyn_cast<ConstantStruct>(elt) ); ctor_elems.push_back(elt); cnt++; elt = ar->getAggregateElement(cnt); } ArrayTy_0 = ArrayType::get(StructTy_1, ctor_elems.size()); current_ctors->eraseFromParent(); } llvm_global_ctors = new GlobalVariable(/*Module=*/module, /*Type=*/ ArrayTy_0, /*isConstant=*/ false, /*Linkage=*/ GlobalValue::AppendingLinkage, /*Initializer=*/0, // has initializer, specified below /*Name=*/ "llvm.global_ctors"); Constant* ctor_array = ConstantArray::get(ArrayTy_0, ctor_elems); // Global Variable Definitions llvm_global_ctors->setInitializer(ctor_array); }