@@ -75,6 +75,7 @@ pub struct SharedCrateContext<'tcx> {
75
75
76
76
available_monomorphizations : RefCell < FnvHashSet < String > > ,
77
77
available_drop_glues : RefCell < FnvHashMap < DropGlueKind < ' tcx > , String > > ,
78
+ use_dll_storage_attrs : bool ,
78
79
}
79
80
80
81
/// The local portion of a `CrateContext`. There is one `LocalCrateContext`
@@ -251,6 +252,51 @@ impl<'tcx> SharedCrateContext<'tcx> {
251
252
create_context_and_module ( & tcx. sess , "metadata" )
252
253
} ;
253
254
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
+
254
300
let mut shared_ccx = SharedCrateContext {
255
301
local_ccxs : Vec :: with_capacity ( local_count) ,
256
302
metadata_llmod : metadata_llmod,
@@ -277,6 +323,7 @@ impl<'tcx> SharedCrateContext<'tcx> {
277
323
check_drop_flag_for_sanity : check_drop_flag_for_sanity,
278
324
available_monomorphizations : RefCell :: new ( FnvHashSet ( ) ) ,
279
325
available_drop_glues : RefCell :: new ( FnvHashMap ( ) ) ,
326
+ use_dll_storage_attrs : use_dll_storage_attrs,
280
327
} ;
281
328
282
329
for i in 0 ..local_count {
@@ -365,6 +412,10 @@ impl<'tcx> SharedCrateContext<'tcx> {
365
412
pub fn stats < ' a > ( & ' a self ) -> & ' a Stats {
366
413
& self . stats
367
414
}
415
+
416
+ pub fn use_dll_storage_attrs ( & self ) -> bool {
417
+ self . use_dll_storage_attrs
418
+ }
368
419
}
369
420
370
421
impl < ' tcx > LocalCrateContext < ' tcx > {
@@ -733,6 +784,10 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
733
784
// values.
734
785
self . shared . check_drop_flag_for_sanity
735
786
}
787
+
788
+ pub fn use_dll_storage_attrs ( & self ) -> bool {
789
+ self . shared . use_dll_storage_attrs ( )
790
+ }
736
791
}
737
792
738
793
/// Declare any llvm intrinsics that you might need
0 commit comments