use crate::facts::{FunctionId, GuardKind, SourceLocation};
pub(crate) type ValueId = u32;
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct ModuleIr {
pub(crate) functions: Vec<FunctionIr>,
pub(crate) diagnostics: Vec<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct FunctionIr {
pub(crate) id: FunctionId,
pub(crate) params: Vec<ValueId>,
pub(crate) blocks: Vec<BlockIr>,
pub(crate) values: Vec<ValueNode>,
pub(crate) dbg_values: Vec<DbgValue>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct BlockIr {
pub(crate) instrs: Vec<ValueId>,
pub(crate) successors: Vec<usize>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct ValueNode {
pub(crate) block: usize,
pub(crate) opcode: OpcodeIr,
pub(crate) operands: Vec<Operand>,
pub(crate) incoming: Vec<usize>,
pub(crate) call: Option<CallIr>,
pub(crate) guard: Option<GuardOpRaw>,
pub(crate) location: Option<SourceLocation>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum OpcodeIr {
Param,
Call,
CallBr,
ICmp,
Select,
BinOp {
op: BinaryOp,
},
Cast {
op: CastOp,
},
Phi,
Load,
Store,
Ret,
Br,
Other,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum BinaryOp {
Add,
FAdd,
Sub,
FSub,
Mul,
FMul,
UDiv,
SDiv,
FDiv,
URem,
SRem,
FRem,
Shl,
LShr,
AShr,
And,
Or,
Xor,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum CastOp {
Trunc,
ZExt,
SExt,
FPToUI,
FPToSI,
UIToFP,
SIToFP,
FPTrunc,
FPExt,
PtrToInt,
PtrToAddr,
IntToPtr,
BitCast,
AddrSpaceCast,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) enum Operand {
Value(ValueId),
Const(ConstVal),
Func(FunctionId),
Other,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct ConstVal {
pub(crate) value: String,
pub(crate) bits: Option<u32>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct CallIr {
pub(crate) callee: Option<FunctionId>,
pub(crate) inline_asm: bool,
pub(crate) returns_void: bool,
pub(crate) args: Vec<Operand>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct GuardOpRaw {
pub(crate) kind: GuardKind,
pub(crate) predicate: Option<String>,
pub(crate) bound: Option<String>,
pub(crate) bits: Option<u32>,
}
pub(crate) struct IntPredicate {
pub(crate) spelling: &'static str,
pub(crate) swapped: &'static str,
pub(crate) clamps: Option<[&'static str; 2]>,
}
pub(crate) const INT_PREDICATES: [IntPredicate; 10] = [
predicate("eq", "eq", None),
predicate("ne", "ne", None),
predicate("ugt", "ult", Some(["umax", "umin"])),
predicate("uge", "ule", Some(["umax", "umin"])),
predicate("ult", "ugt", Some(["umin", "umax"])),
predicate("ule", "uge", Some(["umin", "umax"])),
predicate("sgt", "slt", Some(["smax", "smin"])),
predicate("sge", "sle", Some(["smax", "smin"])),
predicate("slt", "sgt", Some(["smin", "smax"])),
predicate("sle", "sge", Some(["smin", "smax"])),
];
const fn predicate(
spelling: &'static str,
swapped: &'static str,
clamps: Option<[&'static str; 2]>,
) -> IntPredicate {
IntPredicate {
spelling,
swapped,
clamps,
}
}
pub(crate) fn int_predicate(spelling: &str) -> Option<&'static IntPredicate> {
INT_PREDICATES.iter().find(|row| row.spelling == spelling)
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct DbgValue {
pub(crate) name: String,
pub(crate) value: Operand,
pub(crate) at: ValueId,
}