This commit is contained in:
Chris Fallin 2021-12-24 00:28:44 -08:00
parent 726b4da33d
commit f92ea9a556
4 changed files with 87 additions and 24 deletions

View file

@ -1,11 +1,10 @@
//! Final Wasm operator sequence production.
use super::{Locations, SerializedBlockTarget, SerializedBody, SerializedOperator};
use crate::{ops::ty_to_valty, FunctionBody};
use std::borrow::Cow;
use wasm_encoder::BlockType;
use crate::{ops::ty_to_valty, FunctionBody, Operator};
use super::{Locations, SerializedBody, SerializedOperator};
#[derive(Clone, Debug)]
pub struct Wasm {
operators: Vec<wasm_encoder::Instruction<'static>>,
@ -62,36 +61,96 @@ impl Wasm {
self.operators.push(op.clone().into());
}
SerializedOperator::Br(ref target) => {
todo!()
self.translate_target(0, target, locations);
}
SerializedOperator::BrIf {
cond,
ref if_true,
ref if_false,
} => {
todo!()
let loc = *locations.locations.get(&(*cond, 0)).unwrap();
self.operators
.push(wasm_encoder::Instruction::LocalGet(loc));
self.operators.push(wasm_encoder::Instruction::If(
wasm_encoder::BlockType::Empty,
));
self.translate_target(1, if_true, locations);
self.operators.push(wasm_encoder::Instruction::Else);
self.translate_target(1, if_false, locations);
self.operators.push(wasm_encoder::Instruction::End);
}
SerializedOperator::BrTable {
index,
ref targets,
ref default,
} => {
todo!()
for _ in 0..(targets.len() + 2) {
self.operators.push(wasm_encoder::Instruction::Block(
wasm_encoder::BlockType::Empty,
));
}
let loc = *locations.locations.get(&(*index, 0)).unwrap();
self.operators
.push(wasm_encoder::Instruction::LocalGet(loc));
let br_table_targets = (1..=targets.len()).map(|i| i as u32).collect::<Vec<_>>();
self.operators.push(wasm_encoder::Instruction::BrTable(
Cow::Owned(br_table_targets),
0,
));
self.operators.push(wasm_encoder::Instruction::End);
self.translate_target(targets.len() + 1, default, locations);
self.operators.push(wasm_encoder::Instruction::End);
for i in 0..targets.len() {
self.translate_target(targets.len() - i, &targets[i], locations);
self.operators.push(wasm_encoder::Instruction::End);
}
}
SerializedOperator::Get(v, i) => {
todo!()
let loc = *locations.locations.get(&(*v, *i)).unwrap();
self.operators
.push(wasm_encoder::Instruction::LocalGet(loc));
}
SerializedOperator::Set(v, i) => {
todo!()
let loc = *locations.locations.get(&(*v, *i)).unwrap();
self.operators
.push(wasm_encoder::Instruction::LocalSet(loc));
}
SerializedOperator::Tee(v, i) => {
todo!()
let loc = *locations.locations.get(&(*v, *i)).unwrap();
self.operators
.push(wasm_encoder::Instruction::LocalTee(loc));
}
}
}
fn translate_target(
&mut self,
extra_blocks: usize,
target: &SerializedBlockTarget,
locations: &Locations,
) {
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);
}
self.operators.push(wasm_encoder::Instruction::Br(
(branch + extra_blocks) as u32,
));
}
}
}
}
pub fn produce_wasm(f: &FunctionBody, body: &SerializedBody, locations: &Locations) -> Wasm {
pub fn produce_func_wasm(f: &FunctionBody, body: &SerializedBody, locations: &Locations) -> Wasm {
let mut wasm = Wasm {
operators: vec![],
locals: vec![],

View file

@ -65,10 +65,10 @@ impl<'a> Allocator<'a> {
let mut reads = vec![];
let mut writes = vec![];
op.visit_value_locals(
|value, index| {
&mut |value, index| {
reads.push((value, index));
},
|value, index| {
&mut |value, index| {
writes.push((value, index));
},
);
@ -77,7 +77,7 @@ impl<'a> Allocator<'a> {
let span = match self.spans.get_mut(&(value, index)) {
Some(span) => span,
None => {
panic!("Read before any write to local (v{},{})", value, index);
panic!("Read before any write to local ({},{})", value, index);
}
};
span.end = location + 1;

View file

@ -72,12 +72,12 @@ pub enum SerializedOperator {
impl SerializedOperator {
pub fn visit_value_locals<R: FnMut(Value, usize), W: FnMut(Value, usize)>(
&self,
mut r: R,
mut w: W,
r: &mut R,
w: &mut W,
) {
match self {
&SerializedOperator::Br(ref target) => {
target.visit_value_locals(&mut r, &mut w);
target.visit_value_locals(r, w);
}
&SerializedOperator::BrIf {
cond,
@ -85,8 +85,8 @@ impl SerializedOperator {
ref if_false,
} => {
r(cond, 0);
if_true.visit_value_locals(&mut r, &mut w);
if_false.visit_value_locals(&mut r, &mut w);
if_true.visit_value_locals(r, w);
if_false.visit_value_locals(r, w);
}
&SerializedOperator::BrTable {
index,
@ -94,9 +94,9 @@ impl SerializedOperator {
ref targets,
} => {
r(index, 0);
default.visit_value_locals(&mut r, &mut w);
default.visit_value_locals(r, w);
for target in targets {
target.visit_value_locals(&mut r, &mut w);
target.visit_value_locals(r, w);
}
}
&SerializedOperator::Get(v, i) => {
@ -128,7 +128,7 @@ impl SerializedBlockTarget {
&SerializedBlockTarget::Branch(_, ref ops)
| &SerializedBlockTarget::Fallthrough(ref ops) => {
for op in ops {
op.visit_value_locals(|value, i| r(value, i), |value, i| w(value, i));
op.visit_value_locals(r, w);
}
}
}

View file

@ -3,7 +3,7 @@
use std::collections::hash_map::Entry;
use crate::{
backend::{BlockOrder, LoopNest, SerializedBody, WasmRegion},
backend::{produce_func_wasm, BlockOrder, Locations, LoopNest, SerializedBody, WasmRegion},
cfg::CFGInfo,
frontend, Operator,
};
@ -493,6 +493,10 @@ impl<'a> Module<'a> {
let blockorder = BlockOrder::compute(body, &cfg, &regions);
let serialized = SerializedBody::compute(body, &cfg, &blockorder);
log::trace!("serialized: {:?}", serialized);
let locations = Locations::compute(body, &serialized);
log::trace!("locations: {:?}", locations);
let func_body = produce_func_wasm(body, &serialized, &locations);
log::trace!("body: {:?}", func_body);
}
_ => {}
}