@@ -12,6 +12,8 @@ use back::lto;
12
12
use back:: link:: { self , get_linker, remove} ;
13
13
use back:: linker:: LinkerInfo ;
14
14
use back:: symbol_export:: ExportedSymbols ;
15
+ use base;
16
+ use consts;
15
17
use rustc_incremental:: { save_trans_partition, in_incr_comp_dir} ;
16
18
use rustc:: dep_graph:: DepGraph ;
17
19
use rustc:: middle:: cstore:: { LinkMeta , EncodedMetadata } ;
@@ -35,12 +37,13 @@ use syntax::attr;
35
37
use syntax:: ext:: hygiene:: Mark ;
36
38
use syntax_pos:: MultiSpan ;
37
39
use syntax_pos:: symbol:: Symbol ;
40
+ use type_:: Type ;
38
41
use context:: { is_pie_binary, get_reloc_model} ;
39
42
use jobserver:: { Client , Acquired } ;
40
43
use rustc_demangle;
41
44
42
45
use std:: any:: Any ;
43
- use std:: ffi:: CString ;
46
+ use std:: ffi:: { CString , CStr } ;
44
47
use std:: fs;
45
48
use std:: io;
46
49
use std:: io:: Write ;
@@ -315,6 +318,8 @@ pub struct CodegenContext {
315
318
metadata_module_config : Arc < ModuleConfig > ,
316
319
allocator_module_config : Arc < ModuleConfig > ,
317
320
pub tm_factory : Arc < Fn ( ) -> Result < TargetMachineRef , String > + Send + Sync > ,
321
+ pub msvc_imps_needed : bool ,
322
+ pub target_pointer_width : String ,
318
323
319
324
// Number of cgus excluding the allocator/metadata modules
320
325
pub total_cgus : usize ,
@@ -586,6 +591,10 @@ unsafe fn codegen(cgcx: &CodegenContext,
586
591
let module_name = Some ( & module_name[ ..] ) ;
587
592
let handlers = DiagnosticHandlers :: new ( cgcx, diag_handler, llcx) ;
588
593
594
+ if cgcx. msvc_imps_needed {
595
+ create_msvc_imps ( cgcx, llcx, llmod) ;
596
+ }
597
+
589
598
// A codegen-specific pass manager is used to generate object
590
599
// files for an LLVM module.
591
600
//
@@ -1300,6 +1309,8 @@ fn start_executing_work(tcx: TyCtxt,
1300
1309
allocator_module_config : allocator_config,
1301
1310
tm_factory : target_machine_factory ( tcx. sess ) ,
1302
1311
total_cgus,
1312
+ msvc_imps_needed : msvc_imps_needed ( tcx) ,
1313
+ target_pointer_width : tcx. sess . target . target . target_pointer_width . clone ( ) ,
1303
1314
} ;
1304
1315
1305
1316
// This is the "main loop" of parallel work happening for parallel codegen.
@@ -2133,3 +2144,51 @@ pub fn submit_translated_module_to_llvm(tcx: TyCtxt,
2133
2144
cost,
2134
2145
} ) ) ) ;
2135
2146
}
2147
+
2148
+ fn msvc_imps_needed ( tcx : TyCtxt ) -> bool {
2149
+ tcx. sess . target . target . options . is_like_msvc &&
2150
+ tcx. sess . crate_types . borrow ( ) . iter ( ) . any ( |ct| * ct == config:: CrateTypeRlib )
2151
+ }
2152
+
2153
+ // Create a `__imp_<symbol> = &symbol` global for every public static `symbol`.
2154
+ // This is required to satisfy `dllimport` references to static data in .rlibs
2155
+ // when using MSVC linker. We do this only for data, as linker can fix up
2156
+ // code references on its own.
2157
+ // See #26591, #27438
2158
+ fn create_msvc_imps ( cgcx : & CodegenContext , llcx : ContextRef , llmod : ModuleRef ) {
2159
+ if !cgcx. msvc_imps_needed {
2160
+ return
2161
+ }
2162
+ // The x86 ABI seems to require that leading underscores are added to symbol
2163
+ // names, so we need an extra underscore on 32-bit. There's also a leading
2164
+ // '\x01' here which disables LLVM's symbol mangling (e.g. no extra
2165
+ // underscores added in front).
2166
+ let prefix = if cgcx. target_pointer_width == "32" {
2167
+ "\x01 __imp__"
2168
+ } else {
2169
+ "\x01 __imp_"
2170
+ } ;
2171
+ unsafe {
2172
+ let i8p_ty = Type :: i8p_llcx ( llcx) ;
2173
+ let globals = base:: iter_globals ( llmod)
2174
+ . filter ( |& val| {
2175
+ llvm:: LLVMRustGetLinkage ( val) == llvm:: Linkage :: ExternalLinkage &&
2176
+ llvm:: LLVMIsDeclaration ( val) == 0
2177
+ } )
2178
+ . map ( move |val| {
2179
+ let name = CStr :: from_ptr ( llvm:: LLVMGetValueName ( val) ) ;
2180
+ let mut imp_name = prefix. as_bytes ( ) . to_vec ( ) ;
2181
+ imp_name. extend ( name. to_bytes ( ) ) ;
2182
+ let imp_name = CString :: new ( imp_name) . unwrap ( ) ;
2183
+ ( imp_name, val)
2184
+ } )
2185
+ . collect :: < Vec < _ > > ( ) ;
2186
+ for ( imp_name, val) in globals {
2187
+ let imp = llvm:: LLVMAddGlobal ( llmod,
2188
+ i8p_ty. to_ref ( ) ,
2189
+ imp_name. as_ptr ( ) as * const _ ) ;
2190
+ llvm:: LLVMSetInitializer ( imp, consts:: ptrcast ( val, i8p_ty) ) ;
2191
+ llvm:: LLVMRustSetLinkage ( imp, llvm:: Linkage :: ExternalLinkage ) ;
2192
+ }
2193
+ }
2194
+ }
0 commit comments