@@ -56,8 +56,8 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
56
56
57
57
trace ! ( "ptr_op: {:?} {:?} {:?}" , * left, bin_op, * right) ;
58
58
59
- // If intptrcast is enabled, treat everything of integer *type* at integer *value*.
60
- if self . memory ( ) . extra . rng . is_some ( ) && left. layout . ty . is_integral ( ) {
59
+ // Treat everything of integer *type* at integer *value*.
60
+ if left. layout . ty . is_integral ( ) {
61
61
// This is actually an integer operation, so dispatch back to the core engine.
62
62
// TODO: Once intptrcast is the default, librustc_mir should never even call us
63
63
// for integer types.
@@ -188,104 +188,11 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
188
188
right : Scalar < Tag > ,
189
189
) -> InterpResult < ' tcx , bool > {
190
190
let size = self . pointer_size ( ) ;
191
- if self . memory ( ) . extra . rng . is_some ( ) {
192
- // Just compare the integers.
193
- // TODO: Do we really want to *always* do that, even when comparing two live in-bounds pointers?
194
- let left = self . force_bits ( left, size) ?;
195
- let right = self . force_bits ( right, size) ?;
196
- return Ok ( left == right) ;
197
- }
198
- Ok ( match ( left, right) {
199
- ( Scalar :: Raw { .. } , Scalar :: Raw { .. } ) =>
200
- left. to_bits ( size) ? == right. to_bits ( size) ?,
201
- ( Scalar :: Ptr ( left) , Scalar :: Ptr ( right) ) => {
202
- // Comparison illegal if one of them is out-of-bounds, *unless* they
203
- // are in the same allocation.
204
- if left. alloc_id == right. alloc_id {
205
- left. offset == right. offset
206
- } else {
207
- // Make sure both pointers are in-bounds.
208
- // This accepts one-past-the end. Thus, there is still technically
209
- // some non-determinism that we do not fully rule out when two
210
- // allocations sit right next to each other. The C/C++ standards are
211
- // somewhat fuzzy about this case, so pragmatically speaking I think
212
- // for now this check is "good enough".
213
- // FIXME: Once we support intptrcast, we could try to fix these holes.
214
- // Dead allocations in miri cannot overlap with live allocations, but
215
- // on read hardware this can easily happen. Thus for comparisons we require
216
- // both pointers to be live.
217
- if self . pointer_inbounds ( left) . is_ok ( ) && self . pointer_inbounds ( right) . is_ok ( ) {
218
- // Two in-bounds (and hence live) pointers in different allocations are different.
219
- false
220
- } else {
221
- return err ! ( InvalidPointerMath ) ;
222
- }
223
- }
224
- }
225
- // Comparing ptr and integer.
226
- ( Scalar :: Ptr ( ptr) , Scalar :: Raw { data, size } ) |
227
- ( Scalar :: Raw { data, size } , Scalar :: Ptr ( ptr) ) => {
228
- assert_eq ! ( size as u64 , self . pointer_size( ) . bytes( ) ) ;
229
- let bits = data as u64 ;
230
-
231
- // Case I: Comparing real pointers with "small" integers.
232
- // Really we should only do this for NULL, but pragmatically speaking on non-bare-metal systems,
233
- // an allocation will never be at the very bottom of the address space.
234
- // Such comparisons can arise when comparing empty slices, which sometimes are "fake"
235
- // integer pointers (okay because the slice is empty) and sometimes point into a
236
- // real allocation.
237
- // The most common source of such integer pointers is `NonNull::dangling()`, which
238
- // equals the type's alignment. i128 might have an alignment of 16 bytes, but few types have
239
- // alignment 32 or higher, hence the limit of 32.
240
- // FIXME: Once we support intptrcast, we could try to fix these holes.
241
- if bits < 32 {
242
- // Test if the pointer can be different from NULL or not.
243
- // We assume that pointers that are not NULL are also not "small".
244
- if !self . memory ( ) . ptr_may_be_null ( ptr) {
245
- return Ok ( false ) ;
246
- }
247
- }
248
-
249
- let ( alloc_size, alloc_align) = self . memory ( )
250
- . get_size_and_align ( ptr. alloc_id , AllocCheck :: MaybeDead )
251
- . expect ( "alloc info with MaybeDead cannot fail" ) ;
252
-
253
- // Case II: Alignment gives it away
254
- if ptr. offset . bytes ( ) % alloc_align. bytes ( ) == 0 {
255
- // The offset maintains the allocation alignment, so we know `base+offset`
256
- // is aligned by `alloc_align`.
257
- // FIXME: We could be even more general, e.g., offset 2 into a 4-aligned
258
- // allocation cannot equal 3.
259
- if bits % alloc_align. bytes ( ) != 0 {
260
- // The integer is *not* aligned. So they cannot be equal.
261
- return Ok ( false ) ;
262
- }
263
- }
264
- // Case III: The integer is too big, and the allocation goes on a bit
265
- // without wrapping around the address space.
266
- {
267
- // Compute the highest address at which this allocation could live.
268
- // Substract one more, because it must be possible to add the size
269
- // to the base address without overflowing; that is, the very last address
270
- // of the address space is never dereferencable (but it can be in-bounds, i.e.,
271
- // one-past-the-end).
272
- let max_base_addr =
273
- ( ( 1u128 << self . pointer_size ( ) . bits ( ) )
274
- - u128:: from ( alloc_size. bytes ( ) )
275
- - 1
276
- ) as u64 ;
277
- if let Some ( max_addr) = max_base_addr. checked_add ( ptr. offset . bytes ( ) ) {
278
- if bits > max_addr {
279
- // The integer is too big, this cannot possibly be equal.
280
- return Ok ( false )
281
- }
282
- }
283
- }
284
-
285
- // None of the supported cases.
286
- return err ! ( InvalidPointerMath ) ;
287
- }
288
- } )
191
+ // Just compare the integers.
192
+ // TODO: Do we really want to *always* do that, even when comparing two live in-bounds pointers?
193
+ let left = self . force_bits ( left, size) ?;
194
+ let right = self . force_bits ( right, size) ?;
195
+ Ok ( left == right)
289
196
}
290
197
291
198
fn ptr_int_arithmetic (
0 commit comments