@@ -2,7 +2,7 @@ use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
2
2
use llvm:: { self , False , BasicBlock } ;
3
3
use rustc_codegen_ssa:: common:: { IntPredicate , TypeKind , RealPredicate } ;
4
4
use rustc_codegen_ssa:: { self , MemFlags } ;
5
- use common:: Funclet ;
5
+ use common:: { Funclet , val_addr_space , val_addr_space_opt } ;
6
6
use context:: CodegenCx ;
7
7
use type_:: Type ;
8
8
use type_of:: LayoutLlvmExt ;
@@ -18,6 +18,7 @@ use syntax;
18
18
use rustc_codegen_ssa:: base:: to_immediate;
19
19
use rustc_codegen_ssa:: mir:: operand:: { OperandValue , OperandRef } ;
20
20
use rustc_codegen_ssa:: mir:: place:: PlaceRef ;
21
+ use rustc_target:: spec:: AddrSpaceIdx ;
21
22
use std:: borrow:: Cow ;
22
23
use std:: ffi:: CStr ;
23
24
use std:: ops:: { Deref , Range } ;
@@ -846,26 +847,59 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
846
847
847
848
fn ptrtoint ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
848
849
self . count_insn ( "ptrtoint" ) ;
850
+ let val = self . flat_addr_cast ( val) ;
849
851
unsafe {
850
852
llvm:: LLVMBuildPtrToInt ( self . llbuilder , val, dest_ty, noname ( ) )
851
853
}
852
854
}
853
855
854
856
fn inttoptr ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
855
857
self . count_insn ( "inttoptr" ) ;
858
+ let dest_ty = dest_ty. copy_addr_space ( self . cx ( ) . flat_addr_space ( ) ) ;
856
859
unsafe {
857
860
llvm:: LLVMBuildIntToPtr ( self . llbuilder , val, dest_ty, noname ( ) )
858
861
}
859
862
}
860
863
861
864
fn bitcast ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
862
865
self . count_insn ( "bitcast" ) ;
866
+ let dest_ty = dest_ty. copy_addr_space ( val_addr_space ( val) ) ;
863
867
unsafe {
864
868
llvm:: LLVMBuildBitCast ( self . llbuilder , val, dest_ty, noname ( ) )
865
869
}
866
870
}
867
871
872
+ /// address space casts, then bitcasts to dest_ty without changing address spaces.
873
+ fn as_ptr_cast ( & mut self , val : & ' ll Value ,
874
+ addr_space : AddrSpaceIdx ,
875
+ dest_ty : & ' ll Type ) -> & ' ll Value
876
+ {
877
+ let val = self . addrspace_cast ( val, addr_space) ;
878
+ self . pointercast ( val, dest_ty. copy_addr_space ( addr_space) )
879
+ }
880
+ fn flat_as_ptr_cast ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
881
+ self . as_ptr_cast ( val, self . cx ( ) . flat_addr_space ( ) , dest_ty)
882
+ }
868
883
884
+ fn addrspace_cast ( & mut self , val : & ' ll Value , dest : AddrSpaceIdx ) -> & ' ll Value {
885
+ // LLVM considers no-op address space casts to be invalid.
886
+ let src_ty = self . cx . val_ty ( val) ;
887
+ if src_ty. is_ptr ( ) && src_ty. address_space ( ) != dest {
888
+ let dest_ty = src_ty. copy_addr_space ( dest) ;
889
+ self . cx ( ) . check_addr_space_cast ( val, dest_ty) ;
890
+ self . count_insn ( "addrspacecast" ) ;
891
+ unsafe {
892
+ llvm:: LLVMBuildAddrSpaceCast ( self . llbuilder , val,
893
+ dest_ty, noname ( ) )
894
+ }
895
+ } else {
896
+ val
897
+ }
898
+ }
899
+
900
+ fn flat_addr_cast ( & mut self , val : & ' ll Value ) -> & ' ll Value {
901
+ self . addrspace_cast ( val, self . cx ( ) . flat_addr_space ( ) )
902
+ }
869
903
fn intcast ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type , is_signed : bool ) -> & ' ll Value {
870
904
self . count_insn ( "intcast" ) ;
871
905
unsafe {
@@ -875,6 +909,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
875
909
876
910
fn pointercast ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
877
911
self . count_insn ( "pointercast" ) ;
912
+ let dest_ty = dest_ty. copy_addr_space ( val_addr_space ( val) ) ;
878
913
unsafe {
879
914
llvm:: LLVMBuildPointerCast ( self . llbuilder , val, dest_ty, noname ( ) )
880
915
}
@@ -883,7 +918,18 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
883
918
/* Comparisons */
884
919
fn icmp ( & mut self , op : IntPredicate , lhs : & ' ll Value , rhs : & ' ll Value ) -> & ' ll Value {
885
920
self . count_insn ( "icmp" ) ;
921
+
886
922
let op = llvm:: IntPredicate :: from_generic ( op) ;
923
+
924
+ match ( val_addr_space_opt ( lhs) , val_addr_space_opt ( rhs) ) {
925
+ ( Some ( l) , Some ( r) ) if l == r => { } ,
926
+ ( Some ( l) , Some ( r) ) if l != r => {
927
+ bug ! ( "tried to cmp ptrs of different addr spaces: lhs {:?} rhs {:?}" ,
928
+ lhs, rhs) ;
929
+ } ,
930
+ _ => { } ,
931
+ }
932
+
887
933
unsafe {
888
934
llvm:: LLVMBuildICmp ( self . llbuilder , op as c_uint , lhs, rhs, noname ( ) )
889
935
}
@@ -1004,7 +1050,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1004
1050
flags : MemFlags ,
1005
1051
) {
1006
1052
let ptr_width = & self . sess ( ) . target . target . target_pointer_width ;
1007
- let intrinsic_key = format ! ( "llvm.memset.p0i8.i{}" , ptr_width) ;
1053
+ let addr_space = self . val_ty ( ptr) . address_space ( ) ;
1054
+ let intrinsic_key = format ! ( "llvm.memset.p{}i8.i{}" , addr_space, ptr_width) ;
1008
1055
let llintrinsicfn = self . get_intrinsic ( & intrinsic_key) ;
1009
1056
let ptr = self . pointercast ( ptr, self . type_i8p ( ) ) ;
1010
1057
let align = self . const_u32 ( align. bytes ( ) as u32 ) ;
@@ -1352,7 +1399,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1352
1399
ptr : & ' ll Value ) -> & ' ll Value {
1353
1400
let dest_ptr_ty = self . cx . val_ty ( ptr) ;
1354
1401
let stored_ty = self . cx . val_ty ( val) ;
1355
- let stored_ptr_ty = self . cx . type_ptr_to ( stored_ty) ;
1402
+ let stored_ptr_ty = self . cx . type_as_ptr_to ( stored_ty,
1403
+ dest_ptr_ty. address_space ( ) ) ;
1356
1404
1357
1405
assert_eq ! ( self . cx. type_kind( dest_ptr_ty) , TypeKind :: Pointer ) ;
1358
1406
@@ -1398,7 +1446,18 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1398
1446
debug ! ( "Type mismatch in function call of {:?}. \
1399
1447
Expected {:?} for param {}, got {:?}; injecting bitcast",
1400
1448
llfn, expected_ty, i, actual_ty) ;
1401
- self . bitcast ( actual_val, expected_ty)
1449
+ if expected_ty. is_ptr ( ) && actual_ty. is_ptr ( ) {
1450
+ let actual_val = self . addrspace_cast ( actual_val,
1451
+ expected_ty. address_space ( ) ) ;
1452
+ self . pointercast ( actual_val, expected_ty)
1453
+ } else {
1454
+ let actual_val = if actual_ty. is_ptr ( ) {
1455
+ self . flat_addr_cast ( actual_val)
1456
+ } else {
1457
+ actual_val
1458
+ } ;
1459
+ self . bitcast ( actual_val, expected_ty)
1460
+ }
1402
1461
} else {
1403
1462
actual_val
1404
1463
}
@@ -1488,7 +1547,16 @@ impl Builder<'a, 'll, 'tcx> {
1488
1547
return ;
1489
1548
}
1490
1549
1491
- let lifetime_intrinsic = self . cx . get_intrinsic ( intrinsic) ;
1550
+ let addr_space = self . cx . val_ty ( ptr) . address_space ( ) ;
1551
+ // Old LLVMs don't have the address space specific intrinsics.
1552
+ // So as a semi-crude workaround, don't specialize if in the
1553
+ // default address space.
1554
+ let lifetime_intrinsic = if let AddrSpaceIdx ( 0 ) = addr_space {
1555
+ self . cx . get_intrinsic ( intrinsic)
1556
+ } else {
1557
+ let intrinsic = format ! ( "{}.p{}i8" , intrinsic, addr_space) ;
1558
+ self . cx . get_intrinsic ( & intrinsic)
1559
+ } ;
1492
1560
1493
1561
let ptr = self . pointercast ( ptr, self . cx . type_i8p ( ) ) ;
1494
1562
self . call ( lifetime_intrinsic, & [ self . cx . const_u64 ( size) , ptr] , None ) ;
0 commit comments