@@ -31,47 +31,45 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
3131
3232 let fn_abi = cx. fn_abi_of_instance ( instance, ty:: List :: empty ( ) ) ;
3333
34- let llfn = if let Some ( llfn) = cx. get_declared_value ( sym) {
34+ let instance_def_id = instance. def_id ( ) ;
35+ let existing_decl = cx. get_declared_value ( sym) ;
36+
37+ let llfn = if tcx. sess . target . arch == "x86"
38+ && let Some ( dllimport) = get_dllimport ( tcx, instance_def_id, sym) {
39+ // When calling functions in generated import libraries, MSVC needs
40+ // the fully decorated name (as would have been in the declaring
41+ // object file), but MinGW wants the name as exported (as would be
42+ // in the def file) which may be missing decorations.
43+ let mingw_gnu_toolchain = common:: is_mingw_gnu_toolchain ( & tcx. sess . target ) ;
44+ let llfn = cx. declare_fn (
45+ & common:: i686_decorated_name (
46+ dllimport,
47+ mingw_gnu_toolchain,
48+ true ,
49+ !mingw_gnu_toolchain,
50+ ) ,
51+ fn_abi,
52+ Some ( instance) ,
53+ ) ;
54+
55+ // Fix for https://github.com/rust-lang/rust/issues/104453
56+ // On x86 Windows, LLVM uses 'L' as the prefix for any private
57+ // global symbols, so when we create an undecorated function symbol
58+ // that begins with an 'L' LLVM misinterprets that as a private
59+ // global symbol that it created and so fails the compilation at a
60+ // later stage since such a symbol must have a definition.
61+ //
62+ // To avoid this, we set the Storage Class to "DllImport" so that
63+ // LLVM will prefix the name with `__imp_`. Ideally, we'd like the
64+ // existing logic below to set the Storage Class, but it has an
65+ // exemption for MinGW for backwards compatibility.
66+ llvm:: set_dllimport_storage_class ( llfn) ;
3567 llfn
3668 } else {
37- let instance_def_id = instance. def_id ( ) ;
38- let llfn = if tcx. sess . target . arch == "x86"
39- && let Some ( dllimport) = crate :: common:: get_dllimport ( tcx, instance_def_id, sym)
40- {
41- // When calling functions in generated import libraries, MSVC needs
42- // the fully decorated name (as would have been in the declaring
43- // object file), but MinGW wants the name as exported (as would be
44- // in the def file) which may be missing decorations.
45- let mingw_gnu_toolchain = common:: is_mingw_gnu_toolchain ( & tcx. sess . target ) ;
46- let llfn = cx. declare_fn (
47- & common:: i686_decorated_name (
48- dllimport,
49- mingw_gnu_toolchain,
50- true ,
51- !mingw_gnu_toolchain,
52- ) ,
53- fn_abi,
54- Some ( instance) ,
55- ) ;
56-
57- // Fix for https://github.com/rust-lang/rust/issues/104453
58- // On x86 Windows, LLVM uses 'L' as the prefix for any private
59- // global symbols, so when we create an undecorated function symbol
60- // that begins with an 'L' LLVM misinterprets that as a private
61- // global symbol that it created and so fails the compilation at a
62- // later stage since such a symbol must have a definition.
63- //
64- // To avoid this, we set the Storage Class to "DllImport" so that
65- // LLVM will prefix the name with `__imp_`. Ideally, we'd like the
66- // existing logic below to set the Storage Class, but it has an
67- // exemption for MinGW for backwards compatibility.
68- llvm:: set_dllimport_storage_class ( llfn) ;
69- llfn
70- } else {
71- cx. declare_fn ( sym, fn_abi, Some ( instance) )
72- } ;
73- debug ! ( "get_fn: not casting pointer!" ) ;
69+ existing_decl. unwrap_or_else ( || cx. declare_fn ( sym, fn_abi, Some ( instance) ) )
70+ } ;
7471
72+ if existing_decl. map_or ( true , |existing| existing != llfn) {
7573 // Apply an appropriate linkage/visibility value to our item that we
7674 // just declared.
7775 //
@@ -152,7 +150,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
152150 cx. assume_dso_local ( llfn, true ) ;
153151
154152 llfn
155- } ;
153+ }
156154
157155 cx. instances . borrow_mut ( ) . insert ( instance, llfn) ;
158156
0 commit comments