@@ -20,12 +20,14 @@ use monomorphize::MonoItem;
20
20
use common:: { CodegenCx , val_ty} ;
21
21
use declare;
22
22
use monomorphize:: Instance ;
23
+ use syntax_pos:: Span ;
24
+ use syntax_pos:: symbol:: LocalInternedString ;
23
25
use type_:: Type ;
24
26
use type_of:: LayoutLlvmExt ;
25
- use rustc:: ty;
27
+ use rustc:: ty:: { self , Ty } ;
26
28
use rustc:: ty:: layout:: { Align , LayoutOf } ;
27
29
28
- use rustc:: hir:: { self , CodegenFnAttrFlags } ;
30
+ use rustc:: hir:: { self , CodegenFnAttrs , CodegenFnAttrFlags } ;
29
31
30
32
use std:: ffi:: { CStr , CString } ;
31
33
@@ -119,6 +121,8 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
119
121
let ty = instance. ty ( cx. tcx ) ;
120
122
let sym = cx. tcx . symbol_name ( instance) . as_str ( ) ;
121
123
124
+ debug ! ( "get_static: sym={} instance={:?}" , sym, instance) ;
125
+
122
126
let g = if let Some ( id) = cx. tcx . hir . as_local_node_id ( def_id) {
123
127
124
128
let llty = cx. layout_of ( ty) . llvm_type ( cx) ;
@@ -144,50 +148,15 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
144
148
hir_map:: NodeForeignItem ( & hir:: ForeignItem {
145
149
ref attrs, span, node : hir:: ForeignItemKind :: Static ( ..) , ..
146
150
} ) => {
147
- let g = if let Some ( linkage) = cx. tcx . codegen_fn_attrs ( def_id) . linkage {
148
- // If this is a static with a linkage specified, then we need to handle
149
- // it a little specially. The typesystem prevents things like &T and
150
- // extern "C" fn() from being non-null, so we can't just declare a
151
- // static and call it a day. Some linkages (like weak) will make it such
152
- // that the static actually has a null value.
153
- let llty2 = match ty. sty {
154
- ty:: TyRawPtr ( ref mt) => cx. layout_of ( mt. ty ) . llvm_type ( cx) ,
155
- _ => {
156
- cx. sess ( ) . span_fatal ( span, "must have type `*const T` or `*mut T`" ) ;
157
- }
158
- } ;
159
- unsafe {
160
- // Declare a symbol `foo` with the desired linkage.
161
- let g1 = declare:: declare_global ( cx, & sym, llty2) ;
162
- llvm:: LLVMRustSetLinkage ( g1, base:: linkage_to_llvm ( linkage) ) ;
163
-
164
- // Declare an internal global `extern_with_linkage_foo` which
165
- // is initialized with the address of `foo`. If `foo` is
166
- // discarded during linking (for example, if `foo` has weak
167
- // linkage and there are no definitions), then
168
- // `extern_with_linkage_foo` will instead be initialized to
169
- // zero.
170
- let mut real_name = "_rust_extern_with_linkage_" . to_string ( ) ;
171
- real_name. push_str ( & sym) ;
172
- let g2 = declare:: define_global ( cx, & real_name, llty) . unwrap_or_else ( ||{
173
- cx. sess ( ) . span_fatal ( span,
174
- & format ! ( "symbol `{}` is already defined" , & sym) )
175
- } ) ;
176
- llvm:: LLVMRustSetLinkage ( g2, llvm:: Linkage :: InternalLinkage ) ;
177
- llvm:: LLVMSetInitializer ( g2, g1) ;
178
- g2
179
- }
180
- } else {
181
- // Generate an external declaration.
182
- declare:: declare_global ( cx, & sym, llty)
183
- } ;
184
-
185
- ( g, attrs)
151
+ let fn_attrs = cx. tcx . codegen_fn_attrs ( def_id) ;
152
+ ( check_and_apply_linkage ( cx, & fn_attrs, ty, sym, Some ( span) ) , attrs)
186
153
}
187
154
188
155
item => bug ! ( "get_static: expected static, found {:?}" , item)
189
156
} ;
190
157
158
+ debug ! ( "get_static: sym={} attrs={:?}" , sym, attrs) ;
159
+
191
160
for attr in attrs {
192
161
if attr. check_name ( "thread_local" ) {
193
162
llvm:: set_thread_local_mode ( g, cx. tls_model ) ;
@@ -197,19 +166,21 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
197
166
g
198
167
} else {
199
168
// 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) ) ;
169
+ debug ! ( "get_static: sym={} item_attr={:?}" , sym, cx. tcx. item_attrs( def_id) ) ;
170
+
171
+ let attrs = cx. tcx . codegen_fn_attrs ( def_id) ;
172
+ let g = check_and_apply_linkage ( cx, & attrs, ty, sym, None ) ;
173
+
202
174
// Thread-local statics in some other crate need to *always* be linked
203
175
// against in a thread-local fashion, so we need to be sure to apply the
204
176
// thread-local attribute locally if it was present remotely. If we
205
177
// don't do this then linker errors can be generated where the linker
206
178
// complains that one object files has a thread local version of the
207
179
// 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
- }
180
+ if attrs. flags . contains ( CodegenFnAttrFlags :: THREAD_LOCAL ) {
181
+ llvm:: set_thread_local_mode ( g, cx. tls_model ) ;
212
182
}
183
+
213
184
if cx. use_dll_storage_attrs && !cx. tcx . is_foreign_item ( def_id) {
214
185
// This item is external but not foreign, i.e. it originates from an external Rust
215
186
// crate. Since we don't know whether this crate will be linked dynamically or
@@ -242,6 +213,66 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
242
213
g
243
214
}
244
215
216
+ fn check_and_apply_linkage < ' tcx > (
217
+ cx : & CodegenCx < ' _ , ' tcx > ,
218
+ attrs : & CodegenFnAttrs ,
219
+ ty : Ty < ' tcx > ,
220
+ sym : LocalInternedString ,
221
+ span : Option < Span >
222
+ ) -> ValueRef {
223
+ let llty = cx. layout_of ( ty) . llvm_type ( cx) ;
224
+ if let Some ( linkage) = attrs. linkage {
225
+ debug ! ( "get_static: sym={} linkage={:?}" , sym, linkage) ;
226
+
227
+ // If this is a static with a linkage specified, then we need to handle
228
+ // it a little specially. The typesystem prevents things like &T and
229
+ // extern "C" fn() from being non-null, so we can't just declare a
230
+ // static and call it a day. Some linkages (like weak) will make it such
231
+ // that the static actually has a null value.
232
+ let llty2 = match ty. sty {
233
+ ty:: TyRawPtr ( ref mt) => cx. layout_of ( mt. ty ) . llvm_type ( cx) ,
234
+ _ => {
235
+ if span. is_some ( ) {
236
+ cx. sess ( ) . span_fatal ( span. unwrap ( ) , "must have type `*const T` or `*mut T`" )
237
+ } else {
238
+ bug ! ( "must have type `*const T` or `*mut T`" )
239
+ }
240
+ }
241
+ } ;
242
+ unsafe {
243
+ // Declare a symbol `foo` with the desired linkage.
244
+ let g1 = declare:: declare_global ( cx, & sym, llty2) ;
245
+ llvm:: LLVMRustSetLinkage ( g1, base:: linkage_to_llvm ( linkage) ) ;
246
+
247
+ // Declare an internal global `extern_with_linkage_foo` which
248
+ // is initialized with the address of `foo`. If `foo` is
249
+ // discarded during linking (for example, if `foo` has weak
250
+ // linkage and there are no definitions), then
251
+ // `extern_with_linkage_foo` will instead be initialized to
252
+ // zero.
253
+ let mut real_name = "_rust_extern_with_linkage_" . to_string ( ) ;
254
+ real_name. push_str ( & sym) ;
255
+ let g2 = declare:: define_global ( cx, & real_name, llty) . unwrap_or_else ( ||{
256
+ if span. is_some ( ) {
257
+ cx. sess ( ) . span_fatal (
258
+ span. unwrap ( ) ,
259
+ & format ! ( "symbol `{}` is already defined" , & sym)
260
+ )
261
+ } else {
262
+ bug ! ( "symbol `{}` is already defined" , & sym)
263
+ }
264
+ } ) ;
265
+ llvm:: LLVMRustSetLinkage ( g2, llvm:: Linkage :: InternalLinkage ) ;
266
+ llvm:: LLVMSetInitializer ( g2, g1) ;
267
+ g2
268
+ }
269
+ } else {
270
+ // Generate an external declaration.
271
+ // FIXME(nagisa): investigate whether it can be changed into define_global
272
+ declare:: declare_global ( cx, & sym, llty)
273
+ }
274
+ }
275
+
245
276
pub fn codegen_static < ' a , ' tcx > (
246
277
cx : & CodegenCx < ' a , ' tcx > ,
247
278
def_id : DefId ,
0 commit comments