@@ -5,8 +5,8 @@ use super::typ::{self, pointee_type};
5
5
use super :: PropertyClass ;
6
6
use crate :: codegen_cprover_gotoc:: GotocCtx ;
7
7
use 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 ,
10
10
} ;
11
11
use rustc_middle:: mir:: { BasicBlock , Operand , Place } ;
12
12
use rustc_middle:: ty:: layout:: LayoutOf ;
@@ -172,38 +172,6 @@ impl<'tcx> GotocCtx<'tcx> {
172
172
} } ;
173
173
}
174
174
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
-
207
175
// Intrinsics which encode a simple arithmetic operation with overflow check
208
176
macro_rules! codegen_op_with_overflow_check {
209
177
( $f: ident) => { {
@@ -362,7 +330,9 @@ impl<'tcx> GotocCtx<'tcx> {
362
330
}
363
331
364
332
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
+ }
366
336
"arith_offset" => self . codegen_offset ( intrinsic, instance, fargs, p, loc) ,
367
337
"assert_inhabited" => self . codegen_assert_intrinsic ( instance, intrinsic, span) ,
368
338
"assert_mem_uninitialized_valid" => {
@@ -528,7 +498,9 @@ impl<'tcx> GotocCtx<'tcx> {
528
498
"min_align_of_val" => codegen_size_align ! ( align) ,
529
499
"minnumf32" => codegen_simple_intrinsic ! ( Fminf ) ,
530
500
"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
+ }
532
504
"nearbyintf32" => codegen_simple_intrinsic ! ( Nearbyintf ) ,
533
505
"nearbyintf64" => codegen_simple_intrinsic ! ( Nearbyint ) ,
534
506
"needs_drop" => codegen_intrinsic_const ! ( ) ,
@@ -615,7 +587,9 @@ impl<'tcx> GotocCtx<'tcx> {
615
587
"size_of_val" => codegen_size_align ! ( size) ,
616
588
"sqrtf32" => unstable_codegen ! ( codegen_simple_intrinsic!( Sqrtf ) ) ,
617
589
"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
+ }
619
593
"transmute" => self . codegen_intrinsic_transmute ( fargs, ret_ty, p) ,
620
594
"truncf32" => codegen_simple_intrinsic ! ( Truncf ) ,
621
595
"truncf64" => codegen_simple_intrinsic ! ( Trunc ) ,
@@ -719,6 +693,25 @@ impl<'tcx> GotocCtx<'tcx> {
719
693
dividend_is_int_min. and ( divisor_is_minus_one) . not ( )
720
694
}
721
695
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
+
722
715
fn codegen_exact_div ( & mut self , mut fargs : Vec < Expr > , p : & Place < ' tcx > , loc : Location ) -> Stmt {
723
716
// Check for undefined behavior conditions defined in
724
717
// https://doc.rust-lang.org/std/intrinsics/fn.exact_div.html
0 commit comments