diff --git a/src/backend/binaryen.rs b/src/backend/binaryen.rs index 385aa8c..1c5a956 100644 --- a/src/backend/binaryen.rs +++ b/src/backend/binaryen.rs @@ -371,6 +371,10 @@ impl Expression { Expression(module.0, expr) } + pub fn expr_drop(module: &Module, value: Expression) -> Expression { + Expression(module.0, unsafe { BinaryenDrop(module.0, value.1) }) + } + pub fn ret(module: &Module, values: &[Expression]) -> Expression { let expr = if values.len() == 0 { unsafe { BinaryenReturn(module.0, std::ptr::null()) } @@ -713,6 +717,7 @@ extern "C" { n_operands: BinaryenIndex, ) -> BinaryenExpression; fn BinaryenReturn(module: BinaryenModule, expr: BinaryenExpression) -> BinaryenExpression; + fn BinaryenDrop(module: BinaryenModule, expr: BinaryenExpression) -> BinaryenExpression; fn BinaryenAddFunc( module: BinaryenModule, diff --git a/src/backend/lower.rs b/src/backend/lower.rs index 4db2ab9..84ec375 100644 --- a/src/backend/lower.rs +++ b/src/backend/lower.rs @@ -12,7 +12,7 @@ pub(crate) fn generate_body( body: &FunctionBody, into_mod: &mut binaryen::Module, ) -> (Vec, binaryen::Expression) { - let mut ctx = ElabCtx::new(body, into_mod); + let mut ctx = ElabCtx::new(body); // For each block, generate an expr. let mut block_exprs: BTreeMap = BTreeMap::default(); @@ -146,8 +146,35 @@ struct ElabCtx<'a> { } impl<'a> ElabCtx<'a> { - fn new(body: &'a FunctionBody, into_mod: &mut binaryen::Module) -> ElabCtx<'a> { - todo!() + fn new(body: &'a FunctionBody) -> ElabCtx<'a> { + let mut this = ElabCtx { + body, + op_result_locals: FxHashMap::default(), + block_param_locals: FxHashMap::default(), + block_param_next_locals: FxHashMap::default(), + new_locals: vec![], + }; + + // Create operator result locals. + for (value, def) in body.values.entries() { + for (i, &ty) in def.tys().iter().enumerate() { + let new_local = this.new_local(ty); + this.op_result_locals.insert((value, i), new_local); + } + } + + // Create blockparam cur-value and next-value locals. + for (block, def) in body.blocks.entries() { + for (param, &(ty, _)) in def.params.iter().enumerate() { + let cur_value = this.new_local(ty); + let next_value = this.new_local(ty); + this.block_param_locals.insert((block, param), cur_value); + this.block_param_next_locals + .insert((block, param), next_value); + } + } + + this } fn elaborate_value( @@ -155,7 +182,6 @@ impl<'a> ElabCtx<'a> { into_mod: &binaryen::Module, value: Value, ) -> Option { - /* let value = self.body.resolve_alias(value); match &self.body.values[value] { @@ -164,7 +190,13 @@ impl<'a> ElabCtx<'a> { 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))) + .map(|arg_local| { + binaryen::Expression::local_get( + into_mod, + arg_local, + self.local_ty(arg_local), + ) + }) .collect::>(); // Create operator. let expr = self.create_binaryen_op(op, binaryen_args, tys); @@ -172,19 +204,17 @@ impl<'a> ElabCtx<'a> { // 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)) + Some(binaryen::Expression::expr_drop(into_mod, expr)) } else if tys.len() == 1 { // Set value directly. let local = self.get_val_local(value); - Some(into_mod.expr_local_set(local, expr)) + Some(binaryen::Expression::local_set(into_mod, local, expr)) } else { todo!("support multivalue") } } _ => None, } - */ - todo!() } fn get_val_local(&self, value: Value) -> Local { diff --git a/src/ir/value.rs b/src/ir/value.rs index df46141..0808f7e 100644 --- a/src/ir/value.rs +++ b/src/ir/value.rs @@ -24,6 +24,16 @@ impl ValueDef { } } + pub fn tys(&self) -> &[Type] { + match self { + &ValueDef::Operator(_, _, ref tys) => &tys[..], + &ValueDef::BlockParam(_, _, ref ty) + | &ValueDef::PickOutput(_, _, ref ty) + | &ValueDef::Placeholder(ref ty) => std::slice::from_ref(ty), + _ => &[], + } + } + pub fn visit_uses(&self, mut f: F) { match self { &ValueDef::BlockParam { .. } => {}