@@ -37,8 +37,9 @@ use middle::subst::Substs;
37
37
use middle:: ty:: { self , Ty } ;
38
38
use util:: nodemap:: NodeMap ;
39
39
40
+ use std:: ffi:: { CStr , CString } ;
40
41
use libc:: c_uint;
41
- use syntax:: { ast, ast_util} ;
42
+ use syntax:: { ast, ast_util, attr } ;
42
43
use syntax:: parse:: token;
43
44
use syntax:: ptr:: P ;
44
45
@@ -898,37 +899,70 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
898
899
"bad constant expression type in consts::const_expr" ) ,
899
900
}
900
901
}
901
-
902
- pub fn trans_static ( ccx : & CrateContext , m : ast:: Mutability , id : ast:: NodeId ) -> ValueRef {
902
+ pub fn trans_static ( ccx : & CrateContext ,
903
+ m : ast:: Mutability ,
904
+ expr : & ast:: Expr ,
905
+ id : ast:: NodeId ,
906
+ attrs : & Vec < ast:: Attribute > )
907
+ -> ValueRef {
903
908
unsafe {
904
909
let _icx = push_ctxt ( "trans_static" ) ;
905
910
let g = base:: get_item_val ( ccx, id) ;
906
- // At this point, get_item_val has already translated the
907
- // constant's initializer to determine its LLVM type.
908
- let v = ccx. static_values ( ) . borrow ( ) . get ( & id) . unwrap ( ) . clone ( ) ;
911
+
912
+ let empty_substs = ccx. tcx ( ) . mk_substs ( Substs :: trans_empty ( ) ) ;
913
+ let ( v, _) = const_expr ( ccx, expr, empty_substs, None ) ;
914
+
909
915
// boolean SSA values are i1, but they have to be stored in i8 slots,
910
916
// otherwise some LLVM optimization passes don't work as expected
911
- let v = if llvm:: LLVMTypeOf ( v) == Type :: i1 ( ccx) . to_ref ( ) {
912
- llvm:: LLVMConstZExt ( v, Type :: i8 ( ccx) . to_ref ( ) )
917
+ let mut val_llty = llvm:: LLVMTypeOf ( v) ;
918
+ let v = if val_llty == Type :: i1 ( ccx) . to_ref ( ) {
919
+ val_llty = Type :: i8 ( ccx) . to_ref ( ) ;
920
+ llvm:: LLVMConstZExt ( v, val_llty)
913
921
} else {
914
922
v
915
923
} ;
924
+
925
+ let ty = ccx. tcx ( ) . node_id_to_type ( id) ;
926
+ let llty = type_of:: type_of ( ccx, ty) ;
927
+ let g = if val_llty == llty. to_ref ( ) {
928
+ g
929
+ } else {
930
+ // If we created the global with the wrong type,
931
+ // correct the type.
932
+ let empty_string = CString :: new ( "" ) . unwrap ( ) ;
933
+ let name_str_ref = CStr :: from_ptr ( llvm:: LLVMGetValueName ( g) ) ;
934
+ let name_string = CString :: new ( name_str_ref. to_bytes ( ) ) . unwrap ( ) ;
935
+ llvm:: LLVMSetValueName ( g, empty_string. as_ptr ( ) ) ;
936
+ let new_g = llvm:: LLVMGetOrInsertGlobal (
937
+ ccx. llmod ( ) , name_string. as_ptr ( ) , val_llty) ;
938
+ // To avoid breaking any invariants, we leave around the old
939
+ // global for the moment; we'll replace all references to it
940
+ // with the new global later. (See base::trans_crate.)
941
+ ccx. statics_to_rauw ( ) . borrow_mut ( ) . push ( ( g, new_g) ) ;
942
+ new_g
943
+ } ;
916
944
llvm:: LLVMSetInitializer ( g, v) ;
917
945
918
946
// As an optimization, all shared statics which do not have interior
919
947
// mutability are placed into read-only memory.
920
948
if m != ast:: MutMutable {
921
- let node_ty = ccx. tcx ( ) . node_id_to_type ( id) ;
922
- let tcontents = node_ty. type_contents ( ccx. tcx ( ) ) ;
949
+ let tcontents = ty. type_contents ( ccx. tcx ( ) ) ;
923
950
if !tcontents. interior_unsafe ( ) {
924
- llvm:: LLVMSetGlobalConstant ( g, True ) ;
951
+ llvm:: LLVMSetGlobalConstant ( g, llvm :: True ) ;
925
952
}
926
953
}
954
+
927
955
debuginfo:: create_global_var_metadata ( ccx, id, g) ;
956
+
957
+ if attr:: contains_name ( attrs,
958
+ "thread_local" ) {
959
+ llvm:: set_thread_local ( g, true ) ;
960
+ }
928
961
g
929
962
}
930
963
}
931
964
965
+
932
966
fn get_static_val < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > , did : ast:: DefId ,
933
967
ty : Ty < ' tcx > ) -> ValueRef {
934
968
if ast_util:: is_local ( did) { return base:: get_item_val ( ccx, did. node ) }
0 commit comments