]> granicus.if.org Git - clang/commitdiff
add initial support for generating an llvm.globalctors list. Patch by David Chisnall
authorChris Lattner <sabre@nondot.org>
Fri, 14 Mar 2008 17:18:18 +0000 (17:18 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 14 Mar 2008 17:18:18 +0000 (17:18 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@48362 91177308-0d34-0410-b5e6-96231b3b80d8

CodeGen/CodeGenModule.cpp
CodeGen/CodeGenModule.h

index 0b39ca4437817e2388f1c6ad0034c6555f7112e5..43f399a61f29b990f3c5d89e5be0304409fb7ace 100644 (file)
@@ -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<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
+  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<llvm::Constant*> CtorValues;
+  llvm::Constant *MagicNumber = llvm::ConstantInt::get(llvm::IntegerType::Int32Ty,
+      65535,
+      false);
+  for (std::vector<llvm::Constant*>::iterator I = GlobalCtors.begin(), 
+      E = GlobalCtors.end(); I != E; ++I) {
+    std::vector<llvm::Constant*> 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!
index 80ce3076d41ed054e5cc88f256a195877848c938..cbea09fd3ec407eebcec52341732c5e6be9cf3d8 100644 (file)
@@ -58,6 +58,7 @@ class CodeGenModule {
   llvm::Function *MemCpyFn;
   llvm::Function *MemSetFn;
   llvm::DenseMap<const Decl*, llvm::Constant*> GlobalDeclMap;
+  std::vector<llvm::Constant*> GlobalCtors;
     
   llvm::StringMap<llvm::Constant*> CFConstantStringMap;
   llvm::StringMap<llvm::Constant*> 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);