use alloc::{string::String, vec::Vec};
use crate::{LabelId, Op, Type, Unit, ValueId, VarId};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize)]
pub struct Origin {
pub unit: Unit,
pub offset: u32,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, serde::Serialize)]
pub enum Precision {
#[default]
Full,
AtLeast16,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)]
pub struct ValueDef {
pub ty: Type,
pub op: Op,
pub origin: Option<Origin>,
pub precision: Precision,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)]
pub struct Var {
pub name: String,
pub ty: Type,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)]
pub enum Node {
Value(ValueId),
StoreVar(VarId, ValueId),
StoreOutput(u32, u8, ValueId),
Demote,
If {
cond: ValueId,
accept: Region,
reject: Region,
results: Vec<ValueId>,
},
Block {
label: LabelId,
body: Region,
results: Vec<ValueId>,
},
Loop {
label: LabelId,
params: Vec<ValueId>,
inits: Vec<ValueId>,
body: Region,
results: Vec<ValueId>,
},
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)]
pub enum End {
Yield(Vec<ValueId>),
Br(LabelId, Vec<ValueId>),
Continue(LabelId, Vec<ValueId>),
Return,
Kill,
Unreachable,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, serde::Serialize)]
pub struct Region {
pub nodes: Vec<Node>,
pub end: Option<End>,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)]
pub struct Target {
pub block: u32,
pub args: Vec<ValueId>,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)]
pub enum Terminator {
Jump(Target),
Branch {
cond: ValueId,
accept: Target,
reject: Target,
},
Return,
Kill,
Unreachable,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)]
pub struct Block {
pub params: Vec<ValueId>,
pub nodes: Vec<Node>,
pub term: Terminator,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)]
pub enum Body {
Regions(Region),
Cfg(Vec<Block>),
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)]
pub struct Function {
pub name: String,
pub values: Vec<ValueDef>,
pub vars: Vec<Var>,
pub body: Body,
}
impl Function {
pub fn value(&self, v: ValueId) -> Option<&ValueDef> {
self.values.get(v.0 as usize)
}
pub fn ty(&self, v: ValueId) -> Option<Type> {
self.value(v).map(|d| d.ty)
}
}