Skip to content

Commit 2aef548

Browse files
authored
Correct types for alignment expressions (rust-lang#1196)
* Correct types for alignment expressions * Rename `dst` to `ptr`
1 parent fa42232 commit 2aef548

File tree

2 files changed

+29
-16
lines changed

2 files changed

+29
-16
lines changed

kani-compiler/src/codegen_cprover_gotoc/codegen/intrinsic.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright Kani Contributors
22
// SPDX-License-Identifier: Apache-2.0 OR MIT
33
//! this module handles intrinsics
4+
use super::typ::pointee_type;
45
use super::PropertyClass;
56
use crate::codegen_cprover_gotoc::GotocCtx;
67
use cbmc::goto_program::{BuiltinFn, Expr, Location, Stmt, Type};
@@ -142,6 +143,7 @@ impl<'tcx> GotocCtx<'tcx> {
142143
let sig = instance.ty(self.tcx, ty::ParamEnv::reveal_all()).fn_sig(self.tcx);
143144
let sig = self.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
144145
let ret_ty = self.monomorphize(sig.output());
146+
let farg_types = sig.inputs();
145147
let cbmc_ret_ty = self.codegen_ty(ret_ty);
146148

147149
/// https://doc.rust-lang.org/core/intrinsics/fn.copy.html
@@ -681,14 +683,14 @@ impl<'tcx> GotocCtx<'tcx> {
681683
}
682684
"volatile_store" => {
683685
assert!(self.place_ty(p).is_unit());
684-
self.codegen_volatile_store(instance, fargs, loc)
686+
self.codegen_volatile_store(fargs, farg_types, loc)
685687
}
686688
"wrapping_add" => codegen_wrapping_op!(plus),
687689
"wrapping_mul" => codegen_wrapping_op!(mul),
688690
"wrapping_sub" => codegen_wrapping_op!(sub),
689691
"write_bytes" => {
690692
assert!(self.place_ty(p).is_unit());
691-
self.codegen_write_bytes(instance, fargs, loc)
693+
self.codegen_write_bytes(fargs, farg_types, loc)
692694
}
693695
// Unimplemented
694696
_ => codegen_unimplemented_intrinsic!(
@@ -1233,14 +1235,14 @@ impl<'tcx> GotocCtx<'tcx> {
12331235
/// * `dst` must be properly aligned (done by `align_check` below)
12341236
fn codegen_volatile_store(
12351237
&mut self,
1236-
instance: Instance<'tcx>,
12371238
mut fargs: Vec<Expr>,
1239+
farg_types: &[Ty<'tcx>],
12381240
loc: Location,
12391241
) -> Stmt {
12401242
let dst = fargs.remove(0);
12411243
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());
12441246
let align_check = self.codegen_assert(
12451247
align,
12461248
PropertyClass::DefaultAssertion,
@@ -1261,17 +1263,17 @@ impl<'tcx> GotocCtx<'tcx> {
12611263
/// for the `memset` call) would not overflow
12621264
fn codegen_write_bytes(
12631265
&mut self,
1264-
instance: Instance<'tcx>,
12651266
mut fargs: Vec<Expr>,
1267+
farg_types: &[Ty<'tcx>],
12661268
loc: Location,
12671269
) -> Stmt {
12681270
let dst = fargs.remove(0).cast_to(Type::void_pointer());
12691271
let val = fargs.remove(0).cast_to(Type::c_int());
12701272
let count = fargs.remove(0);
12711273

12721274
// 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());
12751277
let align_check = self.codegen_assert(
12761278
align,
12771279
PropertyClass::DefaultAssertion,
@@ -1280,8 +1282,13 @@ impl<'tcx> GotocCtx<'tcx> {
12801282
);
12811283

12821284
// 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+
);
12851292

12861293
let memset_call = BuiltinFn::Memset.call(vec![dst, val, count_bytes], loc);
12871294
Stmt::block(vec![align_check, overflow_check, memset_call.as_stmt(loc)], loc)

kani-compiler/src/codegen_cprover_gotoc/utils/utils.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright Kani Contributors
22
// SPDX-License-Identifier: Apache-2.0 OR MIT
33
use super::super::codegen::TypeExt;
4+
use crate::codegen_cprover_gotoc::codegen::typ::{is_pointer, pointee_type};
45
use crate::codegen_cprover_gotoc::codegen::PropertyClass;
56
use crate::codegen_cprover_gotoc::GotocCtx;
67
use cbmc::goto_program::{Expr, ExprValue, Location, Stmt, SymbolTable, Type};
@@ -77,14 +78,19 @@ impl<'tcx> GotocCtx<'tcx> {
7778
Expr::statement_expression(body, t).with_location(loc)
7879
}
7980

80-
/// Generates an expression `((dst as usize) % align_of(T) == 0`
81-
/// to determine if `dst` is aligned.
82-
pub fn is_aligned(&mut self, typ: Ty<'tcx>, dst: Expr) -> Expr {
83-
let layout = self.layout_of(typ);
81+
/// Generates an expression `(ptr as usize) % align_of(T) == 0`
82+
/// to determine if a pointer `ptr` with pointee type `T` is aligned.
83+
pub fn is_ptr_aligned(&mut self, typ: Ty<'tcx>, ptr: Expr) -> Expr {
84+
// Ensure `typ` is a pointer, then extract the pointee type
85+
assert!(is_pointer(typ));
86+
let pointee_type = pointee_type(typ).unwrap();
87+
// Obtain the alignment for the pointee type `T`
88+
let layout = self.layout_of(pointee_type);
8489
let align = Expr::int_constant(layout.align.abi.bytes(), Type::size_t());
85-
let cast_dst = dst.cast_to(Type::size_t());
90+
// Cast the pointer to `usize` and return the alignment expression
91+
let cast_ptr = ptr.cast_to(Type::size_t());
8692
let zero = Type::size_t().zero();
87-
cast_dst.rem(align).eq(zero)
93+
cast_ptr.rem(align).eq(zero)
8894
}
8995

9096
pub fn unsupported_msg(item: &str, url: Option<&str>) -> String {

0 commit comments

Comments
 (0)