mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-04-29 06:30:39 +03:00
-dllimport=defaultLibsOnly: Avoid -linkonce-templates requirement (#3816)
Via a sorts-of '-linkonce-templates light', only defining all *data* symbols instantiated from druntime/Phobos templates in each referencing CU.
This commit is contained in:
parent
d9b2c936c9
commit
16b9eab374
9 changed files with 35 additions and 34 deletions
|
@ -80,9 +80,7 @@ cl::opt<DLLImport, true> dllimport(
|
||||||
"None (default with -link-defaultlib-shared=false)"),
|
"None (default with -link-defaultlib-shared=false)"),
|
||||||
clEnumValN(DLLImport::defaultLibsOnly, "defaultLibsOnly",
|
clEnumValN(DLLImport::defaultLibsOnly, "defaultLibsOnly",
|
||||||
"Only druntime/Phobos symbols (default with "
|
"Only druntime/Phobos symbols (default with "
|
||||||
"-link-defaultlib-shared and -fvisibility=hidden). May "
|
"-link-defaultlib-shared and -fvisibility=hidden)."),
|
||||||
"likely need to be coupled with -linkonce-templates to "
|
|
||||||
"overcome linker errors wrt. instantiated symbols."),
|
|
||||||
clEnumValN(DLLImport::all, "all",
|
clEnumValN(DLLImport::all, "all",
|
||||||
"All (default with -link-defaultlib-shared and "
|
"All (default with -link-defaultlib-shared and "
|
||||||
"-fvisibility=public)")));
|
"-fvisibility=public)")));
|
||||||
|
|
|
@ -598,7 +598,7 @@ void DtoDeclareFunction(FuncDeclaration *fdecl, const bool willDefine) {
|
||||||
bool defineAsAvailableExternally = false;
|
bool defineAsAvailableExternally = false;
|
||||||
if (willDefine) {
|
if (willDefine) {
|
||||||
// will be defined anyway after declaration
|
// will be defined anyway after declaration
|
||||||
} else if (defineOnDeclare(fdecl)) {
|
} else if (defineOnDeclare(fdecl, /*isFunction=*/true)) {
|
||||||
Logger::println("Function is inside a linkonce_odr template, will be "
|
Logger::println("Function is inside a linkonce_odr template, will be "
|
||||||
"defined after declaration.");
|
"defined after declaration.");
|
||||||
if (fdecl->semanticRun < PASSsemantic3done) {
|
if (fdecl->semanticRun < PASSsemantic3done) {
|
||||||
|
|
|
@ -794,14 +794,6 @@ DValue *DtoPaintType(const Loc &loc, DValue *val, Type *to) {
|
||||||
return new DImValue(to, DtoRVal(val));
|
return new DImValue(to, DtoRVal(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* TEMPLATE HELPERS
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
bool defineOnDeclare(Dsymbol* s) {
|
|
||||||
return global.params.linkonceTemplates && s->isInstantiated();
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* PROCESSING QUEUE HELPERS
|
* PROCESSING QUEUE HELPERS
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
@ -1680,12 +1672,8 @@ std::string llvmTypeToString(llvm::Type *type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is the specified symbol defined in the druntime/Phobos libs?
|
// Is the specified symbol defined in the druntime/Phobos libs?
|
||||||
// Note: fuzzy semantics for instantiated symbols, except with
|
// For instantiated symbols: is the template declared in druntime/Phobos?
|
||||||
// -linkonce-templates.
|
|
||||||
static bool isDefaultLibSymbol(Dsymbol *sym) {
|
static bool isDefaultLibSymbol(Dsymbol *sym) {
|
||||||
if (defineOnDeclare(sym))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto mod = sym->getModule();
|
auto mod = sym->getModule();
|
||||||
if (!mod)
|
if (!mod)
|
||||||
return false;
|
return false;
|
||||||
|
@ -1705,10 +1693,24 @@ static bool isDefaultLibSymbol(Dsymbol *sym) {
|
||||||
(md->packages.length > 1 && md->packages.ptr[1] == Id::io)));
|
(md->packages.length > 1 && md->packages.ptr[1] == Id::io)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dllimportSymbol(Dsymbol *sym) {
|
bool defineOnDeclare(Dsymbol* sym, bool isFunction) {
|
||||||
|
if (global.params.linkonceTemplates)
|
||||||
|
return sym->isInstantiated();
|
||||||
|
|
||||||
|
// With -dllimport=defaultLibsOnly, an instantiated data symbol from a
|
||||||
|
// druntime/Phobos template may be assigned to an arbitrary binary (and culled
|
||||||
|
// from others via `needsCodegen()`). Define it in each referencing CU and
|
||||||
|
// never dllimport.
|
||||||
|
return !isFunction && global.params.dllimport == DLLImport::defaultLibsOnly &&
|
||||||
|
sym->isInstantiated() && isDefaultLibSymbol(sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dllimportDataSymbol(Dsymbol *sym) {
|
||||||
return sym->isExport() || global.params.dllimport == DLLImport::all ||
|
return sym->isExport() || global.params.dllimport == DLLImport::all ||
|
||||||
(global.params.dllimport == DLLImport::defaultLibsOnly &&
|
(global.params.dllimport == DLLImport::defaultLibsOnly &&
|
||||||
isDefaultLibSymbol(sym));
|
// exclude instantiated symbols from druntime/Phobos templates (see
|
||||||
|
// `defineOnDeclare()`)
|
||||||
|
!sym->isInstantiated() && isDefaultLibSymbol(sym));
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::GlobalVariable *declareGlobal(const Loc &loc, llvm::Module &module,
|
llvm::GlobalVariable *declareGlobal(const Loc &loc, llvm::Module &module,
|
||||||
|
|
|
@ -101,10 +101,6 @@ DValue *DtoCast(const Loc &loc, DValue *val, Type *to);
|
||||||
// otherwise returns a new DValue
|
// otherwise returns a new DValue
|
||||||
DValue *DtoPaintType(const Loc &loc, DValue *val, Type *to);
|
DValue *DtoPaintType(const Loc &loc, DValue *val, Type *to);
|
||||||
|
|
||||||
/// Returns true if the specified symbol is to be defined on declaration, for
|
|
||||||
/// -linkonce-templates.
|
|
||||||
bool defineOnDeclare(Dsymbol *s);
|
|
||||||
|
|
||||||
/// Makes sure the declarations corresponding to the given D symbol have been
|
/// Makes sure the declarations corresponding to the given D symbol have been
|
||||||
/// emitted to the currently processed LLVM module.
|
/// emitted to the currently processed LLVM module.
|
||||||
///
|
///
|
||||||
|
@ -245,8 +241,13 @@ LLConstant *toConstantArray(LLType *ct, LLArrayType *at, T *str, size_t len,
|
||||||
|
|
||||||
llvm::Constant *buildStringLiteralConstant(StringExp *se, bool zeroTerm);
|
llvm::Constant *buildStringLiteralConstant(StringExp *se, bool zeroTerm);
|
||||||
|
|
||||||
/// Indicates whether the specified symbol is a general dllimport candidate.
|
/// Returns true if the specified symbol is to be defined on declaration,
|
||||||
bool dllimportSymbol(Dsymbol *sym);
|
/// primarily for -linkonce-templates.
|
||||||
|
bool defineOnDeclare(Dsymbol *sym, bool isFunction);
|
||||||
|
|
||||||
|
/// Indicates whether the specified data symbol is a general dllimport
|
||||||
|
/// candidate.
|
||||||
|
bool dllimportDataSymbol(Dsymbol *sym);
|
||||||
|
|
||||||
/// Tries to declare an LLVM global. If a variable with the same mangled name
|
/// Tries to declare an LLVM global. If a variable with the same mangled name
|
||||||
/// already exists, checks if the types match and returns it instead.
|
/// already exists, checks if the types match and returns it instead.
|
||||||
|
|
|
@ -56,7 +56,7 @@ bool IrAggr::useDLLImport() const {
|
||||||
if (!global.params.targetTriple->isOSWindows())
|
if (!global.params.targetTriple->isOSWindows())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (dllimportSymbol(aggrdecl)) {
|
if (dllimportDataSymbol(aggrdecl)) {
|
||||||
// dllimport, unless defined in a root module (=> no extra indirection for
|
// dllimport, unless defined in a root module (=> no extra indirection for
|
||||||
// other root modules, assuming *all* root modules will be linked together
|
// other root modules, assuming *all* root modules will be linked together
|
||||||
// to one or more binaries).
|
// to one or more binaries).
|
||||||
|
@ -103,7 +103,7 @@ LLConstant *IrAggr::getInitSymbol(bool define) {
|
||||||
init = initGlobal;
|
init = initGlobal;
|
||||||
|
|
||||||
if (!define)
|
if (!define)
|
||||||
define = defineOnDeclare(aggrdecl);
|
define = defineOnDeclare(aggrdecl, /*isFunction=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (define) {
|
if (define) {
|
||||||
|
|
|
@ -73,7 +73,7 @@ LLGlobalVariable *IrClass::getVtblSymbol(bool define) {
|
||||||
/*isConstant=*/true, false, useDLLImport());
|
/*isConstant=*/true, false, useDLLImport());
|
||||||
|
|
||||||
if (!define)
|
if (!define)
|
||||||
define = defineOnDeclare(aggrdecl);
|
define = defineOnDeclare(aggrdecl, /*isFunction=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (define) {
|
if (define) {
|
||||||
|
@ -130,7 +130,7 @@ LLGlobalVariable *IrClass::getClassInfoSymbol(bool define) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!define)
|
if (!define)
|
||||||
define = defineOnDeclare(aggrdecl);
|
define = defineOnDeclare(aggrdecl, /*isFunction=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (define) {
|
if (define) {
|
||||||
|
@ -473,7 +473,7 @@ llvm::GlobalVariable *IrClass::getInterfaceVtblSymbol(BaseClass *b,
|
||||||
interfaceVtblMap.insert({{b->sym, interfaces_index}, gvar});
|
interfaceVtblMap.insert({{b->sym, interfaces_index}, gvar});
|
||||||
|
|
||||||
if (!define)
|
if (!define)
|
||||||
define = defineOnDeclare(aggrdecl);
|
define = defineOnDeclare(aggrdecl, /*isFunction=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (define && !gvar->hasInitializer()) {
|
if (define && !gvar->hasInitializer()) {
|
||||||
|
|
|
@ -27,7 +27,7 @@ llvm::GlobalVariable *IrModule::moduleInfoSymbol() {
|
||||||
|
|
||||||
const auto irMangle = getIRMangledModuleInfoSymbolName(M);
|
const auto irMangle = getIRMangledModuleInfoSymbolName(M);
|
||||||
|
|
||||||
const bool useDLLImport = !M->isRoot() && dllimportSymbol(M);
|
const bool useDLLImport = !M->isRoot() && dllimportDataSymbol(M);
|
||||||
|
|
||||||
moduleInfoVar = declareGlobal(Loc(), gIR->module,
|
moduleInfoVar = declareGlobal(Loc(), gIR->module,
|
||||||
llvm::StructType::create(gIR->context()),
|
llvm::StructType::create(gIR->context()),
|
||||||
|
|
|
@ -57,7 +57,7 @@ LLGlobalVariable* IrStruct::getTypeInfoSymbol(bool define) {
|
||||||
emitTypeInfoMetadata(typeInfo, aggrdecl->type);
|
emitTypeInfoMetadata(typeInfo, aggrdecl->type);
|
||||||
|
|
||||||
if (!define)
|
if (!define)
|
||||||
define = defineOnDeclare(aggrdecl);
|
define = defineOnDeclare(aggrdecl, /*isFunction=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (define) {
|
if (define) {
|
||||||
|
|
|
@ -29,7 +29,7 @@ LLValue *IrGlobal::getValue(bool define) {
|
||||||
declare();
|
declare();
|
||||||
|
|
||||||
if (!define)
|
if (!define)
|
||||||
define = defineOnDeclare(V);
|
define = defineOnDeclare(V, /*isFunction=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (define) {
|
if (define) {
|
||||||
|
@ -86,7 +86,7 @@ void IrGlobal::declare() {
|
||||||
// dllimport isn't supported for thread-local globals (MSVC++ neither)
|
// dllimport isn't supported for thread-local globals (MSVC++ neither)
|
||||||
if (!V->isThreadlocal()) {
|
if (!V->isThreadlocal()) {
|
||||||
// implicitly include extern(D) globals with -dllimport
|
// implicitly include extern(D) globals with -dllimport
|
||||||
if (V->isExport() || (V->linkage == LINK::d && dllimportSymbol(V))) {
|
if (V->isExport() || (V->linkage == LINK::d && dllimportDataSymbol(V))) {
|
||||||
const bool isDefinedInRootModule =
|
const bool isDefinedInRootModule =
|
||||||
!(V->storage_class & STCextern) && !V->inNonRoot();
|
!(V->storage_class & STCextern) && !V->inNonRoot();
|
||||||
if (!isDefinedInRootModule)
|
if (!isDefinedInRootModule)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue