@@ -12,6 +12,8 @@ use back::lto;
1212use back:: link:: { self , get_linker, remove} ;
1313use back:: linker:: LinkerInfo ;
1414use back:: symbol_export:: ExportedSymbols ;
15+ use base;
16+ use consts;
1517use rustc_incremental:: { save_trans_partition, in_incr_comp_dir} ;
1618use rustc:: dep_graph:: DepGraph ;
1719use rustc:: middle:: cstore:: { LinkMeta , EncodedMetadata } ;
@@ -35,12 +37,13 @@ use syntax::attr;
3537use syntax:: ext:: hygiene:: Mark ;
3638use syntax_pos:: MultiSpan ;
3739use syntax_pos:: symbol:: Symbol ;
40+ use type_:: Type ;
3841use context:: { is_pie_binary, get_reloc_model} ;
3942use jobserver:: { Client , Acquired } ;
4043use rustc_demangle;
4144
4245use std:: any:: Any ;
43- use std:: ffi:: CString ;
46+ use std:: ffi:: { CString , CStr } ;
4447use std:: fs;
4548use std:: io;
4649use std:: io:: Write ;
@@ -315,6 +318,8 @@ pub struct CodegenContext {
315318 metadata_module_config : Arc < ModuleConfig > ,
316319 allocator_module_config : Arc < ModuleConfig > ,
317320 pub tm_factory : Arc < Fn ( ) -> Result < TargetMachineRef , String > + Send + Sync > ,
321+ pub msvc_imps_needed : bool ,
322+ pub target_pointer_width : String ,
318323
319324 // Number of cgus excluding the allocator/metadata modules
320325 pub total_cgus : usize ,
@@ -586,6 +591,10 @@ unsafe fn codegen(cgcx: &CodegenContext,
586591 let module_name = Some ( & module_name[ ..] ) ;
587592 let handlers = DiagnosticHandlers :: new ( cgcx, diag_handler, llcx) ;
588593
594+ if cgcx. msvc_imps_needed {
595+ create_msvc_imps ( cgcx, llcx, llmod) ;
596+ }
597+
589598 // A codegen-specific pass manager is used to generate object
590599 // files for an LLVM module.
591600 //
@@ -1300,6 +1309,8 @@ fn start_executing_work(tcx: TyCtxt,
13001309 allocator_module_config : allocator_config,
13011310 tm_factory : target_machine_factory ( tcx. sess ) ,
13021311 total_cgus,
1312+ msvc_imps_needed : msvc_imps_needed ( tcx) ,
1313+ target_pointer_width : tcx. sess . target . target . target_pointer_width . clone ( ) ,
13031314 } ;
13041315
13051316 // 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,
21332144 cost,
21342145 } ) ) ) ;
21352146}
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