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->isnested = NULL;
this->errors = 0;
// LDC
this->tinst = NULL;
this->tmodule = NULL;
assert((size_t)tempdecl->scope > 0x10000);
}
@ -2979,6 +2982,7 @@ void TemplateInstance::semantic(Scope *sc)
// get the enclosing template instance from the scope tinst
tinst = sc->tinst;
tmodule = sc->module;
#if LOG
printf("\tdo semantic\n");

View file

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

View file

@ -324,7 +324,7 @@ static void DtoDeclareInterface(InterfaceDeclaration* cd)
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 @@ void DtoDeclareClass(ClassDeclaration* cd)
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 @@ static void DtoDefineInterface(InterfaceDeclaration* cd)
DefineInterfaceInfos(cd->ir.irStruct);
// define the classinfo
if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd))
if (mustDefineSymbol(cd))
{
DtoDefineClassInfo(cd);
}
@ -851,7 +851,7 @@ void DtoDefineClass(ClassDeclaration* cd)
IrStruct* irstruct = cd->ir.irStruct;
assert(cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd));
assert(mustDefineSymbol(cd));
// sanity check
assert(irstruct->init);

View file

@ -486,20 +486,9 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
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 @@ void DtoDefineFunction(FuncDeclaration* fd)
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;

View file

@ -831,15 +831,14 @@ DValue* DtoPaintType(Loc& loc, DValue* val, Type* to)
// 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 @@ void DtoConstInitGlobal(VarDeclaration* vd)
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 @@ void DtoOverloadedIntrinsicName(TemplateInstance* ti, TemplateDeclaration* td, s
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
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 @@ void findDefaultTarget();
// 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
////////////////////////////////////////////

View file

@ -607,7 +607,7 @@ void DtoDeclareStruct(StructDeclaration* sd)
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);
}

View file

@ -275,7 +275,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
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 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
// 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 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
else if (ClassDeclaration* cd = sym->isClassDeclaration())
{
// template
if (DtoIsTemplateInstance(cd))
if (needsTemplateLinkage(cd))
return TEMPLATE_LINKAGE_TYPE;
}
else
@ -320,7 +320,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
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 DtoInternalLinkage(Dsymbol* sym)
llvm::GlobalValue::LinkageTypes DtoExternalLinkage(Dsymbol* sym)
{
if (DtoIsTemplateInstance(sym))
if (needsTemplateLinkage(sym))
return TEMPLATE_LINKAGE_TYPE;
else
return llvm::GlobalValue::ExternalLinkage;