@@ -16,8 +16,8 @@ use rustc_target::abi::{Abi, Align, FieldIdx, HasDataLayout, Size, FIRST_VARIANT
1616
1717use super :: {
1818 alloc_range, mir_assign_valid_types, AllocId , AllocRef , AllocRefMut , ImmTy , Immediate ,
19- InterpCx , InterpResult , Machine , MemoryKind , OpTy , Operand , Pointer , PointerArithmetic ,
20- Projectable , Provenance , Readable , Scalar ,
19+ InterpCx , InterpResult , Machine , MemoryKind , OffsetMode , OpTy , Operand , Pointer ,
20+ PointerArithmetic , Projectable , Provenance , Readable , Scalar ,
2121} ;
2222
2323#[ derive( Copy , Clone , Hash , PartialEq , Eq , Debug ) ]
@@ -91,6 +91,7 @@ impl<Prov: Provenance> MemPlace<Prov> {
9191 fn offset_with_meta_ < ' mir , ' tcx , M : Machine < ' mir , ' tcx , Provenance = Prov > > (
9292 self ,
9393 offset : Size ,
94+ mode : OffsetMode ,
9495 meta : MemPlaceMeta < Prov > ,
9596 ecx : & InterpCx < ' mir , ' tcx , M > ,
9697 ) -> InterpResult < ' tcx , Self > {
@@ -101,8 +102,12 @@ impl<Prov: Provenance> MemPlace<Prov> {
101102 if offset > ecx. data_layout ( ) . max_size_of_val ( ) {
102103 throw_ub ! ( PointerArithOverflow ) ;
103104 }
104- let offset: i64 = offset. bytes ( ) . try_into ( ) . unwrap ( ) ;
105- let ptr = ecx. ptr_offset_inbounds ( self . ptr , offset) ?;
105+ let ptr = match mode {
106+ OffsetMode :: Inbounds => {
107+ ecx. ptr_offset_inbounds ( self . ptr , offset. bytes ( ) . try_into ( ) . unwrap ( ) ) ?
108+ }
109+ OffsetMode :: Wrapping => self . ptr . wrapping_offset ( offset, ecx) ,
110+ } ;
106111 Ok ( MemPlace { ptr, meta } )
107112 }
108113}
@@ -194,12 +199,13 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for MPlaceTy<'tcx, Prov> {
194199 fn offset_with_meta < ' mir , M : Machine < ' mir , ' tcx , Provenance = Prov > > (
195200 & self ,
196201 offset : Size ,
202+ mode : OffsetMode ,
197203 meta : MemPlaceMeta < Prov > ,
198204 layout : TyAndLayout < ' tcx > ,
199205 ecx : & InterpCx < ' mir , ' tcx , M > ,
200206 ) -> InterpResult < ' tcx , Self > {
201207 Ok ( MPlaceTy {
202- mplace : self . mplace . offset_with_meta_ ( offset, meta, ecx) ?,
208+ mplace : self . mplace . offset_with_meta_ ( offset, mode , meta, ecx) ?,
203209 align : self . align . restrict_for_offset ( offset) ,
204210 layout,
205211 } )
@@ -306,12 +312,13 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for PlaceTy<'tcx, Prov> {
306312 fn offset_with_meta < ' mir , M : Machine < ' mir , ' tcx , Provenance = Prov > > (
307313 & self ,
308314 offset : Size ,
315+ mode : OffsetMode ,
309316 meta : MemPlaceMeta < Prov > ,
310317 layout : TyAndLayout < ' tcx > ,
311318 ecx : & InterpCx < ' mir , ' tcx , M > ,
312319 ) -> InterpResult < ' tcx , Self > {
313320 Ok ( match self . as_mplace_or_local ( ) {
314- Left ( mplace) => mplace. offset_with_meta ( offset, meta, layout, ecx) ?. into ( ) ,
321+ Left ( mplace) => mplace. offset_with_meta ( offset, mode , meta, layout, ecx) ?. into ( ) ,
315322 Right ( ( frame, local, old_offset) ) => {
316323 debug_assert ! ( layout. is_sized( ) , "unsized locals should live in memory" ) ;
317324 assert_matches ! ( meta, MemPlaceMeta :: None ) ; // we couldn't store it anyway...
@@ -952,7 +959,13 @@ where
952959 & mut Operand :: Indirect ( mplace) => mplace, // this already was an indirect local
953960 } ;
954961 if let Some ( offset) = offset {
955- whole_local. offset_with_meta_ ( offset, MemPlaceMeta :: None , self ) ?
962+ // This offset is always inbounds, no need to check it again.
963+ whole_local. offset_with_meta_ (
964+ offset,
965+ OffsetMode :: Wrapping ,
966+ MemPlaceMeta :: None ,
967+ self ,
968+ ) ?
956969 } else {
957970 // Preserve wide place metadata, do not call `offset`.
958971 whole_local
0 commit comments