@@ -16,8 +16,8 @@ use rustc_target::abi::{Abi, Align, FieldIdx, HasDataLayout, Size, FIRST_VARIANT
16
16
17
17
use super :: {
18
18
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 ,
21
21
} ;
22
22
23
23
#[ derive( Copy , Clone , Hash , PartialEq , Eq , Debug ) ]
@@ -91,6 +91,7 @@ impl<Prov: Provenance> MemPlace<Prov> {
91
91
fn offset_with_meta_ < ' mir , ' tcx , M : Machine < ' mir , ' tcx , Provenance = Prov > > (
92
92
self ,
93
93
offset : Size ,
94
+ mode : OffsetMode ,
94
95
meta : MemPlaceMeta < Prov > ,
95
96
ecx : & InterpCx < ' mir , ' tcx , M > ,
96
97
) -> InterpResult < ' tcx , Self > {
@@ -101,8 +102,12 @@ impl<Prov: Provenance> MemPlace<Prov> {
101
102
if offset > ecx. data_layout ( ) . max_size_of_val ( ) {
102
103
throw_ub ! ( PointerArithOverflow ) ;
103
104
}
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
+ } ;
106
111
Ok ( MemPlace { ptr, meta } )
107
112
}
108
113
}
@@ -194,12 +199,13 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for MPlaceTy<'tcx, Prov> {
194
199
fn offset_with_meta < ' mir , M : Machine < ' mir , ' tcx , Provenance = Prov > > (
195
200
& self ,
196
201
offset : Size ,
202
+ mode : OffsetMode ,
197
203
meta : MemPlaceMeta < Prov > ,
198
204
layout : TyAndLayout < ' tcx > ,
199
205
ecx : & InterpCx < ' mir , ' tcx , M > ,
200
206
) -> InterpResult < ' tcx , Self > {
201
207
Ok ( MPlaceTy {
202
- mplace : self . mplace . offset_with_meta_ ( offset, meta, ecx) ?,
208
+ mplace : self . mplace . offset_with_meta_ ( offset, mode , meta, ecx) ?,
203
209
align : self . align . restrict_for_offset ( offset) ,
204
210
layout,
205
211
} )
@@ -306,12 +312,13 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for PlaceTy<'tcx, Prov> {
306
312
fn offset_with_meta < ' mir , M : Machine < ' mir , ' tcx , Provenance = Prov > > (
307
313
& self ,
308
314
offset : Size ,
315
+ mode : OffsetMode ,
309
316
meta : MemPlaceMeta < Prov > ,
310
317
layout : TyAndLayout < ' tcx > ,
311
318
ecx : & InterpCx < ' mir , ' tcx , M > ,
312
319
) -> InterpResult < ' tcx , Self > {
313
320
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 ( ) ,
315
322
Right ( ( frame, local, old_offset) ) => {
316
323
debug_assert ! ( layout. is_sized( ) , "unsized locals should live in memory" ) ;
317
324
assert_matches ! ( meta, MemPlaceMeta :: None ) ; // we couldn't store it anyway...
@@ -952,7 +959,13 @@ where
952
959
& mut Operand :: Indirect ( mplace) => mplace, // this already was an indirect local
953
960
} ;
954
961
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
+ ) ?
956
969
} else {
957
970
// Preserve wide place metadata, do not call `offset`.
958
971
whole_local
0 commit comments