1
1
use crate :: llvm:: { AtomicRmwBinOp , AtomicOrdering , SynchronizationScope } ;
2
2
use crate :: llvm:: { self , False , BasicBlock } ;
3
- use crate :: common:: Funclet ;
3
+ use crate :: common:: { Funclet , val_addr_space , val_addr_space_opt } ;
4
4
use crate :: context:: CodegenCx ;
5
5
use crate :: type_:: Type ;
6
6
use crate :: type_of:: LayoutLlvmExt ;
@@ -18,7 +18,7 @@ use rustc_codegen_ssa::traits::*;
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:: { HasTargetSpec , Target } ;
21
+ use rustc_target:: spec:: { HasTargetSpec , Target , AddrSpaceIdx } ;
22
22
use std:: borrow:: Cow ;
23
23
use std:: ffi:: CStr ;
24
24
use std:: ops:: { Deref , Range } ;
@@ -215,7 +215,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
215
215
funclet : Option < & Funclet < ' ll > > ,
216
216
) -> & ' ll Value {
217
217
218
- debug ! ( "invoke {:?} with args ({:?})" ,
218
+ debug ! ( "Invoke {:?} with args ({:?})" ,
219
219
llfn,
220
220
args) ;
221
221
@@ -548,6 +548,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
548
548
let count = self . const_usize ( count) ;
549
549
let start = dest. project_index ( & mut self , zero) . llval ;
550
550
let end = dest. project_index ( & mut self , count) . llval ;
551
+ let start = self . flat_addr_cast ( start) ;
552
+ let end = self . flat_addr_cast ( end) ;
551
553
552
554
let mut header_bx = self . build_sibling_block ( "repeat_loop_header" ) ;
553
555
let mut body_bx = self . build_sibling_block ( "repeat_loop_body" ) ;
@@ -724,23 +726,56 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
724
726
}
725
727
726
728
fn ptrtoint ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
729
+ let val = self . flat_addr_cast ( val) ;
727
730
unsafe {
728
731
llvm:: LLVMBuildPtrToInt ( self . llbuilder , val, dest_ty, UNNAMED )
729
732
}
730
733
}
731
734
732
735
fn inttoptr ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
736
+ let dest_ty = dest_ty. copy_addr_space ( self . cx ( ) . flat_addr_space ( ) ) ;
733
737
unsafe {
734
738
llvm:: LLVMBuildIntToPtr ( self . llbuilder , val, dest_ty, UNNAMED )
735
739
}
736
740
}
737
741
738
742
fn bitcast ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
743
+ let dest_ty = dest_ty. copy_addr_space ( val_addr_space ( val) ) ;
739
744
unsafe {
740
745
llvm:: LLVMBuildBitCast ( self . llbuilder , val, dest_ty, UNNAMED )
741
746
}
742
747
}
743
748
749
+ fn as_ptr_cast (
750
+ & mut self , val : & ' ll Value ,
751
+ addr_space : AddrSpaceIdx , dest_ty : & ' ll Type
752
+ ) -> & ' ll Value {
753
+ let val = self . addrspace_cast ( val, addr_space) ;
754
+ self . pointercast ( val, dest_ty. copy_addr_space ( addr_space) )
755
+ }
756
+
757
+ fn flat_as_ptr_cast ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
758
+ self . as_ptr_cast ( val, self . cx ( ) . flat_addr_space ( ) , dest_ty)
759
+ }
760
+
761
+ fn addrspace_cast ( & mut self , val : & ' ll Value , dest : AddrSpaceIdx ) -> & ' ll Value {
762
+ let src_ty = self . cx ( ) . val_ty ( val) ;
763
+
764
+ if src_ty. is_ptr ( ) && src_ty. address_space ( ) != dest {
765
+ let dest_ty = src_ty. copy_addr_space ( dest) ;
766
+ self . cx ( ) . check_addr_space_cast ( val, dest_ty) ;
767
+ unsafe {
768
+ llvm:: LLVMBuildAddrSpaceCast ( self . llbuilder , val,
769
+ dest_ty, UNNAMED )
770
+ }
771
+ } else {
772
+ val
773
+ }
774
+ }
775
+
776
+ fn flat_addr_cast ( & mut self , val : & ' ll Value ) -> & ' ll Value {
777
+ self . addrspace_cast ( val, self . cx ( ) . flat_addr_space ( ) )
778
+ }
744
779
745
780
fn intcast ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type , is_signed : bool ) -> & ' ll Value {
746
781
unsafe {
@@ -749,6 +784,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
749
784
}
750
785
751
786
fn pointercast ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
787
+ let dest_ty = dest_ty. copy_addr_space ( val_addr_space ( val) ) ;
752
788
unsafe {
753
789
llvm:: LLVMBuildPointerCast ( self . llbuilder , val, dest_ty, UNNAMED )
754
790
}
@@ -757,6 +793,16 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
757
793
/* Comparisons */
758
794
fn icmp ( & mut self , op : IntPredicate , lhs : & ' ll Value , rhs : & ' ll Value ) -> & ' ll Value {
759
795
let op = llvm:: IntPredicate :: from_generic ( op) ;
796
+
797
+ match ( val_addr_space_opt ( lhs) , val_addr_space_opt ( rhs) ) {
798
+ ( Some ( l) , Some ( r) ) if l == r => { } ,
799
+ ( Some ( l) , Some ( r) ) if l != r => {
800
+ bug ! ( "Tried to compare pointers of different address spaces: lhs {:?} rhs {:?}" ,
801
+ lhs, rhs) ;
802
+ } ,
803
+ _ => { } ,
804
+ }
805
+
760
806
unsafe {
761
807
llvm:: LLVMBuildICmp ( self . llbuilder , op as c_uint , lhs, rhs, UNNAMED )
762
808
}
@@ -818,7 +864,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
818
864
flags : MemFlags ,
819
865
) {
820
866
let ptr_width = & self . sess ( ) . target . target . target_pointer_width ;
821
- let intrinsic_key = format ! ( "llvm.memset.p0i8.i{}" , ptr_width) ;
867
+ let addr_space = self . val_ty ( ptr) . address_space ( ) ;
868
+ let intrinsic_key = format ! ( "llvm.memset.p{}i8.i{}" , addr_space, ptr_width) ;
822
869
let llintrinsicfn = self . get_intrinsic ( & intrinsic_key) ;
823
870
let ptr = self . pointercast ( ptr, self . type_i8p ( ) ) ;
824
871
let align = self . const_u32 ( align. bytes ( ) as u32 ) ;
@@ -1035,7 +1082,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1035
1082
funclet : Option < & Funclet < ' ll > > ,
1036
1083
) -> & ' ll Value {
1037
1084
1038
- debug ! ( "call {:?} with args ({:?})" ,
1085
+ debug ! ( "Call {:?} with args ({:?})" ,
1039
1086
llfn,
1040
1087
args) ;
1041
1088
@@ -1231,14 +1278,15 @@ impl Builder<'a, 'll, 'tcx> {
1231
1278
fn check_store ( & mut self , val : & ' ll Value , ptr : & ' ll Value ) -> & ' ll Value {
1232
1279
let dest_ptr_ty = self . cx . val_ty ( ptr) ;
1233
1280
let stored_ty = self . cx . val_ty ( val) ;
1234
- let stored_ptr_ty = self . cx . type_ptr_to ( stored_ty) ;
1281
+ let stored_ptr_ty = self . cx . type_as_ptr_to ( stored_ty,
1282
+ dest_ptr_ty. address_space ( ) ) ;
1235
1283
1236
1284
assert_eq ! ( self . cx. type_kind( dest_ptr_ty) , TypeKind :: Pointer ) ;
1237
1285
1238
1286
if dest_ptr_ty == stored_ptr_ty {
1239
1287
ptr
1240
1288
} else {
1241
- debug ! ( "type mismatch in store. \
1289
+ debug ! ( "Type mismatch in store. \
1242
1290
Expected {:?}, got {:?}; inserting bitcast",
1243
1291
dest_ptr_ty, stored_ptr_ty) ;
1244
1292
self . bitcast ( ptr, stored_ptr_ty)
@@ -1274,10 +1322,21 @@ impl Builder<'a, 'll, 'tcx> {
1274
1322
. map ( |( i, ( expected_ty, & actual_val) ) | {
1275
1323
let actual_ty = self . val_ty ( actual_val) ;
1276
1324
if expected_ty != actual_ty {
1277
- debug ! ( "type mismatch in function call of {:?}. \
1325
+ debug ! ( "Type mismatch in function call of {:?}. \
1278
1326
Expected {:?} for param {}, got {:?}; injecting bitcast",
1279
1327
llfn, expected_ty, i, actual_ty) ;
1280
- self . bitcast ( actual_val, expected_ty)
1328
+ if expected_ty. is_ptr ( ) && actual_ty. is_ptr ( ) {
1329
+ let actual_val = self . addrspace_cast ( actual_val,
1330
+ expected_ty. address_space ( ) ) ;
1331
+ self . pointercast ( actual_val, expected_ty)
1332
+ } else {
1333
+ let actual_val = if actual_ty. is_ptr ( ) {
1334
+ self . flat_addr_cast ( actual_val)
1335
+ } else {
1336
+ actual_val
1337
+ } ;
1338
+ self . bitcast ( actual_val, expected_ty)
1339
+ }
1281
1340
} else {
1282
1341
actual_val
1283
1342
}
@@ -1303,7 +1362,16 @@ impl Builder<'a, 'll, 'tcx> {
1303
1362
return ;
1304
1363
}
1305
1364
1306
- let lifetime_intrinsic = self . cx . get_intrinsic ( intrinsic) ;
1365
+ let addr_space = self . cx . val_ty ( ptr) . address_space ( ) ;
1366
+ // Old LLVMs don't have the address space specific intrinsics.
1367
+ // So as a semi-crude workaround, don't specialize if in the
1368
+ // default address space.
1369
+ let lifetime_intrinsic = if let AddrSpaceIdx ( 0 ) = addr_space {
1370
+ self . cx . get_intrinsic ( intrinsic)
1371
+ } else {
1372
+ let intrinsic = format ! ( "{}.p{}i8" , intrinsic, addr_space) ;
1373
+ self . cx . get_intrinsic ( & intrinsic)
1374
+ } ;
1307
1375
1308
1376
let ptr = self . pointercast ( ptr, self . cx . type_i8p ( ) ) ;
1309
1377
self . call ( lifetime_intrinsic, & [ self . cx . const_u64 ( size) , ptr] , None ) ;
0 commit comments