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.

This commit is contained in:
Tomas Lindquist Olsen 2009-02-04 18:48:03 +01:00
parent a1e6510c39
commit 9bd52922bd
8 changed files with 57 additions and 40 deletions

View file

@ -2901,7 +2901,10 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti
this->havetempdecl = 1; this->havetempdecl = 1;
this->isnested = NULL; this->isnested = NULL;
this->errors = 0; this->errors = 0;
// LDC
this->tinst = NULL; this->tinst = NULL;
this->tmodule = NULL;
assert((size_t)tempdecl->scope > 0x10000); assert((size_t)tempdecl->scope > 0x10000);
} }
@ -2979,6 +2982,7 @@ void TemplateInstance::semantic(Scope *sc)
// get the enclosing template instance from the scope tinst // get the enclosing template instance from the scope tinst
tinst = sc->tinst; tinst = sc->tinst;
tmodule = sc->module;
#if LOG #if LOG
printf("\tdo semantic\n"); printf("\tdo semantic\n");

View file

@ -326,6 +326,7 @@ struct TemplateInstance : ScopeDsymbol
// LDC // LDC
TemplateInstance *tinst; // enclosing template instance TemplateInstance *tinst; // enclosing template instance
Module* tmodule; // module from outermost enclosing template instantiation
void printInstantiationTrace(); void printInstantiationTrace();
}; };

View file

@ -324,7 +324,7 @@ static void DtoDeclareInterface(InterfaceDeclaration* cd)
gIR->constInitList.push_back(cd); gIR->constInitList.push_back(cd);
// emit typeinfo and request definition // emit typeinfo and request definition
if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd)) if (mustDefineSymbol(cd))
{ {
gIR->defineList.push_back(cd); gIR->defineList.push_back(cd);
DtoTypeInfoOf(cd->type, false); DtoTypeInfoOf(cd->type, false);
@ -360,7 +360,7 @@ void DtoDeclareClass(ClassDeclaration* cd)
gIR->structs.push_back(irstruct); gIR->structs.push_back(irstruct);
bool needs_definition = false; bool needs_definition = false;
if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd)) { if (mustDefineSymbol(cd)) {
needs_definition = true; needs_definition = true;
} }
@ -821,7 +821,7 @@ static void DtoDefineInterface(InterfaceDeclaration* cd)
DefineInterfaceInfos(cd->ir.irStruct); DefineInterfaceInfos(cd->ir.irStruct);
// define the classinfo // define the classinfo
if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd)) if (mustDefineSymbol(cd))
{ {
DtoDefineClassInfo(cd); DtoDefineClassInfo(cd);
} }
@ -851,7 +851,7 @@ void DtoDefineClass(ClassDeclaration* cd)
IrStruct* irstruct = cd->ir.irStruct; IrStruct* irstruct = cd->ir.irStruct;
assert(cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd)); assert(mustDefineSymbol(cd));
// sanity check // sanity check
assert(irstruct->init); assert(irstruct->init);

View file

