@@ -2,7 +2,7 @@ use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
22use llvm:: { self , False , BasicBlock } ;
33use rustc_codegen_ssa:: common:: { IntPredicate , TypeKind , RealPredicate } ;
44use rustc_codegen_ssa:: { self , MemFlags } ;
5- use common:: Funclet ;
5+ use common:: { Funclet , val_addr_space , val_addr_space_opt } ;
66use context:: CodegenCx ;
77use type_:: Type ;
88use type_of:: LayoutLlvmExt ;
@@ -18,6 +18,7 @@ use syntax;
1818use rustc_codegen_ssa:: base:: to_immediate;
1919use rustc_codegen_ssa:: mir:: operand:: { OperandValue , OperandRef } ;
2020use rustc_codegen_ssa:: mir:: place:: PlaceRef ;
21+ use rustc_target:: spec:: AddrSpaceIdx ;
2122use std:: borrow:: Cow ;
2223use std:: ffi:: CStr ;
2324use std:: ops:: { Deref , Range } ;
@@ -846,26 +847,59 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
846847
847848 fn ptrtoint ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
848849 self . count_insn ( "ptrtoint" ) ;
850+ let val = self . flat_addr_cast ( val) ;
849851 unsafe {
850852 llvm:: LLVMBuildPtrToInt ( self . llbuilder , val, dest_ty, noname ( ) )
851853 }
852854 }
853855
854856 fn inttoptr ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
855857 self . count_insn ( "inttoptr" ) ;
858+ let dest_ty = dest_ty. copy_addr_space ( self . cx ( ) . flat_addr_space ( ) ) ;
856859 unsafe {
857860 llvm:: LLVMBuildIntToPtr ( self . llbuilder , val, dest_ty, noname ( ) )
858861 }
859862 }
860863
861864 fn bitcast ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
862865 self . count_insn ( "bitcast" ) ;
866+ let dest_ty = dest_ty. copy_addr_space ( val_addr_space ( val) ) ;
863867 unsafe {
864868 llvm:: LLVMBuildBitCast ( self . llbuilder , val, dest_ty, noname ( ) )
865869 }
866870 }
867871
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+ }
868883
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+ }
869903 fn intcast ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type , is_signed : bool ) -> & ' ll Value {
870904 self . count_insn ( "intcast" ) ;
871905 unsafe {
@@ -875,6 +909,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
875909
876910 fn pointercast ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
877911 self . count_insn ( "pointercast" ) ;
912+ let dest_ty = dest_ty. copy_addr_space ( val_addr_space ( val) ) ;
878913 unsafe {
879914 llvm:: LLVMBuildPointerCast ( self . llbuilder , val, dest_ty, noname ( ) )
880915 }
@@ -883,7 +918,18 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
883918 /* Comparisons */
884919 fn icmp ( & mut self , op : IntPredicate , lhs : & ' ll Value , rhs : & ' ll Value ) -> & ' ll Value {
885920 self . count_insn ( "icmp" ) ;
921+
886922 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+
887933 unsafe {
888934 llvm:: LLVMBuildICmp ( self . llbuilder , op as c_uint , lhs, rhs, noname ( ) )
889935 }
@@ -1004,7 +1050,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
10041050 flags : MemFlags ,
10051051 ) {
10061052 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) ;
10081055 let llintrinsicfn = self . get_intrinsic ( & intrinsic_key) ;
10091056 let ptr = self . pointercast ( ptr, self . type_i8p ( ) ) ;
10101057 let align = self . const_u32 ( align. bytes ( ) as u32 ) ;
@@ -1352,7 +1399,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
13521399 ptr : & ' ll Value ) -> & ' ll Value {
13531400 let dest_ptr_ty = self . cx . val_ty ( ptr) ;
13541401 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 ( ) ) ;
13561404
13571405 assert_eq ! ( self . cx. type_kind( dest_ptr_ty) , TypeKind :: Pointer ) ;
13581406
@@ -1398,7 +1446,18 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
13981446 debug ! ( "Type mismatch in function call of {:?}. \
13991447 Expected {:?} for param {}, got {:?}; injecting bitcast",
14001448 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+ }
14021461 } else {
14031462 actual_val
14041463 }
@@ -1488,7 +1547,16 @@ impl Builder<'a, 'll, 'tcx> {
14881547 return ;
14891548 }
14901549
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+ } ;
14921560
14931561 let ptr = self . pointercast ( ptr, self . cx . type_i8p ( ) ) ;
14941562 self . call ( lifetime_intrinsic, & [ self . cx . const_u64 ( size) , ptr] , None ) ;
0 commit comments