@@ -20,12 +20,14 @@ use monomorphize::MonoItem;
2020use common:: { CodegenCx , val_ty} ;
2121use declare;
2222use monomorphize:: Instance ;
23+ use syntax_pos:: Span ;
24+ use syntax_pos:: symbol:: LocalInternedString ;
2325use type_:: Type ;
2426use type_of:: LayoutLlvmExt ;
25- use rustc:: ty;
27+ use rustc:: ty:: { self , Ty } ;
2628use rustc:: ty:: layout:: { Align , LayoutOf } ;
2729
28- use rustc:: hir:: { self , CodegenFnAttrFlags } ;
30+ use rustc:: hir:: { self , CodegenFnAttrs , CodegenFnAttrFlags } ;
2931
3032use std:: ffi:: { CStr , CString } ;
3133
@@ -146,47 +148,8 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
146148 hir_map:: NodeForeignItem ( & hir:: ForeignItem {
147149 ref attrs, span, node : hir:: ForeignItemKind :: Static ( ..) , ..
148150 } ) => {
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)
190153 }
191154
192155 item => bug ! ( "get_static: expected static, found {:?}" , item)
@@ -205,55 +168,16 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
205168 // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
206169 debug ! ( "get_static: sym={} item_attr={:?}" , sym, cx. tcx. item_attrs( def_id) ) ;
207170
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 ) ;
249173
250174 // Thread-local statics in some other crate need to *always* be linked
251175 // against in a thread-local fashion, so we need to be sure to apply the
252176 // thread-local attribute locally if it was present remotely. If we
253177 // don't do this then linker errors can be generated where the linker
254178 // complains that one object files has a thread local version of the
255179 // symbol and another one doesn't.
256- if codegen_fn_attrs . flags . contains ( CodegenFnAttrFlags :: THREAD_LOCAL ) {
180+ if attrs . flags . contains ( CodegenFnAttrFlags :: THREAD_LOCAL ) {
257181 llvm:: set_thread_local_mode ( g, cx. tls_model ) ;
258182 }
259183
@@ -289,6 +213,66 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
289213 g
290214}
291215
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+
292276pub fn codegen_static < ' a , ' tcx > (
293277 cx : & CodegenCx < ' a , ' tcx > ,
294278 def_id : DefId ,
0 commit comments