Introduce needsCodegen.

This is a backport of the code from 2.065.
This commit is contained in:
kai 2014-06-16 07:00:29 +02:00
parent bef0a62622
commit 7c289fd673
7 changed files with 167 additions and 36 deletions

View file

@ -921,6 +921,9 @@ public:
void toObjFile(int multiobj); // compile to .obj file void toObjFile(int multiobj); // compile to .obj file
int cvMember(unsigned char *p); int cvMember(unsigned char *p);
void buildClosure(IRState *irs); // Should this be inside or outside the #if IN_DMD? void buildClosure(IRState *irs); // Should this be inside or outside the #if IN_DMD?
#endif
#if IN_LLVM // backported from 2.065
bool needsCodegen();
#endif #endif
FuncDeclaration *isFuncDeclaration() { return this; } FuncDeclaration *isFuncDeclaration() { return this; }

View file

@ -821,6 +821,35 @@ void Dsymbol::addComment(utf8_t *comment)
#endif #endif
} }
#if IN_LLVM // backported from 2.065
/****************************************
* Returns true if this symbol is defined in non-root module.
*/
bool Dsymbol::inNonRoot()
{
Dsymbol *s = parent;
for (; s; s = s->parent)
{
if (TemplateInstance *ti = s->isTemplateInstance())
{
if (ti->isTemplateMixin())
continue;
if (!ti->instantiatingModule || !ti->instantiatingModule->isRoot())
return true;
return false;
}
else if (Module *m = s->isModule())
{
if (!m->isRoot())
return true;
break;
}
}
return false;
}
#endif
/********************************* OverloadSet ****************************/ /********************************* OverloadSet ****************************/
#if DMDV2 #if DMDV2

View file

@ -231,6 +231,9 @@ public:
virtual void checkCtorConstInit() { } virtual void checkCtorConstInit() { }
virtual void addComment(utf8_t *comment); virtual void addComment(utf8_t *comment);
#if IN_LLVM // backported from 2.065
bool inNonRoot();
#endif
virtual void emitComment(Scope *sc); virtual void emitComment(Scope *sc);
void emitDitto(Scope *sc); void emitDitto(Scope *sc);

View file

