@@ -119,6 +119,8 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
119119 let ty = instance. ty ( cx. tcx ) ;
120120 let sym = cx. tcx . symbol_name ( instance) . as_str ( ) ;
121121
122+ debug ! ( "get_static: sym={} instance={:?}" , sym, instance) ;
123+
122124 let g = if let Some ( id) = cx. tcx . hir . as_local_node_id ( def_id) {
123125
124126 let llty = cx. layout_of ( ty) . llvm_type ( cx) ;
@@ -145,6 +147,8 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
145147 ref attrs, span, node : hir:: ForeignItemKind :: Static ( ..) , ..
146148 } ) => {
147149 let g = if let Some ( linkage) = cx. tcx . codegen_fn_attrs ( def_id) . linkage {
150+ debug ! ( "get_static: sym={} linkage={:?}" , sym, linkage) ;
151+
148152 // If this is a static with a linkage specified, then we need to handle
149153 // it a little specially. The typesystem prevents things like &T and
150154 // extern "C" fn() from being non-null, so we can't just declare a
@@ -188,6 +192,8 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
188192 item => bug ! ( "get_static: expected static, found {:?}" , item)
189193 } ;
190194
195+ debug ! ( "get_static: sym={} attrs={:?}" , sym, attrs) ;
196+
191197 for attr in attrs {
192198 if attr. check_name ( "thread_local" ) {
193199 llvm:: set_thread_local_mode ( g, cx. tls_model ) ;
@@ -197,19 +203,60 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
197203 g
198204 } else {
199205 // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
200- // FIXME(nagisa): investigate whether it can be changed into define_global
201- let g = declare:: declare_global ( cx, & sym, cx. layout_of ( ty) . llvm_type ( cx) ) ;
206+ debug ! ( "get_static: sym={} item_attr={:?}" , sym, cx. tcx. item_attrs( def_id) ) ;
207+
208+ let codegen_fn_attrs = cx. tcx . codegen_fn_attrs ( def_id) ;
209+ let llty = cx. layout_of ( ty) . llvm_type ( cx) ;
210+ let g = if let Some ( linkage) = codegen_fn_attrs. linkage {
211+ debug ! ( "get_static: sym={} linkage={:?}" , sym, linkage) ;
212+
213+ // If this is a static with a linkage specified, then we need to handle
214+ // it a little specially. The typesystem prevents things like &T and
215+ // extern "C" fn() from being non-null, so we can't just declare a
216+ // static and call it a day. Some linkages (like weak) will make it such
217+ // that the static actually has a null value.
218+ let llty2 = match ty. sty {
219+ ty:: TyRawPtr ( ref mt) => cx. layout_of ( mt. ty ) . llvm_type ( cx) ,
220+ _ => {
221+ bug ! ( "must have type `*const T` or `*mut T`" )
222+ }
223+ } ;
224+ unsafe {
225+ // Declare a symbol `foo` with the desired linkage.
226+ let g1 = declare:: declare_global ( cx, & sym, llty2) ;
227+ llvm:: LLVMRustSetLinkage ( g1, base:: linkage_to_llvm ( linkage) ) ;
228+
229+ // Declare an internal global `extern_with_linkage_foo` which
230+ // is initialized with the address of `foo`. If `foo` is
231+ // discarded during linking (for example, if `foo` has weak
232+ // linkage and there are no definitions), then
233+ // `extern_with_linkage_foo` will instead be initialized to
234+ // zero.
235+ let mut real_name = "_rust_extern_with_linkage_" . to_string ( ) ;
236+ real_name. push_str ( & sym) ;
237+ let g2 = declare:: define_global ( cx, & real_name, llty) . unwrap_or_else ( ||{
238+ bug ! ( "symbol `{}` is already defined" , & sym)
239+ } ) ;
240+ llvm:: LLVMRustSetLinkage ( g2, llvm:: Linkage :: InternalLinkage ) ;
241+ llvm:: LLVMSetInitializer ( g2, g1) ;
242+ g2
243+ }
244+ } else {
245+ // Generate an external declaration.
246+ // FIXME(nagisa): investigate whether it can be changed into define_global
247+ declare:: declare_global ( cx, & sym, llty)
248+ } ;
249+
202250 // Thread-local statics in some other crate need to *always* be linked
203251 // against in a thread-local fashion, so we need to be sure to apply the
204252 // thread-local attribute locally if it was present remotely. If we
205253 // don't do this then linker errors can be generated where the linker
206254 // complains that one object files has a thread local version of the
207255 // symbol and another one doesn't.
208- for attr in cx. tcx . get_attrs ( def_id) . iter ( ) {
209- if attr. check_name ( "thread_local" ) {
210- llvm:: set_thread_local_mode ( g, cx. tls_model ) ;
211- }
256+ if codegen_fn_attrs. flags . contains ( CodegenFnAttrFlags :: THREAD_LOCAL ) {
257+ llvm:: set_thread_local_mode ( g, cx. tls_model ) ;
212258 }
259+
213260 if cx. use_dll_storage_attrs && !cx. tcx . is_foreign_item ( def_id) {
214261 // This item is external but not foreign, i.e. it originates from an external Rust
215262 // crate. Since we don't know whether this crate will be linked dynamically or
0 commit comments