@@ -31,130 +31,128 @@ 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-
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- {
38- llfn
39- } else {
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!" ) ;
77-
78- // Apply an appropriate linkage/visibility value to our item that we
79- // just declared.
80- //
81- // This is sort of subtle. Inside our codegen unit we started off
82- // compilation by predefining all our own `MonoItem` instances. That
83- // is, everything we're codegenning ourselves is already defined. That
84- // means that anything we're actually codegenning in this codegen unit
85- // will have hit the above branch in `get_declared_value`. As a result,
86- // we're guaranteed here that we're declaring a symbol that won't get
87- // defined, or in other words we're referencing a value from another
88- // codegen unit or even another crate.
89- //
90- // So because this is a foreign value we blanket apply an external
91- // linkage directive because it's coming from a different object file.
92- // The visibility here is where it gets tricky. This symbol could be
93- // referencing some foreign crate or foreign library (an `extern`
94- // block) in which case we want to leave the default visibility. We may
95- // also, though, have multiple codegen units. It could be a
96- // monomorphization, in which case its expected visibility depends on
97- // whether we are sharing generics or not. The important thing here is
98- // that the visibility we apply to the declaration is the same one that
99- // has been applied to the definition (wherever that definition may be).
100-
101- llvm:: set_linkage ( llfn, llvm:: Linkage :: ExternalLinkage ) ;
102- let is_generic = instance. args . non_erasable_generics ( ) . next ( ) . is_some ( ) ;
103-
104- let is_hidden = if is_generic {
105- // This is a monomorphization of a generic function.
106- if !( cx. tcx . sess . opts . share_generics ( )
107- || tcx. codegen_instance_attrs ( instance. def ) . inline
108- == rustc_hir:: attrs:: InlineAttr :: Never )
34+ let llfn = match cx. get_declared_value ( sym) {
35+ Some ( llfn) if !cx. tcx . is_codegened_item ( instance. def_id ( ) ) || !instance. def_id ( ) . is_local ( ) => llfn,
36+ _ => {
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)
10940 {
110- // When not sharing generics, all instances are in the same
111- // crate and have hidden visibility.
112- true
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
11370 } else {
114- if let Some ( instance_def_id) = instance_def_id. as_local ( ) {
115- // This is a monomorphization of a generic function
116- // defined in the current crate. It is hidden if:
117- // - the definition is unreachable for downstream
118- // crates, or
119- // - the current crate does not re-export generics
120- // (because the crate is a C library or executable)
121- cx. tcx . is_unreachable_local_definition ( instance_def_id)
122- || !cx. tcx . local_crate_exports_generics ( )
71+ cx. declare_fn ( sym, fn_abi, Some ( instance) )
72+ } ;
73+ debug ! ( "get_fn: not casting pointer!" ) ;
74+
75+ // Apply an appropriate linkage/visibility value to our item that we
76+ // just declared.
77+ //
78+ // This is sort of subtle. Inside our codegen unit we started off
79+ // compilation by predefining all our own `MonoItem` instances. That
80+ // is, everything we're codegenning ourselves is already defined. That
81+ // means that anything we're actually codegenning in this codegen unit
82+ // will have hit the above branch in `get_declared_value`. As a result,
83+ // we're guaranteed here that we're declaring a symbol that won't get
84+ // defined, or in other words we're referencing a value from another
85+ // codegen unit or even another crate.
86+ //
87+ // So because this is a foreign value we blanket apply an external
88+ // linkage directive because it's coming from a different object file.
89+ // The visibility here is where it gets tricky. This symbol could be
90+ // referencing some foreign crate or foreign library (an `extern`
91+ // block) in which case we want to leave the default visibility. We may
92+ // also, though, have multiple codegen units. It could be a
93+ // monomorphization, in which case its expected visibility depends on
94+ // whether we are sharing generics or not. The important thing here is
95+ // that the visibility we apply to the declaration is the same one that
96+ // has been applied to the definition (wherever that definition may be).
97+
98+ llvm:: set_linkage ( llfn, llvm:: Linkage :: ExternalLinkage ) ;
99+ let is_generic = instance. args . non_erasable_generics ( ) . next ( ) . is_some ( ) ;
100+
101+ let is_hidden = if is_generic {
102+ // This is a monomorphization of a generic function.
103+ if !( cx. tcx . sess . opts . share_generics ( )
104+ || tcx. codegen_instance_attrs ( instance. def ) . inline
105+ == rustc_hir:: attrs:: InlineAttr :: Never )
106+ {
107+ // When not sharing generics, all instances are in the same
108+ // crate and have hidden visibility.
109+ true
123110 } else {
124- // This is a monomorphization of a generic function
125- // defined in an upstream crate. It is hidden if:
126- // - it is instantiated in this crate, and
127- // - the current crate does not re-export generics
128- instance. upstream_monomorphization ( tcx) . is_none ( )
129- && !cx. tcx . local_crate_exports_generics ( )
111+ if let Some ( instance_def_id) = instance_def_id. as_local ( ) {
112+ // This is a monomorphization of a generic function
113+ // defined in the current crate. It is hidden if:
114+ // - the definition is unreachable for downstream
115+ // crates, or
116+ // - the current crate does not re-export generics
117+ // (because the crate is a C library or executable)
118+ cx. tcx . is_unreachable_local_definition ( instance_def_id)
119+ || !cx. tcx . local_crate_exports_generics ( )
120+ } else {
121+ // This is a monomorphization of a generic function
122+ // defined in an upstream crate. It is hidden if:
123+ // - it is instantiated in this crate, and
124+ // - the current crate does not re-export generics
125+ instance. upstream_monomorphization ( tcx) . is_none ( )
126+ && !cx. tcx . local_crate_exports_generics ( )
127+ }
130128 }
129+ } else {
130+ // This is a non-generic function. It is hidden if:
131+ // - it is instantiated in the local crate, and
132+ // - it is defined an upstream crate (non-local), or
133+ // - it is not reachable
134+ cx. tcx . is_codegened_item ( instance_def_id)
135+ && ( !instance_def_id. is_local ( )
136+ || !cx. tcx . is_reachable_non_generic ( instance_def_id) )
137+ } ;
138+ if is_hidden {
139+ llvm:: set_visibility ( llfn, llvm:: Visibility :: Hidden ) ;
131140 }
132- } else {
133- // This is a non-generic function. It is hidden if:
134- // - it is instantiated in the local crate, and
135- // - it is defined an upstream crate (non-local), or
136- // - it is not reachable
137- cx. tcx . is_codegened_item ( instance_def_id)
138- && ( !instance_def_id. is_local ( )
139- || !cx. tcx . is_reachable_non_generic ( instance_def_id) )
140- } ;
141- if is_hidden {
142- llvm:: set_visibility ( llfn, llvm:: Visibility :: Hidden ) ;
143- }
144141
145- // MinGW: For backward compatibility we rely on the linker to decide whether it
146- // should use dllimport for functions.
147- if cx. use_dll_storage_attrs
148- && let Some ( library) = tcx. native_library ( instance_def_id)
149- && library. kind . is_dllimport ( )
150- && !matches ! ( tcx. sess. target. env. as_ref( ) , "gnu" | "uclibc" )
151- {
152- llvm:: set_dllimport_storage_class ( llfn) ;
153- }
142+ // MinGW: For backward compatibility we rely on the linker to decide whether it
143+ // should use dllimport for functions.
144+ if cx. use_dll_storage_attrs
145+ && let Some ( library) = tcx. native_library ( instance_def_id)
146+ && library. kind . is_dllimport ( )
147+ && !matches ! ( tcx. sess. target. env. as_ref( ) , "gnu" | "uclibc" )
148+ {
149+ llvm:: set_dllimport_storage_class ( llfn) ;
150+ }
154151
155- cx. assume_dso_local ( llfn, true ) ;
152+ cx. assume_dso_local ( llfn, true ) ;
156153
157- llfn
154+ llfn
155+ }
158156 } ;
159157
160158 cx. instances . borrow_mut ( ) . insert ( instance, llfn) ;
0 commit comments