diff gen/toobj.c @ 85:f869c636a113 trunk

[svn r89] Fixed a bunch of problems with template instance across multiple modules. Fixed initialization of function local static variables, with a non const initializer (now happens on first call using a global to make sure it only happens once.)
author lindquist
date Fri, 02 Nov 2007 06:32:32 +0100
parents 169711a7126e
children
line wrap: on
line diff
--- a/gen/toobj.c	Fri Nov 02 02:27:41 2007 +0100
+++ b/gen/toobj.c	Fri Nov 02 06:32:32 2007 +0100
@@ -569,16 +569,29 @@
     LOG_SCOPE;
     llvm::Module* M = gIR->module;
 
+    if (aliassym)
+    {
+        toAlias()->toObjFile();
+        return;
+    }
+
     // global variable or magic
-    if (isDataseg() || parent->isModule())
+    if (isDataseg())
     {
         if (llvmTouched) return;
         else llvmTouched = true;
 
-        bool _isconst = isConst();
+        bool _isconst = false;
+        if (isConst() && (init && !init->isExpInitializer()))
+            _isconst = true;
 
         llvm::GlobalValue::LinkageTypes _linkage;
-        if (parent && parent->isFuncDeclaration())
+        bool istempl = false;
+        if ((storage_class & STCcomdat) || (parent && DtoIsTemplateInstance(parent))) {
+            _linkage = llvm::GlobalValue::WeakLinkage;
+            istempl = true;
+        }
+        else if (parent && parent->isFuncDeclaration())
             _linkage = llvm::GlobalValue::InternalLinkage;
         else
             _linkage = DtoLinkage(protection, storage_class);
@@ -597,10 +610,33 @@
         llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,0,_name,M);
         llvmValue = gvar;
 
-        // if extern don't emit initializer
-        if (!(storage_class & STCextern) && getModule() == gIR->dmodule)
+        if (!(storage_class & STCextern) && (getModule() == gIR->dmodule || istempl))
         {
-            _init = DtoConstInitializer(t, init);
+            if (parent && parent->isFuncDeclaration() && init && init->isExpInitializer()) {
+                _init = DtoConstInitializer(t, NULL);
+                // create a flag to make sure initialization only happens once
+                llvm::GlobalValue::LinkageTypes gflaglink = istempl ? llvm::GlobalValue::WeakLinkage : llvm::GlobalValue::InternalLinkage;
+                std::string gflagname(_name);
+                gflagname.append("__initflag");
+                llvm::GlobalVariable* gflag = new llvm::GlobalVariable(llvm::Type::Int1Ty,false,gflaglink,DtoConstBool(false),gflagname,M);
+
+                // check flag and do init if not already done
+                llvm::BasicBlock* oldend = gIR->scopeend();
+                llvm::BasicBlock* initbb = new llvm::BasicBlock("ifnotinit",gIR->topfunc(),oldend);
+                llvm::BasicBlock* endinitbb = new llvm::BasicBlock("ifnotinitend",gIR->topfunc(),oldend);
+                llvm::Value* cond = gIR->ir->CreateICmpEQ(gIR->ir->CreateLoad(gflag,"tmp"),DtoConstBool(false));
+                gIR->ir->CreateCondBr(cond, initbb, endinitbb);
+                gIR->scope() = IRScope(initbb,endinitbb);
+                elem* ie = DtoInitializer(init);
+                if (!ie->inplace)
+                    DtoAssign(t, gvar, ie->getValue());
+                gIR->ir->CreateStore(DtoConstBool(true), gflag);
+                gIR->ir->CreateBr(endinitbb);
+                gIR->scope() = IRScope(endinitbb,oldend);
+            }
+            else {
+                _init = DtoConstInitializer(t, init);
+            }
 
             //Logger::cout() << "initializer: " << *_init << '\n';
             if (_type != _init->getType()) {
@@ -765,8 +801,14 @@
     assert(f->llvmType);
     const llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(llvmValue->getType()->getContainedType(0));
 
+    // template instances should have weak linkage
+    assert(parent);
+    if (DtoIsTemplateInstance(parent)) {
+        func->setLinkage(llvm::GlobalValue::WeakLinkage);
+    }
+
     // only members of the current module maybe be defined
-    if (getModule() == gIR->dmodule || parent->isTemplateInstance())
+    if (getModule() == gIR->dmodule || DtoIsTemplateInstance(parent))
     {
         llvmDModule = gIR->dmodule;
 
@@ -838,7 +880,9 @@
                         gIR->ir->CreateStore(a,v);
                         vd->llvmValue = v;
                     }
-                    else assert(0);
+                    else {
+                        Logger::println("*** ATTENTION: some unknown argument: %s", arg ? arg->toChars() : 0);
+                    }
                 }
 
                 // debug info
@@ -941,10 +985,5 @@
 
             gIR->functions.pop_back();
         }
-
-        // template instances should have weak linkage
-        if (parent->isTemplateInstance()) {
-            func->setLinkage(llvm::GlobalValue::WeakLinkage);
-        }
     }
 }