changeset 940:39519a1ff603

Changed the way LDC determines if a template instantiation needs to get a definition, seems to speed up compile times quite a bit in some cases.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Wed, 04 Feb 2009 18:48:03 +0100
parents cac9895be400
children 734e0998c7fd
files dmd/template.c dmd/template.h gen/classes.cpp gen/functions.cpp gen/llvmhelpers.cpp gen/llvmhelpers.h gen/structs.cpp gen/tollvm.cpp
diffstat 8 files changed, 57 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/template.c	Wed Feb 04 18:39:39 2009 +0100
+++ b/dmd/template.c	Wed Feb 04 18:48:03 2009 +0100
@@ -2901,7 +2901,10 @@
     this->havetempdecl = 1;
     this->isnested = NULL;
     this->errors = 0;
+
+    // LDC
     this->tinst = NULL;
+    this->tmodule = NULL;
 
     assert((size_t)tempdecl->scope > 0x10000);
 }
@@ -2979,6 +2982,7 @@
 
     // get the enclosing template instance from the scope tinst
     tinst = sc->tinst;
+    tmodule = sc->module;
 
 #if LOG
     printf("\tdo semantic\n");
--- a/dmd/template.h	Wed Feb 04 18:39:39 2009 +0100
+++ b/dmd/template.h	Wed Feb 04 18:48:03 2009 +0100
@@ -326,6 +326,7 @@
 
     // LDC
     TemplateInstance *tinst; // enclosing template instance
+    Module* tmodule; // module from outermost enclosing template instantiation
     void printInstantiationTrace();
 };
 
--- a/gen/classes.cpp	Wed Feb 04 18:39:39 2009 +0100
+++ b/gen/classes.cpp	Wed Feb 04 18:48:03 2009 +0100
@@ -324,7 +324,7 @@
     gIR->constInitList.push_back(cd);
 
     // emit typeinfo and request definition
-    if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd))
+    if (mustDefineSymbol(cd))
     {
         gIR->defineList.push_back(cd);
         DtoTypeInfoOf(cd->type, false);
@@ -360,7 +360,7 @@
     gIR->structs.push_back(irstruct);
 
     bool needs_definition = false;
-    if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd)) {
+    if (mustDefineSymbol(cd)) {
         needs_definition = true;
     }
 
@@ -821,7 +821,7 @@
     DefineInterfaceInfos(cd->ir.irStruct);
 
     // define the classinfo
-    if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd))
+    if (mustDefineSymbol(cd))
     {
         DtoDefineClassInfo(cd);
     }
@@ -851,7 +851,7 @@
 
     IrStruct* irstruct = cd->ir.irStruct;
 
-    assert(cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd));
+    assert(mustDefineSymbol(cd));
 
     // sanity check
     assert(irstruct->init);
--- a/gen/functions.cpp	Wed Feb 04 18:39:39 2009 +0100
+++ b/gen/functions.cpp	Wed Feb 04 18:48:03 2009 +0100
@@ -486,20 +486,9 @@
     Type* t = fdecl->type->toBasetype();
     TypeFunction* f = (TypeFunction*)t;
 
