diff --git a/src/backend/final.rs b/src/backend/final.rs index c33b222..225cc6d 100644 --- a/src/backend/final.rs +++ b/src/backend/final.rs @@ -1,11 +1,10 @@ //! Final Wasm operator sequence production. +use super::{Locations, SerializedBlockTarget, SerializedBody, SerializedOperator}; +use crate::{ops::ty_to_valty, FunctionBody}; +use std::borrow::Cow; use wasm_encoder::BlockType; -use crate::{ops::ty_to_valty, FunctionBody, Operator}; - -use super::{Locations, SerializedBody, SerializedOperator}; - #[derive(Clone, Debug)] pub struct Wasm { operators: Vec>, @@ -62,36 +61,96 @@ impl Wasm { self.operators.push(op.clone().into()); } SerializedOperator::Br(ref target) => { - todo!() + self.translate_target(0, target, locations); } SerializedOperator::BrIf { cond, ref if_true, ref if_false, } => { - todo!() + let loc = *locations.locations.get(&(*cond, 0)).unwrap(); + self.operators + .push(wasm_encoder::Instruction::LocalGet(loc)); + self.operators.push(wasm_encoder::Instruction::If( + wasm_encoder::BlockType::Empty, + )); + self.translate_target(1, if_true, locations); + self.operators.push(wasm_encoder::Instruction::Else); + self.translate_target(1, if_false, locations); + self.operators.push(wasm_encoder::Instruction::End); } SerializedOperator::BrTable { index, ref targets, ref default, } => { - todo!() + for _ in 0..(targets.len() + 2) { + self.operators.push(wasm_encoder::Instruction::Block( + wasm_encoder::BlockType::Empty, + )); + } + + let loc = *locations.locations.get(&(*index, 0)).unwrap(); + self.operators + .push(wasm_encoder::Instruction::LocalGet(loc)); + let br_table_targets = (1..=targets.len()).map(|i| i as u32).collect::>(); + self.operators.push(wasm_encoder::Instruction::BrTable( + Cow::Owned(br_table_targets), + 0, + )); + self.operators.push(wasm_encoder::Instruction::End); + + self.translate_target(targets.len() + 1, default, locations); + self.operators.push(wasm_encoder::Instruction::End); + + for i in 0..targets.len() { + self.translate_target(targets.len() - i, &targets[i], locations); + self.operators.push(wasm_encoder::Instruction::End); + } } SerializedOperator::Get(v, i) => { - todo!() + let loc = *locations.locations.get(&(*v, *i)).unwrap(); + self.operators + .push(wasm_encoder::Instruction::LocalGet(loc)); } SerializedOperator::Set(v, i) => { - todo!() + let loc = *locations.locations.get(&(*v, *i)).unwrap(); + self.operators + .push(wasm_encoder::Instruction::LocalSet(loc)); } SerializedOperator::Tee(v, i) => { - todo!() + let loc = *locations.locations.get(&(*v, *i)).unwrap(); + self.operators + .push(wasm_encoder::Instruction::LocalTee(loc)); + } + } + } + + fn translate_target( + &mut self, + extra_blocks: usize, + target: &SerializedBlockTarget, + locations: &Locations, + ) { + match target { + &SerializedBlockTarget::Fallthrough(ref ops) => { + for op in ops { + self.translate(op, locations); + } + } + &SerializedBlockTarget::Branch(branch, ref ops) => { + for op in ops { + self.translate(op, locations); + } + self.operators.push(wasm_encoder::Instruction::Br( + (branch + extra_blocks) as u32, + )); } } } } -pub fn produce_wasm(f: &FunctionBody, body: &SerializedBody, locations: &Locations) -> Wasm { +pub fn produce_func_wasm(f: &FunctionBody, body: &SerializedBody, locations: &Locations) -> Wasm { let mut wasm = Wasm { operators: vec![], locals: vec![], diff --git a/src/backend/locations.rs b/src/backend/locations.rs index 1bf4312..18cbf23 100644 --- a/src/backend/locations.rs +++ b/src/backend/locations.rs @@ -65,10 +65,10 @@ impl<'a> Allocator<'a> { let mut reads = vec![]; let mut writes = vec![]; op.visit_value_locals( - |value, index| { + &mut |value, index| { reads.push((value, index)); }, - |value, index| { + &mut |value, index| { writes.push((value, index)); }, ); @@ -77,7 +77,7 @@ impl<'a> Allocator<'a> { let span = match self.spans.get_mut(&(value, index)) { Some(span) => span, None => { - panic!("Read before any write to local (v{},{})", value, index); + panic!("Read before any write to local ({},{})", value, index); } }; span.end = location + 1; diff --git a/src/backend/serialize.rs b/src/backend/serialize.rs index 802016d..7a03f65 100644 --- a/src/backend/serialize.rs +++ b/src/backend/serialize.rs @@ -72,12 +72,12 @@ pub enum SerializedOperator { impl SerializedOperator { pub fn visit_value_locals( &self, - mut r: R, - mut w: W, + r: &mut R, + w: &mut W, ) { match self { &SerializedOperator::Br(ref target) => { - target.visit_value_locals(&mut r, &mut w); + target.visit_value_locals(r, w); } &SerializedOperator::BrIf { cond, @@ -85,8 +85,8 @@ impl SerializedOperator { ref if_false, } => { r(cond, 0); - if_true.visit_value_locals(&mut r, &mut w); - if_false.visit_value_locals(&mut r, &mut w); + if_true.visit_value_locals(r, w); + if_false.visit_value_locals(r, w); } &SerializedOperator::BrTable { index, @@ -94,9 +94,9 @@ impl SerializedOperator { ref targets, } => { r(index, 0); - default.visit_value_locals(&mut r, &mut w); + default.visit_value_locals(r, w); for target in targets { - target.visit_value_locals(&mut r, &mut w); + target.visit_value_locals(r, w); } } &SerializedOperator::Get(v, i) => { @@ -128,7 +128,7 @@ impl SerializedBlockTarget { &SerializedBlockTarget::Branch(_, ref ops) | &SerializedBlockTarget::Fallthrough(ref ops) => { for op in ops { - op.visit_value_locals(|value, i| r(value, i), |value, i| w(value, i)); + op.visit_value_locals(r, w); } } } diff --git a/src/ir.rs b/src/ir.rs index eea694e..96502a1 100644 --- a/src/ir.rs +++ b/src/ir.rs @@ -3,7 +3,7 @@ use std::collections::hash_map::Entry; use crate::{ - backend::{BlockOrder, LoopNest, SerializedBody, WasmRegion}, + backend::{produce_func_wasm, BlockOrder, Locations, LoopNest, SerializedBody, WasmRegion}, cfg::CFGInfo, frontend, Operator, }; @@ -492,7 +492,11 @@ impl<'a> Module<'a> { let regions = WasmRegion::compute(&cfg, &loopnest); let blockorder = BlockOrder::compute(body, &cfg, ®ions); let serialized = SerializedBody::compute(body, &cfg, &blockorder); - log::trace!("serialized:{:?}", serialized); + log::trace!("serialized: {:?}", serialized); + let locations = Locations::compute(body, &serialized); + log::trace!("locations: {:?}", locations); + let func_body = produce_func_wasm(body, &serialized, &locations); + log::trace!("body: {:?}", func_body); } _ => {} }