From d0ecd1238a34bf66b5099fb0492767b257b4fd8a Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Tue, 29 Nov 2022 00:58:55 -0800 Subject: [PATCH] WIP. --- src/backend/localify.rs | 4 +- src/backend/mod.rs | 127 +++++++++++++++++++++++++++++++++++++++- src/backend/stackify.rs | 3 + src/ir.rs | 13 ++++ 4 files changed, 142 insertions(+), 5 deletions(-) diff --git a/src/backend/localify.rs b/src/backend/localify.rs index 34902c3..44e526f 100644 --- a/src/backend/localify.rs +++ b/src/backend/localify.rs @@ -10,8 +10,8 @@ use std::collections::{HashMap, HashSet}; #[derive(Clone, Debug, Default)] pub struct Localifier { - values: PerEntity>, - locals: EntityVec, + pub values: PerEntity>, + pub locals: EntityVec, } impl Localifier { diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 8cf332e..c9d954d 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -1,9 +1,10 @@ //! Backend: IR to Wasm. use crate::cfg::CFGInfo; -use crate::ir::FunctionBody; +use crate::ir::{FunctionBody, Value}; use crate::passes::rpo::RPO; use anyhow::Result; +use std::borrow::Cow; pub mod stackify; use stackify::{Context as StackifyContext, WasmBlock}; @@ -41,7 +42,127 @@ impl<'a> WasmBackend<'a> { }) } - pub fn compile(&self) -> Result> { - Ok(vec![]) + pub fn compile(&self) -> Result { + let mut func = wasm_encoder::Function::new( + self.locals + .locals + .values() + .map(|&ty| (1, wasm_encoder::ValType::from(ty))) + .collect::>(), + ); + + for block in &self.ctrl { + self.lower_block(block, &mut func); + } + + // If the last block was a Block, Loop or If, then the type + // may not match, so end with an Unreachable. + match self.ctrl.last() { + Some(&WasmBlock::Block { .. }) + | Some(&WasmBlock::Loop { .. }) + | Some(&WasmBlock::If { .. }) => { + func.instruction(&wasm_encoder::Instruction::Unreachable); + } + _ => {} + } + + Ok(func) + } + + fn lower_block(&self, block: &WasmBlock<'_>, func: &mut wasm_encoder::Function) { + match block { + WasmBlock::Block { body, .. } => { + func.instruction(&wasm_encoder::Instruction::Block( + wasm_encoder::BlockType::Empty, + )); + for sub_block in &body[..] { + self.lower_block(sub_block, func); + } + func.instruction(&wasm_encoder::Instruction::End); + } + WasmBlock::Loop { body, .. } => { + func.instruction(&wasm_encoder::Instruction::Loop( + wasm_encoder::BlockType::Empty, + )); + for sub_block in &body[..] { + self.lower_block(sub_block, func); + } + func.instruction(&wasm_encoder::Instruction::End); + } + WasmBlock::Br { target } => { + func.instruction(&wasm_encoder::Instruction::Br(target.index())); + } + WasmBlock::If { + cond, + if_true, + if_false, + } => { + self.lower_value(*cond, func); + func.instruction(&wasm_encoder::Instruction::If( + wasm_encoder::BlockType::Empty, + )); + for sub_block in &if_true[..] { + self.lower_block(sub_block, func); + } + if if_false.len() > 0 { + func.instruction(&wasm_encoder::Instruction::Else); + for sub_block in &if_false[..] { + self.lower_block(sub_block, func); + } + } + func.instruction(&wasm_encoder::Instruction::End); + } + WasmBlock::Select { + selector, + targets, + default, + } => { + self.lower_value(*selector, func); + func.instruction(&wasm_encoder::Instruction::BrTable( + Cow::Owned( + targets + .iter() + .map(|label| label.index()) + .collect::>(), + ), + default.index(), + )); + } + WasmBlock::Leaf { block } => { + for &inst in &self.body.blocks[*block].insts { + self.lower_inst(inst, func); + } + } + WasmBlock::BlockParams { from, to } => { + debug_assert_eq!(from.len(), to.len()); + for &from in from.iter() { + self.lower_value(from, func); + } + for &(_, to) in to.iter().rev() { + self.lower_set_value(to, func); + } + } + WasmBlock::Return { values } => { + for &value in &values[..] { + self.lower_value(value, func); + } + func.instruction(&wasm_encoder::Instruction::Return); + } + WasmBlock::Unreachable => { + func.instruction(&wasm_encoder::Instruction::Unreachable); + } + } + } + + fn lower_value(&self, value: Value, func: &mut wasm_encoder::Function) { + todo!() + } + + fn lower_set_value(&self, value: Value, func: &mut wasm_encoder::Function) { + todo!() + } + + fn lower_inst(&self, value: Value, func: &mut wasm_encoder::Function) { + todo!() } } diff --git a/src/backend/stackify.rs b/src/backend/stackify.rs index 203de6d..90bd6ee 100644 --- a/src/backend/stackify.rs +++ b/src/backend/stackify.rs @@ -67,6 +67,9 @@ impl WasmLabel { fn add(&self, extra: usize) -> WasmLabel { WasmLabel(self.0.checked_add(u32::try_from(extra).unwrap()).unwrap()) } + pub fn index(&self) -> u32 { + self.0 + } } pub struct Context<'a, 'b> { diff --git a/src/ir.rs b/src/ir.rs index 1bc1d4c..5fafc10 100644 --- a/src/ir.rs +++ b/src/ir.rs @@ -39,6 +39,19 @@ impl std::fmt::Display for Type { } } +impl From for wasm_encoder::ValType { + fn from(ty: Type) -> wasm_encoder::ValType { + match ty { + Type::I32 => wasm_encoder::ValType::I32, + Type::I64 => wasm_encoder::ValType::I64, + Type::F32 => wasm_encoder::ValType::F32, + Type::F64 => wasm_encoder::ValType::F64, + Type::V128 => wasm_encoder::ValType::V128, + Type::FuncRef => wasm_encoder::ValType::FuncRef, + } + } +} + declare_entity!(Signature, "sig"); declare_entity!(Func, "func"); declare_entity!(Block, "block");