-    bool declareOnly = false;
-    bool templInst = fdecl->parent && DtoIsTemplateInstance(fdecl->parent);
-    if (!templInst && fdecl->getModule() != gIR->dmodule)
-    {
-        Logger::println("not template instance, and not in this module. declare only!");
-        Logger::println("current module: %s", gIR->dmodule->ident->toChars());
-        if(fdecl->getModule())
-            Logger::println("func module: %s", fdecl->getModule()->ident->toChars());
-        else {
-            Logger::println("func not in a module, is runtime");
-        }
-        declareOnly = true;
-    }
-    else if (fdecl->llvmInternal == LLVMva_start)
+    bool declareOnly = !mustDefineSymbol(fdecl);
+
+    if (fdecl->llvmInternal == LLVMva_start)
         declareOnly = true;
 
     if (!fdecl->ir.irFunc) {
@@ -668,9 +657,8 @@
     llvm::Function* func = fd->ir.irFunc->func;
     const llvm::FunctionType* functype = func->getFunctionType();
 
-    // only members of the current module or template instances maybe be defined
-    if (!(fd->getModule() == gIR->dmodule || DtoIsTemplateInstance(fd->parent)))
-        return;
+    // sanity check
+    assert(mustDefineSymbol(fd));
 
     // set module owner
     fd->ir.DModule = gIR->dmodule;
--- a/gen/llvmhelpers.cpp	Wed Feb 04 18:39:39 2009 +0100
+++ b/gen/llvmhelpers.cpp	Wed Feb 04 18:48:03 2009 +0100
@@ -831,15 +831,14 @@
 //      TEMPLATE HELPERS
 ////////////////////////////////////////////////////////////////////////////////////////*/
 
-// FIXME: when is this the right one to use instead of Dsymbol::inTemplateInstance() ?
-bool DtoIsTemplateInstance(Dsymbol* s)
+Module* DtoIsTemplateInstance(Dsymbol* s)
 {
-    if (!s) return false;
+    if (!s) return NULL;
     if (s->isTemplateInstance() && !s->isTemplateMixin())
-        return true;
+        return s->isTemplateInstance()->tmodule;
     else if (s->parent)
         return DtoIsTemplateInstance(s->parent);
-    return false;
+    return NULL;
 }
 
 /****************************************************************************************/
@@ -958,15 +957,10 @@
     assert(!glob->constInit);
     glob->constInit = initVal;
 
-    bool istempl = false;
-    if ((vd->storage_class & STCcomdat) || (vd->parent && DtoIsTemplateInstance(vd->parent))) {
-        istempl = true;
-    }
-
     // assign the initializer
     llvm::GlobalVariable* globalvar = llvm::cast<llvm::GlobalVariable>(glob->value);
 
-    if (!(vd->storage_class & STCextern) && (vd->getModule() == gIR->dmodule || istempl))
+    if (!(vd->storage_class & STCextern) && mustDefineSymbol(vd))
     {
         if (Logger::enabled())
         {
@@ -1559,3 +1553,27 @@
     
     Logger::println("final intrinsic name: %s", name.c_str());
 }
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+bool mustDefineSymbol(Dsymbol* s)
+{
+    Module* M = DtoIsTemplateInstance(s);
+    // if it's a template instance, check the instantiating module
+    // not the module that defines the template
+    if (M)
+        return M == gIR->dmodule;
+    return s->getModule() == gIR->dmodule;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+bool needsTemplateLinkage(Dsymbol* s)
+{
+    Module* M = DtoIsTemplateInstance(s);
+    // only return true if the symbol is a template instances
+    // and if this instance originated in the current module
+    if (M)
+        return M == gIR->dmodule;
+    return false;
+}
--- a/gen/llvmhelpers.h	Wed Feb 04 18:39:39 2009 +0100
+++ b/gen/llvmhelpers.h	Wed Feb 04 18:48:03 2009 +0100
@@ -61,8 +61,8 @@
 // return the same val as passed in, modified to the target type, if possible, otherwise returns a new DValue
 DValue* DtoPaintType(Loc& loc, DValue* val, Type* to);
 
-// is template instance check
-bool DtoIsTemplateInstance(Dsymbol* s);
+// is template instance check, returns module where instantiated
+Module* DtoIsTemplateInstance(Dsymbol* s);
 
 // these are all basically drivers for the codegeneration called by the main loop
 void DtoResolveDsymbol(Dsymbol* dsym);
@@ -108,6 +108,12 @@
 // fixup an overloaded intrinsic name string
 void DtoOverloadedIntrinsicName(TemplateInstance* ti, TemplateDeclaration* td, std::string& name);
 
+// return true if the symbol should be defined in the current module, not just declared
+bool mustDefineSymbol(Dsymbol* s);
+
+// returns true if the symbol needs template linkage, or just external
+bool needsTemplateLinkage(Dsymbol* s);
+
 ////////////////////////////////////////////
 // gen/tocall.cpp stuff below
 ////////////////////////////////////////////
--- a/gen/structs.cpp	Wed Feb 04 18:39:39 2009 +0100
+++ b/gen/structs.cpp	Wed Feb 04 18:48:03 2009 +0100
@@ -607,7 +607,7 @@
     sd->ir.irStruct->init = initvar;
 
     gIR->constInitList.push_back(sd);
-    if (DtoIsTemplateInstance(sd) || sd->getModule() == gIR->dmodule)
+    if (mustDefineSymbol(sd))
         gIR->defineList.push_back(sd);
 }
 
--- a/gen/tollvm.cpp	Wed Feb 04 18:39:39 2009 +0100
+++ b/gen/tollvm.cpp	Wed Feb 04 18:48:03 2009 +0100
@@ -275,7 +275,7 @@
     if (VarDeclaration* vd = sym->isVarDeclaration())
     {
         // template
-        if (DtoIsTemplateInstance(sym))
+        if (needsTemplateLinkage(sym))
             return TEMPLATE_LINKAGE_TYPE;
         // local static
         else if (sym->parent && sym->parent->isFuncDeclaration())
@@ -296,7 +296,7 @@
         // template instances should have weak linkage
         // but only if there's a body, and it's not naked
         // otherwise we make it external
-        else if (DtoIsTemplateInstance(fdecl) && fdecl->fbody && !fdecl->naked)
+        else if (needsTemplateLinkage(fdecl) && fdecl->fbody && !fdecl->naked)
             return TEMPLATE_LINKAGE_TYPE;
         // extern(C) functions are always external
         else if (ft->linkage == LINKc)
@@ -306,7 +306,7 @@
     else if (ClassDeclaration* cd = sym->isClassDeclaration())
     {
         // template
-        if (DtoIsTemplateInstance(cd))
+        if (needsTemplateLinkage(cd))
             return TEMPLATE_LINKAGE_TYPE;
     }
     else
@@ -320,7 +320,7 @@
 
 llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym)
 {
-    if (DtoIsTemplateInstance(sym))
+    if (needsTemplateLinkage(sym))
         return TEMPLATE_LINKAGE_TYPE;
     else
         return llvm::GlobalValue::InternalLinkage;
@@ -328,7 +328,7 @@
 
 llvm::GlobalValue::LinkageTypes DtoExternalLinkage(Dsymbol* sym)
 {
-    if (DtoIsTemplateInstance(sym))
+    if (needsTemplateLinkage(sym))
         return TEMPLATE_LINKAGE_TYPE;
     else
         return llvm::GlobalValue::ExternalLinkage;