waffle/src/ir.rs

243 lines
5.7 KiB
Rust
Raw Normal View History

2021-11-13 06:16:54 +00:00
//! Intermediate representation for Wasm.
2021-11-14 08:00:34 +00:00
use crate::{backend, frontend};
2021-11-14 01:52:30 +00:00
use anyhow::Result;
use wasmparser::{FuncType, Operator, Type};
2021-11-13 06:16:54 +00:00
pub type SignatureId = usize;
pub type FuncId = usize;
2021-11-13 08:20:02 +00:00
pub type BlockId = usize;
pub type InstId = usize;
pub type ValueId = usize;
pub type LocalId = u32;
2021-11-13 06:16:54 +00:00
2021-11-13 22:23:22 +00:00
pub const NO_VALUE: ValueId = usize::MAX;
2021-11-15 07:56:56 +00:00
pub const INVALID_BLOCK: BlockId = usize::MAX;
2021-11-13 22:23:22 +00:00
#[derive(Clone, Debug, Default)]
2021-11-13 10:32:05 +00:00
pub struct Module<'a> {
2021-11-14 08:00:34 +00:00
pub orig_bytes: &'a [u8],
2021-11-13 10:32:05 +00:00
pub funcs: Vec<FuncDecl<'a>>,
2021-11-13 06:16:54 +00:00
pub signatures: Vec<FuncType>,
pub globals: Vec<Type>,
pub tables: Vec<Type>,
2021-11-13 06:16:54 +00:00
}
#[derive(Clone, Debug)]
2021-11-13 10:32:05 +00:00
pub enum FuncDecl<'a> {
2021-11-13 06:16:54 +00:00
Import(SignatureId),
2021-11-13 10:32:05 +00:00
Body(SignatureId, FunctionBody<'a>),
}
impl<'a> FuncDecl<'a> {
pub fn sig(&self) -> SignatureId {
match self {
2021-11-13 11:49:19 +00:00
FuncDecl::Import(sig) => *sig,
FuncDecl::Body(sig, ..) => *sig,
2021-11-13 10:32:05 +00:00
}
}
2021-11-13 06:16:54 +00:00
}
#[derive(Clone, Debug, Default)]
2021-11-13 10:32:05 +00:00
pub struct FunctionBody<'a> {
2021-11-13 06:16:54 +00:00
pub locals: Vec<Type>,
2021-11-13 10:32:05 +00:00
pub blocks: Vec<Block<'a>>,
pub values: Vec<ValueDef>,
}
#[derive(Clone, Debug)]
pub struct ValueDef {
pub kind: ValueKind,
pub ty: Type,
}
#[derive(Clone, Debug)]
pub enum ValueKind {
2021-11-14 06:25:27 +00:00
Arg(usize),
2021-11-13 10:32:05 +00:00
BlockParam(BlockId, usize),
2021-11-14 06:25:27 +00:00
Inst(BlockId, InstId, usize),
}
#[derive(Clone, Debug, Default)]
2021-11-13 10:32:05 +00:00
pub struct Block<'a> {
pub params: Vec<Type>,
2021-11-13 10:32:05 +00:00
pub insts: Vec<Inst<'a>>,
2021-11-14 08:00:34 +00:00
pub terminator: Terminator,
}
2021-11-15 07:56:56 +00:00
impl<'a> Block<'a> {
pub fn successors(&self) -> Vec<BlockId> {
self.terminator.successors()
}
pub fn values<'b>(&'b self) -> impl Iterator<Item = ValueId> + 'b {
self.insts
.iter()
.map(|inst| inst.outputs.iter().cloned())
.flatten()
}
pub fn visit_operands<F: Fn(&Operand)>(&self, f: F) {
for inst in &self.insts {
for input in &inst.inputs {
f(input);
}
}
match &self.terminator {
&Terminator::CondBr { ref cond, .. } => f(cond),
&Terminator::Select { ref value, .. } => f(value),
&Terminator::Return { ref values, .. } => {
for value in values {
f(value);
}
}
_ => {}
}
}
pub fn update_operands<F: Fn(&mut Operand)>(&mut self, f: F) {
for inst in &mut self.insts {
for input in &mut inst.inputs {
f(input);
}
}
match &mut self.terminator {
&mut Terminator::CondBr { ref mut cond, .. } => f(cond),
&mut Terminator::Select { ref mut value, .. } => f(value),
&mut Terminator::Return { ref mut values, .. } => {
for value in values {
f(value);
}
}
_ => {}
}
}
}
#[derive(Clone, Debug)]
2021-11-13 10:32:05 +00:00
pub struct Inst<'a> {
pub operator: Operator<'a>,
pub outputs: Vec<ValueId>,
2021-11-14 08:00:34 +00:00
pub inputs: Vec<Operand>,
}
2021-11-14 08:00:34 +00:00
#[derive(Clone, Copy, Debug)]
pub enum Operand {
2021-11-13 22:23:22 +00:00
/// An SSA value.
Value(ValueId),
2021-11-13 22:23:22 +00:00
/// Undef values are produced when code is unreachable and thus
/// removed/never executed.
Undef,
}
2021-11-14 08:00:34 +00:00
impl Operand {
2021-11-13 22:23:22 +00:00
pub fn value(value: ValueId) -> Self {
if value == NO_VALUE {
Operand::Undef
} else {
Operand::Value(value)
}
}
2021-11-13 06:16:54 +00:00
}
2021-11-13 11:38:47 +00:00
2021-11-13 21:49:57 +00:00
#[derive(Clone, Debug)]
2021-11-14 08:00:34 +00:00
pub struct BlockTarget {
2021-11-13 21:49:57 +00:00
pub block: BlockId,
2021-11-14 08:00:34 +00:00
pub args: Vec<Operand>,
2021-11-13 21:49:57 +00:00
}
2021-11-13 11:38:47 +00:00
#[derive(Clone, Debug)]
2021-11-14 08:00:34 +00:00
pub enum Terminator {
2021-11-13 11:38:47 +00:00
Br {
2021-11-14 08:00:34 +00:00
target: BlockTarget,
2021-11-13 11:38:47 +00:00
},
CondBr {
2021-11-14 08:00:34 +00:00
cond: Operand,
if_true: BlockTarget,
if_false: BlockTarget,
2021-11-13 11:38:47 +00:00
},
Select {
2021-11-14 08:00:34 +00:00
value: Operand,
targets: Vec<BlockTarget>,
default: BlockTarget,
2021-11-13 11:38:47 +00:00
},
Return {
2021-11-14 08:00:34 +00:00
values: Vec<Operand>,
2021-11-13 11:38:47 +00:00
},
None,
}
2021-11-14 08:00:34 +00:00
impl std::default::Default for Terminator {
2021-11-13 11:38:47 +00:00
fn default() -> Self {
Terminator::None
}
}
2021-11-14 01:52:30 +00:00
2021-11-14 08:00:34 +00:00
impl Terminator {
pub fn args(&self) -> Vec<Operand> {
match self {
Terminator::Br { target } => target.args.clone(),
Terminator::CondBr {
cond,
if_true,
if_false,
} => {
let mut ret = vec![*cond];
ret.extend(if_true.args.iter().cloned());
ret.extend(if_false.args.iter().cloned());
ret
}
Terminator::Select {
value,
targets,
default,
} => {
let mut ret = vec![*value];
for target in targets {
ret.extend(target.args.iter().cloned());
}
ret.extend(default.args.clone());
ret
}
Terminator::Return { values } => values.clone(),
Terminator::None => vec![],
}
}
}
2021-11-14 01:52:30 +00:00
impl<'a> Module<'a> {
pub fn from_wasm_bytes(bytes: &'a [u8]) -> Result<Self> {
2021-11-14 06:25:27 +00:00
frontend::wasm_to_ir(bytes)
2021-11-14 04:59:37 +00:00
}
2021-11-14 08:00:34 +00:00
pub fn to_wasm_bytes(mut self) -> Vec<u8> {
// TODO
self.orig_bytes.to_vec()
}
2021-11-14 04:59:37 +00:00
}
2021-11-14 08:00:34 +00:00
impl Terminator {
2021-11-14 04:59:37 +00:00
pub fn successors(&self) -> Vec<BlockId> {
match self {
Terminator::Return { .. } => vec![],
Terminator::Br { target, .. } => vec![target.block],
Terminator::CondBr {
if_true, if_false, ..
} => vec![if_true.block, if_false.block],
Terminator::Select {
ref targets,
default,
..
} => {
let mut ret = targets
.iter()
.map(|target| target.block)
.collect::<Vec<_>>();
ret.push(default.block);
ret
}
Terminator::None => vec![],
}
2021-11-14 01:52:30 +00:00
}
}