This commit is contained in:
Chris Fallin 2022-11-29 00:58:55 -08:00
parent 5859930639
commit d0ecd1238a
4 changed files with 142 additions and 5 deletions

View file

@ -10,8 +10,8 @@ use std::collections::{HashMap, HashSet};
#[derive(Clone, Debug, Default)]
pub struct Localifier {
values: PerEntity<Value, SmallVec<[Local; 2]>>,
locals: EntityVec<Local, Type>,
pub values: PerEntity<Value, SmallVec<[Local; 2]>>,
pub locals: EntityVec<Local, Type>,
}
impl Localifier {

View file

@ -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<Vec<u8>> {
Ok(vec![])
pub fn compile(&self) -> Result<wasm_encoder::Function> {
let mut func = wasm_encoder::Function::new(
self.locals
.locals
.values()
.map(|&ty| (1, wasm_encoder::ValType::from(ty)))
.collect::<Vec<_>>(),
);
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::<Vec<_>>(),
),
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!()
}
}

View file

@ -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> {

View file

@ -39,6 +39,19 @@ impl std::fmt::Display for Type {
}
}
impl From<Type> 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");