@@ -119,6 +119,8 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
119
119
let ty = instance. ty ( cx. tcx ) ;
120
120
let sym = cx. tcx . symbol_name ( instance) . as_str ( ) ;
121
121
122
+ debug ! ( "get_static: sym={} instance={:?}" , sym, instance) ;
123
+
122
124
let g = if let Some ( id) = cx. tcx . hir . as_local_node_id ( def_id) {
123
125
124
126
let llty = cx. layout_of ( ty) . llvm_type ( cx) ;
@@ -145,6 +147,8 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
145
147
ref attrs, span, node : hir:: ForeignItemKind :: Static ( ..) , ..
146
148
} ) => {
147
149
let g = if let Some ( linkage) = cx. tcx . codegen_fn_attrs ( def_id) . linkage {
150
+ debug ! ( "get_static: sym={} linkage={:?}" , sym, linkage) ;
151
+
148
152
// If this is a static with a linkage specified, then we need to handle
149
153
// it a little specially. The typesystem prevents things like &T and
150
154
// 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 {
188
192
item => bug ! ( "get_static: expected static, found {:?}" , item)
189
193
} ;
190
194
195
+ debug ! ( "get_static: sym={} attrs={:?}" , sym, attrs) ;
196
+
191
197
for attr in attrs {
192
198
if attr. check_name ( "thread_local" ) {
193
199
llvm:: set_thread_local_mode ( g, cx. tls_model ) ;
@@ -197,19 +203,60 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
197
203
g
198
204
} else {
199
205
// 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
+
202
250
// Thread-local statics in some other crate need to *always* be linked
203
251
// against in a thread-local fashion, so we need to be sure to apply the
204
252
// thread-local attribute locally if it was present remotely. If we
205
253
// don't do this then linker errors can be generated where the linker
206
254
// complains that one object files has a thread local version of the
207
255
// 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 ) ;
212
258
}
259
+
213
260
if cx. use_dll_storage_attrs && !cx. tcx . is_foreign_item ( def_id) {
214
261
// This item is external but not foreign, i.e. it originates from an external Rust
215
262
// crate. Since we don't know whether this crate will be linked dynamically or
0 commit comments