From: Chris Lattner Date: Fri, 14 Mar 2008 17:18:18 +0000 (+0000) Subject: add initial support for generating an llvm.globalctors list. Patch by David Chisnall X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6d39760673df2e92d9293f46ff8c66dad6ab5e0a;p=clang add initial support for generating an llvm.globalctors list. Patch by David Chisnall git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@48362 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/CodeGen/CodeGenModule.cpp b/CodeGen/CodeGenModule.cpp index 0b39ca4437..43f399a61f 100644 --- a/CodeGen/CodeGenModule.cpp +++ b/CodeGen/CodeGenModule.cpp @@ -38,6 +38,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const LangOptions &LO, } CodeGenModule::~CodeGenModule() { + EmitGlobalCtors(); delete Runtime; } @@ -62,6 +63,59 @@ void CodeGenModule::WarnUnsupported(const Decl *D, const char *Type) { &Msg, 1); } +/// AddGlobalCtor - Add a function to the list that will be called before +/// main() runs. +void CodeGenModule::AddGlobalCtor(llvm::Function * Ctor) { + // TODO: Type coercion of void()* types. + GlobalCtors.push_back(Ctor); +} + +void CodeGenModule::EmitGlobalCtors() { + // Get the type of @llvm.global_ctors + std::vector CtorFields; + CtorFields.push_back(llvm::IntegerType::get(32)); + // Constructor function type + std::vector VoidArgs; + llvm::FunctionType* CtorFuncTy = llvm::FunctionType::get( + llvm::Type::VoidTy, + VoidArgs, + false); + // i32, function type pair + CtorFields.push_back(llvm::PointerType::getUnqual(CtorFuncTy)); + llvm::StructType* CtorStructTy = llvm::StructType::get(CtorFields, false); + // Array of fields + llvm::ArrayType* GlobalCtorsTy = llvm::ArrayType::get(CtorStructTy, + GlobalCtors.size()); + + const std::string GlobalCtorsVar = std::string("llvm.global_ctors"); + // Define the global variable + llvm::GlobalVariable *GlobalCtorsVal = new llvm::GlobalVariable( + GlobalCtorsTy, + false, + llvm::GlobalValue::AppendingLinkage, + (llvm::Constant*)0, + GlobalCtorsVar, + &TheModule); + + // Populate the array + std::vector CtorValues; + llvm::Constant *MagicNumber = llvm::ConstantInt::get(llvm::IntegerType::Int32Ty, + 65535, + false); + for (std::vector::iterator I = GlobalCtors.begin(), + E = GlobalCtors.end(); I != E; ++I) { + std::vector StructValues; + StructValues.push_back(MagicNumber); + StructValues.push_back(*I); + + llvm::Constant* CtorEntry = llvm::ConstantStruct::get(CtorStructTy, StructValues); + CtorValues.push_back(CtorEntry); + } + llvm::Constant* CtorArray = llvm::ConstantArray::get(GlobalCtorsTy, CtorValues); + GlobalCtorsVal->setInitializer(CtorArray); + +} + /// ReplaceMapValuesWith - This is a really slow and bad function that /// searches for any entries in GlobalDeclMap that point to OldVal, changing /// them to point to NewVal. This is badbadbad, FIXME! diff --git a/CodeGen/CodeGenModule.h b/CodeGen/CodeGenModule.h index 80ce3076d4..cbea09fd3e 100644 --- a/CodeGen/CodeGenModule.h +++ b/CodeGen/CodeGenModule.h @@ -58,6 +58,7 @@ class CodeGenModule { llvm::Function *MemCpyFn; llvm::Function *MemSetFn; llvm::DenseMap GlobalDeclMap; + std::vector GlobalCtors; llvm::StringMap CFConstantStringMap; llvm::StringMap ConstantStringMap; @@ -96,6 +97,9 @@ public: llvm::Function *getIntrinsic(unsigned IID, const llvm::Type **Tys = 0, unsigned NumTys = 0); + void AddGlobalCtor(llvm::Function * Ctor); + void EmitGlobalCtors(void); + void EmitFunction(const FunctionDecl *FD); void EmitGlobalVar(const FileVarDecl *D); void EmitGlobalVarDeclarator(const FileVarDecl *D);