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->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");
|
||||
|
|
|
@ -326,6 +326,7 @@ struct TemplateInstance : ScopeDsymbol
|
|||
|
||||
// LDC
|
||||
TemplateInstance *tinst; // enclosing template instance
|
||||
Module* tmodule; // module from outermost enclosing template instantiation
|
||||
void printInstantiationTrace();
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
////////////////////////////////////////////
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue