mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-03 08:30:47 +03:00
Windows: Make implicit dllimport more selective
* Newly require `-link-defaultlib-shared` for implicit dllimport. E.g., this enables to compile druntime DLL with `-fvisibility=public` for pure exports and no (local) imports (such as builtin TypeInfos). * `-link-defaultlib-shared` alone now only implicitly imports symbols from druntime/Phobos. This simplifies building complex DLLs linked against a bunch of static libs (dub only supports static lib dependencies!); the static libs don't need to be compiled with `-fvisibility=public` anymore (if the DLL itself isn't either), `-link-defaultlib-shared` is sufficient. This is mainly useful for existing DLLs with explicit exports, to make them link against *shared* druntime/Phobos and so end up with a single druntime/Phobos for the whole process.
This commit is contained in:
parent
2f0ece3274
commit
9865e459d1
15 changed files with 73 additions and 23 deletions
|
@ -109,6 +109,14 @@ enum FeatureState : byte
|
|||
enabled = 1 /// Specified as `-preview=`
|
||||
}
|
||||
|
||||
version (IN_LLVM)
|
||||
enum DLLImport : byte
|
||||
{
|
||||
none,
|
||||
defaultLibsOnly, // only symbols from druntime/Phobos
|
||||
all
|
||||
}
|
||||
|
||||
// Put command line switches in here
|
||||
extern (C++) struct Param
|
||||
{
|
||||
|
@ -305,7 +313,7 @@ version (IN_LLVM)
|
|||
|
||||
// Windows-specific:
|
||||
bool dllexport; // dllexport ~all defined symbols?
|
||||
bool dllimport; // dllimport data symbols not defined in any root module?
|
||||
DLLImport dllimport; // dllimport data symbols not defined in any root module?
|
||||
} // IN_LLVM
|
||||
}
|
||||
|
||||
|
|
|
@ -98,6 +98,15 @@ enum class FeatureState : signed char
|
|||
enabled = 1 /// Specified as `-preview=`
|
||||
};
|
||||
|
||||
#if IN_LLVM
|
||||
enum class DLLImport : char
|
||||
{
|
||||
none,
|
||||
defaultLibsOnly, // only symbols from druntime/Phobos
|
||||
all
|
||||
};
|
||||
#endif
|
||||
|
||||
// Put command line switches in here
|
||||
struct Param
|
||||
{
|
||||
|
@ -280,7 +289,7 @@ struct Param
|
|||
|
||||
// Windows-specific:
|
||||
bool dllexport; // dllexport ~all defined symbols?
|
||||
bool dllimport; // dllimport data symbols not defined in any root module?
|
||||
DLLImport dllimport; // dllimport data symbols not defined in any root module?
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
3
dmd/id.h
3
dmd/id.h
|
@ -44,6 +44,9 @@ struct Id
|
|||
static Identifier *dcompute;
|
||||
static Identifier *dcPointer;
|
||||
static Identifier *object;
|
||||
static Identifier *core;
|
||||
static Identifier *etc;
|
||||
static Identifier *std;
|
||||
static Identifier *ensure;
|
||||
static Identifier *require;
|
||||
static Identifier *xopEquals;
|
||||
|
|
|
@ -1090,10 +1090,10 @@ int cppmain() {
|
|||
v == opts::SymbolVisibility::public_ ||
|
||||
// default with -shared
|
||||
(v == opts::SymbolVisibility::default_ && global.params.dll);
|
||||
global.params.dllimport =
|
||||
v == opts::SymbolVisibility::public_ ||
|
||||
// enforced when linking against shared default libs
|
||||
linkAgainstSharedDefaultLibs();
|
||||
global.params.dllimport = !linkAgainstSharedDefaultLibs() ? DLLImport::none
|
||||
: v == opts::SymbolVisibility::public_
|
||||
? DLLImport::all
|
||||
: DLLImport::defaultLibsOnly;
|
||||
}
|
||||
|
||||
// allocate the target abi
|
||||
|
|
|
@ -1670,6 +1670,22 @@ std::string llvmTypeToString(llvm::Type *type) {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool isDefaultLibSymbol(Dsymbol *sym) {
|
||||
auto mod = sym->getModule();
|
||||
if (!mod)
|
||||
return false;
|
||||
|
||||
auto md = mod->md;
|
||||
if (!md)
|
||||
return false;
|
||||
|
||||
if (md->packages.length == 0)
|
||||
return md->id == Id::object;
|
||||
|
||||
auto p = md->packages.ptr[0];
|
||||
return p == Id::core || p == Id::std || p == Id::etc || p == Id::ldc;
|
||||
}
|
||||
|
||||
llvm::GlobalVariable *declareGlobal(const Loc &loc, llvm::Module &module,
|
||||
llvm::Type *type,
|
||||
llvm::StringRef mangledName,
|
||||
|
|
|
@ -245,6 +245,9 @@ LLConstant *toConstantArray(LLType *ct, LLArrayType *at, T *str, size_t len,
|
|||
|
||||
llvm::Constant *buildStringLiteralConstant(StringExp *se, bool zeroTerm);
|
||||
|
||||
/// Is the specified symbol part of druntime/Phobos?
|
||||
bool isDefaultLibSymbol(Dsymbol *sym);
|
||||
|
||||
/// 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.
|
||||
///
|
||||
|
|
|
@ -190,8 +190,9 @@ LLFunction *build_module_reference_and_ctor(const char *moduleMangle,
|
|||
LLConstant *mref = gIR->module.getNamedGlobal(mrefIRMangle);
|
||||
LLType *modulerefPtrTy = getPtrToType(modulerefTy);
|
||||
if (!mref) {
|
||||
mref = declareGlobal(Loc(), gIR->module, modulerefPtrTy, mrefIRMangle,
|
||||
false, false, global.params.dllimport);
|
||||
mref =
|
||||
declareGlobal(Loc(), gIR->module, modulerefPtrTy, mrefIRMangle, false,
|
||||
false, global.params.dllimport != DLLImport::none);
|
||||
}
|
||||
mref = DtoBitCast(mref, getPtrToType(modulerefPtrTy));
|
||||
|
||||
|
|
|
@ -423,7 +423,7 @@ bool ldc_optimize_module(llvm::Module *M) {
|
|||
|
||||
addOptimizationPasses(mpm, fpm, optLevel(), sizeLevel());
|
||||
|
||||
if (global.params.dllimport) {
|
||||
if (global.params.dllimport != DLLImport::none) {
|
||||
mpm.add(createDLLImportRelocationPass());
|
||||
}
|
||||
|
||||
|
|
|
@ -439,8 +439,7 @@ void buildTypeInfo(TypeInfoDeclaration *decl) {
|
|||
// immutable on the D side, and e.g. synchronized() can be used on the
|
||||
// implicit monitor.
|
||||
const bool isConstant = false;
|
||||
// TODO: no dllimport when compiling druntime itself
|
||||
const bool useDLLImport = isBuiltin && global.params.dllimport;
|
||||
bool useDLLImport = isBuiltin && global.params.dllimport != DLLImport::none;
|
||||
gvar = declareGlobal(decl->loc, gIR->module, type, irMangle, isConstant,
|
||||
false, useDLLImport);
|
||||
}
|
||||
|
|
|
@ -56,7 +56,9 @@ bool IrAggr::useDLLImport() const {
|
|||
if (!global.params.targetTriple->isOSWindows())
|
||||
return false;
|
||||
|
||||
if (global.params.dllimport || aggrdecl->isExport()) {
|
||||
if (aggrdecl->isExport() || global.params.dllimport == DLLImport::all ||
|
||||
(global.params.dllimport == DLLImport::defaultLibsOnly &&
|
||||
isDefaultLibSymbol(aggrdecl))) {
|
||||
// dllimport, unless defined in a root module (=> no extra indirection for
|
||||
// other root modules, assuming *all* root modules will be linked together
|
||||
// to one or more binaries).
|
||||
|
|
|
@ -27,7 +27,11 @@ llvm::GlobalVariable *IrModule::moduleInfoSymbol() {
|
|||
|
||||
const auto irMangle = getIRMangledModuleInfoSymbolName(M);
|
||||
|
||||
const bool useDLLImport = global.params.dllimport && !M->isRoot();
|
||||
bool useDLLImport = false;
|
||||
if (global.params.dllimport == DLLImport::all)
|
||||
useDLLImport = !M->isRoot();
|
||||
else if (global.params.dllimport == DLLImport::defaultLibsOnly)
|
||||
useDLLImport = !M->isRoot() && isDefaultLibSymbol(M);
|
||||
|
||||
moduleInfoVar = declareGlobal(Loc(), gIR->module,
|
||||
llvm::StructType::create(gIR->context()),
|
||||
|
|
|
@ -85,9 +85,13 @@ void IrGlobal::declare() {
|
|||
if (global.params.targetTriple->isOSWindows()) {
|
||||
// dllimport isn't supported for thread-local globals (MSVC++ neither)
|
||||
if (!V->isThreadlocal()) {
|
||||
// with -fvisibility=public / -link-defaultlib-shared, also include all
|
||||
// with -fvisibility=public / -link-defaultlib-shared, also include
|
||||
// extern(D) globals
|
||||
if (V->isExport() || (global.params.dllimport && V->linkage == LINK::d)) {
|
||||
if (V->isExport() ||
|
||||
(V->linkage == LINK::d &&
|
||||
(global.params.dllimport == DLLImport::all ||
|
||||
(global.params.dllimport == DLLImport::defaultLibsOnly &&
|
||||
isDefaultLibSymbol(V))))) {
|
||||
const bool isDefinedInRootModule =
|
||||
!(V->storage_class & STCextern) && !V->inNonRoot();
|
||||
if (!isDefinedInRootModule)
|
||||
|
|
|
@ -708,7 +708,7 @@ macro(build_runtime_variant d_flags c_flags ld_flags lib_suffix path_suffix emit
|
|||
AND NOT ${all_d_files_at_once})
|
||||
set(phobos2_o "")
|
||||
set(phobos2_bc "")
|
||||
compile_phobos2("${phobos2_d_flags};-relocation-model=pic;-fvisibility=public"
|
||||
compile_phobos2("${phobos2_d_flags};-relocation-model=pic;-fvisibility=public;-link-defaultlib-shared"
|
||||
"${lib_suffix}${SHARED_LIB_SUFFIX}" "${path_suffix}"
|
||||
"${emit_bc}" "${all_d_files_at_once}" "OFF" phobos2_o phobos2_bc)
|
||||
|
||||
|
@ -761,7 +761,7 @@ macro(build_runtime_variant d_flags c_flags ld_flags lib_suffix path_suffix emit
|
|||
if(phobos2_common STREQUAL "")
|
||||
set(phobos2_o "")
|
||||
set(phobos2_bc "")
|
||||
compile_phobos2("${phobos2_d_flags};-relocation-model=pic;-fvisibility=public"
|
||||
compile_phobos2("${phobos2_d_flags};-relocation-model=pic;-fvisibility=public;-link-defaultlib-shared"
|
||||
"${lib_suffix}${SHARED_LIB_SUFFIX}" "${path_suffix}"
|
||||
"OFF" "${all_d_files_at_once}" "${all_d_files_at_once}" phobos2_o phobos2_bc)
|
||||
endif()
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 65a26b5756fd1b4f693b013e1838ac11ac2e19d4
|
||||
Subproject commit c424142bbab8def67d362ac18d534c2be165d39b
|
|
@ -4,11 +4,12 @@
|
|||
|
||||
// REQUIRES: Windows
|
||||
|
||||
// generate DLL and import lib
|
||||
// generate DLL and import lib (public visibility by default)
|
||||
// RUN: %ldc %S/inputs/fvisibility_dll_lib.d -betterC -shared -of=%t_lib.dll
|
||||
|
||||
// compile, link and run the app; -link-defaultlib-shared for importing data symbols as dllimport
|
||||
// RUN: %ldc %s -I%S/inputs -betterC -link-defaultlib-shared %t_lib.lib -of=%t.exe
|
||||
// compile, link and run the app;
|
||||
// `-link-defaultlib-shared -fvisibility=public` for dllimporting data symbols
|
||||
// RUN: %ldc %s -I%S/inputs -betterC -link-defaultlib-shared -fvisibility=public %t_lib.lib -of=%t.exe
|
||||
// RUN: %t.exe
|
||||
|
||||
import fvisibility_dll_lib;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue