isla_lib/
primop.rs

1// BSD 2-Clause License
2//
3// Copyright (c) 2019, 2020 Alasdair Armstrong
4// Copyright (c) 2020 Brian Campbell
5//
6// All rights reserved.
7//
8// Redistribution and use in source and binary forms, with or without
9// modification, are permitted provided that the following conditions are
10// met:
11//
12// 1. Redistributions of source code must retain the above copyright
13// notice, this list of conditions and the following disclaimer.
14//
15// 2. Redistributions in binary form must reproduce the above copyright
16// notice, this list of conditions and the following disclaimer in the
17// documentation and/or other materials provided with the distribution.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31//! This module is a big set of primitive operations and builtins
32//! which are implemented over the [crate::ir::Val] type. Most are not
33//! exported directly but instead are exposed via the [Primops] struct
34//! which contains all the primops. During initialization (via the
35//! [crate::init] module) textual references to primops in the IR are
36//! replaced with direct function pointers to their implementation in
37//! this module. The [Unary], [Binary], and [Variadic] types are
38//! function pointers to unary, binary, and other primops, which are
39//! contained within [Primops].
40
41#![allow(clippy::comparison_chain)]
42#![allow(clippy::cognitive_complexity)]
43
44use std::collections::HashMap;
45use std::convert::{TryFrom, TryInto};
46use std::ops::{BitAnd, BitOr, Not, Shl, Shr};
47use std::str::FromStr;
48
49use crate::bitvector::b64::B64;
50use crate::bitvector::BV;
51use crate::error::ExecError;
52use crate::executor::LocalFrame;
53use crate::ir::{UVal, Val, ELF_ENTRY};
54use crate::smt::smtlib::*;
55use crate::smt::*;
56
57pub type Unary<B> = fn(Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError>;
58pub type Binary<B> = fn(Val<B>, Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError>;
59pub type Variadic<B> = fn(Vec<Val<B>>, solver: &mut Solver<B>, frame: &mut LocalFrame<B>) -> Result<Val<B>, ExecError>;
60
61#[allow(clippy::needless_range_loop)]
62pub fn smt_i128(i: i128) -> Exp {
63    let mut bitvec = [false; 128];
64    for n in 0..128 {
65        if (i >> n & 1) == 1 {
66            bitvec[n] = true
67        }
68    }
69    Exp::Bits(bitvec.to_vec())
70}
71
72pub fn smt_i64(i: i64) -> Exp {
73    Exp::Bits64(B64::new(i as u64, 64))
74}
75
76pub fn smt_u8(i: u8) -> Exp {
77    Exp::Bits64(B64::new(i as u64, 8))
78}
79
80#[allow(clippy::needless_range_loop)]
81fn smt_mask_lower(len: usize, mask_width: usize) -> Exp {
82    if len <= 64 {
83        Exp::Bits64(B64::new(u64::MAX >> (64 - mask_width), len as u32))
84    } else {
85        let mut bitvec = vec![false; len];
86        for i in 0..mask_width {
87            bitvec[i] = true
88        }
89        Exp::Bits(bitvec)
90    }
91}
92
93fn smt_zeros(i: i128) -> Exp {
94    if i <= 64 {
95        Exp::Bits64(B64::zeros(i as u32))
96    } else {
97        Exp::Bits(vec![false; i as usize])
98    }
99}
100
101fn smt_ones(i: i128) -> Exp {
102    if i <= 64 {
103        Exp::Bits64(B64::ones(i as u32))
104    } else {
105        Exp::Bits(vec![true; i as usize])
106    }
107}
108
109pub fn smt_sbits<B: BV>(bv: B) -> Exp {
110    if let Ok(u) = bv.try_into() {
111        bits64(u, bv.len())
112    } else {
113        let mut bitvec = Vec::with_capacity(bv.len().try_into().unwrap());
114        for n in 0..bv.len() {
115            bitvec.push((bv.shiftr(n as i128).lower_u64() & 1) == 1)
116        }
117        Exp::Bits(bitvec)
118    }
119}
120
121macro_rules! unary_primop_copy {
122    ($f:ident, $name:expr, $unwrap:path, $wrap:path, $concrete_op:path, $smt_op:path) => {
123        pub(crate) fn $f<B: BV>(x: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
124            match x {
125                Val::Symbolic(x) => solver.define_const($smt_op(Box::new(Exp::Var(x)))).into(),
126                $unwrap(x) => Ok($wrap($concrete_op(x))),
127                _ => Err(ExecError::Type($name)),
128            }
129        }
130    };
131}
132
133macro_rules! binary_primop_copy {
134    ($f:ident, $name:expr, $unwrap:path, $wrap:path, $concrete_op:path, $smt_op:path, $to_symbolic:path) => {
135        pub(crate) fn $f<B: BV>(x: Val<B>, y: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
136            match (x, y) {
137                (Val::Symbolic(x), Val::Symbolic(y)) => {
138                    solver.define_const($smt_op(Box::new(Exp::Var(x)), Box::new(Exp::Var(y)))).into()
139                }
140                (Val::Symbolic(x), $unwrap(y)) => {
141                    solver.define_const($smt_op(Box::new(Exp::Var(x)), Box::new($to_symbolic(y)))).into()
142                }
143                ($unwrap(x), Val::Symbolic(y)) => {
144                    solver.define_const($smt_op(Box::new($to_symbolic(x)), Box::new(Exp::Var(y)))).into()
145                }
146                ($unwrap(x), $unwrap(y)) => Ok($wrap($concrete_op(x, y))),
147                (_, _) => Err(ExecError::Type($name)),
148            }
149        }
150    };
151}
152
153macro_rules! binary_primop {
154    ($f:ident, $name:expr, $unwrap:path, $wrap:path, $concrete_op:path, $smt_op:path, $to_symbolic:path) => {
155        pub(crate) fn $f<B: BV>(x: Val<B>, y: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
156            match (x, y) {
157                (Val::Symbolic(x), Val::Symbolic(y)) => {
158                    solver.define_const($smt_op(Box::new(Exp::Var(x)), Box::new(Exp::Var(y)))).into()
159                }
160                (Val::Symbolic(x), $unwrap(y)) => {
161                    solver.define_const($smt_op(Box::new(Exp::Var(x)), Box::new($to_symbolic(y)))).into()
162                }
163                ($unwrap(x), Val::Symbolic(y)) => {
164                    solver.define_const($smt_op(Box::new($to_symbolic(x)), Box::new(Exp::Var(y)))).into()
165                }
166                ($unwrap(x), $unwrap(y)) => Ok($wrap($concrete_op(&x, &y))),
167                (_, _) => Err(ExecError::Type($name)),
168            }
169        }
170    };
171}
172
173fn assume<B: BV>(x: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
174    match x {
175        Val::Symbolic(v) => {
176            solver.add(Def::Assert(Exp::Var(v)));
177            Ok(Val::Unit)
178        }
179        Val::Bool(b) => {
180            if b {
181                Ok(Val::Unit)
182            } else {
183                solver.add(Def::Assert(Exp::Bool(false)));
184                Ok(Val::Unit)
185            }
186        }
187        _ => Err(ExecError::Type(format!("assert {:?}", &x))),
188    }
189}
190
191// If the assertion can succeed, it will
192fn optimistic_assert<B: BV>(x: Val<B>, message: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
193    let message = match message {
194        Val::String(message) => message,
195        _ => return Err(ExecError::Type(format!("optimistic_assert {:?}", &message))),
196    };
197    match x {
198        Val::Symbolic(v) => {
199            let test_true = Box::new(Exp::Var(v));
200            let can_be_true = solver.check_sat_with(&test_true).is_sat()?;
201            if can_be_true {
202                solver.add(Def::Assert(Exp::Var(v)));
203                Ok(Val::Unit)
204            } else {
205                Err(ExecError::AssertionFailed(message))
206            }
207        }
208        Val::Bool(b) => {
209            if b {
210                Ok(Val::Unit)
211            } else {
212                Err(ExecError::AssertionFailed(message))
213            }
214        }
215        _ => Err(ExecError::Type(format!("optimistic_assert {:?}", &x))),
216    }
217}
218
219// If the assertion can fail, it will
220fn pessimistic_assert<B: BV>(x: Val<B>, message: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
221    let message = match message {
222        Val::String(message) => message,
223        _ => return Err(ExecError::Type(format!("pessimistic_assert {:?}", &message))),
224    };
225    match x {
226        Val::Symbolic(v) => {
227            let test_false = Exp::Not(Box::new(Exp::Var(v)));
228            let can_be_false = solver.check_sat_with(&test_false).is_sat()?;
229            if can_be_false {
230                Err(ExecError::AssertionFailed(message))
231            } else {
232                Ok(Val::Unit)
233            }
234        }
235        Val::Bool(b) => {
236            if b {
237                Ok(Val::Unit)
238            } else {
239                Err(ExecError::AssertionFailed(message))
240            }
241        }
242        _ => Err(ExecError::Type(format!("pessimistic_assert {:?}", &x))),
243    }
244}
245
246// Conversion functions
247
248fn i64_to_i128<B: BV>(x: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
249    match x {
250        Val::I64(x) => Ok(Val::I128(i128::from(x))),
251        Val::Symbolic(x) => solver.define_const(Exp::SignExtend(64, Box::new(Exp::Var(x)))).into(),
252        _ => Err(ExecError::Type(format!("%i64->%i {:?}", &x))),
253    }
254}
255
256fn i128_to_i64<B: BV>(x: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
257    match x {
258        Val::I128(x) => match i64::try_from(x) {
259            Ok(y) => Ok(Val::I64(y)),
260            Err(_) => Err(ExecError::Overflow),
261        },
262        Val::Symbolic(x) => solver.define_const(Exp::Extract(63, 0, Box::new(Exp::Var(x)))).into(),
263        _ => Err(ExecError::Type(format!("%i->%i64 {:?}", &x))),
264    }
265}
266
267// FIXME: The Sail->C compilation uses xs == NULL to check if a list
268// is empty, so we replicate that here for now, but we should
269// introduce a separate @is_empty operator instead.
270pub(crate) fn op_eq<B: BV>(x: Val<B>, y: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
271    match (x, y) {
272        (Val::List(xs), Val::List(ys)) => {
273            if xs.len() != ys.len() {
274                Ok(Val::Bool(false))
275            } else if xs.is_empty() && ys.is_empty() {
276                Ok(Val::Bool(true))
277            } else {
278                Err(ExecError::Type(format!("op_eq {:?} {:?}", &xs, &ys)))
279            }
280        }
281        (x, y) => eq_anything(x, y, solver),
282    }
283}
284
285pub(crate) fn op_neq<B: BV>(x: Val<B>, y: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
286    match (x, y) {
287        (Val::List(xs), Val::List(ys)) => {
288            if xs.len() != ys.len() {
289                Ok(Val::Bool(true))
290            } else if xs.is_empty() && ys.is_empty() {
291                Ok(Val::Bool(false))
292            } else {
293                Err(ExecError::Type(format!("op_neq {:?} {:?}", &xs, &ys)))
294            }
295        }
296        (x, y) => neq_anything(x, y, solver),
297    }
298}
299
300pub(crate) fn op_head<B: BV>(xs: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
301    match xs {
302        Val::List(mut xs) => match xs.pop() {
303            Some(x) => Ok(x),
304            None => Err(ExecError::Type(format!("op_head (list empty) {:?}", &xs))),
305        },
306        _ => Err(ExecError::Type(format!("op_head {:?}", &xs))),
307    }
308}
309
310pub(crate) fn op_tail<B: BV>(xs: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
311    match xs {
312        Val::List(mut xs) => {
313            xs.pop();
314            Ok(Val::List(xs))
315        }
316        _ => Err(ExecError::Type(format!("op_tail {:?}", &xs))),
317    }
318}
319
320binary_primop!(op_lt, "op_lt".to_string(), Val::I64, Val::Bool, i64::lt, Exp::Bvslt, smt_i64);
321binary_primop!(op_gt, "op_gt".to_string(), Val::I64, Val::Bool, i64::gt, Exp::Bvsgt, smt_i64);
322binary_primop!(op_lteq, "op_lteq".to_string(), Val::I64, Val::Bool, i64::le, Exp::Bvsle, smt_i64);
323binary_primop!(op_gteq, "op_gteq".to_string(), Val::I64, Val::Bool, i64::ge, Exp::Bvsge, smt_i64);
324binary_primop_copy!(op_add, "op_add".to_string(), Val::I64, Val::I64, i64::wrapping_add, Exp::Bvadd, smt_i64);
325binary_primop_copy!(op_sub, "op_sub".to_string(), Val::I64, Val::I64, i64::wrapping_sub, Exp::Bvsub, smt_i64);
326
327pub(crate) fn bit_to_bool<B: BV>(bit: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
328    match bit {
329        Val::Bits(bit) => Ok(Val::Bool(bit == B::BIT_ONE)),
330        Val::Symbolic(bit) => {
331            solver.define_const(Exp::Eq(Box::new(Exp::Bits([true].to_vec())), Box::new(Exp::Var(bit)))).into()
332        }
333        _ => Err(ExecError::Type(format!("bit_to_bool {:?}", &bit))),
334    }
335}
336
337pub(crate) fn op_unsigned<B: BV>(bits: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
338    match bits {
339        Val::Bits(bits) => Ok(Val::I64(bits.unsigned() as i64)),
340        Val::Symbolic(bits) => match solver.length(bits) {
341            Some(length) => solver.define_const(Exp::ZeroExtend(64 - length, Box::new(Exp::Var(bits)))).into(),
342            None => Err(ExecError::Type(format!("op_unsigned {:?}", &bits))),
343        },
344        _ => Err(ExecError::Type(format!("op_unsigned {:?}", &bits))),
345    }
346}
347
348pub(crate) fn op_signed<B: BV>(bits: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
349    match bits {
350        Val::Bits(bits) => Ok(Val::I64(bits.signed() as i64)),
351        Val::Symbolic(bits) => match solver.length(bits) {
352            Some(length) => solver.define_const(Exp::SignExtend(64 - length, Box::new(Exp::Var(bits)))).into(),
353            None => Err(ExecError::Type(format!("op_unsigned (solver cannot determine length) {:?}", &bits))),
354        },
355        _ => Err(ExecError::Type(format!("op_unsigned {:?}", &bits))),
356    }
357}
358
359// Basic comparisons
360
361unary_primop_copy!(not_bool, "not".to_string(), Val::Bool, Val::Bool, bool::not, Exp::Not);
362binary_primop_copy!(and_bool, "and_bool".to_string(), Val::Bool, Val::Bool, bool::bitand, Exp::And, Exp::Bool);
363binary_primop_copy!(or_bool, "or_bool".to_string(), Val::Bool, Val::Bool, bool::bitor, Exp::Or, Exp::Bool);
364binary_primop!(eq_int, "eq_int".to_string(), Val::I128, Val::Bool, i128::eq, Exp::Eq, smt_i128);
365binary_primop!(eq_bool, "eq_bool".to_string(), Val::Bool, Val::Bool, bool::eq, Exp::Eq, Exp::Bool);
366binary_primop!(lteq_int, "lteq".to_string(), Val::I128, Val::Bool, i128::le, Exp::Bvsle, smt_i128);
367binary_primop!(gteq_int, "gteq".to_string(), Val::I128, Val::Bool, i128::ge, Exp::Bvsge, smt_i128);
368binary_primop!(lt_int, "lt".to_string(), Val::I128, Val::Bool, i128::lt, Exp::Bvslt, smt_i128);
369binary_primop!(gt_int, "gt".to_string(), Val::I128, Val::Bool, i128::gt, Exp::Bvsgt, smt_i128);
370
371fn abs_int<B: BV>(x: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
372    match x {
373        Val::I128(x) => Ok(Val::I128(x.abs())),
374        Val::Symbolic(x) => {
375            let y = solver.fresh();
376            solver.add(Def::DefineConst(
377                y,
378                Exp::Ite(
379                    Box::new(Exp::Bvslt(Box::new(Exp::Var(x)), Box::new(smt_i128(0)))),
380                    Box::new(Exp::Bvneg(Box::new(Exp::Var(x)))),
381                    Box::new(Exp::Var(x)),
382                ),
383            ));
384            Ok(Val::Symbolic(y))
385        }
386        _ => Err(ExecError::Type(format!("abs_int {:?}", &x))),
387    }
388}
389
390// Arithmetic operations
391
392binary_primop_copy!(sub_int, "sub_int".to_string(), Val::I128, Val::I128, i128::wrapping_sub, Exp::Bvsub, smt_i128);
393binary_primop_copy!(mult_int, "mult_int".to_string(), Val::I128, Val::I128, i128::wrapping_mul, Exp::Bvmul, smt_i128);
394unary_primop_copy!(neg_int, "neg_int".to_string(), Val::I128, Val::I128, i128::wrapping_neg, Exp::Bvneg);
395binary_primop_copy!(tdiv_int, "tdiv_int".to_string(), Val::I128, Val::I128, i128::wrapping_div, Exp::Bvsdiv, smt_i128);
396binary_primop_copy!(tmod_int, "tmod_int".to_string(), Val::I128, Val::I128, i128::wrapping_rem, Exp::Bvsmod, smt_i128);
397binary_primop_copy!(shl_int, "shl_int".to_string(), Val::I128, Val::I128, i128::shl, Exp::Bvshl, smt_i128);
398binary_primop_copy!(shr_int, "shr_int".to_string(), Val::I128, Val::I128, i128::shr, Exp::Bvashr, smt_i128);
399binary_primop_copy!(shl_mach_int, "shl_mach_int".to_string(), Val::I64, Val::I64, i64::shl, Exp::Bvshl, smt_i64);
400binary_primop_copy!(shr_mach_int, "shr_mach_int".to_string(), Val::I64, Val::I64, i64::shr, Exp::Bvashr, smt_i64);
401binary_primop_copy!(udiv_int, "udiv_int".to_string(), Val::I128, Val::I128, i128::wrapping_div, Exp::Bvudiv, smt_i128);
402
403pub(crate) fn add_int<B: BV>(x: Val<B>, y: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
404    match (x, y) {
405        (Val::Symbolic(x), Val::Symbolic(y)) => {
406            solver.define_const(Exp::Bvadd(Box::new(Exp::Var(x)), Box::new(Exp::Var(y)))).into()
407        }
408        (Val::Symbolic(x), Val::I128(y)) => {
409            if y != 0 {
410                solver.define_const(Exp::Bvadd(Box::new(Exp::Var(x)), Box::new(smt_i128(y)))).into()
411            } else {
412                Ok(Val::Symbolic(x))
413            }
414        }
415        (Val::I128(x), Val::Symbolic(y)) => {
416            if x != 0 {
417                solver.define_const(Exp::Bvadd(Box::new(smt_i128(x)), Box::new(Exp::Var(y)))).into()
418            } else {
419                Ok(Val::Symbolic(y))
420            }
421        }
422        (Val::I128(x), Val::I128(y)) => Ok(Val::I128(i128::wrapping_add(x, y))),
423        (x, y) => Err(ExecError::Type(format!("add_int {:?} {:?}", &x, &y))),
424    }
425}
426
427macro_rules! symbolic_compare {
428    ($op: path, $x: expr, $y: expr, $solver: ident) => {{
429        let z = $solver.fresh();
430        $solver
431            .add(Def::DefineConst(z, Exp::Ite(Box::new($op(Box::new($x), Box::new($y))), Box::new($x), Box::new($y))));
432        Ok(Val::Symbolic(z))
433    }};
434}
435
436fn max_int<B: BV>(x: Val<B>, y: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
437    match (x, y) {
438        (Val::I128(x), Val::I128(y)) => Ok(Val::I128(i128::max(x, y))),
439        (Val::I128(x), Val::Symbolic(y)) => symbolic_compare!(Exp::Bvsgt, smt_i128(x), Exp::Var(y), solver),
440        (Val::Symbolic(x), Val::I128(y)) => symbolic_compare!(Exp::Bvsgt, Exp::Var(x), smt_i128(y), solver),
441        (Val::Symbolic(x), Val::Symbolic(y)) => symbolic_compare!(Exp::Bvsgt, Exp::Var(x), Exp::Var(y), solver),
442        (x, y) => Err(ExecError::Type(format!("max_int {:?} {:?}", &x, &y))),
443    }
444}
445
446fn min_int<B: BV>(x: Val<B>, y: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
447    match (x, y) {
448        (Val::I128(x), Val::I128(y)) => Ok(Val::I128(i128::min(x, y))),
449        (Val::I128(x), Val::Symbolic(y)) => symbolic_compare!(Exp::Bvslt, smt_i128(x), Exp::Var(y), solver),
450        (Val::Symbolic(x), Val::I128(y)) => symbolic_compare!(Exp::Bvslt, Exp::Var(x), smt_i128(y), solver),
451        (Val::Symbolic(x), Val::Symbolic(y)) => symbolic_compare!(Exp::Bvslt, Exp::Var(x), Exp::Var(y), solver),
452        (x, y) => Err(ExecError::Type(format!("max_int {:?} {:?}", &x, &y))),
453    }
454}
455
456fn pow2<B: BV>(x: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
457    match x {
458        Val::I128(x) => Ok(Val::I128(1 << x)),
459        Val::Symbolic(x) => solver.define_const(Exp::Bvshl(Box::new(smt_i128(1)), Box::new(Exp::Var(x)))).into(),
460        _ => Err(ExecError::Type(format!("pow2 {:?}", &x))),
461    }
462}
463
464fn pow_int<B: BV>(x: Val<B>, y: Val<B>, _solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
465    match (x, y) {
466        (Val::I128(x), Val::I128(y)) => Ok(Val::I128(x.pow(y.try_into().map_err(|_| ExecError::Overflow)?))),
467        (x, y) => Err(ExecError::Type(format!("pow_int {:?} {:?}", &x, &y))),
468    }
469}
470
471fn sub_nat<B: BV>(x: Val<B>, y: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
472    match (x, y) {
473        (Val::I128(x), Val::I128(y)) => Ok(Val::I128(i128::max(x - y, 0))),
474        (Val::I128(x), Val::Symbolic(y)) => {
475            symbolic_compare!(Exp::Bvsgt, Exp::Bvsub(Box::new(smt_i128(x)), Box::new(Exp::Var(y))), smt_i128(0), solver)
476        }
477        (Val::Symbolic(x), Val::I128(y)) => {
478            symbolic_compare!(Exp::Bvsgt, Exp::Bvsub(Box::new(Exp::Var(x)), Box::new(smt_i128(y))), smt_i128(0), solver)
479        }
480        (Val::Symbolic(x), Val::Symbolic(y)) => {
481            symbolic_compare!(Exp::Bvsgt, Exp::Bvsub(Box::new(Exp::Var(x)), Box::new(Exp::Var(y))), smt_i128(0), solver)
482        }
483        (x, y) => Err(ExecError::Type(format!("sub_nat {:?} {:?}", &x, &y))),
484    }
485}
486
487// Bitvector operations
488
489fn length<B: BV>(x: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
490    match x {
491        Val::Symbolic(v) => match solver.length(v) {
492            Some(len) => Ok(Val::I128(i128::from(len))),
493            None => Err(ExecError::Type(format!("length (solver cannot determine length) {:?}", &v))),
494        },
495        Val::Bits(bv) => Ok(Val::I128(bv.len_i128())),
496        _ => Err(ExecError::Type(format!("length {:?}", &x))),
497    }
498}
499
500binary_primop!(eq_bits, "eq_bits".to_string(), Val::Bits, Val::Bool, B::eq, Exp::Eq, smt_sbits);
501binary_primop!(neq_bits, "neq_bits".to_string(), Val::Bits, Val::Bool, B::ne, Exp::Neq, smt_sbits);
502unary_primop_copy!(not_bits, "not_bits".to_string(), Val::Bits, Val::Bits, B::not, Exp::Bvnot);
503binary_primop_copy!(xor_bits, "xor_bits".to_string(), Val::Bits, Val::Bits, B::bitxor, Exp::Bvxor, smt_sbits);
504binary_primop_copy!(or_bits, "or_bits".to_string(), Val::Bits, Val::Bits, B::bitor, Exp::Bvor, smt_sbits);
505binary_primop_copy!(and_bits, "and_bits".to_string(), Val::Bits, Val::Bits, B::bitand, Exp::Bvand, smt_sbits);
506binary_primop_copy!(add_bits, "add_bits".to_string(), Val::Bits, Val::Bits, B::add, Exp::Bvadd, smt_sbits);
507binary_primop_copy!(sub_bits, "sub_bits".to_string(), Val::Bits, Val::Bits, B::sub, Exp::Bvsub, smt_sbits);
508
509fn add_bits_int<B: BV>(bits: Val<B>, n: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
510    match (bits, n) {
511        (Val::Bits(bits), Val::I128(n)) => Ok(Val::Bits(bits.add_i128(n))),
512        (Val::Symbolic(bits), Val::I128(n)) => {
513            let result = solver.fresh();
514            let len = match solver.length(bits) {
515                Some(len) => len,
516                None => {
517                    return Err(ExecError::Type(format!(
518                        "add_bits_int (solver cannot determine length) {:?} {:?}",
519                        &bits, &n
520                    )))
521                }
522            };
523            assert!(len <= 128);
524            solver.add(Def::DefineConst(
525                result,
526                Exp::Bvadd(Box::new(Exp::Var(bits)), Box::new(Exp::Extract(len - 1, 0, Box::new(smt_i128(n))))),
527            ));
528            Ok(Val::Symbolic(result))
529        }
530        (Val::Symbolic(bits), Val::Symbolic(n)) => {
531            let result = solver.fresh();
532            let len = match solver.length(bits) {
533                Some(len) => len,
534                None => {
535                    return Err(ExecError::Type(format!(
536                        "add_bits_int (solver cannot determine length) {:?} {:?}",
537                        &bits, &n
538                    )))
539                }
540            };
541            assert!(len <= 128);
542            solver.add(Def::DefineConst(
543                result,
544                Exp::Bvadd(Box::new(Exp::Var(bits)), Box::new(Exp::Extract(len - 1, 0, Box::new(Exp::Var(n))))),
545            ));
546            Ok(Val::Symbolic(result))
547        }
548        (bits, n) => Err(ExecError::Type(format!("add_bits_int {:?} {:?}", &bits, &n))),
549    }
550}
551
552fn sub_bits_int<B: BV>(bits: Val<B>, n: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
553    match (bits, n) {
554        (Val::Bits(bits), Val::I128(n)) => Ok(Val::Bits(bits.sub_i128(n))),
555        (Val::Symbolic(bits), Val::I128(n)) => {
556            let result = solver.fresh();
557            let len = match solver.length(bits) {
558                Some(len) => len,
559                None => {
560                    return Err(ExecError::Type(format!(
561                        "sub_bits_int (solver cannot determine length) {:?} {:?}",
562                        &bits, &n
563                    )))
564                }
565            };
566            assert!(len <= 128);
567            solver.add(Def::DefineConst(
568                result,
569                Exp::Bvsub(Box::new(Exp::Var(bits)), Box::new(Exp::Extract(len - 1, 0, Box::new(smt_i128(n))))),
570            ));
571            Ok(Val::Symbolic(result))
572        }
573        (Val::Symbolic(bits), Val::Symbolic(n)) => {
574            let result = solver.fresh();
575            let len = match solver.length(bits) {
576                Some(len) => len,
577                None => {
578                    return Err(ExecError::Type(format!(
579                        "sub_bits_int (solver cannot determine length) {:?} {:?}",
580                        &bits, &n
581                    )))
582                }
583            };
584            assert!(len <= 128);
585            solver.add(Def::DefineConst(
586                result,
587                Exp::Bvsub(Box::new(Exp::Var(bits)), Box::new(Exp::Extract(len - 1, 0, Box::new(Exp::Var(n))))),
588            ));
589            Ok(Val::Symbolic(result))
590        }
591        (bits, n) => Err(ExecError::Type(format!("sub_bits_int {:?} {:?}", &bits, &n))),
592    }
593}
594
595fn zeros<B: BV>(len: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
596    match len {
597        Val::I128(len) => {
598            if len <= B::MAX_WIDTH as i128 {
599                Ok(Val::Bits(B::zeros(len as u32)))
600            } else {
601                solver.define_const(smt_zeros(len)).into()
602            }
603        }
604        Val::Symbolic(_) => Err(ExecError::SymbolicLength("zeros")),
605        _ => Err(ExecError::Type(format!("zeros {:?}", &len))),
606    }
607}
608
609fn ones<B: BV>(len: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
610    match len {
611        Val::I128(len) => {
612            if len <= B::MAX_WIDTH as i128 {
613                Ok(Val::Bits(B::ones(len as u32)))
614            } else {
615                solver.define_const(smt_ones(len)).into()
616            }
617        }
618        Val::Symbolic(_) => Err(ExecError::SymbolicLength("ones")),
619        _ => Err(ExecError::Type(format!("ones {:?}", &len))),
620    }
621}
622
623/// The zero_extend and sign_extend functions are essentially the
624/// same, so use a macro to define both.
625macro_rules! extension {
626    ($id: ident, $name: expr, $smt_extension: path, $concrete_extension: path) => {
627        pub fn $id<B: BV>(bits: Val<B>, len: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
628            match (bits, len) {
629                (Val::Bits(bits), Val::I128(len)) => {
630                    let len = len as u32;
631                    if len > B::MAX_WIDTH {
632                        let ext = len - bits.len();
633                        solver.define_const($smt_extension(ext, Box::new(smt_sbits(bits)))).into()
634                    } else {
635                        Ok(Val::Bits($concrete_extension(bits, len)))
636                    }
637                }
638                (Val::Symbolic(bits), Val::I128(len)) => {
639                    let ext = match solver.length(bits) {
640                        Some(orig_len) => len as u32 - orig_len,
641                        None => return Err(ExecError::Type($name)),
642                    };
643                    solver.define_const($smt_extension(ext, Box::new(Exp::Var(bits)))).into()
644                }
645                (_, Val::Symbolic(_)) => Err(ExecError::SymbolicLength("extension")),
646                (_, _) => Err(ExecError::Type($name)),
647            }
648        }
649    };
650}
651
652extension!(zero_extend, "zero_extend".to_string(), Exp::ZeroExtend, B::zero_extend);
653extension!(sign_extend, "sign_extend".to_string(), Exp::SignExtend, B::sign_extend);
654
655pub(crate) fn op_zero_extend<B: BV>(bits: Val<B>, len: u32, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
656    match bits {
657        Val::Bits(bits) => {
658            if len > 64 {
659                let ext = len - bits.len();
660                solver.define_const(Exp::ZeroExtend(ext, Box::new(smt_sbits(bits)))).into()
661            } else {
662                Ok(Val::Bits(B::zero_extend(bits, len)))
663            }
664        }
665        Val::Symbolic(bits) => {
666            let ext = match solver.length(bits) {
667                Some(orig_len) => len - orig_len,
668                None => {
669                    return Err(ExecError::Type(format!("op_zero_extend (solver cannot determine length) {:?}", &bits)))
670                }
671            };
672            solver.define_const(Exp::ZeroExtend(ext, Box::new(Exp::Var(bits)))).into()
673        }
674        _ => Err(ExecError::Type(format!("op_zero_extend {:?}", &bits))),
675    }
676}
677
678fn replicate_exp(bits: Exp, times: i128) -> Exp {
679    if times == 0 {
680        bits64(0, 0)
681    } else if times == 1 {
682        bits
683    } else {
684        Exp::Concat(Box::new(bits.clone()), Box::new(replicate_exp(bits, times - 1)))
685    }
686}
687
688fn replicate_bits<B: BV>(bits: Val<B>, times: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
689    match (bits, times) {
690        (Val::Bits(bits), Val::I128(times)) => match bits.replicate(times) {
691            Some(replicated) => Ok(Val::Bits(replicated)),
692            None => solver.define_const(replicate_exp(smt_sbits(bits), times)).into(),
693        },
694        (Val::Symbolic(bits), Val::I128(times)) => {
695            if times == 0 {
696                Ok(Val::Bits(B::zeros(0)))
697            } else {
698                solver.define_const(replicate_exp(Exp::Var(bits), times)).into()
699            }
700        }
701        (bits, times) => Err(ExecError::Type(format!("replicate_bits {:?} {:?}", &bits, &times))),
702    }
703}
704
705/// Return the length of a concrete or symbolic bitvector, or return
706/// [ExecError::Type] if the argument value is not a
707/// bitvector.
708pub fn length_bits<B: BV>(bits: &Val<B>, solver: &mut Solver<B>) -> Result<u32, ExecError> {
709    match bits {
710        Val::Bits(bits) => Ok(bits.len()),
711        Val::Symbolic(bits) => match solver.length(*bits) {
712            Some(len) => Ok(len),
713            None => Err(ExecError::Type(format!("length_bits (solver cannot determine length) {:?}", &bits))),
714        },
715        _ => Err(ExecError::Type(format!("length_bits {:?}", &bits))),
716    }
717}
718
719/// This macro implements the symbolic slice operation for anything
720/// that is implemented as a bitvector in the SMT solver, so it can be
721/// used for slice, get_slice_int, etc.
722macro_rules! slice {
723    ($bits_length: expr, $bits: expr, $from: expr, $slice_length: expr, $solver: ident) => {{
724        assert!(($slice_length as u32) <= $bits_length);
725        match $from {
726            _ if $slice_length == 0 => Ok(Val::Bits(B::zeros(0))),
727
728            Val::Symbolic(from) => {
729                let sliced = $solver.fresh();
730                // As from is symbolic we need to use bvlshr to do a
731                // left shift before extracting between length - 1 to
732                // 0. We therefore need to make from the correct
733                // length so the bvlshr is type-correct.
734                let shift = if $bits_length > 128 {
735                    Exp::ZeroExtend($bits_length - 128, Box::new(Exp::Var(from)))
736                } else if $bits_length < 128 {
737                    Exp::Extract($bits_length - 1, 0, Box::new(Exp::Var(from)))
738                } else {
739                    Exp::Var(from)
740                };
741                $solver.add(Def::DefineConst(
742                    sliced,
743                    Exp::Extract($slice_length as u32 - 1, 0, Box::new(Exp::Bvlshr(Box::new($bits), Box::new(shift)))),
744                ));
745                Ok(Val::Symbolic(sliced))
746            }
747
748            Val::I128(from) => {
749                let sliced = $solver.fresh();
750                if from == 0 && ($slice_length as u32) == $bits_length {
751                    $solver.add(Def::DefineConst(sliced, $bits))
752                } else {
753                    $solver.add(Def::DefineConst(
754                        sliced,
755                        Exp::Extract((from + $slice_length - 1) as u32, from as u32, Box::new($bits)),
756                    ))
757                }
758                Ok(Val::Symbolic(sliced))
759            }
760
761            Val::I64(from) => {
762                let sliced = $solver.fresh();
763                if from == 0 && ($slice_length as u32) == $bits_length {
764                    $solver.add(Def::DefineConst(sliced, $bits))
765                } else {
766                    $solver.add(Def::DefineConst(
767                        sliced,
768                        Exp::Extract((from as i128 + $slice_length - 1) as u32, from as u32, Box::new($bits)),
769                    ))
770                }
771                Ok(Val::Symbolic(sliced))
772            }
773
774            _ => Err(ExecError::Type(format!("slice! {:?}", &$from))),
775        }
776    }};
777}
778
779pub(crate) fn op_slice<B: BV>(
780    bits: Val<B>,
781    from: Val<B>,
782    length: u32,
783    solver: &mut Solver<B>,
784) -> Result<Val<B>, ExecError> {
785    let bits_length = length_bits(&bits, solver)?;
786    match bits {
787        Val::Symbolic(bits) => slice!(bits_length, Exp::Var(bits), from, length as i128, solver),
788        Val::Bits(bits) => match from {
789            Val::I64(from) => match bits.slice(from as u32, length) {
790                Some(bits) => Ok(Val::Bits(bits)),
791                None => Err(ExecError::Type("op_slice (can't slice)".to_string())),
792            },
793            _ if bits.is_zero() => Ok(Val::Bits(B::zeros(bits_length))),
794            _ => slice!(bits_length, smt_sbits(bits), from, length as i128, solver),
795        },
796        _ => Err(ExecError::Type(format!("op_slice {:?}", &bits))),
797    }
798}
799
800fn slice_internal<B: BV>(
801    bits: Val<B>,
802    from: Val<B>,
803    length: Val<B>,
804    solver: &mut Solver<B>,
805) -> Result<Val<B>, ExecError> {
806    let bits_length = length_bits(&bits, solver)?;
807    match length {
808        Val::I128(length) => match bits {
809            Val::Symbolic(bits) => slice!(bits_length, Exp::Var(bits), from, length, solver),
810            Val::Bits(bits) => match from {
811                Val::I128(from) => match bits.slice(from as u32, length as u32) {
812                    Some(bits) => Ok(Val::Bits(bits)),
813                    None => {
814                        // Out-of-range slices shouldn't happen in IR from well-typed Sail, but linearization can
815                        // produce them (although the result will be thrown away).  This should match the semantics
816                        // of the symbolic case but isn't tested because the results aren't used.
817                        match bits.shiftr(from).slice(0, length as u32) {
818                            Some(bits) => Ok(Val::Bits(bits)),
819                            None => {
820                                Err(ExecError::Type(format!("slice_internal (cannot slice) {:?} {:?}", &from, &length)))
821                            }
822                        }
823                    }
824                },
825                _ if bits.is_zero() => Ok(Val::Bits(B::zeros(bits_length))),
826                _ => slice!(bits_length, smt_sbits(bits), from, length, solver),
827            },
828            _ => Err(ExecError::Type(format!("slice_internal {:?}", &bits))),
829        },
830        Val::Symbolic(_) => Err(ExecError::SymbolicLength("slice_internal")),
831        _ => Err(ExecError::Type(format!("slice_internal {:?}", &length))),
832    }
833}
834
835fn slice<B: BV>(args: Vec<Val<B>>, solver: &mut Solver<B>, _: &mut LocalFrame<B>) -> Result<Val<B>, ExecError> {
836    slice_internal(args[0].clone(), args[1].clone(), args[2].clone(), solver)
837}
838
839pub fn subrange_internal<B: BV>(
840    bits: Val<B>,
841    high: Val<B>,
842    low: Val<B>,
843    solver: &mut Solver<B>,
844) -> Result<Val<B>, ExecError> {
845    match (bits, high, low) {
846        (Val::Symbolic(bits), Val::I128(high), Val::I128(low)) => {
847            solver.define_const(Exp::Extract(high as u32, low as u32, Box::new(Exp::Var(bits)))).into()
848        }
849        (Val::Bits(bits), Val::I128(high), Val::I128(low)) => match bits.extract(high as u32, low as u32) {
850            Some(bits) => Ok(Val::Bits(bits)),
851            None => {
852                Err(ExecError::Type(format!("subrange_internal (cannot extract) {:?} {:?} {:?}", &bits, &high, &low)))
853            }
854        },
855        (_, _, Val::Symbolic(_)) => Err(ExecError::SymbolicLength("subrange_internal")),
856        (_, Val::Symbolic(_), _) => Err(ExecError::SymbolicLength("subrange_internal")),
857        (bits, high, low) => Err(ExecError::Type(format!("subrange_internal {:?} {:?} {:?}", &bits, &high, &low))),
858    }
859}
860
861fn subrange<B: BV>(args: Vec<Val<B>>, solver: &mut Solver<B>, _: &mut LocalFrame<B>) -> Result<Val<B>, ExecError> {
862    subrange_internal(args[0].clone(), args[1].clone(), args[2].clone(), solver)
863}
864
865fn sail_truncate<B: BV>(bits: Val<B>, len: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
866    slice_internal(bits, Val::I128(0), len, solver)
867}
868
869fn sail_truncate_lsb<B: BV>(bits: Val<B>, len: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
870    match (bits, len) {
871        (Val::Bits(bits), Val::I128(len)) => match bits.truncate_lsb(len) {
872            Some(truncated) => Ok(Val::Bits(truncated)),
873            None => Err(ExecError::Type(format!("sail_truncateLSB (cannot truncate) {:?} {:?}", &bits, &len))),
874        },
875        (Val::Symbolic(bits), Val::I128(len)) => {
876            if len == 0 {
877                Ok(Val::Bits(B::new(0, 0)))
878            } else if let Some(orig_len) = solver.length(bits) {
879                let low = orig_len - (len as u32);
880                solver.define_const(Exp::Extract(orig_len - 1, low, Box::new(Exp::Var(bits)))).into()
881            } else {
882                Err(ExecError::Type(format!("sail_truncateLSB (invalid length) {:?} {:?}", &bits, &len)))
883            }
884        }
885        (_, Val::Symbolic(_)) => Err(ExecError::SymbolicLength("sail_truncateLSB")),
886        (bits, len) => Err(ExecError::Type(format!("sail_truncateLSB {:?} {:?}", &bits, &len))),
887    }
888}
889
890fn sail_unsigned<B: BV>(bits: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
891    match bits {
892        Val::Bits(bits) => Ok(Val::I128(bits.unsigned())),
893        Val::Symbolic(bits) => match solver.length(bits) {
894            Some(length) => {
895                assert!(length < 128);
896                solver.define_const(Exp::ZeroExtend(128 - length, Box::new(Exp::Var(bits)))).into()
897            }
898            None => Err(ExecError::Type(format!("sail_unsigned (solver cannot determine length) {:?}", &bits))),
899        },
900        _ => Err(ExecError::Type(format!("sail_unsigned {:?}", &bits))),
901    }
902}
903
904fn sail_signed<B: BV>(bits: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
905    match bits {
906        Val::Bits(bits) => Ok(Val::I128(bits.signed())),
907        Val::Symbolic(bits) => match solver.length(bits) {
908            Some(length) => {
909                assert!(length < 128);
910                solver.define_const(Exp::SignExtend(128 - length, Box::new(Exp::Var(bits)))).into()
911            }
912            None => Err(ExecError::Type(format!("sail_signed (solver cannot determine length) {:?}", &bits))),
913        },
914        _ => Err(ExecError::Type(format!("sail_signed {:?}", &bits))),
915    }
916}
917
918fn shiftr<B: BV>(bits: Val<B>, shift: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
919    match (bits, shift) {
920        (Val::Symbolic(x), Val::Symbolic(y)) => match solver.length(x) {
921            Some(length) => {
922                let shift = if length < 128 {
923                    Exp::Extract(length - 1, 0, Box::new(Exp::Var(y)))
924                } else if length > 128 {
925                    Exp::ZeroExtend(length - 128, Box::new(Exp::Var(y)))
926                } else {
927                    Exp::Var(y)
928                };
929                solver.define_const(Exp::Bvlshr(Box::new(Exp::Var(x)), Box::new(shift))).into()
930            }
931            None => Err(ExecError::Type(format!("shiftr {:?} {:?}", &x, &y))),
932        },
933        (Val::Symbolic(x), Val::I128(0)) => Ok(Val::Symbolic(x)),
934        (Val::Symbolic(x), Val::I128(y)) => match solver.length(x) {
935            Some(length) => {
936                let shift = if length < 128 {
937                    Exp::Extract(length - 1, 0, Box::new(smt_i128(y)))
938                } else if length > 128 {
939                    Exp::ZeroExtend(length - 128, Box::new(smt_i128(y)))
940                } else {
941                    smt_i128(y)
942                };
943                solver.define_const(Exp::Bvlshr(Box::new(Exp::Var(x)), Box::new(shift))).into()
944            }
945            None => Err(ExecError::Type(format!("shiftr {:?} {:?}", &x, &y))),
946        },
947        (Val::Bits(x), Val::Symbolic(y)) => solver
948            .define_const(Exp::Bvlshr(
949                Box::new(smt_sbits(x)),
950                Box::new(Exp::Extract(x.len() - 1, 0, Box::new(Exp::Var(y)))),
951            ))
952            .into(),
953        (Val::Bits(x), Val::I128(y)) => Ok(Val::Bits(x.shiftr(y))),
954        (bits, shift) => Err(ExecError::Type(format!("shiftr {:?} {:?}", &bits, &shift))),
955    }
956}
957
958fn arith_shiftr<B: BV>(bits: Val<B>, shift: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
959    match (bits, shift) {
960        (Val::Symbolic(x), Val::Symbolic(y)) => match solver.length(x) {
961            Some(length) => {
962                let shift = if length < 128 {
963                    Exp::Extract(length - 1, 0, Box::new(Exp::Var(y)))
964                } else if length > 128 {
965                    Exp::ZeroExtend(length - 128, Box::new(Exp::Var(y)))
966                } else {
967                    Exp::Var(y)
968                };
969                solver.define_const(Exp::Bvashr(Box::new(Exp::Var(x)), Box::new(shift))).into()
970            }
971            None => Err(ExecError::Type(format!("arith_shiftr {:?} {:?}", &x, &y))),
972        },
973        (Val::Symbolic(x), Val::I128(0)) => Ok(Val::Symbolic(x)),
974        (Val::Symbolic(x), Val::I128(y)) => match solver.length(x) {
975            Some(length) => {
976                let shift = if length < 128 {
977                    Exp::Extract(length - 1, 0, Box::new(smt_i128(y)))
978                } else if length > 128 {
979                    Exp::ZeroExtend(length - 128, Box::new(smt_i128(y)))
980                } else {
981                    smt_i128(y)
982                };
983                solver.define_const(Exp::Bvashr(Box::new(Exp::Var(x)), Box::new(shift))).into()
984            }
985            None => Err(ExecError::Type(format!("arith_shiftr {:?} {:?}", &x, &y))),
986        },
987        (Val::Bits(x), Val::Symbolic(y)) => solver
988            .define_const(Exp::Bvashr(
989                Box::new(smt_sbits(x)),
990                Box::new(Exp::Extract(x.len() - 1, 0, Box::new(Exp::Var(y)))),
991            ))
992            .into(),
993        (Val::Bits(x), Val::I128(y)) => Ok(Val::Bits(x.arith_shiftr(y))),
994        (bits, shift) => Err(ExecError::Type(format!("arith_shiftr {:?} {:?}", &bits, &shift))),
995    }
996}
997
998fn shiftl<B: BV>(bits: Val<B>, len: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
999    match (bits, len) {
1000        (Val::Symbolic(x), Val::Symbolic(y)) => match solver.length(x) {
1001            Some(length) => {
1002                let shift = if length < 128 {
1003                    Exp::Extract(length - 1, 0, Box::new(Exp::Var(y)))
1004                } else if length > 128 {
1005                    Exp::ZeroExtend(length - 128, Box::new(Exp::Var(y)))
1006                } else {
1007                    Exp::Var(y)
1008                };
1009                solver.define_const(Exp::Bvshl(Box::new(Exp::Var(x)), Box::new(shift))).into()
1010            }
1011            None => Err(ExecError::Type(format!("shiftl {:?} {:?}", &x, &y))),
1012        },
1013        (Val::Symbolic(x), Val::I128(0)) => Ok(Val::Symbolic(x)),
1014        (Val::Symbolic(x), Val::I128(y)) => match solver.length(x) {
1015            Some(length) => {
1016                let shift = if length < 128 {
1017                    Exp::Extract(length - 1, 0, Box::new(smt_i128(y)))
1018                } else if length > 128 {
1019                    Exp::ZeroExtend(length - 128, Box::new(smt_i128(y)))
1020                } else {
1021                    smt_i128(y)
1022                };
1023                solver.define_const(Exp::Bvshl(Box::new(Exp::Var(x)), Box::new(shift))).into()
1024            }
1025            None => Err(ExecError::Type(format!("shiftl {:?} {:?}", &x, &y))),
1026        },
1027        (Val::Bits(x), Val::Symbolic(y)) => solver
1028            .define_const(Exp::Bvshl(
1029                Box::new(smt_sbits(x)),
1030                Box::new(Exp::Extract(x.len() - 1, 0, Box::new(Exp::Var(y)))),
1031            ))
1032            .into(),
1033        (Val::Bits(x), Val::I128(y)) => Ok(Val::Bits(x.shiftl(y))),
1034        (bits, len) => Err(ExecError::Type(format!("shiftl {:?} {:?}", &bits, &len))),
1035    }
1036}
1037
1038fn shift_bits_right<B: BV>(bits: Val<B>, shift: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1039    let bits_len = length_bits(&bits, solver)?;
1040    let shift_len = length_bits(&bits, solver)?;
1041    match (&bits, &shift) {
1042        (Val::Symbolic(_), Val::Symbolic(_)) | (Val::Bits(_), Val::Symbolic(_)) | (Val::Symbolic(_), Val::Bits(_)) => {
1043            let shift = if bits_len < shift_len {
1044                Exp::Extract(bits_len - 1, 0, Box::new(smt_value(&shift)?))
1045            } else if bits_len > shift_len {
1046                Exp::ZeroExtend(bits_len - shift_len, Box::new(smt_value(&shift)?))
1047            } else {
1048                smt_value(&shift)?
1049            };
1050            solver.define_const(Exp::Bvlshr(Box::new(smt_value(&bits)?), Box::new(shift))).into()
1051        }
1052        (Val::Bits(x), Val::Bits(y)) => {
1053            let shift: u64 = (*y).try_into()?;
1054            Ok(Val::Bits(x.shiftr(shift as i128)))
1055        }
1056        (_, _) => Err(ExecError::Type(format!("shift_bits_right {:?} {:?}", &bits, &shift))),
1057    }
1058}
1059
1060fn shift_bits_left<B: BV>(bits: Val<B>, shift: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1061    let bits_len = length_bits(&bits, solver)?;
1062    let shift_len = length_bits(&bits, solver)?;
1063    match (&bits, &shift) {
1064        (Val::Symbolic(_), Val::Symbolic(_)) | (Val::Bits(_), Val::Symbolic(_)) | (Val::Symbolic(_), Val::Bits(_)) => {
1065            let shift = if bits_len < shift_len {
1066                Exp::Extract(bits_len - 1, 0, Box::new(smt_value(&shift)?))
1067            } else if bits_len > shift_len {
1068                Exp::ZeroExtend(bits_len - shift_len, Box::new(smt_value(&shift)?))
1069            } else {
1070                smt_value(&shift)?
1071            };
1072            solver.define_const(Exp::Bvshl(Box::new(smt_value(&bits)?), Box::new(shift))).into()
1073        }
1074        (Val::Bits(x), Val::Bits(y)) => {
1075            let shift: u64 = (*y).try_into()?;
1076            Ok(Val::Bits(x.shiftl(shift as i128)))
1077        }
1078        (_, _) => Err(ExecError::Type(format!("shift_bits_left {:?} {:?}", &bits, &shift))),
1079    }
1080}
1081
1082pub(crate) fn append<B: BV>(lhs: Val<B>, rhs: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1083    match (lhs, rhs) {
1084        (Val::Symbolic(x), Val::Symbolic(y)) => {
1085            solver.define_const(Exp::Concat(Box::new(Exp::Var(x)), Box::new(Exp::Var(y)))).into()
1086        }
1087        (Val::Symbolic(x), Val::Bits(y)) => {
1088            if y.len() == 0 {
1089                solver.define_const(Exp::Var(x)).into()
1090            } else {
1091                solver.define_const(Exp::Concat(Box::new(Exp::Var(x)), Box::new(smt_sbits(y)))).into()
1092            }
1093        }
1094        (Val::Bits(x), Val::Symbolic(y)) => {
1095            if x.len() == 0 {
1096                solver.define_const(Exp::Var(y)).into()
1097            } else {
1098                solver.define_const(Exp::Concat(Box::new(smt_sbits(x)), Box::new(Exp::Var(y)))).into()
1099            }
1100        }
1101        (Val::Bits(x), Val::Bits(y)) => match x.append(y) {
1102            Some(z) => Ok(Val::Bits(z)),
1103            None => solver.define_const(Exp::Concat(Box::new(smt_sbits(x)), Box::new(smt_sbits(y)))).into(),
1104        },
1105        (lhs, rhs) => Err(ExecError::Type(format!("append {:?} {:?}", &lhs, &rhs))),
1106    }
1107}
1108
1109pub(crate) fn vector_access<B: BV>(vec: Val<B>, n: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1110    match (vec, n) {
1111        (Val::Symbolic(bits), Val::Symbolic(n)) => match solver.length(bits) {
1112            Some(length) => {
1113                let shift = if length < 128 {
1114                    Exp::Extract(length - 1, 0, Box::new(Exp::Var(n)))
1115                } else if length > 128 {
1116                    Exp::ZeroExtend(length - 128, Box::new(Exp::Var(n)))
1117                } else {
1118                    Exp::Var(n)
1119                };
1120                solver
1121                    .define_const(Exp::Extract(0, 0, Box::new(Exp::Bvlshr(Box::new(Exp::Var(bits)), Box::new(shift)))))
1122                    .into()
1123            }
1124            None => Err(ExecError::Type(format!("vector_access {:?} {:?}", &bits, &n))),
1125        },
1126        (Val::Symbolic(bits), Val::I128(n)) => match solver.length(bits) {
1127            Some(length) => {
1128                let shift = if length < 128 {
1129                    Exp::Extract(length - 1, 0, Box::new(smt_i128(n)))
1130                } else if length > 128 {
1131                    Exp::ZeroExtend(length - 128, Box::new(smt_i128(n)))
1132                } else {
1133                    smt_i128(n)
1134                };
1135                solver
1136                    .define_const(Exp::Extract(0, 0, Box::new(Exp::Bvlshr(Box::new(Exp::Var(bits)), Box::new(shift)))))
1137                    .into()
1138            }
1139            None => Err(ExecError::Type(format!("vector_access {:?} {:?}", &bits, &n))),
1140        },
1141        (Val::Bits(bits), Val::Symbolic(n)) => {
1142            let shift = Exp::Extract(bits.len() - 1, 0, Box::new(Exp::Var(n)));
1143            solver
1144                .define_const(Exp::Extract(0, 0, Box::new(Exp::Bvlshr(Box::new(smt_sbits(bits)), Box::new(shift)))))
1145                .into()
1146        }
1147        (Val::Bits(bits), Val::I128(n)) => match bits.slice(n as u32, 1) {
1148            Some(bit) => Ok(Val::Bits(bit)),
1149            None => Err(ExecError::Type(format!("vector_access {:?} {:?}", &bits, &n))),
1150        },
1151        (Val::Vector(vec), Val::I128(n)) => match vec.get(n as usize) {
1152            Some(elem) => Ok(elem.clone()),
1153            None => Err(ExecError::OutOfBounds("vector_access")),
1154        },
1155        (vec, n) => Err(ExecError::Type(format!("vector_access {:?} {:?}", &vec, &n))),
1156    }
1157}
1158
1159/// The set_slice! macro implements the Sail set_slice builtin for any
1160/// combination of symbolic or concrete operands, with the result
1161/// always being symbolic. The argument order is the same as the Sail
1162/// function it implements, plus the solver as a final argument.
1163macro_rules! set_slice {
1164    ($bits_length: expr, $update_length: ident, $bits: expr, $n: expr, $update: expr, $solver: ident) => {
1165        if $bits_length == 0 {
1166            Ok(Val::Bits(B::zeros(0)))
1167        } else if $update_length == 0 {
1168            $solver.define_const($bits).into()
1169        } else {
1170            let mask_lower = smt_mask_lower($bits_length as usize, $update_length as usize);
1171            let update = if $bits_length == $update_length {
1172                $update
1173            } else {
1174                Exp::ZeroExtend($bits_length - $update_length, Box::new($update))
1175            };
1176            let shift = if $bits_length < 128 {
1177                Exp::Extract($bits_length - 1, 0, Box::new($n))
1178            } else if $bits_length > 128 {
1179                Exp::ZeroExtend($bits_length - 128, Box::new($n))
1180            } else {
1181                $n
1182            };
1183            let sliced = $solver.fresh();
1184            $solver.add(Def::DefineConst(
1185                sliced,
1186                Exp::Bvor(
1187                    Box::new(Exp::Bvand(
1188                        Box::new($bits),
1189                        Box::new(Exp::Bvnot(Box::new(Exp::Bvshl(Box::new(mask_lower), Box::new(shift.clone()))))),
1190                    )),
1191                    Box::new(Exp::Bvshl(Box::new(update), Box::new(shift))),
1192                ),
1193            ));
1194            Ok(Val::Symbolic(sliced))
1195        }
1196    };
1197}
1198
1199/// A special case of set_slice! for when $n == 0, and therefore no shift needs to be applied.
1200macro_rules! set_slice_n0 {
1201    ($bits_length: expr, $update_length: ident, $bits: expr, $update: expr, $solver: ident) => {
1202        if $bits_length == 0 {
1203            Ok(Val::Bits(B::zeros(0)))
1204        } else if $update_length == 0 {
1205            $solver.define_const($bits).into()
1206        } else {
1207            let mask_lower = smt_mask_lower($bits_length as usize, $update_length as usize);
1208            let update = if $bits_length == $update_length {
1209                $update
1210            } else {
1211                Exp::ZeroExtend($bits_length - $update_length, Box::new($update))
1212            };
1213            let sliced = $solver.fresh();
1214            $solver.add(Def::DefineConst(
1215                sliced,
1216                Exp::Bvor(
1217                    Box::new(Exp::Bvand(Box::new($bits), Box::new(Exp::Bvnot(Box::new(mask_lower))))),
1218                    Box::new(update),
1219                ),
1220            ));
1221            Ok(Val::Symbolic(sliced))
1222        }
1223    };
1224}
1225
1226fn set_slice_internal<B: BV>(
1227    bits: Val<B>,
1228    n: Val<B>,
1229    update: Val<B>,
1230    solver: &mut Solver<B>,
1231) -> Result<Val<B>, ExecError> {
1232    let bits_length = length_bits(&bits, solver)?;
1233    let update_length = length_bits(&update, solver)?;
1234    match (bits, n, update) {
1235        (Val::Symbolic(bits), Val::Symbolic(n), Val::Symbolic(update)) => {
1236            set_slice!(bits_length, update_length, Exp::Var(bits), Exp::Var(n), Exp::Var(update), solver)
1237        }
1238        (Val::Symbolic(bits), Val::Symbolic(n), Val::Bits(update)) => {
1239            set_slice!(bits_length, update_length, Exp::Var(bits), Exp::Var(n), smt_sbits(update), solver)
1240        }
1241        (Val::Symbolic(bits), Val::I128(n), Val::Symbolic(update)) => {
1242            if n == 0 {
1243                set_slice_n0!(bits_length, update_length, Exp::Var(bits), Exp::Var(update), solver)
1244            } else {
1245                set_slice!(bits_length, update_length, Exp::Var(bits), smt_i128(n), Exp::Var(update), solver)
1246            }
1247        }
1248        (Val::Symbolic(bits), Val::I128(n), Val::Bits(update)) => {
1249            if n == 0 {
1250                if bits_length == update_length {
1251                    Ok(Val::Bits(update))
1252                } else {
1253                    set_slice_n0!(bits_length, update_length, Exp::Var(bits), smt_sbits(update), solver)
1254                }
1255            } else {
1256                set_slice!(bits_length, update_length, Exp::Var(bits), smt_i128(n), smt_sbits(update), solver)
1257            }
1258        }
1259        (Val::Bits(bits), Val::Symbolic(n), Val::Symbolic(update)) => {
1260            set_slice!(bits_length, update_length, smt_sbits(bits), Exp::Var(n), Exp::Var(update), solver)
1261        }
1262        (Val::Bits(bits), Val::Symbolic(n), Val::Bits(update)) => {
1263            set_slice!(bits_length, update_length, smt_sbits(bits), Exp::Var(n), smt_sbits(update), solver)
1264        }
1265        (Val::Bits(bits), Val::I128(n), Val::Symbolic(update)) => {
1266            if n == 0 {
1267                set_slice_n0!(bits_length, update_length, smt_sbits(bits), Exp::Var(update), solver)
1268            } else {
1269                set_slice!(bits_length, update_length, smt_sbits(bits), smt_i128(n), Exp::Var(update), solver)
1270            }
1271        }
1272        (Val::Bits(bits), Val::I128(n), Val::Bits(update)) => Ok(Val::Bits(bits.set_slice(n as u32, update))),
1273        (bits, n, update) => Err(ExecError::Type(format!("set_slice {:?} {:?} {:?}", &bits, &n, &update))),
1274    }
1275}
1276
1277fn set_slice<B: BV>(args: Vec<Val<B>>, solver: &mut Solver<B>, _: &mut LocalFrame<B>) -> Result<Val<B>, ExecError> {
1278    // set_slice Sail builtin takes 2 additional integer parameters
1279    // for the bitvector lengths, which we can ignore.
1280    set_slice_internal(args[2].clone(), args[3].clone(), args[4].clone(), solver)
1281}
1282
1283fn set_slice_int_internal<B: BV>(
1284    int: Val<B>,
1285    n: Val<B>,
1286    update: Val<B>,
1287    solver: &mut Solver<B>,
1288) -> Result<Val<B>, ExecError> {
1289    let update_length = length_bits(&update, solver)?;
1290    match (int, n, update) {
1291        (Val::Symbolic(int), Val::Symbolic(n), Val::Symbolic(update)) => {
1292            set_slice!(128, update_length, Exp::Var(int), Exp::Var(n), Exp::Var(update), solver)
1293        }
1294        (Val::Symbolic(int), Val::Symbolic(n), Val::Bits(update)) => {
1295            set_slice!(128, update_length, Exp::Var(int), Exp::Var(n), smt_sbits(update), solver)
1296        }
1297        (Val::Symbolic(int), Val::I128(n), Val::Symbolic(update)) => {
1298            if n == 0 {
1299                set_slice_n0!(128, update_length, Exp::Var(int), Exp::Var(update), solver)
1300            } else {
1301                set_slice!(128, update_length, Exp::Var(int), smt_i128(n), Exp::Var(update), solver)
1302            }
1303        }
1304        (Val::Symbolic(int), Val::I128(n), Val::Bits(update)) => {
1305            if n == 0 {
1306                set_slice_n0!(128, update_length, Exp::Var(int), smt_sbits(update), solver)
1307            } else {
1308                set_slice!(128, update_length, Exp::Var(int), smt_i128(n), smt_sbits(update), solver)
1309            }
1310        }
1311        (Val::I128(int), Val::Symbolic(n), Val::Symbolic(update)) => {
1312            set_slice!(128, update_length, smt_i128(int), Exp::Var(n), Exp::Var(update), solver)
1313        }
1314        (Val::I128(int), Val::Symbolic(n), Val::Bits(update)) => {
1315            set_slice!(128, update_length, smt_i128(int), Exp::Var(n), smt_sbits(update), solver)
1316        }
1317        (Val::I128(int), Val::I128(n), Val::Symbolic(update)) => {
1318            if n == 0 {
1319                set_slice_n0!(128, update_length, smt_i128(int), Exp::Var(update), solver)
1320            } else {
1321                set_slice!(128, update_length, smt_i128(int), smt_i128(n), Exp::Var(update), solver)
1322            }
1323        }
1324        (Val::I128(int), Val::I128(n), Val::Bits(update)) => Ok(Val::I128(B::set_slice_int(int, n as u32, update))),
1325        (int, n, update) => Err(ExecError::Type(format!("set_slice_int {:?} {:?} {:?}", &int, &n, &update))),
1326    }
1327}
1328
1329fn set_slice_int<B: BV>(args: Vec<Val<B>>, solver: &mut Solver<B>, _: &mut LocalFrame<B>) -> Result<Val<B>, ExecError> {
1330    // set_slice_int Sail builtin takes 1 additional integer parameter for the bitvector length,
1331    // which we can ignore.
1332    set_slice_int_internal(args[1].clone(), args[2].clone(), args[3].clone(), solver)
1333}
1334
1335/// op_set_slice is just set_slice_internal with 64-bit integers rather than 128-bit.
1336pub(crate) fn op_set_slice<B: BV>(
1337    bits: Val<B>,
1338    n: Val<B>,
1339    update: Val<B>,
1340    solver: &mut Solver<B>,
1341) -> Result<Val<B>, ExecError> {
1342    let bits_length = length_bits(&bits, solver)?;
1343    let update_length = length_bits(&update, solver)?;
1344    match (bits, n, update) {
1345        (Val::Symbolic(bits), Val::Symbolic(n), Val::Symbolic(update)) => {
1346            set_slice!(bits_length, update_length, Exp::Var(bits), Exp::Var(n), Exp::Var(update), solver)
1347        }
1348        (Val::Symbolic(bits), Val::Symbolic(n), Val::Bits(update)) => {
1349            set_slice!(bits_length, update_length, Exp::Var(bits), Exp::Var(n), smt_sbits(update), solver)
1350        }
1351        (Val::Symbolic(bits), Val::I64(n), Val::Symbolic(update)) => {
1352            if n == 0 {
1353                set_slice_n0!(bits_length, update_length, Exp::Var(bits), Exp::Var(update), solver)
1354            } else {
1355                set_slice!(bits_length, update_length, Exp::Var(bits), smt_i64(n), Exp::Var(update), solver)
1356            }
1357        }
1358        (Val::Symbolic(bits), Val::I64(n), Val::Bits(update)) => {
1359            if n == 0 {
1360                set_slice_n0!(bits_length, update_length, Exp::Var(bits), smt_sbits(update), solver)
1361            } else {
1362                set_slice!(bits_length, update_length, Exp::Var(bits), smt_i64(n), smt_sbits(update), solver)
1363            }
1364        }
1365        (Val::Bits(bits), Val::Symbolic(n), Val::Symbolic(update)) => {
1366            set_slice!(bits_length, update_length, smt_sbits(bits), Exp::Var(n), Exp::Var(update), solver)
1367        }
1368        (Val::Bits(bits), Val::Symbolic(n), Val::Bits(update)) => {
1369            set_slice!(bits_length, update_length, smt_sbits(bits), Exp::Var(n), smt_sbits(update), solver)
1370        }
1371        (Val::Bits(bits), Val::I64(n), Val::Symbolic(update)) => {
1372            if n == 0 {
1373                set_slice_n0!(bits_length, update_length, smt_sbits(bits), Exp::Var(update), solver)
1374            } else {
1375                set_slice!(bits_length, update_length, smt_sbits(bits), smt_i64(n), Exp::Var(update), solver)
1376            }
1377        }
1378        (Val::Bits(bits), Val::I64(n), Val::Bits(update)) => Ok(Val::Bits(bits.set_slice(n as u32, update))),
1379        (bits, n, update) => Err(ExecError::Type(format!("set_slice {:?} {:?} {:?}", &bits, &n, &update))),
1380    }
1381}
1382
1383/// `vector_update` is a special case of `set_slice` where the update
1384/// is a bitvector of length 1. It can also update ordinary (non bit-)
1385/// vectors.
1386pub fn vector_update<B: BV>(
1387    args: Vec<Val<B>>,
1388    solver: &mut Solver<B>,
1389    _: &mut LocalFrame<B>,
1390) -> Result<Val<B>, ExecError> {
1391    let arg0 = args[0].clone();
1392    match arg0 {
1393        Val::Vector(mut vec) => match args[1] {
1394            Val::I128(n) => {
1395                vec[n as usize] = args[2].clone();
1396                Ok(Val::Vector(vec))
1397            }
1398            Val::I64(n) => {
1399                vec[n as usize] = args[2].clone();
1400                Ok(Val::Vector(vec))
1401            }
1402            Val::Symbolic(n) => {
1403                for (i, item) in vec.iter_mut().enumerate() {
1404                    let var = solver.fresh();
1405                    solver.add(Def::DefineConst(
1406                        var,
1407                        Exp::Ite(
1408                            Box::new(Exp::Eq(Box::new(Exp::Var(n)), Box::new(bits64(i as u64, 128)))),
1409                            Box::new(smt_value(&args[2])?),
1410                            Box::new(smt_value(&item)?),
1411                        ),
1412                    ));
1413                    *item = Val::Symbolic(var);
1414                }
1415                Ok(Val::Vector(vec))
1416            }
1417            _ => {
1418                eprintln!("{:?}", args);
1419                Err(ExecError::Type(format!("vector_update (index) {:?}", &args[1])))
1420            }
1421        },
1422        Val::Bits(_) => {
1423            // If the argument is a bitvector then `vector_update` is a special case of `set_slice`
1424            // where the update is a bitvector of length 1
1425            set_slice_internal(arg0, args[1].clone(), args[2].clone(), solver)
1426        }
1427        Val::Symbolic(v) if solver.is_bitvector(v) => {
1428            set_slice_internal(arg0, args[1].clone(), args[2].clone(), solver)
1429        }
1430        _ => Err(ExecError::Type(format!("vector_update {:?}", &arg0))),
1431    }
1432}
1433
1434fn vector_update_subrange<B: BV>(
1435    args: Vec<Val<B>>,
1436    solver: &mut Solver<B>,
1437    _: &mut LocalFrame<B>,
1438) -> Result<Val<B>, ExecError> {
1439    set_slice_internal(args[0].clone(), args[2].clone(), args[3].clone(), solver)
1440}
1441
1442fn undefined_vector<B: BV>(len: Val<B>, elem: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1443    if let Val::I128(len) = len {
1444        if let Ok(len) = usize::try_from(len) {
1445            Ok(Val::Vector(vec![elem; len]))
1446        } else {
1447            Err(ExecError::Overflow)
1448        }
1449    } else {
1450        Err(ExecError::SymbolicLength("undefined_vector"))
1451    }
1452}
1453
1454fn bitvector_update<B: BV>(
1455    args: Vec<Val<B>>,
1456    solver: &mut Solver<B>,
1457    _: &mut LocalFrame<B>,
1458) -> Result<Val<B>, ExecError> {
1459    op_set_slice(args[0].clone(), args[1].clone(), args[2].clone(), solver)
1460}
1461
1462fn get_slice_int_internal<B: BV>(
1463    length: Val<B>,
1464    n: Val<B>,
1465    from: Val<B>,
1466    solver: &mut Solver<B>,
1467) -> Result<Val<B>, ExecError> {
1468    match length {
1469        Val::I128(length) => match n {
1470            Val::Symbolic(n) => slice!(128, Exp::Var(n), from, length, solver),
1471            Val::I128(n) => match from {
1472                Val::I128(from) if length <= B::MAX_WIDTH as i128 => {
1473                    Ok(Val::Bits(B::get_slice_int(length as u32, n, from as u32)))
1474                }
1475                _ => slice!(128, smt_i128(n), from, length, solver),
1476            },
1477            _ => Err(ExecError::Type(format!("get_slice_int {:?}", &length))),
1478        },
1479        Val::Symbolic(_) => Err(ExecError::SymbolicLength("get_slice_int")),
1480        _ => Err(ExecError::Type(format!("get_slice_int length is {:?}", &length))),
1481    }
1482}
1483
1484fn get_slice_int<B: BV>(args: Vec<Val<B>>, solver: &mut Solver<B>, _: &mut LocalFrame<B>) -> Result<Val<B>, ExecError> {
1485    get_slice_int_internal(args[0].clone(), args[1].clone(), args[2].clone(), solver)
1486}
1487
1488fn unimplemented<B: BV>(_: Vec<Val<B>>, _: &mut Solver<B>, _: &mut LocalFrame<B>) -> Result<Val<B>, ExecError> {
1489    Err(ExecError::Unimplemented)
1490}
1491
1492fn eq_string<B: BV>(lhs: Val<B>, rhs: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1493    match (lhs, rhs) {
1494        (Val::String(lhs), Val::String(rhs)) => Ok(Val::Bool(lhs == rhs)),
1495        (lhs, rhs) => Err(ExecError::Type(format!("eq_string {:?} {:?}", &lhs, &rhs))),
1496    }
1497}
1498
1499fn concat_str<B: BV>(lhs: Val<B>, rhs: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1500    match (lhs, rhs) {
1501        (Val::String(lhs), Val::String(rhs)) => Ok(Val::String(format!("{}{}", lhs, rhs))),
1502        (lhs, rhs) => Err(ExecError::Type(format!("concat_str {:?} {:?}", &lhs, &rhs))),
1503    }
1504}
1505
1506fn hex_str<B: BV>(n: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1507    match n {
1508        Val::I128(n) => Ok(Val::String(format!("0x{:x}", n))),
1509        Val::Symbolic(v) => Ok(Val::String(format!("0x[{}]", v))),
1510        _ => Err(ExecError::Type(format!("hex_str {:?}", &n))),
1511    }
1512}
1513
1514fn dec_str<B: BV>(n: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1515    match n {
1516        Val::I128(n) => Ok(Val::String(format!("{}", n))),
1517        Val::Symbolic(v) => Ok(Val::String(format!("[{}]", v))),
1518        _ => Err(ExecError::Type(format!("dec_str {:?}", &n))),
1519    }
1520}
1521
1522// Strings can never be symbolic
1523fn undefined_string<B: BV>(_: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1524    Ok(Val::Poison)
1525}
1526
1527fn string_to_i128<B: BV>(s: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1528    if let Val::String(s) = s {
1529        if let Ok(n) = i128::from_str(&s) {
1530            Ok(Val::I128(n))
1531        } else {
1532            Err(ExecError::Overflow)
1533        }
1534    } else {
1535        Err(ExecError::Type(format!("%string->%int {:?}", &s)))
1536    }
1537}
1538
1539fn eq_anything<B: BV>(lhs: Val<B>, rhs: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1540    match (lhs, rhs) {
1541        (Val::Symbolic(lhs), Val::Symbolic(rhs)) => {
1542            solver.define_const(Exp::Eq(Box::new(Exp::Var(lhs)), Box::new(Exp::Var(rhs)))).into()
1543        }
1544        (lhs, Val::Symbolic(rhs)) => {
1545            solver.define_const(Exp::Eq(Box::new(smt_value(&lhs)?), Box::new(Exp::Var(rhs)))).into()
1546        }
1547        (Val::Symbolic(lhs), rhs) => {
1548            solver.define_const(Exp::Eq(Box::new(Exp::Var(lhs)), Box::new(smt_value(&rhs)?))).into()
1549        }
1550
1551        (Val::Bits(lhs), Val::Bits(rhs)) => Ok(Val::Bool(lhs == rhs)),
1552        (Val::Enum(lhs), Val::Enum(rhs)) => Ok(Val::Bool(lhs == rhs)),
1553        (Val::Bool(lhs), Val::Bool(rhs)) => Ok(Val::Bool(lhs == rhs)),
1554        (Val::I128(lhs), Val::I128(rhs)) => Ok(Val::Bool(lhs == rhs)),
1555        (Val::I64(lhs), Val::I64(rhs)) => Ok(Val::Bool(lhs == rhs)),
1556        (Val::Struct(lhs), Val::Struct(rhs)) => {
1557            let mut vars = vec![];
1558            for (k, lhs_v) in lhs {
1559                let rhs_v = match rhs.get(&k) {
1560                    Some(v) => v,
1561                    None => return Err(ExecError::Type("eq_anything None".to_string())),
1562                };
1563                let result = eq_anything(lhs_v, rhs_v.clone(), solver)?;
1564                match result {
1565                    Val::Bool(true) => (),
1566                    Val::Bool(false) => return Ok(Val::Bool(false)),
1567                    Val::Symbolic(r) => vars.push(r),
1568                    _ => return Err(ExecError::Type(format!("eq_anything {:?}", &result))),
1569                }
1570            }
1571            match vars.pop() {
1572                None => Ok(Val::Bool(true)),
1573                Some(init) => {
1574                    let exp = vars
1575                        .iter()
1576                        .map(|v| Exp::Var(*v))
1577                        .fold(Exp::Var(init), |e1, e2| Exp::And(Box::new(e1), Box::new(e2)));
1578                    solver.define_const(exp).into()
1579                }
1580            }
1581        }
1582
1583        (lhs, rhs) => Err(ExecError::Type(format!("eq_anything {:?} {:?}", &lhs, &rhs))),
1584    }
1585}
1586
1587fn neq_anything<B: BV>(lhs: Val<B>, rhs: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1588    match (lhs, rhs) {
1589        (Val::Symbolic(lhs), Val::Symbolic(rhs)) => {
1590            solver.define_const(Exp::Neq(Box::new(Exp::Var(lhs)), Box::new(Exp::Var(rhs)))).into()
1591        }
1592        (Val::Bits(lhs), Val::Symbolic(rhs)) => {
1593            solver.define_const(Exp::Neq(Box::new(smt_sbits(lhs)), Box::new(Exp::Var(rhs)))).into()
1594        }
1595        (Val::Symbolic(lhs), Val::Bits(rhs)) => {
1596            solver.define_const(Exp::Neq(Box::new(Exp::Var(lhs)), Box::new(smt_sbits(rhs)))).into()
1597        }
1598        (Val::Bits(lhs), Val::Bits(rhs)) => Ok(Val::Bool(lhs != rhs)),
1599
1600        (Val::Symbolic(lhs), Val::Enum(rhs)) => {
1601            solver.define_const(Exp::Neq(Box::new(Exp::Var(lhs)), Box::new(Exp::Enum(rhs)))).into()
1602        }
1603        (Val::Enum(lhs), Val::Symbolic(rhs)) => {
1604            solver.define_const(Exp::Neq(Box::new(Exp::Enum(lhs)), Box::new(Exp::Var(rhs)))).into()
1605        }
1606        (Val::Enum(lhs), Val::Enum(rhs)) => Ok(Val::Bool(lhs != rhs)),
1607
1608        (lhs, rhs) => Err(ExecError::Type(format!("neq_anything {:?} {:?}", &lhs, &rhs))),
1609    }
1610}
1611
1612fn string_startswith<B: BV>(s: Val<B>, prefix: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1613    match (s, prefix) {
1614        (Val::String(s), Val::String(prefix)) => Ok(Val::Bool(s.starts_with(&prefix))),
1615        other => Err(ExecError::Type(format!("string_startswith {:?}", &other))),
1616    }
1617}
1618
1619fn string_length<B: BV>(s: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1620    if let Val::String(s) = s {
1621        Ok(Val::I128(s.len() as i128))
1622    } else {
1623        Err(ExecError::Type(format!("string_length {:?}", &s)))
1624    }
1625}
1626
1627fn string_drop<B: BV>(s: Val<B>, n: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1628    match (s, n) {
1629        (Val::String(s), Val::I128(n)) => Ok(Val::String(s.get((n as usize)..).unwrap_or("").to_string())),
1630        other => Err(ExecError::Type(format!("string_drop {:?}", &other))),
1631    }
1632}
1633
1634fn string_take<B: BV>(s: Val<B>, n: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1635    match (s, n) {
1636        (Val::String(s), Val::I128(n)) => Ok(Val::String(s.get(..(n as usize)).unwrap_or(&s).to_string())),
1637        other => Err(ExecError::Type(format!("string_take {:?}", &other))),
1638    }
1639}
1640
1641fn string_of_bits<B: BV>(bv: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1642    match bv {
1643        Val::Bits(bv) => Ok(Val::String(format!("{}", bv))),
1644        Val::Symbolic(v) => Ok(Val::String(format!("v{}", v))),
1645        other => Err(ExecError::Type(format!("string_of_bits {:?}", &other))),
1646    }
1647}
1648
1649fn decimal_string_of_bits<B: BV>(bv: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1650    match bv {
1651        Val::Bits(bv) => Ok(Val::String(format!("{}", bv.signed()))),
1652        Val::Symbolic(v) => Ok(Val::String(format!("v{}", v))),
1653        other => Err(ExecError::Type(format!("decimal_string_of_bits {:?}", &other))),
1654    }
1655}
1656
1657fn string_of_int<B: BV>(n: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1658    match n {
1659        Val::I128(n) => Ok(Val::String(format!("{}", n))),
1660        Val::Symbolic(v) => Ok(Val::String(format!("v{}", v))),
1661        other => Err(ExecError::Type(format!("string_of_int {:?}", &other))),
1662    }
1663}
1664
1665fn putchar<B: BV>(_c: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1666    //if let Val::I128(c) = c {
1667    //    eprintln!("Stdout: {}", char::from(c as u8))
1668    //}
1669    Ok(Val::Unit)
1670}
1671
1672fn print<B: BV>(_message: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1673    //if let Val::String(message) = message {
1674    //    eprintln!("Stdout: {}", message)
1675    //}
1676    Ok(Val::Unit)
1677}
1678
1679fn prerr<B: BV>(_message: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1680    //if let Val::String(message) = message {
1681    //    eprintln!("Stderr: {}", message)
1682    //}
1683    Ok(Val::Unit)
1684}
1685
1686fn print_string<B: BV>(_prefix: Val<B>, _message: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1687    Ok(Val::Unit)
1688}
1689
1690fn prerr_string<B: BV>(_prefix: Val<B>, _message: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1691    Ok(Val::Unit)
1692}
1693
1694fn print_int<B: BV>(_prefix: Val<B>, _n: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1695    Ok(Val::Unit)
1696}
1697
1698fn prerr_int<B: BV>(_prefix: Val<B>, _n: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1699    Ok(Val::Unit)
1700}
1701
1702fn print_endline<B: BV>(_message: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1703    Ok(Val::Unit)
1704}
1705
1706fn prerr_endline<B: BV>(_message: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1707    Ok(Val::Unit)
1708}
1709
1710fn print_bits<B: BV>(_message: Val<B>, _bits: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1711    //if let Val::String(message) = message {
1712    //    eprintln!("Stdout: {}{:?}", message, bits)
1713    //}
1714    Ok(Val::Unit)
1715}
1716
1717fn prerr_bits<B: BV>(_message: Val<B>, _bits: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1718    //if let Val::String(message) = message {
1719    //    eprintln!("Stderr: {}{:?}", message, bits)
1720    //}
1721    Ok(Val::Unit)
1722}
1723
1724fn undefined_bitvector<B: BV>(sz: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1725    if let Val::I128(sz) = sz {
1726        solver.declare_const(Ty::BitVec(sz as u32)).into()
1727    } else {
1728        Err(ExecError::Type(format!("undefined_bitvector {:?}", &sz)))
1729    }
1730}
1731
1732fn undefined_bool<B: BV>(_: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1733    solver.declare_const(Ty::Bool).into()
1734}
1735
1736fn undefined_int<B: BV>(_: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1737    solver.declare_const(Ty::BitVec(128)).into()
1738}
1739
1740fn undefined_nat<B: BV>(_: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1741    let sym = solver.fresh();
1742    solver.add(Def::DeclareConst(sym, Ty::BitVec(128)));
1743    solver.add(Def::Assert(Exp::Bvsge(Box::new(Exp::Var(sym)), Box::new(smt_i128(0)))));
1744    Ok(Val::Symbolic(sym))
1745}
1746
1747fn undefined_range<B: BV>(lo: Val<B>, hi: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1748    let sym = solver.fresh();
1749    solver.add(Def::DeclareConst(sym, Ty::BitVec(128)));
1750    solver.add(Def::Assert(Exp::Bvsle(Box::new(smt_value(&lo)?), Box::new(Exp::Var(sym)))));
1751    solver.add(Def::Assert(Exp::Bvsle(Box::new(Exp::Var(sym)), Box::new(smt_value(&hi)?))));
1752    Ok(Val::Symbolic(sym))
1753}
1754
1755fn undefined_unit<B: BV>(_: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1756    Ok(Val::Unit)
1757}
1758
1759fn one_if<B: BV>(condition: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1760    match condition {
1761        Val::Bool(true) => Ok(Val::Bits(B::BIT_ONE)),
1762        Val::Bool(false) => Ok(Val::Bits(B::BIT_ZERO)),
1763        Val::Symbolic(v) => solver
1764            .define_const(Exp::Ite(
1765                Box::new(Exp::Var(v)),
1766                Box::new(smt_sbits(B::BIT_ONE)),
1767                Box::new(smt_sbits(B::BIT_ZERO)),
1768            ))
1769            .into(),
1770        _ => Err(ExecError::Type(format!("one_if {:?}", &condition))),
1771    }
1772}
1773
1774fn zero_if<B: BV>(condition: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1775    match condition {
1776        Val::Bool(true) => Ok(Val::Bits(B::BIT_ZERO)),
1777        Val::Bool(false) => Ok(Val::Bits(B::BIT_ONE)),
1778        Val::Symbolic(v) => solver
1779            .define_const(Exp::Ite(
1780                Box::new(Exp::Var(v)),
1781                Box::new(smt_sbits(B::BIT_ZERO)),
1782                Box::new(smt_sbits(B::BIT_ONE)),
1783            ))
1784            .into(),
1785        other => Err(ExecError::Type(format!("one_if {:?}", &other))),
1786    }
1787}
1788
1789fn cons<B: BV>(x: Val<B>, xs: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1790    match xs {
1791        /* TODO: Make this not a hack */
1792        Val::Poison => Ok(Val::List(vec![x])),
1793        Val::List(mut xs) => {
1794            xs.push(x);
1795            Ok(Val::List(xs))
1796        }
1797        _ => Err(ExecError::Type(format!("cons {:?}", &xs))),
1798    }
1799}
1800
1801/// Convert base values into SMT equivalents.
1802pub fn smt_value<B: BV>(v: &Val<B>) -> Result<Exp, ExecError> {
1803    Ok(match v {
1804        Val::I128(n) => smt_i128(*n),
1805        Val::I64(n) => smt_i64(*n),
1806        Val::Bits(bv) => smt_sbits(*bv),
1807        Val::Bool(b) => Exp::Bool(*b),
1808        Val::Enum(e) => Exp::Enum(*e),
1809        Val::Symbolic(v) => Exp::Var(*v),
1810        _ => return Err(ExecError::Type(format!("smt_value {:?}", &v))),
1811    })
1812}
1813
1814fn choice_chain<B: BV>(sym: Sym, n: u64, sz: u32, mut xs: Vec<Val<B>>) -> Result<Exp, ExecError> {
1815    if xs.len() == 1 {
1816        smt_value(&xs[0])
1817    } else {
1818        let x = xs.pop().unwrap();
1819        Ok(Exp::Ite(
1820            Box::new(Exp::Eq(Box::new(Exp::Var(sym)), Box::new(bits64(n, sz)))),
1821            Box::new(smt_value(&x)?),
1822            Box::new(choice_chain(sym, n + 1, sz, xs)?),
1823        ))
1824    }
1825}
1826
1827fn choice<B: BV>(xs: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1828    match xs {
1829        Val::List(xs) => {
1830            // We need to choose an element between 0 and n - 1 where
1831            // n is the list length, this choice is represented as a
1832            // bitvector that is just long enough to represent the
1833            // numbers 0 to n.
1834            let sz = ((xs.len() + 1) as f64).log2().ceil() as u32;
1835            let sym = solver.fresh();
1836            let choice = solver.fresh();
1837            solver.add(Def::DeclareConst(sym, Ty::BitVec(sz)));
1838            solver.add(Def::DefineConst(choice, choice_chain(sym, 0, sz, xs)?));
1839            Ok(Val::Symbolic(choice))
1840        }
1841        _ => Err(ExecError::Type(format!("choice {:?}", &xs))),
1842    }
1843}
1844
1845fn read_mem<B: BV>(args: Vec<Val<B>>, solver: &mut Solver<B>, frame: &mut LocalFrame<B>) -> Result<Val<B>, ExecError> {
1846    frame.memory().read(args[0].clone(), args[2].clone(), args[3].clone(), solver, false)
1847}
1848
1849fn read_memt<B: BV>(args: Vec<Val<B>>, solver: &mut Solver<B>, frame: &mut LocalFrame<B>) -> Result<Val<B>, ExecError> {
1850    frame.memory().read(args[0].clone(), args[1].clone(), args[2].clone(), solver, true)
1851}
1852
1853fn bad_read<B: BV>(_: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1854    Err(ExecError::BadRead("spec-defined bad read"))
1855}
1856
1857fn write_mem<B: BV>(args: Vec<Val<B>>, solver: &mut Solver<B>, frame: &mut LocalFrame<B>) -> Result<Val<B>, ExecError> {
1858    frame.memory_mut().write(args[0].clone(), args[2].clone(), args[4].clone(), solver, None)
1859}
1860
1861fn write_memt<B: BV>(
1862    args: Vec<Val<B>>,
1863    solver: &mut Solver<B>,
1864    frame: &mut LocalFrame<B>,
1865) -> Result<Val<B>, ExecError> {
1866    frame.memory_mut().write(args[0].clone(), args[1].clone(), args[3].clone(), solver, Some(args[4].clone()))
1867}
1868
1869fn bad_write<B: BV>(_: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1870    Err(ExecError::BadWrite("spec-defined bad write"))
1871}
1872
1873fn write_mem_ea<B: BV>(
1874    _: Vec<Val<B>>,
1875    _solver: &mut Solver<B>,
1876    _frame: &mut LocalFrame<B>,
1877) -> Result<Val<B>, ExecError> {
1878    Ok(Val::Unit)
1879}
1880
1881fn cycle_count<B: BV>(_: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1882    solver.cycle_count();
1883    Ok(Val::Unit)
1884}
1885
1886fn get_cycle_count<B: BV>(_: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1887    Ok(Val::I128(solver.get_cycle_count()))
1888}
1889
1890fn get_verbosity<B: BV>(_: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1891    Ok(Val::Bits(B::zeros(64)))
1892}
1893
1894fn sleeping<B: BV>(_: Val<B>, _solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1895    // let sym = solver.fresh();
1896    // solver.add(Def::DeclareConst(sym, Ty::Bool));
1897    // solver.add_event(Event::Sleeping(sym));
1898    // Ok(Val::Symbolic(sym))
1899    Ok(Val::Bool(false))
1900}
1901
1902fn wakeup_request<B: BV>(_: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1903    solver.add_event(Event::WakeupRequest);
1904    Ok(Val::Unit)
1905}
1906
1907fn sleep_request<B: BV>(_: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1908    solver.add_event(Event::WakeupRequest);
1909    Ok(Val::Unit)
1910}
1911
1912fn instr_announce<B: BV>(opcode: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1913    solver.add_event(Event::Instr(opcode));
1914    Ok(Val::Unit)
1915}
1916
1917fn branch_announce<B: BV>(_: Val<B>, target: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1918    solver.add_event(Event::Branch { address: target });
1919    Ok(Val::Unit)
1920}
1921
1922fn barrier<B: BV>(barrier_kind: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1923    solver.add_event(Event::Barrier { barrier_kind });
1924    Ok(Val::Unit)
1925}
1926
1927fn cache_maintenance<B: BV>(
1928    args: Vec<Val<B>>,
1929    solver: &mut Solver<B>,
1930    _: &mut LocalFrame<B>,
1931) -> Result<Val<B>, ExecError> {
1932    solver.add_event(Event::CacheOp { cache_op_kind: args[0].clone(), address: args[2].clone() });
1933    Ok(Val::Unit)
1934}
1935
1936fn elf_entry<B: BV>(_: Vec<Val<B>>, _: &mut Solver<B>, frame: &mut LocalFrame<B>) -> Result<Val<B>, ExecError> {
1937    match frame.lets().get(&ELF_ENTRY) {
1938        Some(UVal::Init(value)) => Ok(value.clone()),
1939        _ => Err(ExecError::NoElfEntry),
1940    }
1941}
1942
1943fn monomorphize<B: BV>(val: Val<B>, _: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1944    Ok(val)
1945}
1946
1947fn mark_register<B: BV>(r: Val<B>, mark: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1948    match (r, mark) {
1949        (Val::Ref(r), Val::String(mark)) => {
1950            solver.add_event(Event::MarkReg { regs: vec![r], mark });
1951            Ok(Val::Unit)
1952        }
1953        (r, mark) => Err(ExecError::Type(format!("mark_register {:?} {:?}", &r, &mark))),
1954    }
1955}
1956
1957fn mark_register_pair_internal<B: BV>(
1958    r1: Val<B>,
1959    r2: Val<B>,
1960    mark: Val<B>,
1961    solver: &mut Solver<B>,
1962) -> Result<Val<B>, ExecError> {
1963    match (r1, r2, mark) {
1964        (Val::Ref(r1), Val::Ref(r2), Val::String(mark)) => {
1965            solver.add_event(Event::MarkReg { regs: vec![r1, r2], mark });
1966            Ok(Val::Unit)
1967        }
1968        (r1, r2, mark) => Err(ExecError::Type(format!("mark_register_pair {:?} {:?} {:?}", &r1, &r2, &mark))),
1969    }
1970}
1971
1972fn mark_register_pair<B: BV>(
1973    mut args: Vec<Val<B>>,
1974    solver: &mut Solver<B>,
1975    _: &mut LocalFrame<B>,
1976) -> Result<Val<B>, ExecError> {
1977    if args.len() == 3 {
1978        let mark = args.pop().unwrap();
1979        let r2 = args.pop().unwrap();
1980        let r1 = args.pop().unwrap();
1981        mark_register_pair_internal(r1, r2, mark, solver)
1982    } else {
1983        Err(ExecError::Type("Incorrect number of arguments for mark_register_pair".to_string()))
1984    }
1985}
1986
1987fn align_bits<B: BV>(bv: Val<B>, alignment: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
1988    let bv_len = length_bits(&bv, solver)?;
1989    match (bv, alignment) {
1990        // Fast path for small bitvectors with power of two alignments
1991        (Val::Symbolic(bv), Val::I128(alignment)) if (bv_len <= 64) & ((alignment & (alignment - 1)) == 0) => {
1992            let mask = !B::new((alignment as u64) - 1, bv_len);
1993            solver.define_const(Exp::Bvand(Box::new(Exp::Var(bv)), Box::new(smt_sbits(mask)))).into()
1994        }
1995        (bv, alignment) => {
1996            let x = sail_unsigned(bv, solver)?;
1997            let aligned_x = mult_int(alignment.clone(), udiv_int(x, alignment, solver)?, solver)?;
1998            get_slice_int_internal(Val::I128(bv_len as i128), aligned_x, Val::I128(0), solver)
1999        }
2000    }
2001}
2002
2003/// Implement count leading zeros (clz) in the SMT solver as a binary
2004/// search, splitting on the midpoint of the bitvector.
2005fn smt_clz<B: BV>(bv: Sym, len: u32, solver: &mut Solver<B>) -> Sym {
2006    if len == 1 {
2007        solver.define_const(Exp::Ite(
2008            Box::new(Exp::Eq(Box::new(Exp::Var(bv)), Box::new(smt_zeros(1)))),
2009            Box::new(smt_i128(1)),
2010            Box::new(smt_i128(0)),
2011        ))
2012    } else {
2013        let low_len = len / 2;
2014        let top_len = len - low_len;
2015
2016        let top = solver.define_const(Exp::Extract(len - 1, low_len, Box::new(Exp::Var(bv))));
2017        let low = solver.define_const(Exp::Extract(low_len - 1, 0, Box::new(Exp::Var(bv))));
2018
2019        let top_bits_are_zero = Exp::Eq(Box::new(Exp::Var(top)), Box::new(smt_zeros(top_len as i128)));
2020
2021        let top_clz = smt_clz(top, top_len, solver);
2022        let low_clz = smt_clz(low, low_len, solver);
2023
2024        solver.define_const(Exp::Ite(
2025            Box::new(top_bits_are_zero),
2026            Box::new(Exp::Bvadd(Box::new(smt_i128(top_len as i128)), Box::new(Exp::Var(low_clz)))),
2027            Box::new(Exp::Var(top_clz)),
2028        ))
2029    }
2030}
2031
2032fn count_leading_zeros<B: BV>(bv: Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
2033    match bv {
2034        Val::Bits(bv) => Ok(Val::I128(bv.leading_zeros() as i128)),
2035        Val::Symbolic(bv) => {
2036            if let Some(len) = solver.length(bv) {
2037                smt_clz(bv, len, solver).into()
2038            } else {
2039                Err(ExecError::Type("count_leading_zeros (solver could not determine length)".to_string()))
2040            }
2041        }
2042        _ => Err(ExecError::Type(format!("count_leading_zeros {:?}", &bv))),
2043    }
2044}
2045
2046fn build_ite<B: BV>(b: Sym, lhs: &Val<B>, rhs: &Val<B>, solver: &mut Solver<B>) -> Result<Val<B>, ExecError> {
2047    match (lhs, rhs) {
2048        (Val::Struct(l_fields), Val::Struct(r_fields)) => {
2049            let fields: Result<_, _> = l_fields
2050                .iter()
2051                .map(|(k, l_val)| match r_fields.get(k) {
2052                    None => Err(ExecError::Type(format!("build_ite {:?}", &k))),
2053                    Some(r_val) => Ok((*k, build_ite(b, l_val, r_val, solver)?)),
2054                })
2055                .collect();
2056            Ok(Val::Struct(fields?))
2057        }
2058        _ => solver
2059            .define_const(Exp::Ite(Box::new(Exp::Var(b)), Box::new(smt_value(lhs)?), Box::new(smt_value(rhs)?)))
2060            .into(),
2061    }
2062}
2063
2064fn ite<B: BV>(args: Vec<Val<B>>, solver: &mut Solver<B>, _: &mut LocalFrame<B>) -> Result<Val<B>, ExecError> {
2065    match args[0] {
2066        Val::Symbolic(b) => build_ite(b, &args[1], &args[2], solver),
2067        Val::Bool(true) => Ok(args[1].clone()),
2068        Val::Bool(false) => Ok(args[2].clone()),
2069        _ => Err(ExecError::Type(format!("ite {:?}", &args[0]))),
2070    }
2071}
2072
2073pub fn unary_primops<B: BV>() -> HashMap<String, Unary<B>> {
2074    let mut primops = HashMap::new();
2075    primops.insert("%i64->%i".to_string(), i64_to_i128 as Unary<B>);
2076    primops.insert("%i->%i64".to_string(), i128_to_i64 as Unary<B>);
2077    primops.insert("%string->%i".to_string(), string_to_i128 as Unary<B>);
2078    primops.insert("bit_to_bool".to_string(), bit_to_bool as Unary<B>);
2079    primops.insert("assume".to_string(), assume as Unary<B>);
2080    primops.insert("not".to_string(), not_bool as Unary<B>);
2081    primops.insert("neg_int".to_string(), neg_int as Unary<B>);
2082    primops.insert("abs_int".to_string(), abs_int as Unary<B>);
2083    primops.insert("pow2".to_string(), pow2 as Unary<B>);
2084    primops.insert("not_bits".to_string(), not_bits as Unary<B>);
2085    primops.insert("length".to_string(), length as Unary<B>);
2086    primops.insert("zeros".to_string(), zeros as Unary<B>);
2087    primops.insert("ones".to_string(), ones as Unary<B>);
2088    primops.insert("sail_unsigned".to_string(), sail_unsigned as Unary<B>);
2089    primops.insert("sail_signed".to_string(), sail_signed as Unary<B>);
2090    primops.insert("sail_putchar".to_string(), putchar as Unary<B>);
2091    primops.insert("print".to_string(), print as Unary<B>);
2092    primops.insert("prerr".to_string(), prerr as Unary<B>);
2093    primops.insert("print_endline".to_string(), print_endline as Unary<B>);
2094    primops.insert("prerr_endline".to_string(), prerr_endline as Unary<B>);
2095    primops.insert("count_leading_zeros".to_string(), count_leading_zeros as Unary<B>);
2096    primops.insert("undefined_bitvector".to_string(), undefined_bitvector as Unary<B>);
2097    primops.insert("undefined_bool".to_string(), undefined_bool as Unary<B>);
2098    primops.insert("undefined_int".to_string(), undefined_int as Unary<B>);
2099    primops.insert("undefined_nat".to_string(), undefined_nat as Unary<B>);
2100    primops.insert("undefined_unit".to_string(), undefined_unit as Unary<B>);
2101    primops.insert("undefined_string".to_string(), undefined_string as Unary<B>);
2102    primops.insert("one_if".to_string(), one_if as Unary<B>);
2103    primops.insert("zero_if".to_string(), zero_if as Unary<B>);
2104    primops.insert("internal_pick".to_string(), choice as Unary<B>);
2105    primops.insert("bad_read".to_string(), bad_read as Unary<B>);
2106    primops.insert("bad_write".to_string(), bad_write as Unary<B>);
2107    primops.insert("hex_str".to_string(), hex_str as Unary<B>);
2108    primops.insert("dec_str".to_string(), dec_str as Unary<B>);
2109    primops.insert("string_length".to_string(), string_length as Unary<B>);
2110    primops.insert("string_of_bits".to_string(), string_of_bits as Unary<B>);
2111    primops.insert("decimal_string_of_bits".to_string(), decimal_string_of_bits as Unary<B>);
2112    primops.insert("string_of_int".to_string(), string_of_int as Unary<B>);
2113    primops.insert("cycle_count".to_string(), cycle_count as Unary<B>);
2114    primops.insert("get_cycle_count".to_string(), get_cycle_count as Unary<B>);
2115    primops.insert("sail_get_verbosity".to_string(), get_verbosity as Unary<B>);
2116    primops.insert("sleeping".to_string(), sleeping as Unary<B>);
2117    primops.insert("sleep_request".to_string(), sleep_request as Unary<B>);
2118    primops.insert("wakeup_request".to_string(), wakeup_request as Unary<B>);
2119    primops.insert("platform_instr_announce".to_string(), instr_announce as Unary<B>);
2120    primops.insert("platform_barrier".to_string(), barrier as Unary<B>);
2121    primops.insert("monomorphize".to_string(), monomorphize as Unary<B>);
2122    primops
2123}
2124
2125pub fn binary_primops<B: BV>() -> HashMap<String, Binary<B>> {
2126    let mut primops = HashMap::new();
2127    primops.insert("optimistic_assert".to_string(), optimistic_assert as Binary<B>);
2128    primops.insert("pessimistic_assert".to_string(), pessimistic_assert as Binary<B>);
2129    primops.insert("and_bool".to_string(), and_bool as Binary<B>);
2130    primops.insert("strict_and_bool".to_string(), and_bool as Binary<B>);
2131    primops.insert("or_bool".to_string(), or_bool as Binary<B>);
2132    primops.insert("strict_or_bool".to_string(), or_bool as Binary<B>);
2133    primops.insert("eq_int".to_string(), eq_int as Binary<B>);
2134    primops.insert("eq_bool".to_string(), eq_bool as Binary<B>);
2135    primops.insert("lteq".to_string(), lteq_int as Binary<B>);
2136    primops.insert("gteq".to_string(), gteq_int as Binary<B>);
2137    primops.insert("lt".to_string(), lt_int as Binary<B>);
2138    primops.insert("gt".to_string(), gt_int as Binary<B>);
2139    primops.insert("add_int".to_string(), add_int as Binary<B>);
2140    primops.insert("sub_int".to_string(), sub_int as Binary<B>);
2141    primops.insert("sub_nat".to_string(), sub_nat as Binary<B>);
2142    primops.insert("mult_int".to_string(), mult_int as Binary<B>);
2143    primops.insert("tdiv_int".to_string(), tdiv_int as Binary<B>);
2144    primops.insert("tmod_int".to_string(), tmod_int as Binary<B>);
2145    // FIXME: use correct euclidian operations
2146    primops.insert("ediv_int".to_string(), tdiv_int as Binary<B>);
2147    primops.insert("emod_int".to_string(), tmod_int as Binary<B>);
2148    primops.insert("pow_int".to_string(), pow_int as Binary<B>);
2149    primops.insert("shl_int".to_string(), shl_int as Binary<B>);
2150    primops.insert("shr_int".to_string(), shr_int as Binary<B>);
2151    primops.insert("shl_mach_int".to_string(), shl_mach_int as Binary<B>);
2152    primops.insert("shr_mach_int".to_string(), shr_mach_int as Binary<B>);
2153    primops.insert("max_int".to_string(), max_int as Binary<B>);
2154    primops.insert("min_int".to_string(), min_int as Binary<B>);
2155    primops.insert("eq_bit".to_string(), eq_bits as Binary<B>);
2156    primops.insert("eq_bits".to_string(), eq_bits as Binary<B>);
2157    primops.insert("neq_bits".to_string(), neq_bits as Binary<B>);
2158    primops.insert("xor_bits".to_string(), xor_bits as Binary<B>);
2159    primops.insert("or_bits".to_string(), or_bits as Binary<B>);
2160    primops.insert("and_bits".to_string(), and_bits as Binary<B>);
2161    primops.insert("add_bits".to_string(), add_bits as Binary<B>);
2162    primops.insert("sub_bits".to_string(), sub_bits as Binary<B>);
2163    primops.insert("add_bits_int".to_string(), add_bits_int as Binary<B>);
2164    primops.insert("sub_bits_int".to_string(), sub_bits_int as Binary<B>);
2165    primops.insert("align_bits".to_string(), align_bits as Binary<B>);
2166    primops.insert("undefined_range".to_string(), undefined_range as Binary<B>);
2167    primops.insert("zero_extend".to_string(), zero_extend as Binary<B>);
2168    primops.insert("sign_extend".to_string(), sign_extend as Binary<B>);
2169    primops.insert("sail_truncate".to_string(), sail_truncate as Binary<B>);
2170    primops.insert("sail_truncateLSB".to_string(), sail_truncate_lsb as Binary<B>);
2171    primops.insert("replicate_bits".to_string(), replicate_bits as Binary<B>);
2172    primops.insert("shiftr".to_string(), shiftr as Binary<B>);
2173    primops.insert("shiftl".to_string(), shiftl as Binary<B>);
2174    primops.insert("arith_shiftr".to_string(), arith_shiftr as Binary<B>);
2175    primops.insert("shift_bits_right".to_string(), shift_bits_right as Binary<B>);
2176    primops.insert("shift_bits_left".to_string(), shift_bits_left as Binary<B>);
2177    primops.insert("append".to_string(), append as Binary<B>);
2178    primops.insert("append_64".to_string(), append as Binary<B>);
2179    primops.insert("vector_access".to_string(), vector_access as Binary<B>);
2180    primops.insert("eq_anything".to_string(), eq_anything as Binary<B>);
2181    primops.insert("eq_string".to_string(), eq_string as Binary<B>);
2182    primops.insert("concat_str".to_string(), concat_str as Binary<B>);
2183    primops.insert("string_startswith".to_string(), string_startswith as Binary<B>);
2184    primops.insert("string_drop".to_string(), string_drop as Binary<B>);
2185    primops.insert("string_take".to_string(), string_take as Binary<B>);
2186    primops.insert("cons".to_string(), cons as Binary<B>);
2187    primops.insert("undefined_vector".to_string(), undefined_vector as Binary<B>);
2188    primops.insert("print_string".to_string(), print_string as Binary<B>);
2189    primops.insert("prerr_string".to_string(), prerr_string as Binary<B>);
2190    primops.insert("print_int".to_string(), print_int as Binary<B>);
2191    primops.insert("prerr_int".to_string(), prerr_int as Binary<B>);
2192    primops.insert("print_bits".to_string(), print_bits as Binary<B>);
2193    primops.insert("prerr_bits".to_string(), prerr_bits as Binary<B>);
2194    primops.insert("platform_branch_announce".to_string(), branch_announce as Binary<B>);
2195    primops.insert("mark_register".to_string(), mark_register as Binary<B>);
2196    primops
2197}
2198
2199pub fn variadic_primops<B: BV>() -> HashMap<String, Variadic<B>> {
2200    let mut primops = HashMap::new();
2201    primops.insert("slice".to_string(), slice as Variadic<B>);
2202    primops.insert("vector_subrange".to_string(), subrange as Variadic<B>);
2203    primops.insert("vector_update".to_string(), vector_update as Variadic<B>);
2204    primops.insert("vector_update_subrange".to_string(), vector_update_subrange as Variadic<B>);
2205    primops.insert("bitvector_update".to_string(), bitvector_update as Variadic<B>);
2206    primops.insert("set_slice".to_string(), set_slice as Variadic<B>);
2207    primops.insert("get_slice_int".to_string(), get_slice_int as Variadic<B>);
2208    primops.insert("set_slice_int".to_string(), set_slice_int as Variadic<B>);
2209    primops.insert("platform_read_mem".to_string(), read_mem as Variadic<B>);
2210    primops.insert("platform_read_memt".to_string(), read_memt as Variadic<B>);
2211    primops.insert("platform_write_mem".to_string(), write_mem as Variadic<B>);
2212    primops.insert("platform_write_memt".to_string(), write_memt as Variadic<B>);
2213    primops.insert("platform_write_mem_ea".to_string(), write_mem_ea as Variadic<B>);
2214    primops.insert("platform_cache_maintenance".to_string(), cache_maintenance as Variadic<B>);
2215    primops.insert("elf_entry".to_string(), elf_entry as Variadic<B>);
2216    primops.insert("ite".to_string(), ite as Variadic<B>);
2217    primops.insert("mark_register_pair".to_string(), mark_register_pair as Variadic<B>);
2218    // We explicitly don't handle anything real number related right now
2219    primops.insert("%string->%real".to_string(), unimplemented as Variadic<B>);
2220    primops.insert("neg_real".to_string(), unimplemented as Variadic<B>);
2221    primops.insert("mult_real".to_string(), unimplemented as Variadic<B>);
2222    primops.insert("sub_real".to_string(), unimplemented as Variadic<B>);
2223    primops.insert("add_real".to_string(), unimplemented as Variadic<B>);
2224    primops.insert("div_real".to_string(), unimplemented as Variadic<B>);
2225    primops.insert("sqrt_real".to_string(), unimplemented as Variadic<B>);
2226    primops.insert("abs_real".to_string(), unimplemented as Variadic<B>);
2227    primops.insert("round_down".to_string(), unimplemented as Variadic<B>);
2228    primops.insert("round_up".to_string(), unimplemented as Variadic<B>);
2229    primops.insert("to_real".to_string(), unimplemented as Variadic<B>);
2230    primops.insert("eq_real".to_string(), unimplemented as Variadic<B>);
2231    primops.insert("lt_real".to_string(), unimplemented as Variadic<B>);
2232    primops.insert("gt_real".to_string(), unimplemented as Variadic<B>);
2233    primops.insert("lteq_real".to_string(), unimplemented as Variadic<B>);
2234    primops.insert("gteq_real".to_string(), unimplemented as Variadic<B>);
2235    primops.insert("real_power".to_string(), unimplemented as Variadic<B>);
2236    primops.insert("print_real".to_string(), unimplemented as Variadic<B>);
2237    primops.insert("prerr_real".to_string(), unimplemented as Variadic<B>);
2238    primops.insert("undefined_real".to_string(), unimplemented as Variadic<B>);
2239    primops
2240}
2241
2242pub struct Primops<B> {
2243    pub unary: HashMap<String, Unary<B>>,
2244    pub binary: HashMap<String, Binary<B>>,
2245    pub variadic: HashMap<String, Variadic<B>>,
2246}
2247
2248impl<B: BV> Default for Primops<B> {
2249    fn default() -> Self {
2250        Primops { unary: unary_primops(), binary: binary_primops(), variadic: variadic_primops() }
2251    }
2252}