diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 86 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 25 |
2 files changed, 65 insertions, 46 deletions
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index a65c2b3807..b531616b13 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -53,7 +53,8 @@ CodeGenModule::~CodeGenModule() { llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction(); if (ObjCInitFunction) AddGlobalCtor(ObjCInitFunction); - EmitGlobalCtors(); + EmitCtorList(GlobalCtors, "llvm.global_ctors"); + EmitCtorList(GlobalDtors, "llvm.global_dtors"); EmitAnnotations(); delete Runtime; delete DebugInfo; @@ -102,55 +103,48 @@ void CodeGenModule::setVisibility(llvm::GlobalValue *GV, /// AddGlobalCtor - Add a function to the list that will be called before /// main() runs. -void CodeGenModule::AddGlobalCtor(llvm::Function * Ctor) { +void CodeGenModule::AddGlobalCtor(llvm::Function * Ctor, int Priority) { // TODO: Type coercion of void()* types. - GlobalCtors.push_back(Ctor); + GlobalCtors.push_back(std::make_pair(Ctor, Priority)); } -/// EmitGlobalCtors - Generates the array of contsturctor functions to be -/// called on module load, if any have been registered with AddGlobalCtor. -void CodeGenModule::EmitGlobalCtors() { - if (GlobalCtors.empty()) return; - - // Get the type of @llvm.global_ctors - std::vector<const llvm::Type*> CtorFields; - CtorFields.push_back(llvm::IntegerType::get(32)); - // Constructor function type - std::vector<const llvm::Type*> VoidArgs; - llvm::FunctionType* CtorFuncTy = - llvm::FunctionType::get(llvm::Type::VoidTy, VoidArgs, false); - - // i32, function type pair - const llvm::Type *FPType = llvm::PointerType::getUnqual(CtorFuncTy); +/// AddGlobalDtor - Add a function to the list that will be called +/// when the module is unloaded. +void CodeGenModule::AddGlobalDtor(llvm::Function * Dtor, int Priority) { + // TODO: Type coercion of void()* types. + GlobalDtors.push_back(std::make_pair(Dtor, Priority)); +} + +void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) { + // Ctor function type is void()*. + llvm::FunctionType* CtorFTy = + llvm::FunctionType::get(llvm::Type::VoidTy, + std::vector<const llvm::Type*>(), + false); + llvm::Type *CtorPFTy = llvm::PointerType::getUnqual(CtorFTy); + + // Get the type of a ctor entry, { i32, void ()* }. llvm::StructType* CtorStructTy = - llvm::StructType::get(llvm::Type::Int32Ty, FPType, NULL); - // Array of fields - llvm::ArrayType* GlobalCtorsTy = - llvm::ArrayType::get(CtorStructTy, GlobalCtors.size()); - - // Define the global variable - llvm::GlobalVariable *GlobalCtorsVal = - new llvm::GlobalVariable(GlobalCtorsTy, false, + llvm::StructType::get(llvm::Type::Int32Ty, + llvm::PointerType::getUnqual(CtorFTy), NULL); + + // Construct the constructor and destructor arrays. + std::vector<llvm::Constant*> Ctors; + for (CtorList::const_iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) { + std::vector<llvm::Constant*> S; + S.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, I->second, false)); + S.push_back(llvm::ConstantExpr::getBitCast(I->first, CtorPFTy)); + Ctors.push_back(llvm::ConstantStruct::get(CtorStructTy, S)); + } + + if (!Ctors.empty()) { + llvm::ArrayType *AT = llvm::ArrayType::get(CtorStructTy, Ctors.size()); + new llvm::GlobalVariable(AT, false, llvm::GlobalValue::AppendingLinkage, - (llvm::Constant*)0, "llvm.global_ctors", + llvm::ConstantArray::get(AT, Ctors), + GlobalName, &TheModule); - - // Populate the array - std::vector<llvm::Constant*> CtorValues; - llvm::Constant *MagicNumber = - llvm::ConstantInt::get(llvm::Type::Int32Ty, 65535, false); - std::vector<llvm::Constant*> StructValues; - for (std::vector<llvm::Constant*>::iterator I = GlobalCtors.begin(), - E = GlobalCtors.end(); I != E; ++I) { - StructValues.clear(); - StructValues.push_back(MagicNumber); - StructValues.push_back(*I); - - CtorValues.push_back(llvm::ConstantStruct::get(CtorStructTy, StructValues)); } - - GlobalCtorsVal->setInitializer(llvm::ConstantArray::get(GlobalCtorsTy, - CtorValues)); } void CodeGenModule::EmitAnnotations() { @@ -796,6 +790,12 @@ void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) { } else { llvm::Function *Fn = cast<llvm::Function>(Entry); CodeGenFunction(*this).GenerateCode(D, Fn); + + if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>()) { + AddGlobalCtor(Fn, CA->getPriority()); + } else if (const DestructorAttr *DA = D->getAttr<DestructorAttr>()) { + AddGlobalDtor(Fn, DA->getPriority()); + } } } diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 3a39eb3f79..1fb2cf7ae0 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -54,6 +54,8 @@ namespace CodeGen { /// CodeGenModule - This class organizes the cross-module state that is used /// while generating LLVM code. class CodeGenModule { + typedef std::vector< std::pair<llvm::Constant*, int> > CtorList; + ASTContext &Context; const LangOptions &Features; llvm::Module &TheModule; @@ -80,7 +82,16 @@ class CodeGenModule { /// which actually define something. std::vector<const ValueDecl*> StaticDecls; - std::vector<llvm::Constant*> GlobalCtors; + /// GlobalCtors - Store the list of global constructors and their + /// respective priorities to be emitted when the translation unit is + /// complete. + CtorList GlobalCtors; + + /// GlobalDtors - Store the list of global destructors and their + /// respective priorities to be emitted when the translation unit is + /// complete. + CtorList GlobalDtors; + std::vector<llvm::Constant*> Annotations; llvm::StringMap<llvm::Constant*> CFConstantStringMap; @@ -173,9 +184,17 @@ private: llvm::GlobalValue *EmitForwardFunctionDefinition(const FunctionDecl *D); void EmitGlobalFunctionDefinition(const FunctionDecl *D); void EmitGlobalVarDefinition(const VarDecl *D); + + // FIXME: Hardcoding priority here is gross. + void AddGlobalCtor(llvm::Function * Ctor, int Priority=65535); + void AddGlobalDtor(llvm::Function * Dtor, int Priority=65535); + + /// EmitCtorList - Generates a global array of functions and + /// priorities using the given list and name. This array will have + /// appending linkage and is suitable for use as a LLVM constructor + /// or destructor array. + void EmitCtorList(const CtorList &Fns, const char *GlobalName); - void AddGlobalCtor(llvm::Function * Ctor); - void EmitGlobalCtors(void); void EmitAnnotations(void); void EmitStatics(void); |