@@ -75,6 +75,7 @@ pub struct SharedCrateContext<'tcx> {
7575
7676 available_monomorphizations : RefCell < FnvHashSet < String > > ,
7777 available_drop_glues : RefCell < FnvHashMap < DropGlueKind < ' tcx > , String > > ,
78+ use_dll_storage_attrs : bool ,
7879}
7980
8081/// The local portion of a `CrateContext`. There is one `LocalCrateContext`
@@ -251,6 +252,51 @@ impl<'tcx> SharedCrateContext<'tcx> {
251252 create_context_and_module ( & tcx. sess , "metadata" )
252253 } ;
253254
255+ // An interesting part of Windows which MSVC forces our hand on (and
256+ // apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
257+ // attributes in LLVM IR as well as native dependencies (in C these
258+ // correspond to `__declspec(dllimport)`).
259+ //
260+ // Whenever a dynamic library is built by MSVC it must have its public
261+ // interface specified by functions tagged with `dllexport` or otherwise
262+ // they're not available to be linked against. This poses a few problems
263+ // for the compiler, some of which are somewhat fundamental, but we use
264+ // the `use_dll_storage_attrs` variable below to attach the `dllexport`
265+ // attribute to all LLVM functions that are reachable (e.g. they're
266+ // already tagged with external linkage). This is suboptimal for a few
267+ // reasons:
268+ //
269+ // * If an object file will never be included in a dynamic library,
270+ // there's no need to attach the dllexport attribute. Most object
271+ // files in Rust are not destined to become part of a dll as binaries
272+ // are statically linked by default.
273+ // * If the compiler is emitting both an rlib and a dylib, the same
274+ // source object file is currently used but with MSVC this may be less
275+ // feasible. The compiler may be able to get around this, but it may
276+ // involve some invasive changes to deal with this.
277+ //
278+ // The flipside of this situation is that whenever you link to a dll and
279+ // you import a function from it, the import should be tagged with
280+ // `dllimport`. At this time, however, the compiler does not emit
281+ // `dllimport` for any declarations other than constants (where it is
282+ // required), which is again suboptimal for even more reasons!
283+ //
284+ // * Calling a function imported from another dll without using
285+ // `dllimport` causes the linker/compiler to have extra overhead (one
286+ // `jmp` instruction on x86) when calling the function.
287+ // * The same object file may be used in different circumstances, so a
288+ // function may be imported from a dll if the object is linked into a
289+ // dll, but it may be just linked against if linked into an rlib.
290+ // * The compiler has no knowledge about whether native functions should
291+ // be tagged dllimport or not.
292+ //
293+ // For now the compiler takes the perf hit (I do not have any numbers to
294+ // this effect) by marking very little as `dllimport` and praying the
295+ // linker will take care of everything. Fixing this problem will likely
296+ // require adding a few attributes to Rust itself (feature gated at the
297+ // start) and then strongly recommending static linkage on MSVC!
298+ let use_dll_storage_attrs = tcx. sess . target . target . options . is_like_msvc ;
299+
254300 let mut shared_ccx = SharedCrateContext {
255301 local_ccxs : Vec :: with_capacity ( local_count) ,
256302 metadata_llmod : metadata_llmod,
@@ -277,6 +323,7 @@ impl<'tcx> SharedCrateContext<'tcx> {
277323 check_drop_flag_for_sanity : check_drop_flag_for_sanity,
278324 available_monomorphizations : RefCell :: new ( FnvHashSet ( ) ) ,
279325 available_drop_glues : RefCell :: new ( FnvHashMap ( ) ) ,
326+ use_dll_storage_attrs : use_dll_storage_attrs,
280327 } ;
281328
282329 for i in 0 ..local_count {
@@ -365,6 +412,10 @@ impl<'tcx> SharedCrateContext<'tcx> {
365412 pub fn stats < ' a > ( & ' a self ) -> & ' a Stats {
366413 & self . stats
367414 }
415+
416+ pub fn use_dll_storage_attrs ( & self ) -> bool {
417+ self . use_dll_storage_attrs
418+ }
368419}
369420
370421impl < ' tcx > LocalCrateContext < ' tcx > {
@@ -733,6 +784,10 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
733784 // values.
734785 self . shared . check_drop_flag_for_sanity
735786 }
787+
788+ pub fn use_dll_storage_attrs ( & self ) -> bool {
789+ self . shared . use_dll_storage_attrs ( )
790+ }
736791}
737792
738793/// Declare any llvm intrinsics that you might need
0 commit comments