From 74aa7e1eaeb8a38ee5d97ae85a498d6d46b5635d Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Fri, 1 Aug 2008 00:01:51 +0000 Subject: Support constructor and destructor attributes in CodeGen - There is an miscompilation issue remaining due to a poor interaction between the delayed emission of static functions and the emission of constructors, but that already existed prior to this change. llvm-svn: 54258 --- clang/lib/CodeGen/CodeGenModule.cpp | 86 ++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 43 deletions(-) (limited to 'clang/lib/CodeGen/CodeGenModule.cpp') diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index a65c2b3807d..b531616b13c 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/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 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 - 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(), + 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 Ctors; + for (CtorList::const_iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) { + std::vector 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 CtorValues; - llvm::Constant *MagicNumber = - llvm::ConstantInt::get(llvm::Type::Int32Ty, 65535, false); - std::vector StructValues; - for (std::vector::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(Entry); CodeGenFunction(*this).GenerateCode(D, Fn); + + if (const ConstructorAttr *CA = D->getAttr()) { + AddGlobalCtor(Fn, CA->getPriority()); + } else if (const DestructorAttr *DA = D->getAttr()) { + AddGlobalDtor(Fn, DA->getPriority()); + } } } -- cgit v1.2.3