@@ -5,8 +5,8 @@ use super::typ::{self, pointee_type};
55use super :: PropertyClass ;
66use crate :: codegen_cprover_gotoc:: GotocCtx ;
77use cbmc:: goto_program:: {
8- arithmetic_overflow_result_type, ArithmeticOverflowResult , BuiltinFn , Expr , Location , Stmt ,
9- Type , ARITH_OVERFLOW_OVERFLOWED_FIELD , ARITH_OVERFLOW_RESULT_FIELD ,
8+ arithmetic_overflow_result_type, ArithmeticOverflowResult , BinaryOperator , BuiltinFn , Expr ,
9+ Location , Stmt , Type , ARITH_OVERFLOW_OVERFLOWED_FIELD , ARITH_OVERFLOW_RESULT_FIELD ,
1010} ;
1111use rustc_middle:: mir:: { BasicBlock , Operand , Place } ;
1212use rustc_middle:: ty:: layout:: LayoutOf ;
@@ -172,38 +172,6 @@ impl<'tcx> GotocCtx<'tcx> {
172172 } } ;
173173 }
174174
175- // Intrinsics of the form *_with_overflow
176- macro_rules! codegen_op_with_overflow {
177- ( $f: ident) => { {
178- let pt = self . place_ty( p) ;
179- let t = self . codegen_ty( pt) ;
180- let a = fargs. remove( 0 ) ;
181- let b = fargs. remove( 0 ) ;
182- let op_type = a. typ( ) . clone( ) ;
183- let res = a. $f( b) ;
184- // add to symbol table
185- let struct_tag = self . codegen_arithmetic_overflow_result_type( op_type. clone( ) ) ;
186- assert_eq!( * res. typ( ) , struct_tag) ;
187-
188- // store the result in a temporary variable
189- let ( var, decl) = self . decl_temp_variable( struct_tag, Some ( res) , loc) ;
190- // cast into result type
191- let e = Expr :: struct_expr_from_values(
192- t. clone( ) ,
193- vec![
194- var. clone( ) . member( ARITH_OVERFLOW_RESULT_FIELD , & self . symbol_table) ,
195- var. member( ARITH_OVERFLOW_OVERFLOWED_FIELD , & self . symbol_table)
196- . cast_to( Type :: c_bool( ) ) ,
197- ] ,
198- & self . symbol_table,
199- ) ;
200- self . codegen_expr_to_place(
201- p,
202- Expr :: statement_expression( vec![ decl, e. as_stmt( loc) ] , t) ,
203- )
204- } } ;
205- }
206-
207175 // Intrinsics which encode a simple arithmetic operation with overflow check
208176 macro_rules! codegen_op_with_overflow_check {
209177 ( $f: ident) => { {
@@ -362,7 +330,9 @@ impl<'tcx> GotocCtx<'tcx> {
362330 }
363331
364332 match intrinsic {
365- "add_with_overflow" => codegen_op_with_overflow ! ( add_overflow_result) ,
333+ "add_with_overflow" => {
334+ self . codegen_op_with_overflow ( BinaryOperator :: OverflowResultPlus , fargs, p, loc)
335+ }
366336 "arith_offset" => self . codegen_offset ( intrinsic, instance, fargs, p, loc) ,
367337 "assert_inhabited" => self . codegen_assert_intrinsic ( instance, intrinsic, span) ,
368338 "assert_mem_uninitialized_valid" => {
@@ -528,7 +498,9 @@ impl<'tcx> GotocCtx<'tcx> {
528498 "min_align_of_val" => codegen_size_align ! ( align) ,
529499 "minnumf32" => codegen_simple_intrinsic ! ( Fminf ) ,
530500 "minnumf64" => codegen_simple_intrinsic ! ( Fmin ) ,
531- "mul_with_overflow" => codegen_op_with_overflow ! ( mul_overflow_result) ,
501+ "mul_with_overflow" => {
502+ self . codegen_op_with_overflow ( BinaryOperator :: OverflowResultMult , fargs, p, loc)
503+ }
532504 "nearbyintf32" => codegen_simple_intrinsic ! ( Nearbyintf ) ,
533505 "nearbyintf64" => codegen_simple_intrinsic ! ( Nearbyint ) ,
534506 "needs_drop" => codegen_intrinsic_const ! ( ) ,
@@ -615,7 +587,9 @@ impl<'tcx> GotocCtx<'tcx> {
615587 "size_of_val" => codegen_size_align ! ( size) ,
616588 "sqrtf32" => unstable_codegen ! ( codegen_simple_intrinsic!( Sqrtf ) ) ,
617589 "sqrtf64" => unstable_codegen ! ( codegen_simple_intrinsic!( Sqrt ) ) ,
618- "sub_with_overflow" => codegen_op_with_overflow ! ( sub_overflow_result) ,
590+ "sub_with_overflow" => {
591+ self . codegen_op_with_overflow ( BinaryOperator :: OverflowResultMinus , fargs, p, loc)
592+ }
619593 "transmute" => self . codegen_intrinsic_transmute ( fargs, ret_ty, p) ,
620594 "truncf32" => codegen_simple_intrinsic ! ( Truncf ) ,
621595 "truncf64" => codegen_simple_intrinsic ! ( Trunc ) ,
@@ -719,6 +693,25 @@ impl<'tcx> GotocCtx<'tcx> {
719693 dividend_is_int_min. and ( divisor_is_minus_one) . not ( )
720694 }
721695
696+ /// Intrinsics of the form *_with_overflow
697+ fn codegen_op_with_overflow (
698+ & mut self ,
699+ binop : BinaryOperator ,
700+ mut fargs : Vec < Expr > ,
701+ place : & Place < ' tcx > ,
702+ loc : Location ,
703+ ) -> Stmt {
704+ let place_ty = self . place_ty ( place) ;
705+ let result_type = self . codegen_ty ( place_ty) ;
706+ let left = fargs. remove ( 0 ) ;
707+ let right = fargs. remove ( 0 ) ;
708+ let res = self . codegen_binop_with_overflow ( binop, left, right, result_type. clone ( ) , loc) ;
709+ self . codegen_expr_to_place (
710+ place,
711+ Expr :: statement_expression ( vec ! [ res. as_stmt( loc) ] , result_type) ,
712+ )
713+ }
714+
722715 fn codegen_exact_div ( & mut self , mut fargs : Vec < Expr > , p : & Place < ' tcx > , loc : Location ) -> Stmt {
723716 // Check for undefined behavior conditions defined in
724717 // https://doc.rust-lang.org/std/intrinsics/fn.exact_div.html
0 commit comments