mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
Emit template symbols into correct module during many-at-once compilation.
Previously, it could happen that regular symbols referenced only as part of a template instance (e.g. a lambda passed as an alias parameter) were not even emitted in the wrong module, but not at all because mustDefineSymbol would return false to them when being analyzed during codegen of the wrong module. This issue might affect incremental compilation with DMD as well, and the fix should be discussed with the upstream devs. GitHub: Fixes #249.
This commit is contained in:
@@ -936,6 +936,28 @@ void Module::semantic(Scope* unused_sc)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IN_LLVM
|
||||
// If this is a root module (i.e. one we generate an object file for),
|
||||
// make sure all template instances created as part of semantic analysis
|
||||
// of this module are actually emitted during codegen for this module, and
|
||||
// not while generating another random module that happened to import a
|
||||
// given module "first" (the frontend usually only sets importedFrom once).
|
||||
// This is especially important for LDC, as we base the decision of whether
|
||||
// to actually emit code for a declaration (mustDefineSymbol) on whether
|
||||
// the module being codegen'ed is the module the symbol was defined in.
|
||||
if (importedFrom == this)
|
||||
{
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Import *s = (*members)[i]->isImport();
|
||||
if (s)
|
||||
{
|
||||
s->mod->updateImportedFrom(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Do semantic() on members that don't depend on others
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
@@ -1260,6 +1282,26 @@ int Module::selfImports()
|
||||
}
|
||||
|
||||
|
||||
#if IN_LLVM
|
||||
void Module::updateImportedFrom(Module *newRoot)
|
||||
{
|
||||
// If this is also a root, there is nothing to do.
|
||||
if (importedFrom == this || importedFrom == newRoot)
|
||||
return;
|
||||
|
||||
importedFrom = newRoot;
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Import *s = (*members)[i]->isImport();
|
||||
if (s)
|
||||
{
|
||||
s->mod->updateImportedFrom(newRoot);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* =========================== ModuleDeclaration ===================== */
|
||||
|
||||
ModuleDeclaration::ModuleDeclaration(Identifiers *packages, Identifier *id, bool safe)
|
||||
|
||||
@@ -196,7 +196,10 @@ struct Module : Package
|
||||
void genmoduleinfo();
|
||||
|
||||
#if IN_LLVM
|
||||
// LDC
|
||||
/// Recursively sets the importedFrom field of any non-root modules
|
||||
/// imported by this (including the module itself) to the given module.
|
||||
void updateImportedFrom(Module *newRoot);
|
||||
|
||||
llvm::Module* genLLVMModule(llvm::LLVMContext& context, Ir* sir);
|
||||
void buildTargetFiles(bool singleObj);
|
||||
File* buildFilePath(const char* forcename, const char* path, const char* ext);
|
||||
|
||||
Reference in New Issue
Block a user