@@ -91,42 +91,43 @@ pub trait PointerArithmetic: layout::HasDataLayout {
9191 }
9292
9393 //// Trunace the given value to the pointer size; also return whether there was an overflow
94+ #[ inline]
9495 fn truncate_to_ptr ( & self , val : u128 ) -> ( u64 , bool ) {
9596 let max_ptr_plus_1 = 1u128 << self . pointer_size ( ) . bits ( ) ;
9697 ( ( val % max_ptr_plus_1) as u64 , val >= max_ptr_plus_1)
9798 }
9899
99- // Overflow checking only works properly on the range from -u64 to +u64.
100- fn overflowing_signed_offset ( & self , val : u64 , i : i128 ) -> ( u64 , bool ) {
101- // FIXME: is it possible to over/underflow here?
102- if i < 0 {
103- // trickery to ensure that i64::min_value() works fine
104- // this formula only works for true negative values, it panics for zero!
105- let n = u64:: max_value ( ) - ( i as u64 ) + 1 ;
106- val. overflowing_sub ( n)
107- } else {
108- self . overflowing_offset ( val, i as u64 )
109- }
100+ #[ inline]
101+ fn offset < ' tcx > ( & self , val : u64 , i : u64 ) -> EvalResult < ' tcx , u64 > {
102+ let ( res, over) = self . overflowing_offset ( val, i) ;
103+ if over { err ! ( Overflow ( mir:: BinOp :: Add ) ) } else { Ok ( res) }
110104 }
111105
106+ #[ inline]
112107 fn overflowing_offset ( & self , val : u64 , i : u64 ) -> ( u64 , bool ) {
113108 let ( res, over1) = val. overflowing_add ( i) ;
114- let ( res, over2) = self . truncate_to_ptr ( res as u128 ) ;
109+ let ( res, over2) = self . truncate_to_ptr ( u128:: from ( res ) ) ;
115110 ( res, over1 || over2)
116111 }
117112
113+ #[ inline]
118114 fn signed_offset < ' tcx > ( & self , val : u64 , i : i64 ) -> EvalResult < ' tcx , u64 > {
119- let ( res, over) = self . overflowing_signed_offset ( val, i as i128 ) ;
115+ let ( res, over) = self . overflowing_signed_offset ( val, i128:: from ( i ) ) ;
120116 if over { err ! ( Overflow ( mir:: BinOp :: Add ) ) } else { Ok ( res) }
121117 }
122118
123- fn offset < ' tcx > ( & self , val : u64 , i : u64 ) -> EvalResult < ' tcx , u64 > {
124- let ( res, over) = self . overflowing_offset ( val, i) ;
125- if over { err ! ( Overflow ( mir:: BinOp :: Add ) ) } else { Ok ( res) }
126- }
127-
128- fn wrapping_signed_offset ( & self , val : u64 , i : i64 ) -> u64 {
129- self . overflowing_signed_offset ( val, i as i128 ) . 0
119+ // Overflow checking only works properly on the range from -u64 to +u64.
120+ #[ inline]
121+ fn overflowing_signed_offset ( & self , val : u64 , i : i128 ) -> ( u64 , bool ) {
122+ // FIXME: is it possible to over/underflow here?
123+ if i < 0 {
124+ // trickery to ensure that i64::min_value() works fine
125+ // this formula only works for true negative values, it panics for zero!
126+ let n = u64:: max_value ( ) - ( i as u64 ) + 1 ;
127+ val. overflowing_sub ( n)
128+ } else {
129+ self . overflowing_offset ( val, i as u64 )
130+ }
130131 }
131132}
132133
@@ -176,19 +177,27 @@ impl<'tcx, Tag> Pointer<Tag> {
176177 Pointer { alloc_id, offset, tag }
177178 }
178179
179- pub fn wrapping_signed_offset ( self , i : i64 , cx : & impl HasDataLayout ) -> Self {
180- Pointer :: new_with_tag (
180+ #[ inline]
181+ pub fn offset ( self , i : Size , cx : & impl HasDataLayout ) -> EvalResult < ' tcx , Self > {
182+ Ok ( Pointer :: new_with_tag (
181183 self . alloc_id ,
182- Size :: from_bytes ( cx. data_layout ( ) . wrapping_signed_offset ( self . offset . bytes ( ) , i) ) ,
183- self . tag ,
184- )
184+ Size :: from_bytes ( cx. data_layout ( ) . offset ( self . offset . bytes ( ) , i. bytes ( ) ) ? ) ,
185+ self . tag
186+ ) )
185187 }
186188
187- pub fn overflowing_signed_offset ( self , i : i128 , cx : & impl HasDataLayout ) -> ( Self , bool ) {
188- let ( res, over) = cx. data_layout ( ) . overflowing_signed_offset ( self . offset . bytes ( ) , i) ;
189+ #[ inline]
190+ pub fn overflowing_offset ( self , i : Size , cx : & impl HasDataLayout ) -> ( Self , bool ) {
191+ let ( res, over) = cx. data_layout ( ) . overflowing_offset ( self . offset . bytes ( ) , i. bytes ( ) ) ;
189192 ( Pointer :: new_with_tag ( self . alloc_id , Size :: from_bytes ( res) , self . tag ) , over)
190193 }
191194
195+ #[ inline( always) ]
196+ pub fn wrapping_offset ( self , i : Size , cx : & impl HasDataLayout ) -> Self {
197+ self . overflowing_offset ( i, cx) . 0
198+ }
199+
200+ #[ inline]
192201 pub fn signed_offset ( self , i : i64 , cx : & impl HasDataLayout ) -> EvalResult < ' tcx , Self > {
193202 Ok ( Pointer :: new_with_tag (
194203 self . alloc_id ,
@@ -197,20 +206,18 @@ impl<'tcx, Tag> Pointer<Tag> {
197206 ) )
198207 }
199208
200- pub fn overflowing_offset ( self , i : Size , cx : & impl HasDataLayout ) -> ( Self , bool ) {
201- let ( res, over) = cx. data_layout ( ) . overflowing_offset ( self . offset . bytes ( ) , i. bytes ( ) ) ;
209+ #[ inline]
210+ pub fn overflowing_signed_offset ( self , i : i128 , cx : & impl HasDataLayout ) -> ( Self , bool ) {
211+ let ( res, over) = cx. data_layout ( ) . overflowing_signed_offset ( self . offset . bytes ( ) , i) ;
202212 ( Pointer :: new_with_tag ( self . alloc_id , Size :: from_bytes ( res) , self . tag ) , over)
203213 }
204214
205- pub fn offset ( self , i : Size , cx : & impl HasDataLayout ) -> EvalResult < ' tcx , Self > {
206- Ok ( Pointer :: new_with_tag (
207- self . alloc_id ,
208- Size :: from_bytes ( cx. data_layout ( ) . offset ( self . offset . bytes ( ) , i. bytes ( ) ) ?) ,
209- self . tag
210- ) )
215+ #[ inline( always) ]
216+ pub fn wrapping_signed_offset ( self , i : i64 , cx : & impl HasDataLayout ) -> Self {
217+ self . overflowing_signed_offset ( i128:: from ( i) , cx) . 0
211218 }
212219
213- #[ inline]
220+ #[ inline( always ) ]
214221 pub fn erase_tag ( self ) -> Pointer {
215222 Pointer { alloc_id : self . alloc_id , offset : self . offset , tag : ( ) }
216223 }
0 commit comments