[swift-dev] swift (ABI) and Windows
jgroff at apple.com
Wed Apr 6 13:39:53 CDT 2016
> On Apr 6, 2016, at 10:21 AM, Saleem Abdulrasool via swift-dev <swift-dev at swift.org> wrote:
> I was playing around with the idea of swift and Windows since there are some interesting differences between COFF/PE and (ELF and MachO).
> PE/COFF does not directly address symbols in external modules (DSOs/dylibs/DLLs). Instead, there is an indirect addressing model (thunks in Windows parlance). Fortunately, LLVM has a nice way to model this: GlobalValues have an associated "DLLStorageClass" which indicates whether something is "imported" (provided by an external module), "exported" (provided to external modules), or "default" (everything else).
> Adjusting the IRGen to correctly annotate this part of the semantics should get us part of the way to supporting swift on PE/COFF.
> The thing to consider with this is that the DLL storage class is dependent on how the module(s) are being built. For example, something may change from the exported storage to default if being built into a static library rather than a shared object and is not meant to be re-exported.
> Part of this information really needs to be threaded from the build system so that we know whether a given SIL module is external or internal.
> Given that this would potentially effect ABI stability, it seems like this is a good time to tackle it so that we can push this into the resilience work that is being done for swift 3.
> I would appreciate any pointers and suggestions as to how to best go about handling this.
As Jordan noted, we probably want to thread this information through for ELF and Mach-O builds too, for a couple of reasons. One, if you're building a static library as opposed to a .so or .dylib, it's not desirable to reexport that static library's API by default through any executables or dynamic libraries that use it. We currently get this wrong; if the compiler knew it was building for a static library, it could give public symbols in the .a 'hidden' visibility so that they do the right thing when linked into dylibs. Second, ELF's default visibility is problematic for Swift, since it allows default-visibility symbols to be interposed at load time by other dynamic libraries. This imposes a performance penalty on shared libraries accessing their own data, interferes with some of the load-time optimizations we do with metadata that assume we can hardcode relative references within a linkage unit, and is flat-out dangerous in the face of interprocedural optimization. For these reasons, we export symbols with "protected" visibility when we're emitting them as part of the current dylib, but import external public symbols with default visibility. Since we already need to track this distinction, it should be possible to approximate the right thing for Windows by using dllexport where we set protected visibility on ELF, or dllimport otherwise.
More information about the swift-dev