mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-05 01:20:51 +03:00
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:
parent
a1e6510c39
commit
9bd52922bd
8 changed files with 57 additions and 40 deletions
|
@ -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");
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue