Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/isle/veri/veri_ir/src/annotation_ir.rs
1693 views
1
/// A higher-level annotation IR that does not specify bitvector widths.
2
/// This allows annotations to be generic over possible types, which
3
/// corresponds to how ISLE rewrites are written.
4
use std::fmt;
5
/// A bound variable, including the VIR type
6
#[derive(Clone, Debug, PartialEq, Eq)]
7
pub struct BoundVar {
8
pub name: String,
9
pub ty: Option<Type>,
10
}
11
12
impl BoundVar {
13
/// Construct a new bound variable
14
pub fn new_with_ty(name: &str, ty: &Type) -> Self {
15
BoundVar {
16
name: name.to_string(),
17
ty: Some(ty.clone()),
18
}
19
}
20
21
/// Construct a new bound variable, cloning from references
22
pub fn new(name: &str) -> Self {
23
BoundVar {
24
name: name.to_string(),
25
ty: None,
26
}
27
}
28
29
/// An expression with the bound variable's name
30
pub fn as_expr(&self) -> Expr {
31
Expr::Var(self.name.clone())
32
}
33
}
34
35
/// A function signature annotation, including the bound variable names for all
36
/// arguments and the return value.
37
#[derive(Clone, Debug, PartialEq, Eq)]
38
pub struct TermSignature {
39
pub args: Vec<BoundVar>,
40
pub ret: BoundVar,
41
}
42
43
/// Verification IR annotations for an ISLE term consist of the function
44
/// signature and a list of assertions.
45
#[derive(Clone, Debug, PartialEq, Eq)]
46
pub struct TermAnnotation {
47
pub sig: TermSignature,
48
// Note: extra Box for now for ease of parsing
49
#[allow(clippy::vec_box)]
50
pub assumptions: Vec<Box<Expr>>,
51
52
#[allow(clippy::vec_box)]
53
pub assertions: Vec<Box<Expr>>,
54
}
55
56
impl TermAnnotation {
57
/// New annotation
58
pub fn new(sig: TermSignature, assumptions: Vec<Expr>, assertions: Vec<Expr>) -> Self {
59
TermAnnotation {
60
sig,
61
assumptions: assumptions.iter().map(|x| Box::new(x.clone())).collect(),
62
assertions: assertions.iter().map(|x| Box::new(x.clone())).collect(),
63
}
64
}
65
66
pub fn sig(&self) -> &TermSignature {
67
&self.sig
68
}
69
70
pub fn assertions(&self) -> Vec<Expr> {
71
self.assumptions.iter().map(|x| *x.clone()).collect()
72
}
73
}
74
75
/// Higher-level type, not including bitwidths.
76
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
77
pub enum Type {
78
/// Internal type used solely for type inference
79
Poly(u32),
80
81
/// The expression is a bitvector, currently modeled in the
82
/// logic QF_BV https://SMT-LIB.cs.uiowa.edu/version1/logics/QF_BV.smt
83
/// This corresponds to Cranelift's Isle type:
84
/// (type Value (primitive Value))
85
BitVector,
86
87
/// Use if the width is known
88
BitVectorWithWidth(usize),
89
90
// Use if the width is unknown after inference, indexed by a
91
// canonical type variable
92
BitVectorUnknown(u32),
93
94
/// The expression is an integer (currently used for ISLE type,
95
/// representing bitwidth)
96
Int,
97
98
/// The expression is a boolean.
99
Bool,
100
101
/// Unit, removed before SMT-Lib
102
Unit,
103
}
104
105
impl fmt::Display for Type {
106
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107
match self {
108
Type::Poly(_) => write!(f, "poly"),
109
Type::BitVector => write!(f, "bv"),
110
Type::BitVectorWithWidth(w) => write!(f, "bv{}", *w),
111
Type::BitVectorUnknown(_) => write!(f, "bv"),
112
Type::Int => write!(f, "Int"),
113
Type::Bool => write!(f, "Bool"),
114
Type::Unit => write!(f, "Unit"),
115
}
116
}
117
}
118
119
impl Type {
120
pub fn is_poly(&self) -> bool {
121
matches!(self, Type::Poly(_))
122
}
123
}
124
125
/// Type-specified constants
126
#[derive(Clone, Debug, PartialEq, Eq)]
127
pub struct Const {
128
pub ty: Type,
129
pub value: i128,
130
pub width: usize,
131
}
132
133
/// Width arguments
134
#[derive(Clone, Debug, PartialEq, Eq)]
135
pub enum Width {
136
Const(usize),
137
RegWidth,
138
}
139
140
/// Typed expressions (u32 is the type var)
141
#[derive(Clone, Debug, PartialEq, Eq)]
142
pub enum Expr {
143
// Terminal nodes
144
Var(String),
145
Const(Const),
146
True,
147
False,
148
149
// Get the width of a bitvector
150
WidthOf(Box<Expr>),
151
152
// Boolean operations
153
Not(Box<Expr>),
154
And(Box<Expr>, Box<Expr>),
155
Or(Box<Expr>, Box<Expr>),
156
Imp(Box<Expr>, Box<Expr>),
157
Eq(Box<Expr>, Box<Expr>),
158
Lte(Box<Expr>, Box<Expr>),
159
Lt(Box<Expr>, Box<Expr>),
160
161
BVSgt(Box<Expr>, Box<Expr>),
162
BVSgte(Box<Expr>, Box<Expr>),
163
BVSlt(Box<Expr>, Box<Expr>),
164
BVSlte(Box<Expr>, Box<Expr>),
165
BVUgt(Box<Expr>, Box<Expr>),
166
BVUgte(Box<Expr>, Box<Expr>),
167
BVUlt(Box<Expr>, Box<Expr>),
168
BVUlte(Box<Expr>, Box<Expr>),
169
170
BVSaddo(Box<Expr>, Box<Expr>),
171
172
// Bitvector operations
173
// Note: these follow the naming conventions of the SMT theory of bitvectors:
174
// https://SMT-LIB.cs.uiowa.edu/version1/logics/QF_BV.smt
175
// Unary operators
176
BVNeg(Box<Expr>),
177
BVNot(Box<Expr>),
178
CLZ(Box<Expr>),
179
CLS(Box<Expr>),
180
Rev(Box<Expr>),
181
BVPopcnt(Box<Expr>),
182
183
// Binary operators
184
BVMul(Box<Expr>, Box<Expr>),
185
BVUDiv(Box<Expr>, Box<Expr>),
186
BVSDiv(Box<Expr>, Box<Expr>),
187
BVAdd(Box<Expr>, Box<Expr>),
188
BVSub(Box<Expr>, Box<Expr>),
189
BVUrem(Box<Expr>, Box<Expr>),
190
BVSrem(Box<Expr>, Box<Expr>),
191
BVAnd(Box<Expr>, Box<Expr>),
192
BVOr(Box<Expr>, Box<Expr>),
193
BVXor(Box<Expr>, Box<Expr>),
194
BVRotl(Box<Expr>, Box<Expr>),
195
BVRotr(Box<Expr>, Box<Expr>),
196
BVShl(Box<Expr>, Box<Expr>),
197
BVShr(Box<Expr>, Box<Expr>),
198
BVAShr(Box<Expr>, Box<Expr>),
199
200
// Includes type
201
BVSubs(Box<Expr>, Box<Expr>, Box<Expr>),
202
203
// Conversions
204
// Zero extend, static and dynamic width
205
BVZeroExtTo(Box<Width>, Box<Expr>),
206
BVZeroExtToVarWidth(Box<Expr>, Box<Expr>),
207
208
// Sign extend, static and dynamic width
209
BVSignExtTo(Box<Width>, Box<Expr>),
210
BVSignExtToVarWidth(Box<Expr>, Box<Expr>),
211
212
// Extract specified bits
213
BVExtract(usize, usize, Box<Expr>),
214
215
// Concat two bitvectors
216
BVConcat(Vec<Expr>),
217
218
// Convert integer to bitvector
219
BVIntToBv(usize, Box<Expr>),
220
221
// Convert bitvector to integer
222
BVToInt(Box<Expr>),
223
224
// Conversion to wider/narrower bits, without an explicit extend
225
// Allow the destination width to be symbolic.
226
BVConvTo(Box<Expr>, Box<Expr>),
227
228
// Conditional if-then-else
229
Conditional(Box<Expr>, Box<Expr>, Box<Expr>),
230
231
// Switch
232
Switch(Box<Expr>, Vec<(Expr, Expr)>),
233
234
LoadEffect(Box<Expr>, Box<Expr>, Box<Expr>),
235
236
StoreEffect(Box<Expr>, Box<Expr>, Box<Expr>, Box<Expr>),
237
}
238
239
impl Expr {
240
pub fn var(s: &str) -> Expr {
241
Expr::Var(s.to_string())
242
}
243
244
pub fn unary<F: Fn(Box<Expr>) -> Expr>(f: F, x: Expr) -> Expr {
245
f(Box::new(x))
246
}
247
248
pub fn binary<F: Fn(Box<Expr>, Box<Expr>) -> Expr>(f: F, x: Expr, y: Expr) -> Expr {
249
f(Box::new(x), Box::new(y))
250
}
251
}
252
253