WIP.
This commit is contained in:
parent
ab260c224f
commit
f483b964bb
|
@ -6,7 +6,9 @@ use crate::ir::*;
|
||||||
use crate::op_traits::{op_inputs, op_outputs};
|
use crate::op_traits::{op_inputs, op_outputs};
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use wasmparser::{ImportSectionEntryType, Operator, Parser, Payload, Type, TypeDef};
|
use wasmparser::{
|
||||||
|
ImportSectionEntryType, Operator, Parser, Payload, Type, TypeDef, TypeOrFuncType,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn wasm_to_ir<'a>(bytes: &'a [u8]) -> Result<Module<'a>> {
|
pub fn wasm_to_ir<'a>(bytes: &'a [u8]) -> Result<Module<'a>> {
|
||||||
let mut module = Module::default();
|
let mut module = Module::default();
|
||||||
|
@ -158,12 +160,29 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
| Operator::LocalSet { .. }
|
| Operator::LocalSet { .. }
|
||||||
| Operator::LocalTee { .. } => self.emit(op.clone())?,
|
| Operator::LocalTee { .. } => self.emit(op.clone())?,
|
||||||
|
|
||||||
Operator::End => {
|
Operator::End => match self.ctrl_stack.pop() {
|
||||||
if self.ctrl_stack.is_empty() {
|
None => {
|
||||||
self.emit(Operator::Return)?;
|
self.emit(Operator::Return)?;
|
||||||
} else {
|
|
||||||
bail!("Unsupported End");
|
|
||||||
}
|
}
|
||||||
|
Some(Frame::Block { out, .. }) | Some(Frame::Loop { out, .. }) => {
|
||||||
|
// No need to manipulate stack: assuming the input
|
||||||
|
// Wasm was validated properly, the `results`
|
||||||
|
// values must be on the top of the stack now, and
|
||||||
|
// they will remain so once we exit the block.
|
||||||
|
self.emit_branch(out);
|
||||||
|
self.cur_block = out;
|
||||||
|
}
|
||||||
|
_ => bail!("unsupported block type"),
|
||||||
|
},
|
||||||
|
|
||||||
|
Operator::Block { ty } => {
|
||||||
|
let (params, results) = self.block_params_and_results(ty);
|
||||||
|
let out = self.create_block();
|
||||||
|
self.ctrl_stack.push(Frame::Block {
|
||||||
|
out,
|
||||||
|
params,
|
||||||
|
results,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => bail!("Unsupported operator: {:?}", op),
|
_ => bail!("Unsupported operator: {:?}", op),
|
||||||
|
@ -172,6 +191,30 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_block(&mut self) -> BlockId {
|
||||||
|
let id = self.body.blocks.len() as BlockId;
|
||||||
|
self.body.blocks.push(Block::default());
|
||||||
|
id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_params_and_results(&self, ty: TypeOrFuncType) -> (Vec<Type>, Vec<Type>) {
|
||||||
|
match ty {
|
||||||
|
TypeOrFuncType::Type(ret_ty) => (vec![], vec![ret_ty]),
|
||||||
|
TypeOrFuncType::FuncType(sig_idx) => {
|
||||||
|
let sig = &self.module.signatures[sig_idx as SignatureId];
|
||||||
|
(
|
||||||
|
Vec::from(sig.params.clone()),
|
||||||
|
Vec::from(sig.returns.clone()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_branch(&mut self, target: BlockId) {
|
||||||
|
let block = self.cur_block;
|
||||||
|
self.body.blocks[block].terminator = Terminator::Br { target };
|
||||||
|
}
|
||||||
|
|
||||||
fn emit(&mut self, op: Operator<'a>) -> Result<()> {
|
fn emit(&mut self, op: Operator<'a>) -> Result<()> {
|
||||||
let block = self.cur_block;
|
let block = self.cur_block;
|
||||||
let inst = self.body.blocks[block].insts.len() as InstId;
|
let inst = self.body.blocks[block].insts.len() as InstId;
|
||||||
|
|
28
src/ir.rs
28
src/ir.rs
|
@ -52,6 +52,7 @@ pub enum ValueKind {
|
||||||
pub struct Block<'a> {
|
pub struct Block<'a> {
|
||||||
pub params: Vec<Type>,
|
pub params: Vec<Type>,
|
||||||
pub insts: Vec<Inst<'a>>,
|
pub insts: Vec<Inst<'a>>,
|
||||||
|
pub terminator: Terminator<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -66,3 +67,30 @@ pub enum Operand<'a> {
|
||||||
Value(ValueId),
|
Value(ValueId),
|
||||||
Sub(Box<Inst<'a>>),
|
Sub(Box<Inst<'a>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Terminator<'a> {
|
||||||
|
Br {
|
||||||
|
target: BlockId,
|
||||||
|
},
|
||||||
|
CondBr {
|
||||||
|
cond: Operand<'a>,
|
||||||
|
if_true: BlockId,
|
||||||
|
if_false: BlockId,
|
||||||
|
},
|
||||||
|
Select {
|
||||||
|
value: Operand<'a>,
|
||||||
|
targets: Vec<BlockId>,
|
||||||
|
default: BlockId,
|
||||||
|
},
|
||||||
|
Return {
|
||||||
|
values: Vec<Operand<'a>>,
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> std::default::Default for Terminator<'a> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Terminator::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue