Skip to content

Commit f77263a

Browse files
danielsntedinski
authored andcommitted
Break min/max_int into their own util functions, and have them return BigInt to avoid any arbitrary width constraints (rust-lang#605)
1 parent cb6ecf9 commit f77263a

File tree

2 files changed

+69
-23
lines changed

2 files changed

+69
-23
lines changed

compiler/cbmc/src/goto_program/typ.rs

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0 OR MIT
33
use self::DatatypeComponent::*;
44
use self::Type::*;
5-
use super::super::utils::aggr_name;
5+
use super::super::utils::{aggr_name, max_int, min_int};
66
use super::super::MachineModel;
77
use super::{Expr, SymbolTable};
88
use std::collections::BTreeMap;
@@ -790,33 +790,18 @@ impl Type {
790790

791791
/// Constants from Types, for use in Expr contexts
792792
impl Type {
793-
//TODO second mathematical check
794-
pub fn max_int(&self, mm: &MachineModel) -> i128 {
795-
assert!(self.is_integer());
796-
let w = self.native_width(mm).unwrap();
797-
assert!(w < 128);
798-
let shift = if self.is_signed(mm) { 129 - w } else { 128 - w };
799-
let max: u128 = u128::MAX >> shift;
800-
max.try_into().unwrap()
801-
}
802-
803793
pub fn max_int_expr(&self, mm: &MachineModel) -> Expr {
804-
Expr::int_constant(self.max_int(mm), self.clone())
805-
}
806-
807-
pub fn min_int(&self, mm: &MachineModel) -> i128 {
808794
assert!(self.is_integer());
809-
if self.is_unsigned(mm) {
810-
0
811-
} else {
812-
let max = self.max_int(mm);
813-
let min = -max - 1;
814-
min
815-
}
795+
let width = self.native_width(mm).unwrap();
796+
let signed = self.is_signed(mm);
797+
Expr::int_constant(max_int(width, signed), self.clone())
816798
}
817799

818800
pub fn min_int_expr(&self, mm: &MachineModel) -> Expr {
819-
Expr::int_constant(self.min_int(mm), self.clone())
801+
assert!(self.is_integer());
802+
let width = self.native_width(mm).unwrap();
803+
let signed = self.is_signed(mm);
804+
Expr::int_constant(min_int(width, signed), self.clone())
820805
}
821806

822807
/// an expression of nondeterministic value of type self

compiler/cbmc/src/utils.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// SPDX-License-Identifier: Apache-2.0 OR MIT
33
//! Useful utilities for CBMC
44
5+
use num::bigint::BigInt;
6+
57
/// RMC bug report URL, for asserts/errors
68
pub const BUG_REPORT_URL: &str =
79
"https://github.com/model-checking/rmc/issues/new?template=bug_report.md";
@@ -42,3 +44,62 @@ macro_rules! btree_string_map {
4244
(BTreeMap::from_iter(vec![$($x),*].into_iter().map(|(k,v)|(k.to_string(),v))))
4345
}}
4446
}
47+
48+
pub fn max_int(width: u64, signed: bool) -> BigInt {
49+
let mut bi = BigInt::from(0);
50+
if signed {
51+
bi.set_bit(width - 1, true);
52+
} else {
53+
bi.set_bit(width, true);
54+
}
55+
bi - 1
56+
}
57+
58+
pub fn min_int(width: u64, signed: bool) -> BigInt {
59+
if signed {
60+
let max = max_int(width, true);
61+
let min = -max - 1;
62+
min
63+
} else {
64+
BigInt::from(0)
65+
}
66+
}
67+
68+
#[cfg(test)]
69+
mod tests {
70+
use crate::utils::{max_int, min_int};
71+
use num::BigInt;
72+
#[test]
73+
fn test_max_int() {
74+
// Unsigned
75+
assert_eq!(max_int(8, false), BigInt::from(u8::MAX));
76+
assert_eq!(max_int(16, false), BigInt::from(u16::MAX));
77+
assert_eq!(max_int(32, false), BigInt::from(u32::MAX));
78+
assert_eq!(max_int(64, false), BigInt::from(u64::MAX));
79+
assert_eq!(max_int(128, false), BigInt::from(u128::MAX));
80+
81+
//Signed
82+
assert_eq!(max_int(8, true), BigInt::from(i8::MAX));
83+
assert_eq!(max_int(16, true), BigInt::from(i16::MAX));
84+
assert_eq!(max_int(32, true), BigInt::from(i32::MAX));
85+
assert_eq!(max_int(64, true), BigInt::from(i64::MAX));
86+
assert_eq!(max_int(128, true), BigInt::from(i128::MAX));
87+
}
88+
89+
#[test]
90+
fn test_min_int() {
91+
// Unsigned
92+
assert_eq!(min_int(8, false), BigInt::from(u8::MIN));
93+
assert_eq!(min_int(16, false), BigInt::from(u16::MIN));
94+
assert_eq!(min_int(32, false), BigInt::from(u32::MIN));
95+
assert_eq!(min_int(64, false), BigInt::from(u64::MIN));
96+
assert_eq!(min_int(128, false), BigInt::from(u128::MIN));
97+
98+
//Signed
99+
assert_eq!(min_int(8, true), BigInt::from(i8::MIN));
100+
assert_eq!(min_int(16, true), BigInt::from(i16::MIN));
101+
assert_eq!(min_int(32, true), BigInt::from(i32::MIN));
102+
assert_eq!(min_int(64, true), BigInt::from(i64::MIN));
103+
assert_eq!(min_int(128, true), BigInt::from(i128::MIN));
104+
}
105+
}

0 commit comments

Comments
 (0)