1
- use super :: { AllocId , InterpResult } ;
1
+ use super :: AllocId ;
2
2
3
3
use rustc_data_structures:: static_assert_size;
4
4
use rustc_macros:: { HashStable , TyDecodable , TyEncodable } ;
@@ -39,62 +39,13 @@ pub trait PointerArithmetic: HasDataLayout {
39
39
}
40
40
41
41
#[ inline]
42
- fn target_usize_to_isize ( & self , val : u64 ) -> i64 {
43
- let val = val as i64 ;
44
- // Now wrap-around into the machine_isize range.
45
- if val > self . target_isize_max ( ) {
46
- // This can only happen if the ptr size is < 64, so we know max_usize_plus_1 fits into
47
- // i64.
48
- debug_assert ! ( self . pointer_size( ) . bits( ) < 64 ) ;
49
- let max_usize_plus_1 = 1u128 << self . pointer_size ( ) . bits ( ) ;
50
- val - i64:: try_from ( max_usize_plus_1) . unwrap ( )
51
- } else {
52
- val
53
- }
54
- }
55
-
56
- /// Helper function: truncate given value-"overflowed flag" pair to pointer size and
57
- /// update "overflowed flag" if there was an overflow.
58
- /// This should be called by all the other methods before returning!
59
- #[ inline]
60
- fn truncate_to_ptr ( & self , ( val, over) : ( u64 , bool ) ) -> ( u64 , bool ) {
61
- let val = u128:: from ( val) ;
62
- let max_ptr_plus_1 = 1u128 << self . pointer_size ( ) . bits ( ) ;
63
- ( u64:: try_from ( val % max_ptr_plus_1) . unwrap ( ) , over || val >= max_ptr_plus_1)
64
- }
65
-
66
- #[ inline]
67
- fn overflowing_offset ( & self , val : u64 , i : u64 ) -> ( u64 , bool ) {
68
- // We do not need to check if i fits in a machine usize. If it doesn't,
69
- // either the wrapping_add will wrap or res will not fit in a pointer.
70
- let res = val. overflowing_add ( i) ;
71
- self . truncate_to_ptr ( res)
72
- }
73
-
74
- #[ inline]
75
- fn overflowing_signed_offset ( & self , val : u64 , i : i64 ) -> ( u64 , bool ) {
76
- // We need to make sure that i fits in a machine isize.
77
- let n = i. unsigned_abs ( ) ;
78
- if i >= 0 {
79
- let ( val, over) = self . overflowing_offset ( val, n) ;
80
- ( val, over || i > self . target_isize_max ( ) )
81
- } else {
82
- let res = val. overflowing_sub ( n) ;
83
- let ( val, over) = self . truncate_to_ptr ( res) ;
84
- ( val, over || i < self . target_isize_min ( ) )
85
- }
86
- }
87
-
88
- #[ inline]
89
- fn offset < ' tcx > ( & self , val : u64 , i : u64 ) -> InterpResult < ' tcx , u64 > {
90
- let ( res, over) = self . overflowing_offset ( val, i) ;
91
- if over { throw_ub ! ( PointerArithOverflow ) } else { Ok ( res) }
42
+ fn truncate_to_target_usize ( & self , val : u64 ) -> u64 {
43
+ self . pointer_size ( ) . truncate ( val. into ( ) ) . try_into ( ) . unwrap ( )
92
44
}
93
45
94
46
#[ inline]
95
- fn signed_offset < ' tcx > ( & self , val : u64 , i : i64 ) -> InterpResult < ' tcx , u64 > {
96
- let ( res, over) = self . overflowing_signed_offset ( val, i) ;
97
- if over { throw_ub ! ( PointerArithOverflow ) } else { Ok ( res) }
47
+ fn sign_extend_to_target_isize ( & self , val : u64 ) -> i64 {
48
+ self . pointer_size ( ) . sign_extend ( val. into ( ) ) . try_into ( ) . unwrap ( )
98
49
}
99
50
}
100
51
@@ -330,7 +281,7 @@ impl<Prov> Pointer<Option<Prov>> {
330
281
}
331
282
}
332
283
333
- impl < ' tcx , Prov > Pointer < Prov > {
284
+ impl < Prov > Pointer < Prov > {
334
285
#[ inline( always) ]
335
286
pub fn new ( provenance : Prov , offset : Size ) -> Self {
336
287
Pointer { provenance, offset }
@@ -348,43 +299,16 @@ impl<'tcx, Prov> Pointer<Prov> {
348
299
Pointer { provenance : f ( self . provenance ) , ..self }
349
300
}
350
301
351
- #[ inline]
352
- pub fn offset ( self , i : Size , cx : & impl HasDataLayout ) -> InterpResult < ' tcx , Self > {
353
- Ok ( Pointer {
354
- offset : Size :: from_bytes ( cx. data_layout ( ) . offset ( self . offset . bytes ( ) , i. bytes ( ) ) ?) ,
355
- ..self
356
- } )
357
- }
358
-
359
- #[ inline]
360
- pub fn overflowing_offset ( self , i : Size , cx : & impl HasDataLayout ) -> ( Self , bool ) {
361
- let ( res, over) = cx. data_layout ( ) . overflowing_offset ( self . offset . bytes ( ) , i. bytes ( ) ) ;
362
- let ptr = Pointer { offset : Size :: from_bytes ( res) , ..self } ;
363
- ( ptr, over)
364
- }
365
-
366
302
#[ inline( always) ]
367
303
pub fn wrapping_offset ( self , i : Size , cx : & impl HasDataLayout ) -> Self {
368
- self . overflowing_offset ( i, cx) . 0
369
- }
370
-
371
- #[ inline]
372
- pub fn signed_offset ( self , i : i64 , cx : & impl HasDataLayout ) -> InterpResult < ' tcx , Self > {
373
- Ok ( Pointer {
374
- offset : Size :: from_bytes ( cx. data_layout ( ) . signed_offset ( self . offset . bytes ( ) , i) ?) ,
375
- ..self
376
- } )
377
- }
378
-
379
- #[ inline]
380
- pub fn overflowing_signed_offset ( self , i : i64 , cx : & impl HasDataLayout ) -> ( Self , bool ) {
381
- let ( res, over) = cx. data_layout ( ) . overflowing_signed_offset ( self . offset . bytes ( ) , i) ;
382
- let ptr = Pointer { offset : Size :: from_bytes ( res) , ..self } ;
383
- ( ptr, over)
304
+ let res =
305
+ cx. data_layout ( ) . truncate_to_target_usize ( self . offset . bytes ( ) . wrapping_add ( i. bytes ( ) ) ) ;
306
+ Pointer { offset : Size :: from_bytes ( res) , ..self }
384
307
}
385
308
386
309
#[ inline( always) ]
387
310
pub fn wrapping_signed_offset ( self , i : i64 , cx : & impl HasDataLayout ) -> Self {
388
- self . overflowing_signed_offset ( i, cx) . 0
311
+ // It's wrapping anyway, so we can just cast to `u64`.
312
+ self . wrapping_offset ( Size :: from_bytes ( i as u64 ) , cx)
389
313
}
390
314
}
0 commit comments