WIP.
This commit is contained in:
parent
5859930639
commit
d0ecd1238a
|
@ -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 {
|
||||
|
|
|
@ -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!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
|
|
13
src/ir.rs
13
src/ir.rs
|
@ -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");
|
||||
|
|
Loading…
Reference in a new issue