changeset 149:4c577c2b7229 trunk

[svn r155] Fixed a bunch of linkage problems (especially with templates)
author lindquist
date Mon, 24 Mar 2008 19:43:02 +0100
parents 86d3bb8ca33e
children 2c336566ffed
files gen/classes.cpp gen/functions.cpp gen/structs.cpp gen/tollvm.cpp gen/tollvm.h gen/toobj.cpp llvmdc.kdevelop llvmdc.kdevelop.filelist tangotests/a.d
diffstat 9 files changed, 170 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/gen/classes.cpp	Sat Mar 22 12:20:32 2008 +0100
+++ b/gen/classes.cpp	Mon Mar 24 19:43:02 2008 +0100
@@ -350,7 +350,7 @@
         needs_definition = true;
     }
 
-    llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
+    llvm::GlobalValue::LinkageTypes _linkage = DtoLinkage(cd);
 
     // interfaces have no static initializer
     // same goes for abstract classes
@@ -1201,7 +1201,7 @@
 
     const llvm::Type* st = cinfo->type->llvmType->get();
 
-    cd->irStruct->classInfo = new llvm::GlobalVariable(st, true, llvm::GlobalValue::ExternalLinkage, NULL, gname, gIR->module);
+    cd->irStruct->classInfo = new llvm::GlobalVariable(st, true, DtoLinkage(cd), NULL, gname, gIR->module);
 }
 
 static llvm::Constant* build_offti_entry(VarDeclaration* vd)
@@ -1275,7 +1275,8 @@
 
         std::string name(cd->type->vtinfo->toChars());
         name.append("__OffsetTypeInfos");
-        llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrTy,true,llvm::GlobalValue::InternalLinkage,arrInit,name,gIR->module);
+
+        llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrTy,true,DtoInternalLinkage(cd),arrInit,name,gIR->module);
         ptr = llvm::ConstantExpr::getBitCast(gvar, getPtrToType(sTy));
     }
     else {
@@ -1307,7 +1308,7 @@
     gname.append(cd->mangle());
     gname.append("12__destructorMFZv");
 
-    llvm::Function* func = new llvm::Function(fnTy, llvm::GlobalValue::InternalLinkage, gname, gIR->module);
+    llvm::Function* func = new llvm::Function(fnTy, DtoInternalLinkage(cd), gname, gIR->module);
     llvm::Value* thisptr = func->arg_begin();
     thisptr->setName("this");
 
--- a/gen/functions.cpp	Sat Mar 22 12:20:32 2008 +0100
+++ b/gen/functions.cpp	Mon Mar 24 19:43:02 2008 +0100
@@ -353,7 +353,7 @@
     const llvm::FunctionType* functype = DtoFunctionType(fdecl);
     llvm::Function* func = vafunc ? vafunc : gIR->module->getFunction(mangled_name);
     if (!func)
-        func = new llvm::Function(functype, DtoLinkage(fdecl->protection, fdecl->storage_class), mangled_name, gIR->module);
+        func = new llvm::Function(functype, DtoLinkage(fdecl), mangled_name, gIR->module);
     else
         assert(func->getFunctionType() == functype);
 
@@ -363,21 +363,8 @@
     // calling convention
     if (!vafunc && fdecl->llvmInternal != LLVMintrinsic)
         func->setCallingConv(DtoCallingConv(f->linkage));
-
-    // template instances should have weak linkage
-    if (!vafunc && fdecl->llvmInternal != LLVMintrinsic && fdecl->parent && DtoIsTemplateInstance(fdecl->parent))
-        func->setLinkage(llvm::GlobalValue::WeakLinkage);
-
-    // extern(C) functions are always external
-    if (f->linkage == LINKc)
-        func->setLinkage(llvm::GlobalValue::ExternalLinkage);
-
-    // intrinsics are always external C
-    if (fdecl->llvmInternal == LLVMintrinsic)
-    {
-        func->setLinkage(llvm::GlobalValue::ExternalLinkage);
+    else // fall back to C, it should be the right thing to do
         func->setCallingConv(llvm::CallingConv::C);
-    }
 
     fdecl->irFunc->func = func;
     assert(llvm::isa<llvm::FunctionType>(f->llvmType->get()));
--- a/gen/structs.cpp	Sat Mar 22 12:20:32 2008 +0100
+++ b/gen/structs.cpp	Mon Mar 24 19:43:02 2008 +0100
@@ -332,7 +332,7 @@
     initname.append(sd->mangle());
     initname.append("6__initZ");
 
-    llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
+    llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(sd);
     llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module);
     sd->irStruct->init = initvar;
 
