@@ -2570,20 +2570,6 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<&str>) {
25702570 unsafe {
25712571 let mut declared = HashSet :: new ( ) ;
25722572
2573- let iter_globals = |llmod| {
2574- ValueIter {
2575- cur : llvm:: LLVMGetFirstGlobal ( llmod) ,
2576- step : llvm:: LLVMGetNextGlobal ,
2577- }
2578- } ;
2579-
2580- let iter_functions = |llmod| {
2581- ValueIter {
2582- cur : llvm:: LLVMGetFirstFunction ( llmod) ,
2583- step : llvm:: LLVMGetNextFunction ,
2584- }
2585- } ;
2586-
25872573 // Collect all external declarations in all compilation units.
25882574 for ccx in cx. iter ( ) {
25892575 for val in iter_globals ( ccx. llmod ( ) ) . chain ( iter_functions ( ccx. llmod ( ) ) ) {
@@ -2623,28 +2609,83 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<&str>) {
26232609 }
26242610 }
26252611 }
2612+ }
2613+
2614+ // Create a `__imp_<symbol> = &symbol` global for every public static `symbol`.
2615+ // This is required to satisfy `dllimport` references to static data in .rlibs
2616+ // when using MSVC linker. We do this only for data, as linker can fix up
2617+ // code references on its own.
2618+ // See #26591, #27438
2619+ fn create_imps ( cx : & SharedCrateContext ) {
2620+ // The x86 ABI seems to require that leading underscores are added to symbol
2621+ // names, so we need an extra underscore on 32-bit. There's also a leading
2622+ // '\x01' here which disables LLVM's symbol mangling (e.g. no extra
2623+ // underscores added in front).
2624+ let prefix = if cx. sess ( ) . target . target . target_pointer_width == "32" {
2625+ "\x01 __imp__"
2626+ } else {
2627+ "\x01 __imp_"
2628+ } ;
2629+ unsafe {
2630+ for ccx in cx. iter ( ) {
2631+ let exported: Vec < _ > = iter_globals ( ccx. llmod ( ) )
2632+ . filter ( |& val| llvm:: LLVMGetLinkage ( val) == llvm:: ExternalLinkage as c_uint &&
2633+ llvm:: LLVMIsDeclaration ( val) == 0 )
2634+ . collect ( ) ;
2635+
2636+ let i8p_ty = Type :: i8p ( & ccx) ;
2637+ for val in exported {
2638+ let name = CStr :: from_ptr ( llvm:: LLVMGetValueName ( val) ) ;
2639+ let mut imp_name = prefix. as_bytes ( ) . to_vec ( ) ;
2640+ imp_name. extend ( name. to_bytes ( ) ) ;
2641+ let imp_name = CString :: new ( imp_name) . unwrap ( ) ;
2642+ let imp = llvm:: LLVMAddGlobal ( ccx. llmod ( ) , i8p_ty. to_ref ( ) ,
2643+ imp_name. as_ptr ( ) as * const _ ) ;
2644+ let init = llvm:: LLVMConstBitCast ( val, i8p_ty. to_ref ( ) ) ;
2645+ llvm:: LLVMSetInitializer ( imp, init) ;
2646+ llvm:: SetLinkage ( imp, llvm:: ExternalLinkage ) ;
2647+ }
2648+ }
2649+ }
2650+ }
26262651
2652+ struct ValueIter {
2653+ cur : ValueRef ,
2654+ step : unsafe extern "C" fn ( ValueRef ) -> ValueRef ,
2655+ }
2656+
2657+ impl Iterator for ValueIter {
2658+ type Item = ValueRef ;
26272659
2628- struct ValueIter {
2629- cur : ValueRef ,
2630- step : unsafe extern "C" fn ( ValueRef ) -> ValueRef ,
2660+ fn next ( & mut self ) -> Option < ValueRef > {
2661+ let old = self . cur ;
2662+ if !old. is_null ( ) {
2663+ self . cur = unsafe {
2664+ let step: unsafe extern "C" fn ( ValueRef ) -> ValueRef =
2665+ mem:: transmute_copy ( & self . step ) ;
2666+ step ( old)
2667+ } ;
2668+ Some ( old)
2669+ } else {
2670+ None
2671+ }
26312672 }
2673+ }
26322674
2633- impl Iterator for ValueIter {
2634- type Item = ValueRef ;
2675+ fn iter_globals ( llmod : llvm:: ModuleRef ) -> ValueIter {
2676+ unsafe {
2677+ ValueIter {
2678+ cur : llvm:: LLVMGetFirstGlobal ( llmod) ,
2679+ step : llvm:: LLVMGetNextGlobal ,
2680+ }
2681+ }
2682+ }
26352683
2636- fn next ( & mut self ) -> Option < ValueRef > {
2637- let old = self . cur ;
2638- if !old. is_null ( ) {
2639- self . cur = unsafe {
2640- let step: unsafe extern "C" fn ( ValueRef ) -> ValueRef =
2641- mem:: transmute_copy ( & self . step ) ;
2642- step ( old)
2643- } ;
2644- Some ( old)
2645- } else {
2646- None
2647- }
2684+ fn iter_functions ( llmod : llvm:: ModuleRef ) -> ValueIter {
2685+ unsafe {
2686+ ValueIter {
2687+ cur : llvm:: LLVMGetFirstFunction ( llmod) ,
2688+ step : llvm:: LLVMGetNextFunction ,
26482689 }
26492690 }
26502691}
@@ -2824,6 +2865,11 @@ pub fn trans_crate(tcx: &ty::ctxt, analysis: ty::CrateAnalysis) -> CrateTranslat
28242865 & reachable_symbols. iter ( ) . map ( |x| & x[ ..] ) . collect ( ) ) ;
28252866 }
28262867
2868+ if sess. target . target . options . is_like_msvc &&
2869+ sess. crate_types . borrow ( ) . iter ( ) . any ( |ct| * ct == config:: CrateTypeRlib ) {
2870+ create_imps ( & shared_ccx) ;
2871+ }
2872+
28272873 let metadata_module = ModuleTranslation {
28282874 llcx : shared_ccx. metadata_llcx ( ) ,
28292875 llmod : shared_ccx. metadata_llmod ( ) ,
0 commit comments