@@ -91,42 +91,43 @@ pub trait PointerArithmetic: layout::HasDataLayout {
91
91
}
92
92
93
93
//// Trunace the given value to the pointer size; also return whether there was an overflow
94
+ #[ inline]
94
95
fn truncate_to_ptr ( & self , val : u128 ) -> ( u64 , bool ) {
95
96
let max_ptr_plus_1 = 1u128 << self . pointer_size ( ) . bits ( ) ;
96
97
( ( val % max_ptr_plus_1) as u64 , val >= max_ptr_plus_1)
97
98
}
98
99
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) }
110
104
}
111
105
106
+ #[ inline]
112
107
fn overflowing_offset ( & self , val : u64 , i : u64 ) -> ( u64 , bool ) {
113
108
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 ) ) ;
115
110
( res, over1 || over2)
116
111
}
117
112
113
+ #[ inline]
118
114
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 ) ) ;
120
116
if over { err ! ( Overflow ( mir:: BinOp :: Add ) ) } else { Ok ( res) }
121
117
}
122
118
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
+ }
130
131
}
131
132
}
132
133
@@ -176,19 +177,27 @@ impl<'tcx, Tag> Pointer<Tag> {
176
177
Pointer { alloc_id, offset, tag }
177
178
}
178
179
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 (
181
183
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
+ ) )
185
187
}
186
188
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 ( ) ) ;
189
192
( Pointer :: new_with_tag ( self . alloc_id , Size :: from_bytes ( res) , self . tag ) , over)
190
193
}
191
194
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]
192
201
pub fn signed_offset ( self , i : i64 , cx : & impl HasDataLayout ) -> EvalResult < ' tcx , Self > {
193
202
Ok ( Pointer :: new_with_tag (
194
203
self . alloc_id ,
@@ -197,20 +206,18 @@ impl<'tcx, Tag> Pointer<Tag> {
197
206
) )
198
207
}
199
208
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) ;
202
212
( Pointer :: new_with_tag ( self . alloc_id , Size :: from_bytes ( res) , self . tag ) , over)
203
213
}
204
214
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
211
218
}
212
219
213
- #[ inline]
220
+ #[ inline( always ) ]
214
221
pub fn erase_tag ( self ) -> Pointer {
215
222
Pointer { alloc_id : self . alloc_id , offset : self . offset , tag : ( ) }
216
223
}
0 commit comments