Skip to content

Commit

Permalink
Intrinsics rint, roundeven, nearbyint replaced by `round_ties_e…
Browse files Browse the repository at this point in the history
…ven`.

Propagate changes from rust-lang/rust#136543
Use `__sort_of_CPROVER_round_to_integral` to model `round_ties_even`.
Update tests.
  • Loading branch information
Remi Delmas committed Feb 27, 2025
1 parent 26706b4 commit d9ad6e1
Show file tree
Hide file tree
Showing 11 changed files with 82 additions and 265 deletions.
13 changes: 12 additions & 1 deletion cprover_bindings/src/goto_program/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use super::{Expr, Location, Symbol, Type};

use std::fmt::Display;

#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum BuiltinFn {
Abort,
Assert,
Expand Down Expand Up @@ -59,6 +59,8 @@ pub enum BuiltinFn {
Rintf,
Round,
Roundf,
RoundToIntegralF,
RoundToIntegral,
Sin,
Sinf,
Sqrt,
Expand Down Expand Up @@ -123,6 +125,9 @@ impl Display for BuiltinFn {
Rintf => "rintf",
Round => "round",
Roundf => "roundf",
// TODO remove the sort_of prefix once we move up from CBMC 6.4.1
RoundToIntegralF => "__sort_of_CPROVER_round_to_integralf",
RoundToIntegral => "__sort_of_CPROVER_round_to_integral",
Sin => "sin",
Sinf => "sinf",
Sqrt => "sqrt",
Expand Down Expand Up @@ -188,6 +193,8 @@ impl BuiltinFn {
Rintf => vec![Type::float()],
Round => vec![Type::double()],
Roundf => vec![Type::float()],
RoundToIntegralF => vec![Type::c_int(), Type::float()],
RoundToIntegral => vec![Type::c_int(), Type::double()],
Sin => vec![Type::double()],
Sinf => vec![Type::float()],
Sqrt => vec![Type::double()],
Expand Down Expand Up @@ -252,6 +259,8 @@ impl BuiltinFn {
Rintf => Type::float(),
Round => Type::double(),
Roundf => Type::float(),
RoundToIntegralF => Type::float(),
RoundToIntegral => Type::double(),
Sin => Type::double(),
Sinf => Type::float(),
Sqrt => Type::double(),
Expand Down Expand Up @@ -316,6 +325,8 @@ impl BuiltinFn {
Rintf,
Round,
Roundf,
RoundToIntegralF,
RoundToIntegral,
Sin,
Sinf,
Sqrt,
Expand Down
1 change: 1 addition & 0 deletions cprover_bindings/src/machine_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ pub enum RoundingMode {
Downward = 1,
Upward = 2,
TowardsZero = 3,
ToAway = 4,
}

impl From<RoundingMode> for BigInt {
Expand Down
8 changes: 4 additions & 4 deletions docs/src/rust-feature-support/intrinsics.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,6 @@ minnumf32 | Yes | |
minnumf64 | Yes | |
move_val_init | No | |
mul_with_overflow | Yes | |
nearbyintf32 | Yes | |
nearbyintf64 | Yes | |
needs_drop | Yes | |
nontemporal_store | No | |
offset | Partial | Doesn't check [all UB conditions](https://doc.rust-lang.org/std/primitive.pointer.html#safety-2) |
Expand All @@ -198,8 +196,10 @@ ptr_guaranteed_eq | Yes | |
ptr_guaranteed_ne | Yes | |
ptr_offset_from | Partial | Doesn't check [all UB conditions](https://doc.rust-lang.org/std/primitive.pointer.html#safety-4) |
raw_eq | Partial | Cannot detect [uninitialized memory](#uninitialized-memory) |
rintf32 | Yes | |
rintf64 | Yes | |
round_ties_even_f16 | No | |
round_ties_even_f32 | Yes | |
round_ties_even_f64 | Yes | |
round_ties_even_f128 | No | |
rotate_left | Yes | |
rotate_right | Yes | |
roundf32 | Yes | |
Expand Down
39 changes: 35 additions & 4 deletions kani-compiler/src/codegen_cprover_gotoc/codegen/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,8 +414,6 @@ impl GotocCtx<'_> {
Intrinsic::MulWithOverflow => {
self.codegen_op_with_overflow(BinaryOperator::OverflowResultMult, fargs, place, loc)
}
Intrinsic::NearbyIntF32 => codegen_simple_intrinsic!(Nearbyintf),
Intrinsic::NearbyIntF64 => codegen_simple_intrinsic!(Nearbyint),
Intrinsic::NeedsDrop => codegen_intrinsic_const!(),
Intrinsic::PowF32 => codegen_simple_intrinsic!(Powf),
Intrinsic::PowF64 => codegen_simple_intrinsic!(Pow),
Expand All @@ -425,12 +423,24 @@ impl GotocCtx<'_> {
Intrinsic::PtrGuaranteedCmp => self.codegen_ptr_guaranteed_cmp(fargs, place, loc),
Intrinsic::RawEq => self.codegen_intrinsic_raw_eq(instance, fargs, place, loc),
Intrinsic::RetagBoxToRaw => self.codegen_retag_box_to_raw(fargs, place, loc),
Intrinsic::RintF32 => codegen_simple_intrinsic!(Rintf),
Intrinsic::RintF64 => codegen_simple_intrinsic!(Rint),
Intrinsic::RotateLeft => codegen_intrinsic_binop!(rol),
Intrinsic::RotateRight => codegen_intrinsic_binop!(ror),
Intrinsic::RoundF32 => codegen_simple_intrinsic!(Roundf),
Intrinsic::RoundF64 => codegen_simple_intrinsic!(Round),
Intrinsic::RoundTiesEvenF32 => self.codegen_round_to_integral(
BuiltinFn::RoundToIntegralF,
cbmc::RoundingMode::ToNearest,
fargs,
place,
loc,
),
Intrinsic::RoundTiesEvenF64 => self.codegen_round_to_integral(
BuiltinFn::RoundToIntegral,
cbmc::RoundingMode::ToNearest,
fargs,
place,
loc,
),
Intrinsic::SaturatingAdd => codegen_intrinsic_binop_with_mm!(saturating_add),
Intrinsic::SaturatingSub => codegen_intrinsic_binop_with_mm!(saturating_sub),
Intrinsic::SinF32 => codegen_simple_intrinsic!(Sinf),
Expand Down Expand Up @@ -638,6 +648,27 @@ impl GotocCtx<'_> {
dividend_is_int_min.and(divisor_is_minus_one).not()
}

// Builds a call to the round_to_integral CPROVER function with specified cbmc::RoundingMode.
fn codegen_round_to_integral(
&mut self,
function: BuiltinFn,
rounding_mode: cbmc::RoundingMode,
mut fargs: Vec<Expr>,
place: &Place,
loc: Location,
) -> Stmt {
assert!(function == BuiltinFn::RoundToIntegralF || function == BuiltinFn::RoundToIntegral);
let mm = self.symbol_table.machine_model();
fargs.insert(0, Expr::int_constant(rounding_mode, Type::c_int()));
let casted_fargs = Expr::cast_arguments_to_target_equivalent_function_parameter_types(
&function.as_expr(),
fargs,
mm,
);
let expr = function.call(casted_fargs, loc);
self.codegen_expr_to_place_stable(place, expr, loc)
}

/// Intrinsics of the form *_with_overflow
fn codegen_op_with_overflow(
&mut self,
Expand Down
30 changes: 10 additions & 20 deletions kani-compiler/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,6 @@ pub enum Intrinsic {
MinNumF32,
MinNumF64,
MulWithOverflow,
NearbyIntF32,
NearbyIntF64,
NeedsDrop,
PowF32,
PowF64,
Expand All @@ -99,12 +97,12 @@ pub enum Intrinsic {
PtrOffsetFromUnsigned,
RawEq,
RetagBoxToRaw,
RintF32,
RintF64,
RotateLeft,
RotateRight,
RoundF32,
RoundF64,
RoundTiesEvenF32,
RoundTiesEvenF64,
SaturatingAdd,
SaturatingSub,
SinF32,
Expand Down Expand Up @@ -676,10 +674,6 @@ fn try_match_f32(intrinsic_instance: &Instance) -> Option<Intrinsic> {
assert_sig_matches!(sig, RigidTy::Float(FloatTy::F32), RigidTy::Float(FloatTy::F32) => RigidTy::Float(FloatTy::F32));
Some(Intrinsic::MinNumF32)
}
"nearbyintf32" => {
assert_sig_matches!(sig, RigidTy::Float(FloatTy::F32) => RigidTy::Float(FloatTy::F32));
Some(Intrinsic::NearbyIntF32)
}
"powf32" => {
assert_sig_matches!(sig, RigidTy::Float(FloatTy::F32), RigidTy::Float(FloatTy::F32) => RigidTy::Float(FloatTy::F32));
Some(Intrinsic::PowF32)
Expand All @@ -688,14 +682,14 @@ fn try_match_f32(intrinsic_instance: &Instance) -> Option<Intrinsic> {
assert_sig_matches!(sig, RigidTy::Float(FloatTy::F32), RigidTy::Int(IntTy::I32) => RigidTy::Float(FloatTy::F32));
Some(Intrinsic::PowIF32)
}
"rintf32" => {
assert_sig_matches!(sig, RigidTy::Float(FloatTy::F32) => RigidTy::Float(FloatTy::F32));
Some(Intrinsic::RintF32)
}
"roundf32" => {
assert_sig_matches!(sig, RigidTy::Float(FloatTy::F32) => RigidTy::Float(FloatTy::F32));
Some(Intrinsic::RoundF32)
}
"round_ties_even_f32" => {
assert_sig_matches!(sig, RigidTy::Float(FloatTy::F32) => RigidTy::Float(FloatTy::F32));
Some(Intrinsic::RoundTiesEvenF32)
}
"sinf32" => {
assert_sig_matches!(sig, RigidTy::Float(FloatTy::F32) => RigidTy::Float(FloatTy::F32));
Some(Intrinsic::SinF32)
Expand Down Expand Up @@ -770,10 +764,6 @@ fn try_match_f64(intrinsic_instance: &Instance) -> Option<Intrinsic> {
assert_sig_matches!(sig, RigidTy::Float(FloatTy::F64), RigidTy::Float(FloatTy::F64) => RigidTy::Float(FloatTy::F64));
Some(Intrinsic::MinNumF64)
}
"nearbyintf64" => {
assert_sig_matches!(sig, RigidTy::Float(FloatTy::F64) => RigidTy::Float(FloatTy::F64));
Some(Intrinsic::NearbyIntF64)
}
"powf64" => {
assert_sig_matches!(sig, RigidTy::Float(FloatTy::F64), RigidTy::Float(FloatTy::F64) => RigidTy::Float(FloatTy::F64));
Some(Intrinsic::PowF64)
Expand All @@ -782,14 +772,14 @@ fn try_match_f64(intrinsic_instance: &Instance) -> Option<Intrinsic> {
assert_sig_matches!(sig, RigidTy::Float(FloatTy::F64), RigidTy::Int(IntTy::I32) => RigidTy::Float(FloatTy::F64));
Some(Intrinsic::PowIF64)
}
"rintf64" => {
assert_sig_matches!(sig, RigidTy::Float(FloatTy::F64) => RigidTy::Float(FloatTy::F64));
Some(Intrinsic::RintF64)
}
"roundf64" => {
assert_sig_matches!(sig, RigidTy::Float(FloatTy::F64) => RigidTy::Float(FloatTy::F64));
Some(Intrinsic::RoundF64)
}
"round_ties_even_f64" => {
assert_sig_matches!(sig, RigidTy::Float(FloatTy::F64) => RigidTy::Float(FloatTy::F64));
Some(Intrinsic::RoundTiesEvenF64)
}
"sinf64" => {
assert_sig_matches!(sig, RigidTy::Float(FloatTy::F64) => RigidTy::Float(FloatTy::F64));
Some(Intrinsic::SinF64)
Expand Down
4 changes: 0 additions & 4 deletions kani-compiler/src/kani_middle/points_to/points_to_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -664,8 +664,6 @@ fn is_identity_aliasing_intrinsic(intrinsic: Intrinsic) -> bool {
| Intrinsic::MinNumF32
| Intrinsic::MinNumF64
| Intrinsic::MulWithOverflow
| Intrinsic::NearbyIntF32
| Intrinsic::NearbyIntF64
| Intrinsic::NeedsDrop
| Intrinsic::PowF32
| Intrinsic::PowF64
Expand All @@ -677,8 +675,6 @@ fn is_identity_aliasing_intrinsic(intrinsic: Intrinsic) -> bool {
| Intrinsic::PtrOffsetFromUnsigned
| Intrinsic::RawEq
| Intrinsic::RetagBoxToRaw
| Intrinsic::RintF32
| Intrinsic::RintF64
| Intrinsic::RotateLeft
| Intrinsic::RotateRight
| Intrinsic::RoundF32
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -625,17 +625,13 @@ fn can_skip_intrinsic(intrinsic: Intrinsic) -> bool {
| Intrinsic::MinNumF32
| Intrinsic::MinNumF64
| Intrinsic::MulWithOverflow
| Intrinsic::NearbyIntF32
| Intrinsic::NearbyIntF64
| Intrinsic::NeedsDrop
| Intrinsic::PowF32
| Intrinsic::PowF64
| Intrinsic::PowIF32
| Intrinsic::PowIF64
| Intrinsic::PrefAlignOf
| Intrinsic::RawEq
| Intrinsic::RintF32
| Intrinsic::RintF64
| Intrinsic::RotateLeft
| Intrinsic::RotateRight
| Intrinsic::RoundF32
Expand Down
104 changes: 0 additions & 104 deletions tests/kani/Intrinsics/Math/Rounding/RInt/rintf32.rs

This file was deleted.

Loading

0 comments on commit d9ad6e1

Please sign in to comment.