--- a/gen/tollvm.cpp	Sat Mar 22 12:20:32 2008 +0100
+++ b/gen/tollvm.cpp	Mon Mar 24 19:43:02 2008 +0100
@@ -344,36 +344,71 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-llvm::GlobalValue::LinkageTypes DtoLinkage(PROT prot, uint stc)
+llvm::GlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
 {
-    // turns out we can't really make anything internal with the way D works :(
-    // the things we can need much more info than this can extract.
-    // TODO : remove this useless function
-    switch(prot)
+    // global variable
+    if (VarDeclaration* vd = sym->isVarDeclaration())
     {
-    case PROTprivate:
-        //if (stc & STCextern)
+        // template
+        if (DtoIsTemplateInstance(sym))
+            return llvm::GlobalValue::WeakLinkage;
+        // local static
+        else if (sym->parent && sym->parent->isFuncDeclaration())
+            return llvm::GlobalValue::InternalLinkage;
+    }
+    // function
+    else if (FuncDeclaration* fdecl = sym->isFuncDeclaration())
+    {
+        assert(fdecl->type->ty == Tfunction);
+        TypeFunction* ft = (TypeFunction*)fdecl->type;
+
+        // intrinsics are always external
+        if (fdecl->llvmInternal == LLVMintrinsic)
             return llvm::GlobalValue::ExternalLinkage;
-        //else
-        //    return llvm::GlobalValue::InternalLinkage;
+        // template instances should have weak linkage
+        else if (DtoIsTemplateInstance(fdecl))
+            return llvm::GlobalValue::WeakLinkage;
+        // extern(C) functions are always external
+        else if (ft->linkage == LINKc)
+            return llvm::GlobalValue::ExternalLinkage;
+    }
+    // class
+    else if (ClassDeclaration* cd = sym->isClassDeclaration())
+    {
+        // template
+        if (DtoIsTemplateInstance(cd))
+            return llvm::GlobalValue::WeakLinkage;
+    }
+    else
+    {
+        assert(0 && "not global/function");
+    }
 
-    case PROTpublic:
-    case PROTpackage:
-    case PROTprotected:
-    case PROTexport:
-        return llvm::GlobalValue::ExternalLinkage;
-
-    case PROTundefined:
-    case PROTnone:
-        assert(0 && "Unsupported linkage type");
-    }
+    // default to external linkage
     return llvm::GlobalValue::ExternalLinkage;
 
+// llvm linkage types
 /*      ExternalLinkage = 0, LinkOnceLinkage, WeakLinkage, AppendingLinkage,
   InternalLinkage, DLLImportLinkage, DLLExportLinkage, ExternalWeakLinkage,
   GhostLinkage */
 }
 
+llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym)
+{
+    if (DtoIsTemplateInstance(sym))
+        return llvm::GlobalValue::WeakLinkage;
+    else
+        return llvm::GlobalValue::InternalLinkage;
+}
+
+llvm::GlobalValue::LinkageTypes DtoExternalLinkage(Dsymbol* sym)
+{
+    if (DtoIsTemplateInstance(sym))
+        return llvm::GlobalValue::WeakLinkage;
+    else
+        return llvm::GlobalValue::ExternalLinkage;
+}
+
 //////////////////////////////////////////////////////////////////////////////////////////
 
 unsigned DtoCallingConv(LINK l)