@ -486,20 +486,9 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
Type* t = fdecl->type->toBasetype(); Type* t = fdecl->type->toBasetype();
TypeFunction* f = (TypeFunction*)t; TypeFunction* f = (TypeFunction*)t;
bool declareOnly = false; bool declareOnly = !mustDefineSymbol(fdecl);
bool templInst = fdecl->parent && DtoIsTemplateInstance(fdecl->parent);
if (!templInst && fdecl->getModule() != gIR->dmodule) if (fdecl->llvmInternal == LLVMva_start)
{
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)
declareOnly = true; declareOnly = true;
if (!fdecl->ir.irFunc) { if (!fdecl->ir.irFunc) {
@ -668,9 +657,8 @@ void DtoDefineFunction(FuncDeclaration* fd)
llvm::Function* func = fd->ir.irFunc->func; llvm::Function* func = fd->ir.irFunc->func;
const llvm::FunctionType* functype = func->getFunctionType(); const llvm::FunctionType* functype = func->getFunctionType();
// only members of the current module or template instances maybe be defined // sanity check
if (!(fd->getModule() == gIR->dmodule || DtoIsTemplateInstance(fd->parent))) assert(mustDefineSymbol(fd));
return;
// set module owner // set module owner
fd->ir.DModule = gIR->dmodule; fd->ir.DModule = gIR->dmodule;

View file

@ -831,15 +831,14 @@ DValue* DtoPaintType(Loc& loc, DValue* val, Type* to)
// TEMPLATE HELPERS // TEMPLATE HELPERS
////////////////////////////////////////////////////////////////////////////////////////*/ ////////////////////////////////////////////////////////////////////////////////////////*/
// FIXME: when is this the right one to use instead of Dsymbol::inTemplateInstance() ? Module* DtoIsTemplateInstance(Dsymbol* s)
bool DtoIsTemplateInstance(Dsymbol* s)
{ {
if (!s) return false; if (!s) return NULL;
if (s->isTemplateInstance() && !s->isTemplateMixin()) if (s->isTemplateInstance() && !s->isTemplateMixin())
return true; return s->isTemplateInstance()->tmodule;
else if (s->parent) else if (s->parent)
return DtoIsTemplateInstance(s->parent); return DtoIsTemplateInstance(s->parent);
return false; return NULL;
} }
/****************************************************************************************/ /****************************************************************************************/
@ -958,15 +957,10 @@ void DtoConstInitGlobal(VarDeclaration* vd)
assert(!glob->constInit); assert(!glob->constInit);
glob->constInit = initVal; glob->constInit = initVal;
bool istempl = false;
if ((vd->storage_class & STCcomdat) || (vd->parent && DtoIsTemplateInstance(vd->parent))) {
istempl = true;
}
// assign the initializer // assign the initializer
llvm::GlobalVariable* globalvar = llvm::cast<llvm::GlobalVariable>(glob->value); 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()) if (Logger::enabled())
{ {
@ -1559,3 +1553,27 @@ void DtoOverloadedIntrinsicName(TemplateInstance* ti, TemplateDeclaration* td, s
Logger::println("final intrinsic name: %s", name.c_str()); 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;
}

View file

@ -61,8 +61,8 @@ DValue* DtoCast(Loc& loc, DValue* val, Type* to);
// return the same val as passed in, modified to the target type, if possible, otherwise returns a new DValue // 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); DValue* DtoPaintType(Loc& loc, DValue* val, Type* to);
// is template instance check // is template instance check, returns module where instantiated
bool DtoIsTemplateInstance(Dsymbol* s); Module* DtoIsTemplateInstance(Dsymbol* s);
// these are all basically drivers for the codegeneration called by the main loop // these are all basically drivers for the codegeneration called by the main loop
void DtoResolveDsymbol(Dsymbol* dsym); void DtoResolveDsymbol(Dsymbol* dsym);
@ -108,6 +108,12 @@ void findDefaultTarget();
// fixup an overloaded intrinsic name string // fixup an overloaded intrinsic name string
void DtoOverloadedIntrinsicName(TemplateInstance* ti, TemplateDeclaration* td, std::string& name); 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 // gen/tocall.cpp stuff below
//////////////////////////////////////////// ////////////////////////////////////////////

View file

@ -607,7 +607,7 @@ void DtoDeclareStruct(StructDeclaration* sd)
sd->ir.irStruct->init = initvar; sd->ir.irStruct->init = initvar;
gIR->constInitList.push_back(sd); gIR->constInitList.push_back(sd);
if (DtoIsTemplateInstance(sd) || sd->getModule() == gIR->dmodule) if (mustDefineSymbol(sd))
gIR->defineList.push_back(sd); gIR->defineList.push_back(sd);
} }

View file

@ -275,7 +275,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
if (VarDeclaration* vd = sym->isVarDeclaration()) if (VarDeclaration* vd = sym->isVarDeclaration())
{ {
// template // template
if (DtoIsTemplateInstance(sym)) if (needsTemplateLinkage(sym))
return TEMPLATE_LINKAGE_TYPE; return TEMPLATE_LINKAGE_TYPE;
// local static // local static
else if (sym->parent && sym->parent->isFuncDeclaration()) else if (sym->parent && sym->parent->isFuncDeclaration())
@ -296,7 +296,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
// template instances should have weak linkage // template instances should have weak linkage
// but only if there's a body, and it's not naked // but only if there's a body, and it's not naked
// otherwise we make it external // 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; return TEMPLATE_LINKAGE_TYPE;
// extern(C) functions are always external // extern(C) functions are always external
else if (ft->linkage == LINKc) else if (ft->linkage == LINKc)
@ -306,7 +306,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
else if (ClassDeclaration* cd = sym->isClassDeclaration()) else if (ClassDeclaration* cd = sym->isClassDeclaration())
{ {
// template // template
if (DtoIsTemplateInstance(cd)) if (needsTemplateLinkage(cd))
return TEMPLATE_LINKAGE_TYPE; return TEMPLATE_LINKAGE_TYPE;
} }
else else
@ -320,7 +320,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym) llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym)
{ {
if (DtoIsTemplateInstance(sym)) if (needsTemplateLinkage(sym))
return TEMPLATE_LINKAGE_TYPE; return TEMPLATE_LINKAGE_TYPE;
else else
return llvm::GlobalValue::InternalLinkage; return llvm::GlobalValue::InternalLinkage;
@ -328,7 +328,7 @@ llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym)
llvm::GlobalValue::LinkageTypes DtoExternalLinkage(Dsymbol* sym) llvm::GlobalValue::LinkageTypes DtoExternalLinkage(Dsymbol* sym)
{ {
if (DtoIsTemplateInstance(sym)) if (needsTemplateLinkage(sym))
return TEMPLATE_LINKAGE_TYPE; return TEMPLATE_LINKAGE_TYPE;
else else
return llvm::GlobalValue::ExternalLinkage; return llvm::GlobalValue::ExternalLinkage;