waffle/src/backend/final.rs

178 lines
6.1 KiB
Rust
Raw Normal View History

2021-12-24 08:07:45 +00:00
//! Final Wasm operator sequence production.
2021-12-24 08:28:44 +00:00
use super::{Locations, SerializedBlockTarget, SerializedBody, SerializedOperator};
use crate::{ops::ty_to_valty, FunctionBody};
use std::borrow::Cow;
2021-12-24 08:07:45 +00:00
use wasm_encoder::BlockType;
2021-12-24 21:00:21 +00:00
use wasmparser::Type;
2021-12-24 08:07:45 +00:00
#[derive(Clone, Debug)]
pub struct Wasm {
2021-12-24 21:00:21 +00:00
pub operators: Vec<wasm_encoder::Instruction<'static>>,
pub locals: Vec<wasm_encoder::ValType>,
2021-12-24 08:07:45 +00:00
}
2021-12-24 21:00:21 +00:00
struct WasmContext<'a, FT: FuncTypeSink> {
wasm: &'a mut Wasm,
func_type_sink: &'a mut FT,
}
pub trait FuncTypeSink {
fn add_signature(&mut self, params: Vec<Type>, results: Vec<Type>) -> u32;
}
impl<'a, FT: FuncTypeSink> WasmContext<'a, FT> {
fn create_type(&mut self, params: Vec<Type>, results: Vec<Type>) -> u32 {
self.func_type_sink.add_signature(params, results)
2021-12-24 08:07:45 +00:00
}
2021-12-24 21:00:21 +00:00
2021-12-24 08:07:45 +00:00
fn translate(&mut self, op: &SerializedOperator, locations: &Locations) {
2021-12-24 22:50:23 +00:00
log::trace!("translate: {:?}", op);
2021-12-24 08:07:45 +00:00
match op {
SerializedOperator::StartBlock {
ref params,
ref results,
..
} => {
2021-12-24 21:00:21 +00:00
let ty =
self.create_type(params.iter().map(|&(ty, _)| ty).collect(), results.clone());
self.wasm.operators.push(wasm_encoder::Instruction::Block(
BlockType::FunctionType(ty),
));
2021-12-24 08:07:45 +00:00
}
SerializedOperator::StartLoop {
ref params,
ref results,
..
} => {
2021-12-24 21:00:21 +00:00
let ty =
self.create_type(params.iter().map(|&(ty, _)| ty).collect(), results.clone());
self.wasm
.operators
2021-12-24 08:07:45 +00:00
.push(wasm_encoder::Instruction::Loop(BlockType::FunctionType(ty)));
}
SerializedOperator::End => {
2021-12-24 21:00:21 +00:00
self.wasm.operators.push(wasm_encoder::Instruction::End);
2021-12-24 08:07:45 +00:00
}
SerializedOperator::GetArg(index) => {
2021-12-24 21:00:21 +00:00
self.wasm
.operators
2021-12-24 08:07:45 +00:00
.push(wasm_encoder::Instruction::LocalGet(*index as u32));
}
SerializedOperator::Operator(op) => {
2021-12-24 21:00:21 +00:00
self.wasm.operators.push(op.clone().into());
2021-12-24 08:07:45 +00:00
}
SerializedOperator::Br(ref target) => {
2021-12-24 08:28:44 +00:00
self.translate_target(0, target, locations);
2021-12-24 08:07:45 +00:00
}
SerializedOperator::BrIf {
ref if_true,
ref if_false,
} => {
2021-12-24 21:00:21 +00:00
self.wasm.operators.push(wasm_encoder::Instruction::If(
2021-12-24 08:28:44 +00:00
wasm_encoder::BlockType::Empty,
));
self.translate_target(1, if_true, locations);
2021-12-24 21:00:21 +00:00
self.wasm.operators.push(wasm_encoder::Instruction::Else);
2021-12-24 08:28:44 +00:00
self.translate_target(1, if_false, locations);
2021-12-24 21:00:21 +00:00
self.wasm.operators.push(wasm_encoder::Instruction::End);
2021-12-24 08:07:45 +00:00
}
SerializedOperator::BrTable {
ref targets,
ref default,
} => {
2021-12-24 21:00:21 +00:00
let ty = self.create_type(vec![Type::I32], vec![]);
2021-12-24 08:28:44 +00:00
for _ in 0..(targets.len() + 2) {
2021-12-24 21:00:21 +00:00
self.wasm.operators.push(wasm_encoder::Instruction::Block(
2021-12-24 08:35:18 +00:00
wasm_encoder::BlockType::FunctionType(ty),
2021-12-24 08:28:44 +00:00
));
}
let br_table_targets = (1..=targets.len()).map(|i| i as u32).collect::<Vec<_>>();
2021-12-24 21:00:21 +00:00
self.wasm.operators.push(wasm_encoder::Instruction::BrTable(
2021-12-24 08:28:44 +00:00
Cow::Owned(br_table_targets),
0,
));
2021-12-24 21:00:21 +00:00
self.wasm.operators.push(wasm_encoder::Instruction::End);
2021-12-24 08:28:44 +00:00
self.translate_target(targets.len() + 1, default, locations);
2021-12-24 21:00:21 +00:00
self.wasm.operators.push(wasm_encoder::Instruction::End);
2021-12-24 08:28:44 +00:00
for i in 0..targets.len() {
self.translate_target(targets.len() - i, &targets[i], locations);
2021-12-24 21:00:21 +00:00
self.wasm.operators.push(wasm_encoder::Instruction::End);
2021-12-24 08:28:44 +00:00
}
2021-12-24 08:07:45 +00:00
}
SerializedOperator::Get(v, i) => {
2021-12-24 08:28:44 +00:00
let loc = *locations.locations.get(&(*v, *i)).unwrap();
2021-12-24 21:00:21 +00:00
self.wasm
.operators
2021-12-24 08:28:44 +00:00
.push(wasm_encoder::Instruction::LocalGet(loc));
2021-12-24 08:07:45 +00:00
}
SerializedOperator::Set(v, i) => {
2021-12-24 08:28:44 +00:00
let loc = *locations.locations.get(&(*v, *i)).unwrap();
2021-12-24 21:00:21 +00:00
self.wasm
.operators
2021-12-24 08:28:44 +00:00
.push(wasm_encoder::Instruction::LocalSet(loc));
2021-12-24 08:07:45 +00:00
}
SerializedOperator::Tee(v, i) => {
2021-12-24 08:28:44 +00:00
let loc = *locations.locations.get(&(*v, *i)).unwrap();
2021-12-24 21:00:21 +00:00
self.wasm
.operators
2021-12-24 08:28:44 +00:00
.push(wasm_encoder::Instruction::LocalTee(loc));
}
}
}
fn translate_target(
&mut self,
extra_blocks: usize,
target: &SerializedBlockTarget,
locations: &Locations,
) {
2021-12-24 22:50:23 +00:00
log::trace!("translate_target: {:?}", target);
2021-12-24 08:28:44 +00:00
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);
}
2021-12-24 21:00:21 +00:00
self.wasm.operators.push(wasm_encoder::Instruction::Br(
2021-12-24 08:28:44 +00:00
(branch + extra_blocks) as u32,
));
2021-12-24 08:07:45 +00:00
}
}
}
}
2021-12-24 21:00:21 +00:00
pub fn produce_func_wasm<FT: FuncTypeSink>(
f: &FunctionBody,
body: &SerializedBody,
locations: &Locations,
ft: &mut FT,
) -> Wasm {
2021-12-24 08:07:45 +00:00
let mut wasm = Wasm {
operators: vec![],
locals: vec![],
};
wasm.locals
.extend(f.locals.iter().map(|ty| ty_to_valty(*ty)));
wasm.locals
.extend(locations.new_locals.iter().map(|ty| ty_to_valty(*ty)));
2021-12-24 21:00:21 +00:00
let mut ctx = WasmContext {
wasm: &mut wasm,
func_type_sink: ft,
};
2021-12-24 19:42:02 +00:00
for operator in &body.operators {
2021-12-24 21:00:21 +00:00
ctx.translate(operator, locations);
2021-12-24 08:07:45 +00:00
}
2021-12-24 22:29:32 +00:00
wasm.operators.push(wasm_encoder::Instruction::End);
2021-12-24 08:07:45 +00:00
wasm
}