--- a/gen/tollvm.h	Sat Mar 22 12:20:32 2008 +0100
+++ b/gen/tollvm.h	Mon Mar 24 19:43:02 2008 +0100
@@ -21,8 +21,10 @@
 llvm::Value* DtoDelegateCopy(llvm::Value* dst, llvm::Value* src);
 llvm::Value* DtoCompareDelegate(TOK op, llvm::Value* lhs, llvm::Value* rhs);
 
-// return linkage types for general cases
-llvm::GlobalValue::LinkageTypes DtoLinkage(PROT prot, uint stc);
+// return linkage type for symbol using the current ir state for context
+llvm::GlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym);
+llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym);
+llvm::GlobalValue::LinkageTypes DtoExternalLinkage(Dsymbol* sym);
 
 // convert DMD calling conv to LLVM
 unsigned DtoCallingConv(LINK l);
--- a/gen/toobj.cpp	Sat Mar 22 12:20:32 2008 +0100
+++ b/gen/toobj.cpp	Mon Mar 24 19:43:02 2008 +0100
@@ -519,27 +519,21 @@
 
         Logger::println("parent: %s (%s)", parent->toChars(), parent->kind());
 
-        bool _isconst = isConst();
-        if (parent && parent->isFuncDeclaration() && init && init->isExpInitializer())
-            _isconst = false;
-
-        llvm::GlobalValue::LinkageTypes _linkage;
-        bool istempl = false;
+        // handle static local variables
         bool static_local = false;
-        if ((storage_class & STCcomdat) || (parent && DtoIsTemplateInstance(parent))) {
-            _linkage = llvm::GlobalValue::WeakLinkage;
-            istempl = true;
+        bool _isconst = isConst();
+        if (parent && parent->isFuncDeclaration())
+        {
+            static_local = true;
+            if (init && init->isExpInitializer()) {
+                _isconst = false;
+            }
         }
-        else if (parent && parent->isFuncDeclaration()) {
-            _linkage = llvm::GlobalValue::InternalLinkage;
-            static_local = true;
-        }
-        else
-            _linkage = DtoLinkage(protection, storage_class);
+
+        Logger::println("Creating global variable");
 
         const llvm::Type* _type = irGlobal->type.get();
-
-        Logger::println("Creating global variable");
+        llvm::GlobalValue::LinkageTypes _linkage = DtoLinkage(this);
         std::string _name(mangle());
 
         llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,NULL,_name,gIR->module);
--- a/llvmdc.kdevelop	Sat Mar 22 12:20:32 2008 +0100
+++ b/llvmdc.kdevelop	Mon Mar 24 19:43:02 2008 +0100
@@ -572,6 +572,94 @@
       <path>dmd25/utf.h</path>
       <path>dmd25/version.c</path>
       <path>dmd25/version.h</path>