@ -3965,6 +3965,93 @@ bool FuncDeclaration::hasNestedFrameRefs()
return false; return false;
} }
#if IN_LLVM // backported from 2.065
/***********************************************
* Returns true if this function is not defined in non-root module, nor
* obviously instantiated in non-root module.
*
* Note: ti->instantiatingModule does not stabilize until semantic analysis is completed,
* so don't call this function during semantic analysis to return precise result.
*/
bool FuncDeclaration::needsCodegen()
{
assert(semanticRun == PASSsemantic3done);
for (FuncDeclaration *fd = this; fd; )
{
if (!fd->inTemplateInstance() && fd->inNonRoot())
return false;
if (fd->isNested())
fd = fd->toParent2()->isFuncDeclaration();
else
break;
}
/* The issue is that if the importee is compiled with a different -debug
* setting than the importer, the importer may believe it exists
* in the compiled importee when it does not, when the instantiation
* is behind a conditional debug declaration.
*/
// workaround for Bugzilla 11239
if (global.params.useUnitTests ||
global.params.allInst ||
global.params.debuglevel)
{
return true;
}
FuncDeclaration *fd = this;
Lagain:
TemplateInstance *ti = fd->inTemplateInstance();
if (ti && ti->instantiatingModule && !ti->instantiatingModule->isRoot())
{
Module *mi = ti->instantiatingModule;
// If mi imports any root modules, we still need to generate the code.
for (size_t i = 0; i < Module::amodules.dim; ++i)
{
Module *m = Module::amodules[i];
m->insearch = 0;
}
bool importsRoot = false;
for (size_t i = 0; i < Module::amodules.dim; ++i)
{
Module *m = Module::amodules[i];
if (m->isRoot() && mi->imports(m))
{
importsRoot = true;
break;
}
}
for (size_t i = 0; i < Module::amodules.dim; ++i)
{
Module *m = Module::amodules[i];
m->insearch = 0;
}
if (!importsRoot)
{
//printf("instantiated by %s %s\n", ti->instantiatingModule->toChars(), ti->toChars());
return false;
}
}
if (fd->isNested())
{
/* Bugzilla 11863: The enclosing function must have its code generated first.
* Therefore if parent is instantiated in non-root, this function also prevent
* code generation.
*/
fd = fd->toParent2()->isFuncDeclaration();
if (fd)
goto Lagain;
}
//if (AggregateDeclaration *ad = fd->isMember2()) { ... }
return true;
}
#endif
/********************************************* /*********************************************
* Return the function's parameter list, and whether * Return the function's parameter list, and whether
* it is variadic or not. * it is variadic or not.

View file

@ -801,6 +801,7 @@ static void dumpPredefinedVersions()
} }
static Module *entrypoint = NULL; static Module *entrypoint = NULL;
static Module *rootHasMain = NULL;
/// Callback to generate a C main() function, invoked by the frontend. /// Callback to generate a C main() function, invoked by the frontend.
void genCmain(Scope *sc) void genCmain(Scope *sc)
@ -830,7 +831,7 @@ void genCmain(Scope *sc)
char v = global.params.verbose; char v = global.params.verbose;
global.params.verbose = 0; global.params.verbose = 0;
m->importedFrom = sc->module; m->importedFrom = m;
m->importAll(NULL); m->importAll(NULL);
m->semantic(); m->semantic();
m->semantic2(); m->semantic2();
@ -838,6 +839,7 @@ void genCmain(Scope *sc)
global.params.verbose = v; global.params.verbose = v;
entrypoint = m; entrypoint = m;
rootHasMain = sc->module;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
@ -1252,7 +1254,7 @@ int main(int argc, char **argv)
if (global.params.obj) if (global.params.obj)
{ {
llvm::Module* lm = m->genLLVMModule(context); llvm::Module* lm = m->genLLVMModule(context);
if (entrypoint && entrypoint->importedFrom == m) if (entrypoint && rootHasMain == m)
{ {
#if LDC_LLVM_VER >= 303 #if LDC_LLVM_VER >= 303
llvm::Linker linker(lm); llvm::Linker linker(lm);

View file

@ -928,44 +928,44 @@ void DtoDefineFunction(FuncDeclaration* fd)
if (fd->ir.defined) return; if (fd->ir.defined) return;
if ((fd->type && fd->type->ty == Tfunction && static_cast<TypeFunction *>(fd->type)->next == NULL) ||
(fd->type && fd->type->ty == Tfunction && static_cast<TypeFunction *>(fd->type)->next->ty == Terror))
{
IF_LOG Logger::println("Ignoring; no return type or return error type");
fd->ir.defined = true;
return;
}
if (fd->isUnitTestDeclaration() && !global.params.useUnitTests)
{
IF_LOG Logger::println("No code generation for unit test declaration %s", fd->toChars());
fd->ir.defined = true;
return;
}
if (fd->semanticRun == PASSsemanticdone)
{
/* What happened is this function failed semantic3() with errors,
* but the errors were gagged.
* Try to reproduce those errors, and then fail.
*/
error("errors compiling function %s", fd->toPrettyChars());
fd->ir.defined = true;
return;
}
assert(fd->semanticRun == PASSsemantic3done);
assert(fd->ident != Id::empty);
// Skip generating code for this part of a TemplateInstance if it has been // Skip generating code for this part of a TemplateInstance if it has been
// instantiated by any non-root module (i.e. a module not listed on the // instantiated by any non-root module (i.e. a module not listed on the
// command line). // command line).
// See DMD's FuncDeclaration::toObjFile. Check this before calling // Check this before calling DtoDeclareFunction to avoid touching
// DtoDeclareFunction DtoDeclareFunction to avoid touching unanalyzed code. // unanalyzed code.
TemplateInstance *ti = fd->inTemplateInstance(); if (!fd->needsCodegen())
if (!global.params.useUnitTests &&
ti && ti->instantiatingModule && !ti->instantiatingModule->isRoot())
{ {
Module *mi = ti->instantiatingModule; IF_LOG Logger::println("No code generation for %s", fd->toChars());
fd->ir.defined = true;
// If mi imports any root modules, we still need to generate the code. return;
for (size_t i = 0; i < Module::amodules.dim; ++i)
{
Module *m = Module::amodules[i];
m->insearch = 0;
}
bool importsRoot = false;
for (size_t i = 0; i < Module::amodules.dim; ++i)
{
Module *m = Module::amodules[i];
if (m->isRoot() && mi->imports(m))
{
importsRoot = true;
break;
}
}
for (size_t i = 0; i < Module::amodules.dim; ++i)
{
Module *m = Module::amodules[i];
m->insearch = 0;
}
if (!importsRoot)
{
IF_LOG Logger::println("Ignoring; already instantiated in %s (%s)", ti->instantiatingModule->toChars(), ti->toChars());
fd->ir.defined = true;
return;
}
} }
DtoDeclareFunction(fd); DtoDeclareFunction(fd);

View file

@ -2839,6 +2839,13 @@ DValue* FuncExp::toElem(IRState* p)
// We need to actually codegen the function here, as literals are not added // We need to actually codegen the function here, as literals are not added
// to the module member list. // to the module member list.
fd->codegen(p); fd->codegen(p);
if (!fd->ir.irFunc)
{
// See DtoDefineFunction for reasons why codegen was suppressed.
// Instead just declare the function.
DtoDeclareFunction(fd);
assert(!fd->isNested());
}
assert(fd->ir.irFunc->func); assert(fd->ir.irFunc->func);
if (fd->isNested()) { if (fd->isNested()) {