-
-
Notifications
You must be signed in to change notification settings - Fork 267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Windows: Make -fvisibility=public export all defined symbols and import external data #3703
Conversation
@rainers: Do you happen to have any idea about the data symbols? |
Okay, non-TLS globals work in some scenarios now. Trying to access TLS globals across DLL boundaries yields a linking error; both MSVC and clang don't support them in C++ and fail at compile-time: extern __declspec(dllimport) thread_local int impGlobal; =>
|
I guess you are aware of Benjamin Thaut's work, see for example https://forum.dlang.org/thread/shonvwuauwbhrszysmrz@forum.dlang.org I agree that an "export all" switch avoids much of the hassle of his DIP. It's also what happens on linux, and there haven't really been any complaints recently AFAICT. It's also what I implemented 11 years ago: https://issues.dlang.org/show_bug.cgi?id=4071 ;-) dllimported data needs different code to access it (IIRC dmd has support for that, probably not too hard to add the extra indirection). The more problematic case is imported data referenced from preinitialized data. This needs an additional relocation pass at EXE/DLL initialization time using compiler generated info: https://github.com/Ingrater/druntime/blob/DllSupport80/src/rt/sections_win64.d#L432 An alternative might be to emit initializer functions. IIRC that is what MSVC does, though your comment above suggests it is not supported (anymore?). |
Thx Rainer.
Yep exactly, this seems to account for most Phobos linking failures in #3704. It's especially bad for generated TypeInfos, because they reference e.g. the Living with no direct TLS globals access across DLLs would IMO be doable, but not being able to access non-TLS globals in initializers for static data in other DLLs seems like the biggest hurdle for DLLs on Windows indeed. |
To pave the way for simple DLL generation (end goal: druntime-ldc-shared.dll). The dllexport storage class for functions definitions is enough; the automatically generated import .lib seems to resolve the regular symbol name to the actual symbol (__imp_*), so dllimport for declarations seems superfluous. For global variables, things are apparently different unfortunately.
Functions can and apparently are magically stubbed (something like `void myFunc() { (*__imp_myFunc)(); }`), but it seems we cannot avoid dllimport for global variables exported from other DLLs/executables. In order to try to make druntime etc. work as DLL without explicitly exporting all required globals, `-fvisibility=public` now also assumes all `extern(D)` globals *not* defined in some root module are exported from some binary and dllimports them accordingly. So e.g. compiling Phobos with `-fvisibility=public` means * Phobos exports all defined symbols, * Phobos dllimports extern(D) druntime symbols, and * extern(C) globals, e.g., from the C runtime, remain external and are linked regularly.
…ity=public Mainly, don't export any linkonce_odr symbols.
Otherwise the functions aren't exported. We have some @weak functions in druntime.
Init symbols, TypeInfos (classes only) & vtables - unless defined in a root module. For explicitly exported aggregates, or, with `-fvisibility=public`, all aggregates.
References to dllimported globals in static data initializers lead to undefined-symbol linker errors. We need to resolve the indirection manually at runtime. I went with an extra LLVM pass for Windows targets when using `-fvisibility=public`, and scanning the initializers of all global variables (well, only thread-global ones). The problematic pointers in the initializers are nullified and initialized at runtime early via a CRT constructor (working with -betterC as well).
I've added an LLVM pass performing the manual |
Having it a in a separate pass is pretty neat :-) For tls-variables, you could export an accessor-function instead that returns a reference/pointer to the variable. |
:) Yeah, LLVM's rich/heavy IR does have advantages...
I hope such direct accesses are sufficiently rare that manual workarounds like ldc-developers/druntime@f23246f will do for the/some time being. That was sufficient for the druntime/Phobos DLL boundary; linking all druntime and Phobos DLL variants now works, incl. linking the shared test runner executables (see here). That should be mostly it from the compiler side, and work can begin on making druntime DLL a truly shared druntime analogous to Posix' |
This fixes segfaults when running the shared Phobos test runners; it previously tried to fix up fields of constant data.
…h -link-defaultlib-shared
To pave the way for simple DLL generation (end goal:
druntime-ldc-shared.dll
).The
dllexport
storage class for functions definitions is enough; the automatically generated import .lib seems to resolve the regular symbol name to the actual symbol (__imp_*
), sodllimport
for declarations seems superfluous.For global variables, things are apparently different unfortunately.