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