@@ -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
@@ -146,47 +148,8 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
146
148
hir_map:: NodeForeignItem ( & hir:: ForeignItem {
147
149
ref attrs, span, node : hir:: ForeignItemKind :: Static ( ..) , ..
148
150
} ) => {
149
- let g = if let Some ( linkage) = cx. tcx . codegen_fn_attrs ( def_id) . linkage {
150
- debug ! ( "get_static: sym={} linkage={:?}" , sym, linkage) ;
151
-
152
- // If this is a static with a linkage specified, then we need to handle
153
- // it a little specially. The typesystem prevents things like &T and
154
- // extern "C" fn() from being non-null, so we can't just declare a
155
- // static and call it a day. Some linkages (like weak) will make it such
156
- // that the static actually has a null value.
157
- let llty2 = match ty. sty {
158
- ty:: TyRawPtr ( ref mt) => cx. layout_of ( mt. ty ) . llvm_type ( cx) ,
159
- _ => {
160
- cx. sess ( ) . span_fatal ( span, "must have type `*const T` or `*mut T`" ) ;
161
- }
162
- } ;
163
- unsafe {
164
- // Declare a symbol `foo` with the desired linkage.
165
- let g1 = declare:: declare_global ( cx, & sym, llty2) ;
166
- llvm:: LLVMRustSetLinkage ( g1, base:: linkage_to_llvm ( linkage) ) ;
167
-
168
- // Declare an internal global `extern_with_linkage_foo` which
169
- // is initialized with the address of `foo`. If `foo` is
170
- // discarded during linking (for example, if `foo` has weak
171
- // linkage and there are no definitions), then
172
- // `extern_with_linkage_foo` will instead be initialized to
173
- // zero.
174
- let mut real_name = "_rust_extern_with_linkage_" . to_string ( ) ;
175
- real_name. push_str ( & sym) ;
176
- let g2 = declare:: define_global ( cx, & real_name, llty) . unwrap_or_else ( ||{
177
- cx. sess ( ) . span_fatal ( span,
178
- & format ! ( "symbol `{}` is already defined" , & sym) )
179
- } ) ;
180
- llvm:: LLVMRustSetLinkage ( g2, llvm:: Linkage :: InternalLinkage ) ;
181
- llvm:: LLVMSetInitializer ( g2, g1) ;
182
- g2
183
- }
184
- } else {
185
- // Generate an external declaration.
186
- declare:: declare_global ( cx, & sym, llty)
187
- } ;
188
-
189
- ( 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)
190
153
}
191
154
192
155
item => bug ! ( "get_static: expected static, found {:?}" , item)
@@ -205,55 +168,16 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
205
168
// FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
206
169
debug ! ( "get_static: sym={} item_attr={:?}" , sym, cx. tcx. item_attrs( def_id) ) ;
207
170
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
- } ;
171
+ let attrs = cx. tcx . codegen_fn_attrs ( def_id) ;
172
+ let g = check_and_apply_linkage ( cx, & attrs, ty, sym, None ) ;
249
173
250
174
// Thread-local statics in some other crate need to *always* be linked
251
175
// against in a thread-local fashion, so we need to be sure to apply the
252
176
// thread-local attribute locally if it was present remotely. If we
253
177
// don't do this then linker errors can be generated where the linker
254
178
// complains that one object files has a thread local version of the
255
179
// symbol and another one doesn't.
256
- if codegen_fn_attrs . flags . contains ( CodegenFnAttrFlags :: THREAD_LOCAL ) {
180
+ if attrs . flags . contains ( CodegenFnAttrFlags :: THREAD_LOCAL ) {
257
181
llvm:: set_thread_local_mode ( g, cx. tls_model ) ;
258
182
}
259
183
@@ -289,6 +213,66 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
289
213
g
290
214
}
291
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
+
292
276
pub fn codegen_static < ' a , ' tcx > (
293
277
cx : & CodegenCx < ' a , ' tcx > ,
294
278
def_id : DefId ,
0 commit comments