@@ -20,6 +20,7 @@ use num::bigint::BigInt;
2020use  rustc_middle:: ty:: { TyCtxt ,  VtblEntry } ; 
2121use  rustc_smir:: rustc_internal; 
2222use  rustc_target:: abi:: { FieldsShape ,  TagEncoding ,  Variants } ; 
23+ use  stable_mir:: abi:: { Primitive ,  Scalar ,  ValueAbi } ; 
2324use  stable_mir:: mir:: mono:: Instance ; 
2425use  stable_mir:: mir:: { 
2526    AggregateKind ,  BinOp ,  CastKind ,  NullOp ,  Operand ,  Place ,  PointerCoercion ,  Rvalue ,  UnOp , 
@@ -32,9 +33,11 @@ impl<'tcx> GotocCtx<'tcx> {
3233    fn  codegen_comparison ( & mut  self ,  op :  & BinOp ,  e1 :  & Operand ,  e2 :  & Operand )  -> Expr  { 
3334        let  left_op = self . codegen_operand_stable ( e1) ; 
3435        let  right_op = self . codegen_operand_stable ( e2) ; 
35-         let  is_float =
36-             matches ! ( self . operand_ty_stable( e1) . kind( ) ,  TyKind :: RigidTy ( RigidTy :: Float ( ..) ) ) ; 
37-         comparison_expr ( op,  left_op,  right_op,  is_float) 
36+         let  left_ty = self . operand_ty_stable ( e1) ; 
37+         let  right_ty = self . operand_ty_stable ( e2) ; 
38+         let  res_ty = op. ty ( left_ty,  right_ty) ; 
39+         let  is_float = matches ! ( left_ty. kind( ) ,  TyKind :: RigidTy ( RigidTy :: Float ( ..) ) ) ; 
40+         self . comparison_expr ( op,  left_op,  right_op,  res_ty,  is_float) 
3841    } 
3942
4043    /// This function codegen comparison for fat pointers. 
@@ -72,16 +75,18 @@ impl<'tcx> GotocCtx<'tcx> {
7275            Expr :: statement_expression ( body,  ret_type) . with_location ( loc) 
7376        }  else  { 
7477            // Compare data pointer. 
78+             let  res_ty = op. ty ( left_typ,  right_typ) ; 
7579            let  left_ptr = self . codegen_operand_stable ( left_op) ; 
7680            let  left_data = left_ptr. clone ( ) . member ( "data" ,  & self . symbol_table ) ; 
7781            let  right_ptr = self . codegen_operand_stable ( right_op) ; 
7882            let  right_data = right_ptr. clone ( ) . member ( "data" ,  & self . symbol_table ) ; 
79-             let  data_cmp = comparison_expr ( op,  left_data. clone ( ) ,  right_data. clone ( ) ,  false ) ; 
83+             let  data_cmp =
84+                 self . comparison_expr ( op,  left_data. clone ( ) ,  right_data. clone ( ) ,  res_ty,  false ) ; 
8085
8186            // Compare the slice metadata (this logic could be adapted to compare vtable if needed). 
8287            let  left_len = left_ptr. member ( "len" ,  & self . symbol_table ) ; 
8388            let  right_len = right_ptr. member ( "len" ,  & self . symbol_table ) ; 
84-             let  metadata_cmp = comparison_expr ( op,  left_len,  right_len,  false ) ; 
89+             let  metadata_cmp = self . comparison_expr ( op,  left_len,  right_len,  res_ty ,  false ) ; 
8590
8691            // Join the results. 
8792            // https://github.com/rust-lang/rust/pull/29781 
@@ -93,10 +98,20 @@ impl<'tcx> GotocCtx<'tcx> {
9398                // If data is different, only compare data. 
9499                // If data is equal, apply operator to metadata. 
95100                BinOp :: Lt  | BinOp :: Le  | BinOp :: Ge  | BinOp :: Gt  => { 
96-                     let  data_eq =
97-                         comparison_expr ( & BinOp :: Eq ,  left_data. clone ( ) ,  right_data. clone ( ) ,  false ) ; 
98-                     let  data_strict_comp =
99-                         comparison_expr ( & get_strict_operator ( op) ,  left_data,  right_data,  false ) ; 
101+                     let  data_eq = self . comparison_expr ( 
102+                         & BinOp :: Eq , 
103+                         left_data. clone ( ) , 
104+                         right_data. clone ( ) , 
105+                         res_ty, 
106+                         false , 
107+                     ) ; 
108+                     let  data_strict_comp = self . comparison_expr ( 
109+                         & get_strict_operator ( op) , 
110+                         left_data, 
111+                         right_data, 
112+                         res_ty, 
113+                         false , 
114+                     ) ; 
100115                    data_strict_comp. or ( data_eq. and ( metadata_cmp) ) 
101116                } 
102117                _ => unreachable ! ( "Unexpected operator {:?}" ,  op) , 
@@ -376,7 +391,7 @@ impl<'tcx> GotocCtx<'tcx> {
376391            BinOp :: BitXor  | BinOp :: BitAnd  | BinOp :: BitOr  => { 
377392                self . codegen_unchecked_scalar_binop ( op,  e1,  e2) 
378393            } 
379-             BinOp :: Eq  | BinOp :: Lt  | BinOp :: Le  | BinOp :: Ne  | BinOp :: Ge  | BinOp :: Gt  => { 
394+             BinOp :: Eq  | BinOp :: Lt  | BinOp :: Le  | BinOp :: Ne  | BinOp :: Ge  | BinOp :: Gt  |  BinOp :: Cmp   => { 
380395                let  op_ty = self . operand_ty_stable ( e1) ; 
381396                if  self . is_fat_pointer_stable ( op_ty)  { 
382397                    self . codegen_comparison_fat_ptr ( op,  e1,  e2,  loc) 
@@ -681,7 +696,7 @@ impl<'tcx> GotocCtx<'tcx> {
681696                | CastKind :: FnPtrToPtr 
682697                | CastKind :: PtrToPtr 
683698                | CastKind :: PointerExposeAddress 
684-                 | CastKind :: PointerFromExposedAddress , 
699+                 | CastKind :: PointerWithExposedProvenance , 
685700                e, 
686701                t, 
687702            )  => self . codegen_misc_cast ( e,  * t) , 
@@ -1260,7 +1275,7 @@ impl<'tcx> GotocCtx<'tcx> {
12601275    fn  check_vtable_size ( & mut  self ,  operand_type :  Ty ,  vt_size :  Expr )  -> Stmt  { 
12611276        // Check against the size we get from the layout from the what we 
12621277        // get constructing a value of that type 
1263-         let  ty:   Type  = self . codegen_ty_stable ( operand_type) ; 
1278+         let  ty = self . codegen_ty_stable ( operand_type) ; 
12641279        let  codegen_size = ty. sizeof ( & self . symbol_table ) ; 
12651280        assert_eq ! ( vt_size. int_constant_value( ) . unwrap( ) ,  BigInt :: from( codegen_size) ) ; 
12661281
@@ -1423,6 +1438,65 @@ impl<'tcx> GotocCtx<'tcx> {
14231438            } 
14241439        } 
14251440    } 
1441+ 
1442+     fn  comparison_expr ( 
1443+         & mut  self , 
1444+         op :  & BinOp , 
1445+         left :  Expr , 
1446+         right :  Expr , 
1447+         res_ty :  Ty , 
1448+         is_float :  bool , 
1449+     )  -> Expr  { 
1450+         match  op { 
1451+             BinOp :: Eq  => { 
1452+                 if  is_float { 
1453+                     left. feq ( right) 
1454+                 }  else  { 
1455+                     left. eq ( right) 
1456+                 } 
1457+             } 
1458+             BinOp :: Lt  => left. lt ( right) , 
1459+             BinOp :: Le  => left. le ( right) , 
1460+             BinOp :: Ne  => { 
1461+                 if  is_float { 
1462+                     left. fneq ( right) 
1463+                 }  else  { 
1464+                     left. neq ( right) 
1465+                 } 
1466+             } 
1467+             BinOp :: Ge  => left. ge ( right) , 
1468+             BinOp :: Gt  => left. gt ( right) , 
1469+             BinOp :: Cmp  => { 
1470+                 // Implement https://doc.rust-lang.org/core/cmp/trait.Ord.html as done in cranelift, 
1471+                 // i.e., (left > right) - (left < right) 
1472+                 // Return value is the Ordering enumeration: 
1473+                 // ``` 
1474+                 // #[repr(i8)] 
1475+                 // pub enum Ordering { 
1476+                 //     Less = -1, 
1477+                 //     Equal = 0, 
1478+                 //     Greater = 1, 
1479+                 // } 
1480+                 // ``` 
1481+                 let  res_typ = self . codegen_ty_stable ( res_ty) ; 
1482+                 let  ValueAbi :: Scalar ( Scalar :: Initialized  {  value,  valid_range } )  =
1483+                     res_ty. layout ( ) . unwrap ( ) . shape ( ) . abi 
1484+                 else  { 
1485+                     unreachable ! ( "Unexpected layout" ) 
1486+                 } ; 
1487+                 assert_eq ! ( valid_range. start,  -1i8  as  u8  as  u128 ) ; 
1488+                 assert_eq ! ( valid_range. end,  1 ) ; 
1489+                 let  Primitive :: Int  {  length,  signed :  true  }  = value else  {  unreachable ! ( )  } ; 
1490+                 let  scalar_typ = Type :: signed_int ( length. bits ( ) ) ; 
1491+                 left. clone ( ) 
1492+                     . gt ( right. clone ( ) ) 
1493+                     . cast_to ( scalar_typ. clone ( ) ) 
1494+                     . sub ( left. lt ( right) . cast_to ( scalar_typ) ) 
1495+                     . transmute_to ( res_typ,  & self . symbol_table ) 
1496+             } 
1497+             _ => unreachable ! ( ) , 
1498+         } 
1499+     } 
14261500} 
14271501
14281502/// Perform a wrapping subtraction of an Expr with a constant "expr - constant" 
@@ -1445,30 +1519,6 @@ fn wrapping_sub(expr: &Expr, constant: u64) -> Expr {
14451519    } 
14461520} 
14471521
1448- fn  comparison_expr ( op :  & BinOp ,  left :  Expr ,  right :  Expr ,  is_float :  bool )  -> Expr  { 
1449-     match  op { 
1450-         BinOp :: Eq  => { 
1451-             if  is_float { 
1452-                 left. feq ( right) 
1453-             }  else  { 
1454-                 left. eq ( right) 
1455-             } 
1456-         } 
1457-         BinOp :: Lt  => left. lt ( right) , 
1458-         BinOp :: Le  => left. le ( right) , 
1459-         BinOp :: Ne  => { 
1460-             if  is_float { 
1461-                 left. fneq ( right) 
1462-             }  else  { 
1463-                 left. neq ( right) 
1464-             } 
1465-         } 
1466-         BinOp :: Ge  => left. ge ( right) , 
1467-         BinOp :: Gt  => left. gt ( right) , 
1468-         _ => unreachable ! ( ) , 
1469-     } 
1470- } 
1471- 
14721522/// Remove the equality from an operator. Translates `<=` to `<` and `>=` to `>` 
14731523fn  get_strict_operator ( op :  & BinOp )  -> BinOp  { 
14741524    match  op { 
0 commit comments