11use log:: trace;
22
33use rustc_middle:: { mir, ty:: Ty } ;
4+ use rustc_target:: abi:: Size ;
45
56use crate :: * ;
67
@@ -11,8 +12,6 @@ pub trait EvalContextExt<'tcx> {
1112 left : & ImmTy < ' tcx , Tag > ,
1213 right : & ImmTy < ' tcx , Tag > ,
1314 ) -> InterpResult < ' tcx , ( Scalar < Tag > , bool , Ty < ' tcx > ) > ;
14-
15- fn ptr_eq ( & self , left : Scalar < Tag > , right : Scalar < Tag > ) -> InterpResult < ' tcx , bool > ;
1615}
1716
1817impl < ' mir , ' tcx > EvalContextExt < ' tcx > for super :: MiriEvalContext < ' mir , ' tcx > {
@@ -27,23 +26,8 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
2726 trace ! ( "ptr_op: {:?} {:?} {:?}" , * left, bin_op, * right) ;
2827
2928 Ok ( match bin_op {
30- Eq | Ne => {
31- // This supports fat pointers.
32- #[ rustfmt:: skip]
33- let eq = match ( * * left, * * right) {
34- ( Immediate :: Scalar ( left) , Immediate :: Scalar ( right) ) => {
35- self . ptr_eq ( left. check_init ( ) ?, right. check_init ( ) ?) ?
36- }
37- ( Immediate :: ScalarPair ( left1, left2) , Immediate :: ScalarPair ( right1, right2) ) => {
38- self . ptr_eq ( left1. check_init ( ) ?, right1. check_init ( ) ?) ?
39- && self . ptr_eq ( left2. check_init ( ) ?, right2. check_init ( ) ?) ?
40- }
41- _ => bug ! ( "Type system should not allow comparing Scalar with ScalarPair" ) ,
42- } ;
43- ( Scalar :: from_bool ( if bin_op == Eq { eq } else { !eq } ) , false , self . tcx . types . bool )
44- }
45-
46- Lt | Le | Gt | Ge => {
29+ Eq | Ne | Lt | Le | Gt | Ge => {
30+ assert_eq ! ( left. layout. abi, right. layout. abi) ; // types an differ, e.g. fn ptrs with different `for`
4731 let size = self . pointer_size ( ) ;
4832 // Just compare the bits. ScalarPairs are compared lexicographically.
4933 // We thus always compare pairs and simply fill scalars up with 0.
@@ -58,35 +42,49 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
5842 ( r1. check_init ( ) ?. to_bits ( size) ?, r2. check_init ( ) ?. to_bits ( size) ?) ,
5943 } ;
6044 let res = match bin_op {
45+ Eq => left == right,
46+ Ne => left != right,
6147 Lt => left < right,
6248 Le => left <= right,
6349 Gt => left > right,
6450 Ge => left >= right,
65- _ => bug ! ( "We already established it has to be one of these operators." ) ,
51+ _ => bug ! ( ) ,
6652 } ;
6753 ( Scalar :: from_bool ( res) , false , self . tcx . types . bool )
6854 }
6955
7056 Offset => {
57+ assert ! ( left. layout. ty. is_unsafe_ptr( ) ) ;
58+ let ptr = self . scalar_to_ptr ( left. to_scalar ( ) ?) ?;
59+ let offset = right. to_scalar ( ) ?. to_machine_isize ( self ) ?;
60+
7161 let pointee_ty =
7262 left. layout . ty . builtin_deref ( true ) . expect ( "Offset called on non-ptr type" ) . ty ;
73- let ptr = self . ptr_offset_inbounds (
74- self . scalar_to_ptr ( left. to_scalar ( ) ?) ?,
75- pointee_ty,
76- right. to_scalar ( ) ?. to_machine_isize ( self ) ?,
77- ) ?;
63+ let ptr = self . ptr_offset_inbounds ( ptr, pointee_ty, offset) ?;
7864 ( Scalar :: from_maybe_pointer ( ptr, self ) , false , left. layout . ty )
7965 }
8066
81- _ => bug ! ( "Invalid operator on pointers: {:?}" , bin_op) ,
82- } )
83- }
67+ // Some more operations are possible with atomics.
68+ // The return value always has the provenance of the *left* operand.
69+ Add | Sub | BitOr | BitAnd | BitXor => {
70+ assert ! ( left. layout. ty. is_unsafe_ptr( ) ) ;
71+ assert ! ( right. layout. ty. is_unsafe_ptr( ) ) ;
72+ let ptr = self . scalar_to_ptr ( left. to_scalar ( ) ?) ?;
73+ // We do the actual operation with usize-typed scalars.
74+ let left = ImmTy :: from_uint ( ptr. addr ( ) . bytes ( ) , self . machine . layouts . usize ) ;
75+ let right = ImmTy :: from_uint (
76+ right. to_scalar ( ) ?. to_machine_usize ( self ) ?,
77+ self . machine . layouts . usize ,
78+ ) ;
79+ let ( result, overflowing, _ty) =
80+ self . overflowing_binary_op ( bin_op, & left, & right) ?;
81+ // Construct a new pointer with the provenance of `ptr` (the LHS).
82+ let result_ptr =
83+ Pointer :: new ( ptr. provenance , Size :: from_bytes ( result. to_machine_usize ( self ) ?) ) ;
84+ ( Scalar :: from_maybe_pointer ( result_ptr, self ) , overflowing, left. layout . ty )
85+ }
8486
85- fn ptr_eq ( & self , left : Scalar < Tag > , right : Scalar < Tag > ) -> InterpResult < ' tcx , bool > {
86- let size = self . pointer_size ( ) ;
87- // Just compare the integers.
88- let left = left. to_bits ( size) ?;
89- let right = right. to_bits ( size) ?;
90- Ok ( left == right)
87+ _ => span_bug ! ( self . cur_span( ) , "Invalid operator on pointers: {:?}" , bin_op) ,
88+ } )
9189 }
9290}
0 commit comments