diff --git a/dmd/template.c b/dmd/template.c index 210d45cc..a70b353e 100644 --- a/dmd/template.c +++ b/dmd/template.c @@ -3106,7 +3106,7 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti #if IN_LLVM // LDC - this->tinst = NULL; + this->emittedInModule = NULL; this->tmodule = NULL; #endif diff --git a/gen/irstate.h b/gen/irstate.h index f4f7e27a..04d477eb 100644 --- a/gen/irstate.h +++ b/gen/irstate.h @@ -158,6 +158,13 @@ struct IRState FuncDeclVector ctors; FuncDeclVector dtors; FuncDeclVector unitTests; + + // all template instances that had members emitted + // currently only filled for singleobj + // used to make sure the complete template instance gets emitted in the + // first file that touches a member, see #318 + typedef std::set TemplateInstanceSet; + TemplateInstanceSet seenTemplateInstances; // for inline asm IRAsmBlock* asmBlock; diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 3070aacd..bfbbab2b 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1409,7 +1409,10 @@ bool mustDefineSymbol(Dsymbol* s) return true; if (!tinst->emittedInModule) + { + gIR->seenTemplateInstances.insert(tinst); tinst->emittedInModule = gIR->dmodule; + } return tinst->emittedInModule == gIR->dmodule; } diff --git a/gen/toobj.cpp b/gen/toobj.cpp index a52f1825..02987fb2 100644 --- a/gen/toobj.cpp +++ b/gen/toobj.cpp @@ -142,6 +142,21 @@ llvm::Module* Module::genLLVMModule(Ir* sir) // emit function bodies sir->emitFunctionBodies(); + // for singleobj-compilation, fully emit all seen template instances + if (opts::singleObj) + { + while (!ir.seenTemplateInstances.empty()) + { + IRState::TemplateInstanceSet::iterator it, end = ir.seenTemplateInstances.end(); + for (it = ir.seenTemplateInstances.begin(); it != end; ++it) + (*it)->codegen(sir); + ir.seenTemplateInstances.clear(); + + // emit any newly added function bodies + sir->emitFunctionBodies(); + } + } + // generate ModuleInfo genmoduleinfo();