+      <path>dmd26</path>
+      <path>dmd26/access.c</path>
+      <path>dmd26/aggregate.h</path>
+      <path>dmd26/array.c</path>
+      <path>dmd26/arraytypes.h</path>
+      <path>dmd26/attrib.c</path>
+      <path>dmd26/attrib.h</path>
+      <path>dmd26/cast.c</path>
+      <path>dmd26/class.c</path>
+      <path>dmd26/complex_t.h</path>
+      <path>dmd26/cond.c</path>
+      <path>dmd26/cond.h</path>
+      <path>dmd26/constfold.c</path>
+      <path>dmd26/dchar.c</path>
+      <path>dmd26/dchar.h</path>
+      <path>dmd26/declaration.c</path>
+      <path>dmd26/declaration.h</path>
+      <path>dmd26/delegatize.c</path>
+      <path>dmd26/doc.c</path>
+      <path>dmd26/doc.h</path>
+      <path>dmd26/dsymbol.c</path>
+      <path>dmd26/dsymbol.h</path>
+      <path>dmd26/dump.c</path>
+      <path>dmd26/entity.c</path>
+      <path>dmd26/enum.c</path>
+      <path>dmd26/enum.h</path>
+      <path>dmd26/expression.c</path>
+      <path>dmd26/expression.h</path>
+      <path>dmd26/func.c</path>
+      <path>dmd26/gnuc.c</path>
+      <path>dmd26/gnuc.h</path>
+      <path>dmd26/hdrgen.c</path>
+      <path>dmd26/hdrgen.h</path>
+      <path>dmd26/html.c</path>
+      <path>dmd26/html.h</path>
+      <path>dmd26/identifier.c</path>
+      <path>dmd26/identifier.h</path>
+      <path>dmd26/idgen.c</path>
+      <path>dmd26/impcnvgen.c</path>
+      <path>dmd26/import.c</path>
+      <path>dmd26/import.h</path>
+      <path>dmd26/inifile.c</path>
+      <path>dmd26/init.c</path>
+      <path>dmd26/init.h</path>
+      <path>dmd26/inline.c</path>
+      <path>dmd26/interpret.c</path>
+      <path>dmd26/lexer.c</path>
+      <path>dmd26/lexer.h</path>
+      <path>dmd26/link.c</path>
+      <path>dmd26/lstring.c</path>
+      <path>dmd26/lstring.h</path>
+      <path>dmd26/macro.c</path>
+      <path>dmd26/macro.h</path>
+      <path>dmd26/mangle.c</path>
+      <path>dmd26/mars.c</path>
+      <path>dmd26/mars.h</path>
+      <path>dmd26/mem.c</path>
+      <path>dmd26/mem.h</path>
+      <path>dmd26/module.c</path>
+      <path>dmd26/module.h</path>
+      <path>dmd26/mtype.c</path>
+      <path>dmd26/mtype.h</path>
+      <path>dmd26/opover.c</path>
+      <path>dmd26/optimize.c</path>
+      <path>dmd26/parse.c</path>
+      <path>dmd26/parse.h</path>
+      <path>dmd26/port.h</path>
+      <path>dmd26/root.c</path>
+      <path>dmd26/root.h</path>
+      <path>dmd26/scope.c</path>
+      <path>dmd26/scope.h</path>
+      <path>dmd26/statement.c</path>
+      <path>dmd26/statement.h</path>
+      <path>dmd26/staticassert.c</path>
+      <path>dmd26/staticassert.h</path>
+      <path>dmd26/stringtable.c</path>
+      <path>dmd26/stringtable.h</path>
+      <path>dmd26/struct.c</path>
+      <path>dmd26/template.c</path>
+      <path>dmd26/template.h</path>
+      <path>dmd26/total.h</path>
+      <path>dmd26/unialpha.c</path>
+      <path>dmd26/utf.c</path>
+      <path>dmd26/utf.h</path>
+      <path>dmd26/version.c</path>
+      <path>dmd26/version.h</path>
+      <path>todo</path>
+      <path>todo/lib.d</path>
     </blacklist>
     <build>
       <buildtool>make</buildtool>
--- a/llvmdc.kdevelop.filelist	Sat Mar 22 12:20:32 2008 +0100
+++ b/llvmdc.kdevelop.filelist	Mon Mar 24 19:43:02 2008 +0100
@@ -765,9 +765,7 @@
 tangotests/q.d
 tangotests/r.d
 tangotests/s.d
-tangotests/stdout1.d
 tangotests/t.d
-tangotests/v.d
 test
 test/a.d
 test/aa1.d
--- a/tangotests/a.d	Sat Mar 22 12:20:32 2008 +0100
+++ b/tangotests/a.d	Mon Mar 24 19:43:02 2008 +0100
@@ -27,3 +27,8 @@
 {
     auto bar = new Bar(12);
 }
+
+void main()
+{
+    func();
+}