waffle/src/backend/lower.rs

156 lines
5 KiB
Rust
Raw Normal View History

2022-11-01 22:43:47 -05:00
/*
2022-10-28 16:39:38 -05:00
use crate::backend::binaryen;
2022-11-01 22:43:47 -05:00
use crate::entity::EntityRef;
2022-10-28 16:39:38 -05:00
use crate::ir::*;
2022-11-01 04:26:21 -05:00
use crate::Operator;
2022-10-28 16:39:38 -05:00
use fxhash::FxHashMap;
2022-10-29 17:19:26 -05:00
use wasmparser::Type;
2022-10-28 16:39:38 -05:00
2022-10-29 17:19:26 -05:00
/// Creates a body expression for a function. Returns that expression,
/// and new locals (as their types) that were created as temporaries
/// and need to be appended to `body.locals`.
2022-10-28 16:39:38 -05:00
pub(crate) fn generate_body(
body: &FunctionBody,
into_mod: &mut binaryen::Module,
2022-10-29 17:19:26 -05:00
) -> (Vec<Type>, binaryen::Expression) {
2022-11-01 04:26:21 -05:00
let mut ctx = ElabCtx::new(body, into_mod);
2022-10-28 16:39:38 -05:00
// For each block, generate an expr.
2022-11-01 22:43:47 -05:00
let mut block_exprs: FxHashMap<Block, binaryen::Expression> = FxHashMap::default();
for (block_id, block) in body.blocks.entries() {
let exprs = block
2022-10-28 16:39:38 -05:00
.insts
.iter()
2022-11-01 04:26:21 -05:00
.flat_map(|&inst| {
2022-10-28 16:39:38 -05:00
let inst = body.resolve_alias(inst);
2022-11-01 04:26:21 -05:00
ctx.elaborate_value(into_mod, inst)
2022-10-28 16:39:38 -05:00
})
2022-11-01 04:26:21 -05:00
.collect::<Vec<binaryen::Expression>>();
2022-11-01 22:43:47 -05:00
block_exprs.insert(block_id, binaryen::Expression::block(into_mod, &exprs[..]));
2022-10-28 16:39:38 -05:00
}
2022-11-01 04:26:21 -05:00
// Combine blocks into a single body expression, using the
// relooper/stackifier support built into Binaryen.
let mut relooper = binaryen::Relooper::new(into_mod);
let mut entry = None;
2022-11-01 22:43:47 -05:00
let mut relooper_blocks: FxHashMap<Block, binaryen::RelooperBlock> = FxHashMap::default();
2022-11-01 04:26:21 -05:00
for (block_id, block_expr) in block_exprs {}
let index_var = ctx.new_local(Type::I32);
2022-11-01 22:43:47 -05:00
let expr = relooper.construct(entry.unwrap(), index_var.index());
2022-11-01 04:26:21 -05:00
(ctx.new_locals, expr)
2022-10-28 16:39:38 -05:00
}
2022-10-29 17:19:26 -05:00
#[derive(Clone, Debug)]
2022-11-01 04:26:21 -05:00
struct ElabCtx<'a> {
body: &'a FunctionBody,
2022-11-01 22:43:47 -05:00
op_result_locals: FxHashMap<(Value, usize), Local>,
block_param_locals: FxHashMap<(Block, usize), Local>,
2022-10-29 17:19:26 -05:00
new_locals: Vec<Type>,
2022-10-28 16:39:38 -05:00
}
2022-11-01 04:26:21 -05:00
impl<'a> ElabCtx<'a> {
fn new(body: &'a FunctionBody, into_mod: &mut binaryen::Module) -> ElabCtx<'a> {
2022-11-01 22:43:47 -05:00
todo!()
2022-11-01 04:26:21 -05:00
}
fn elaborate_value(
&mut self,
into_mod: &binaryen::Module,
value: Value,
) -> Option<binaryen::Expression> {
2022-11-01 22:43:47 -05:00
/*
2022-11-01 04:26:21 -05:00
let value = self.body.resolve_alias(value);
2022-11-01 22:43:47 -05:00
match &self.body.values[value] {
2022-11-01 04:26:21 -05:00
&ValueDef::Operator(op, ref args, ref tys) => {
// Get expressions for each arg.
let args = args.iter().map(|&arg| self.get_val_local(arg));
// Create `get_local` expressions for each arg.
let binaryen_args = args
.map(|arg_local| into_mod.expr_local_get(arg_local, self.local_ty(arg_local)))
.collect::<Vec<_>>();
// Create operator.
let expr = self.create_binaryen_op(op, binaryen_args, tys);
// Set local(s) as appropriate.
if tys.len() == 0 {
// Nothing. Create a `drop` expr that wraps the actual operator.
Some(into_mod.expr_drop(expr))
} else if tys.len() == 1 {
// Set value directly.
let local = self.get_val_local(value);
Some(into_mod.expr_local_set(local, expr))
} else {
todo!("support multivalue")
}
}
_ => None,
2022-10-29 17:19:26 -05:00
}
2022-11-01 22:43:47 -05:00
*/
todo!()
2022-10-28 16:39:38 -05:00
}
2022-11-01 22:43:47 -05:00
fn get_val_local(&self, value: Value) -> Local {
match &self.body.values[value] {
&ValueDef::Arg(idx, _) => Local::new(idx),
2022-11-01 04:26:21 -05:00
&ValueDef::BlockParam(block, idx, _) => {
self.block_param_locals.get(&(block, idx)).copied().unwrap()
}
&ValueDef::Operator(..) => self.op_result_locals.get(&(value, 0)).copied().unwrap(),
&ValueDef::PickOutput(value, idx, _) => {
self.op_result_locals.get(&(value, idx)).copied().unwrap()
}
&ValueDef::Alias(val) => self.get_val_local(val),
&ValueDef::Placeholder(_) => unreachable!(),
}
2022-10-28 16:39:38 -05:00
}
2022-11-01 22:43:47 -05:00
fn new_local(&mut self, ty: Type) -> Local {
let index = Local::new(self.body.locals.len() + self.new_locals.len());
2022-11-01 04:26:21 -05:00
self.new_locals.push(ty);
index
}
2022-10-28 16:39:38 -05:00
2022-11-01 04:26:21 -05:00
fn create_binaryen_op(
&mut self,
op: Operator,
args: Vec<binaryen::Expression>,
tys: &[Type],
) -> binaryen::Expression {
todo!()
2022-10-28 16:39:38 -05:00
}
2022-11-01 22:43:47 -05:00
fn local_ty(&self, local: Local) -> Type {
2022-11-01 04:26:21 -05:00
self.body
.locals
2022-11-01 22:43:47 -05:00
.get(local)
2022-11-01 04:26:21 -05:00
.copied()
2022-11-01 22:43:47 -05:00
.unwrap_or_else(|| self.new_locals[local.index() - self.body.locals.len()])
2022-11-01 04:26:21 -05:00
}
2022-10-28 16:39:38 -05:00
}
pub(crate) fn create_new_func(
module: &Module,
2022-11-01 22:43:47 -05:00
sig: Signature,
2022-10-28 16:39:38 -05:00
body: &FunctionBody,
into_mod: &mut binaryen::Module,
body_expr: binaryen::Expression,
2022-10-29 17:19:26 -05:00
new_locals: Vec<Type>,
2022-10-28 16:39:38 -05:00
) {
// Create param types.
let sig = module.signature(sig);
let _func = binaryen::Function::create(
into_mod,
sig.params.iter().copied(),
sig.returns.iter().copied(),
2022-10-29 17:19:26 -05:00
body.locals
2022-11-01 22:43:47 -05:00
.values()
2022-10-29 17:19:26 -05:00
.copied()
.skip(body.n_params)
.chain(new_locals.into_iter()),
2022-10-28 16:39:38 -05:00
body_expr,
);
}
2022-11-01 22:43:47 -05:00
*/