1
1
// Copyright Kani Contributors
2
2
// SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
//! this module handles intrinsics
4
+ use super :: typ:: pointee_type;
4
5
use super :: PropertyClass ;
5
6
use crate :: codegen_cprover_gotoc:: GotocCtx ;
6
7
use cbmc:: goto_program:: { BuiltinFn , Expr , Location , Stmt , Type } ;
@@ -142,6 +143,7 @@ impl<'tcx> GotocCtx<'tcx> {
142
143
let sig = instance. ty ( self . tcx , ty:: ParamEnv :: reveal_all ( ) ) . fn_sig ( self . tcx ) ;
143
144
let sig = self . tcx . normalize_erasing_late_bound_regions ( ty:: ParamEnv :: reveal_all ( ) , sig) ;
144
145
let ret_ty = self . monomorphize ( sig. output ( ) ) ;
146
+ let farg_types = sig. inputs ( ) ;
145
147
let cbmc_ret_ty = self . codegen_ty ( ret_ty) ;
146
148
147
149
/// https://doc.rust-lang.org/core/intrinsics/fn.copy.html
@@ -681,14 +683,14 @@ impl<'tcx> GotocCtx<'tcx> {
681
683
}
682
684
"volatile_store" => {
683
685
assert ! ( self . place_ty( p) . is_unit( ) ) ;
684
- self . codegen_volatile_store ( instance , fargs , loc)
686
+ self . codegen_volatile_store ( fargs , farg_types , loc)
685
687
}
686
688
"wrapping_add" => codegen_wrapping_op ! ( plus) ,
687
689
"wrapping_mul" => codegen_wrapping_op ! ( mul) ,
688
690
"wrapping_sub" => codegen_wrapping_op ! ( sub) ,
689
691
"write_bytes" => {
690
692
assert ! ( self . place_ty( p) . is_unit( ) ) ;
691
- self . codegen_write_bytes ( instance , fargs , loc)
693
+ self . codegen_write_bytes ( fargs , farg_types , loc)
692
694
}
693
695
// Unimplemented
694
696
_ => codegen_unimplemented_intrinsic ! (
@@ -1233,14 +1235,14 @@ impl<'tcx> GotocCtx<'tcx> {
1233
1235
/// * `dst` must be properly aligned (done by `align_check` below)
1234
1236
fn codegen_volatile_store (
1235
1237
& mut self ,
1236
- instance : Instance < ' tcx > ,
1237
1238
mut fargs : Vec < Expr > ,
1239
+ farg_types : & [ Ty < ' tcx > ] ,
1238
1240
loc : Location ,
1239
1241
) -> Stmt {
1240
1242
let dst = fargs. remove ( 0 ) ;
1241
1243
let src = fargs. remove ( 0 ) ;
1242
- let typ = instance . substs . type_at ( 0 ) ;
1243
- let align = self . is_aligned ( typ , dst. clone ( ) ) ;
1244
+ let dst_typ = farg_types [ 0 ] ;
1245
+ let align = self . is_ptr_aligned ( dst_typ , dst. clone ( ) ) ;
1244
1246
let align_check = self . codegen_assert (
1245
1247
align,
1246
1248
PropertyClass :: DefaultAssertion ,
@@ -1261,17 +1263,17 @@ impl<'tcx> GotocCtx<'tcx> {
1261
1263
/// for the `memset` call) would not overflow
1262
1264
fn codegen_write_bytes (
1263
1265
& mut self ,
1264
- instance : Instance < ' tcx > ,
1265
1266
mut fargs : Vec < Expr > ,
1267
+ farg_types : & [ Ty < ' tcx > ] ,
1266
1268
loc : Location ,
1267
1269
) -> Stmt {
1268
1270
let dst = fargs. remove ( 0 ) . cast_to ( Type :: void_pointer ( ) ) ;
1269
1271
let val = fargs. remove ( 0 ) . cast_to ( Type :: c_int ( ) ) ;
1270
1272
let count = fargs. remove ( 0 ) ;
1271
1273
1272
1274
// Check that `dst` is properly aligned
1273
- let ty = self . monomorphize ( instance . substs . type_at ( 0 ) ) ;
1274
- let align = self . is_aligned ( ty , dst. clone ( ) ) ;
1275
+ let dst_typ = farg_types [ 0 ] ;
1276
+ let align = self . is_ptr_aligned ( dst_typ , dst. clone ( ) ) ;
1275
1277
let align_check = self . codegen_assert (
1276
1278
align,
1277
1279
PropertyClass :: DefaultAssertion ,
@@ -1280,8 +1282,13 @@ impl<'tcx> GotocCtx<'tcx> {
1280
1282
) ;
1281
1283
1282
1284
// Check that computing `count` in bytes would not overflow
1283
- let ( count_bytes, overflow_check) =
1284
- self . count_in_bytes ( count, ty, Type :: size_t ( ) , "write_bytes" , loc) ;
1285
+ let ( count_bytes, overflow_check) = self . count_in_bytes (
1286
+ count,
1287
+ pointee_type ( dst_typ) . unwrap ( ) ,
1288
+ Type :: size_t ( ) ,
1289
+ "write_bytes" ,
1290
+ loc,
1291
+ ) ;
1285
1292
1286
1293
let memset_call = BuiltinFn :: Memset . call ( vec ! [ dst, val, count_bytes] , loc) ;
1287
1294
Stmt :: block ( vec ! [ align_check, overflow_check, memset_call. as_stmt( loc) ] , loc)
0 commit comments