Path: blob/main/cranelift/isle/veri/veri_ir/src/annotation_ir.rs
1693 views
/// A higher-level annotation IR that does not specify bitvector widths.1/// This allows annotations to be generic over possible types, which2/// corresponds to how ISLE rewrites are written.3use std::fmt;4/// A bound variable, including the VIR type5#[derive(Clone, Debug, PartialEq, Eq)]6pub struct BoundVar {7pub name: String,8pub ty: Option<Type>,9}1011impl BoundVar {12/// Construct a new bound variable13pub fn new_with_ty(name: &str, ty: &Type) -> Self {14BoundVar {15name: name.to_string(),16ty: Some(ty.clone()),17}18}1920/// Construct a new bound variable, cloning from references21pub fn new(name: &str) -> Self {22BoundVar {23name: name.to_string(),24ty: None,25}26}2728/// An expression with the bound variable's name29pub fn as_expr(&self) -> Expr {30Expr::Var(self.name.clone())31}32}3334/// A function signature annotation, including the bound variable names for all35/// arguments and the return value.36#[derive(Clone, Debug, PartialEq, Eq)]37pub struct TermSignature {38pub args: Vec<BoundVar>,39pub ret: BoundVar,40}4142/// Verification IR annotations for an ISLE term consist of the function43/// signature and a list of assertions.44#[derive(Clone, Debug, PartialEq, Eq)]45pub struct TermAnnotation {46pub sig: TermSignature,47// Note: extra Box for now for ease of parsing48#[allow(clippy::vec_box)]49pub assumptions: Vec<Box<Expr>>,5051#[allow(clippy::vec_box)]52pub assertions: Vec<Box<Expr>>,53}5455impl TermAnnotation {56/// New annotation57pub fn new(sig: TermSignature, assumptions: Vec<Expr>, assertions: Vec<Expr>) -> Self {58TermAnnotation {59sig,60assumptions: assumptions.iter().map(|x| Box::new(x.clone())).collect(),61assertions: assertions.iter().map(|x| Box::new(x.clone())).collect(),62}63}6465pub fn sig(&self) -> &TermSignature {66&self.sig67}6869pub fn assertions(&self) -> Vec<Expr> {70self.assumptions.iter().map(|x| *x.clone()).collect()71}72}7374/// Higher-level type, not including bitwidths.75#[derive(Clone, Debug, Hash, PartialEq, Eq)]76pub enum Type {77/// Internal type used solely for type inference78Poly(u32),7980/// The expression is a bitvector, currently modeled in the81/// logic QF_BV https://SMT-LIB.cs.uiowa.edu/version1/logics/QF_BV.smt82/// This corresponds to Cranelift's Isle type:83/// (type Value (primitive Value))84BitVector,8586/// Use if the width is known87BitVectorWithWidth(usize),8889// Use if the width is unknown after inference, indexed by a90// canonical type variable91BitVectorUnknown(u32),9293/// The expression is an integer (currently used for ISLE type,94/// representing bitwidth)95Int,9697/// The expression is a boolean.98Bool,99100/// Unit, removed before SMT-Lib101Unit,102}103104impl fmt::Display for Type {105fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {106match self {107Type::Poly(_) => write!(f, "poly"),108Type::BitVector => write!(f, "bv"),109Type::BitVectorWithWidth(w) => write!(f, "bv{}", *w),110Type::BitVectorUnknown(_) => write!(f, "bv"),111Type::Int => write!(f, "Int"),112Type::Bool => write!(f, "Bool"),113Type::Unit => write!(f, "Unit"),114}115}116}117118impl Type {119pub fn is_poly(&self) -> bool {120matches!(self, Type::Poly(_))121}122}123124/// Type-specified constants125#[derive(Clone, Debug, PartialEq, Eq)]126pub struct Const {127pub ty: Type,128pub value: i128,129pub width: usize,130}131132/// Width arguments133#[derive(Clone, Debug, PartialEq, Eq)]134pub enum Width {135Const(usize),136RegWidth,137}138139/// Typed expressions (u32 is the type var)140#[derive(Clone, Debug, PartialEq, Eq)]141pub enum Expr {142// Terminal nodes143Var(String),144Const(Const),145True,146False,147148// Get the width of a bitvector149WidthOf(Box<Expr>),150151// Boolean operations152Not(Box<Expr>),153And(Box<Expr>, Box<Expr>),154Or(Box<Expr>, Box<Expr>),155Imp(Box<Expr>, Box<Expr>),156Eq(Box<Expr>, Box<Expr>),157Lte(Box<Expr>, Box<Expr>),158Lt(Box<Expr>, Box<Expr>),159160BVSgt(Box<Expr>, Box<Expr>),161BVSgte(Box<Expr>, Box<Expr>),162BVSlt(Box<Expr>, Box<Expr>),163BVSlte(Box<Expr>, Box<Expr>),164BVUgt(Box<Expr>, Box<Expr>),165BVUgte(Box<Expr>, Box<Expr>),166BVUlt(Box<Expr>, Box<Expr>),167BVUlte(Box<Expr>, Box<Expr>),168169BVSaddo(Box<Expr>, Box<Expr>),170171// Bitvector operations172// Note: these follow the naming conventions of the SMT theory of bitvectors:173// https://SMT-LIB.cs.uiowa.edu/version1/logics/QF_BV.smt174// Unary operators175BVNeg(Box<Expr>),176BVNot(Box<Expr>),177CLZ(Box<Expr>),178CLS(Box<Expr>),179Rev(Box<Expr>),180BVPopcnt(Box<Expr>),181182// Binary operators183BVMul(Box<Expr>, Box<Expr>),184BVUDiv(Box<Expr>, Box<Expr>),185BVSDiv(Box<Expr>, Box<Expr>),186BVAdd(Box<Expr>, Box<Expr>),187BVSub(Box<Expr>, Box<Expr>),188BVUrem(Box<Expr>, Box<Expr>),189BVSrem(Box<Expr>, Box<Expr>),190BVAnd(Box<Expr>, Box<Expr>),191BVOr(Box<Expr>, Box<Expr>),192BVXor(Box<Expr>, Box<Expr>),193BVRotl(Box<Expr>, Box<Expr>),194BVRotr(Box<Expr>, Box<Expr>),195BVShl(Box<Expr>, Box<Expr>),196BVShr(Box<Expr>, Box<Expr>),197BVAShr(Box<Expr>, Box<Expr>),198199// Includes type200BVSubs(Box<Expr>, Box<Expr>, Box<Expr>),201202// Conversions203// Zero extend, static and dynamic width204BVZeroExtTo(Box<Width>, Box<Expr>),205BVZeroExtToVarWidth(Box<Expr>, Box<Expr>),206207// Sign extend, static and dynamic width208BVSignExtTo(Box<Width>, Box<Expr>),209BVSignExtToVarWidth(Box<Expr>, Box<Expr>),210211// Extract specified bits212BVExtract(usize, usize, Box<Expr>),213214// Concat two bitvectors215BVConcat(Vec<Expr>),216217// Convert integer to bitvector218BVIntToBv(usize, Box<Expr>),219220// Convert bitvector to integer221BVToInt(Box<Expr>),222223// Conversion to wider/narrower bits, without an explicit extend224// Allow the destination width to be symbolic.225BVConvTo(Box<Expr>, Box<Expr>),226227// Conditional if-then-else228Conditional(Box<Expr>, Box<Expr>, Box<Expr>),229230// Switch231Switch(Box<Expr>, Vec<(Expr, Expr)>),232233LoadEffect(Box<Expr>, Box<Expr>, Box<Expr>),234235StoreEffect(Box<Expr>, Box<Expr>, Box<Expr>, Box<Expr>),236}237238impl Expr {239pub fn var(s: &str) -> Expr {240Expr::Var(s.to_string())241}242243pub fn unary<F: Fn(Box<Expr>) -> Expr>(f: F, x: Expr) -> Expr {244f(Box::new(x))245}246247pub fn binary<F: Fn(Box<Expr>, Box<Expr>) -> Expr>(f: F, x: Expr, y: Expr) -> Expr {248f(Box::new(x), Box::new(y))249}250}251252253