Skip to content

Commit f08a3e9

Browse files
authored
Enable powf*, exp*, log* intrinsics (#2996)
CBMC provides approximating implementations of these. Resolves: #2966
1 parent 129375f commit f08a3e9

File tree

7 files changed

+129
-16
lines changed

7 files changed

+129
-16
lines changed

docs/src/rust-feature-support/intrinsics.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,10 @@ cttz_nonzero | Yes | |
148148
discriminant_value | Yes | |
149149
drop_in_place | No | |
150150
exact_div | Yes | |
151-
exp2f32 | No | |
152-
exp2f64 | No | |
153-
expf32 | No | |
154-
expf64 | No | |
151+
exp2f32 | Partial | Results are overapproximated |
152+
exp2f64 | Partial | Results are overapproximated |
153+
expf32 | Partial | Results are overapproximated |
154+
expf64 | Partial | Results are overapproximated |
155155
fabsf32 | Yes | |
156156
fabsf64 | Yes | |
157157
fadd_fast | Yes | |
@@ -170,8 +170,8 @@ log10f32 | No | |
170170
log10f64 | No | |
171171
log2f32 | No | |
172172
log2f64 | No | |
173-
logf32 | No | |
174-
logf64 | No | |
173+
logf32 | Partial | Results are overapproximated |
174+
logf64 | Partial | Results are overapproximated |
175175
maxnumf32 | Yes | |
176176
maxnumf64 | Yes | |
177177
min_align_of | Yes | |
@@ -185,8 +185,8 @@ nearbyintf64 | Yes | |
185185
needs_drop | Yes | |
186186
nontemporal_store | No | |
187187
offset | Partial | Doesn't check [all UB conditions](https://doc.rust-lang.org/std/primitive.pointer.html#safety-2) |
188-
powf32 | No | |
189-
powf64 | No | |
188+
powf32 | Partial | Results are overapproximated |
189+
powf64 | Partial | Results are overapproximated |
190190
powif32 | No | |
191191
powif64 | No | |
192192
pref_align_of | Yes | |

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -420,10 +420,10 @@ impl<'tcx> GotocCtx<'tcx> {
420420
self.codegen_expr_to_place_stable(place, e)
421421
}
422422
"exact_div" => self.codegen_exact_div(fargs, place, loc),
423-
"exp2f32" => unstable_codegen!(codegen_simple_intrinsic!(Exp2f)),
424-
"exp2f64" => unstable_codegen!(codegen_simple_intrinsic!(Exp2)),
425-
"expf32" => unstable_codegen!(codegen_simple_intrinsic!(Expf)),
426-
"expf64" => unstable_codegen!(codegen_simple_intrinsic!(Exp)),
423+
"exp2f32" => codegen_simple_intrinsic!(Exp2f),
424+
"exp2f64" => codegen_simple_intrinsic!(Exp2),
425+
"expf32" => codegen_simple_intrinsic!(Expf),
426+
"expf64" => codegen_simple_intrinsic!(Exp),
427427
"fabsf32" => codegen_simple_intrinsic!(Fabsf),
428428
"fabsf64" => codegen_simple_intrinsic!(Fabs),
429429
"fadd_fast" => {
@@ -456,8 +456,8 @@ impl<'tcx> GotocCtx<'tcx> {
456456
"log10f64" => unstable_codegen!(codegen_simple_intrinsic!(Log10)),
457457
"log2f32" => unstable_codegen!(codegen_simple_intrinsic!(Log2f)),
458458
"log2f64" => unstable_codegen!(codegen_simple_intrinsic!(Log2)),
459-
"logf32" => unstable_codegen!(codegen_simple_intrinsic!(Logf)),
460-
"logf64" => unstable_codegen!(codegen_simple_intrinsic!(Log)),
459+
"logf32" => codegen_simple_intrinsic!(Logf),
460+
"logf64" => codegen_simple_intrinsic!(Log),
461461
"maxnumf32" => codegen_simple_intrinsic!(Fmaxf),
462462
"maxnumf64" => codegen_simple_intrinsic!(Fmax),
463463
"min_align_of" => codegen_intrinsic_const!(),
@@ -474,8 +474,8 @@ impl<'tcx> GotocCtx<'tcx> {
474474
"offset" => unreachable!(
475475
"Expected `core::intrinsics::unreachable` to be handled by `BinOp::OffSet`"
476476
),
477-
"powf32" => unstable_codegen!(codegen_simple_intrinsic!(Powf)),
478-
"powf64" => unstable_codegen!(codegen_simple_intrinsic!(Pow)),
477+
"powf32" => codegen_simple_intrinsic!(Powf),
478+
"powf64" => codegen_simple_intrinsic!(Pow),
479479
"powif32" => unstable_codegen!(codegen_simple_intrinsic!(Powif)),
480480
"powif64" => unstable_codegen!(codegen_simple_intrinsic!(Powi)),
481481
"pref_align_of" => codegen_intrinsic_const!(),
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
//
4+
// This test will trigger use of the `expf32` and `expf64` intrinsics, which in turn invoke
5+
// functions modelled in CBMC's math library. These models use approximations as documented in
6+
// CBMC's source code: https://github.com/diffblue/cbmc/blob/develop/src/ansi-c/library/math.c.
7+
8+
#[kani::proof]
9+
fn verify_exp32() {
10+
let two = 2.0_f32;
11+
let two_sq = std::f32::consts::E * std::f32::consts::E;
12+
let two_exp = two.exp();
13+
14+
assert!((two_sq - two_exp).abs() <= 0.192);
15+
}
16+
17+
#[kani::proof]
18+
fn verify_exp64() {
19+
let two = 2.0_f64;
20+
let two_sq = std::f64::consts::E * std::f64::consts::E;
21+
let two_exp = two.exp();
22+
23+
assert!((two_sq - two_exp).abs() <= 0.192);
24+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
//
4+
// This test will trigger use of the `exp2f32` and `exp2f64` intrinsics, which in turn invoke
5+
// functions modelled in CBMC's math library. These models use approximations as documented in
6+
// CBMC's source code: https://github.com/diffblue/cbmc/blob/develop/src/ansi-c/library/math.c.
7+
8+
#[kani::proof]
9+
fn verify_exp2_32() {
10+
let two = 2.0_f32;
11+
let two_two = two.exp2();
12+
13+
assert!((two_two - 4.0).abs() <= 0.345);
14+
}
15+
16+
#[kani::proof]
17+
fn verify_exp2_64() {
18+
let two = 2.0_f64;
19+
let two_two = two.exp2();
20+
21+
assert!((two_two - 4.0).abs() <= 0.345);
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
//
4+
// This test will trigger use of the `logf32` and `logf64` intrinsics, which in turn invoke
5+
// functions modelled in CBMC's math library. These models use approximations as documented in
6+
// CBMC's source code: https://github.com/diffblue/cbmc/blob/develop/src/ansi-c/library/math.c.
7+
8+
#[kani::proof]
9+
fn verify_logf32() {
10+
let e = std::f32::consts::E;
11+
let e_log = e.ln();
12+
13+
assert!((e_log - 1.0).abs() <= 0.058);
14+
}
15+
16+
#[kani::proof]
17+
fn verify_logf64() {
18+
let e = std::f64::consts::E;
19+
let e_log = e.ln();
20+
21+
assert!((e_log - 1.0).abs() <= 0.058);
22+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
//
4+
// This test will trigger use of the `powf32` intrinsic, which in turn invoke functions modelled in
5+
// CBMC's math library. These models use approximations as documented in CBMC's source code:
6+
// https://github.com/diffblue/cbmc/blob/develop/src/ansi-c/library/math.c.
7+
8+
#[kani::proof]
9+
fn verify_pow() {
10+
let x: f32 = kani::any();
11+
kani::assume(x.is_normal());
12+
kani::assume(x > 1.0 && x < u16::MAX.into());
13+
let x2 = x.powf(2.0);
14+
assert!(x2 >= 0.0);
15+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
//
4+
// This test will trigger use of the `powf64` intrinsic, which in turn invoke functions modelled in
5+
// CBMC's math library. These models use approximations as documented in CBMC's source code:
6+
// https://github.com/diffblue/cbmc/blob/develop/src/ansi-c/library/math.c.
7+
8+
pub fn f(a: u64) -> u64 {
9+
const C: f64 = 0.618;
10+
(a as f64).powf(C) as u64
11+
}
12+
13+
#[cfg(kani)]
14+
mod verification {
15+
use super::*;
16+
17+
#[kani::proof]
18+
fn verify_f() {
19+
const LIMIT: u64 = 10;
20+
let x: u64 = kani::any();
21+
let y: u64 = kani::any();
22+
// outside these limits our approximation may yield spurious results
23+
kani::assume(x > LIMIT && x < LIMIT * 3);
24+
kani::assume(y > LIMIT && y < LIMIT * 3);
25+
kani::assume(x > y);
26+
let x_ = f(x);
27+
let y_ = f(y);
28+
assert!(x_ >= y_);
29+
}
30+
}

0 commit comments

Comments
 (0)