Implement block returns
This commit is contained in:
parent
30a0589fbe
commit
57b3c7f22a
@ -1,4 +1,4 @@
|
|||||||
use parity_wasm::elements::{Instruction, Local, Module};
|
use parity_wasm::elements::{BlockType, Instruction, Local, Module};
|
||||||
|
|
||||||
use crate::backend::translator::arity::{Arity, List as ArityList};
|
use crate::backend::translator::arity::{Arity, List as ArityList};
|
||||||
|
|
||||||
@ -27,14 +27,14 @@ pub struct Transformer<'a> {
|
|||||||
last_stack: usize,
|
last_stack: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_now_else(inst: &[Instruction]) -> bool {
|
|
||||||
inst.get(0) == Some(&Instruction::Else)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn local_sum(list: &[Local]) -> u32 {
|
fn local_sum(list: &[Local]) -> u32 {
|
||||||
list.iter().map(Local::count).sum()
|
list.iter().map(Local::count).sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_else_stat(list: &[Instruction]) -> bool {
|
||||||
|
list.get(0) == Some(&Instruction::Else)
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Transformer<'a> {
|
impl<'a> Transformer<'a> {
|
||||||
pub fn new(wasm: &'a Module, arity: &'a ArityList, name: usize) -> Transformer<'a> {
|
pub fn new(wasm: &'a Module, arity: &'a ArityList, name: usize) -> Transformer<'a> {
|
||||||
Transformer {
|
Transformer {
|
||||||
@ -61,7 +61,7 @@ impl<'a> Transformer<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_push_recall(&mut self, num: u32) {
|
fn push_recall(&mut self, num: u32) {
|
||||||
let len = self.living.len();
|
let len = self.living.len();
|
||||||
|
|
||||||
(len..len + num as usize)
|
(len..len + num as usize)
|
||||||
@ -69,6 +69,14 @@ impl<'a> Transformer<'a> {
|
|||||||
.for_each(|v| self.living.push(v));
|
.for_each(|v| self.living.push(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn push_block_result(&mut self, typ: BlockType) {
|
||||||
|
if matches!(typ, BlockType::NoResult) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.push_recall(1);
|
||||||
|
}
|
||||||
|
|
||||||
// If any expressions are still pending at the start of
|
// If any expressions are still pending at the start of
|
||||||
// statement, we leak them into variables.
|
// statement, we leak them into variables.
|
||||||
// Since expressions do not have set ordering rules, this is
|
// Since expressions do not have set ordering rules, this is
|
||||||
@ -99,15 +107,7 @@ impl<'a> Transformer<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn load_pending(&mut self) {
|
fn load_pending(&mut self) {
|
||||||
let mut old = self.sleeping.pop().unwrap();
|
self.living = self.sleeping.pop().unwrap();
|
||||||
|
|
||||||
if self.living.len() > old.len() {
|
|
||||||
let rem = self.living.drain(old.len()..);
|
|
||||||
|
|
||||||
old.extend(rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.living = old;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_return(&mut self, stat: &mut Vec<Statement>) {
|
fn gen_return(&mut self, stat: &mut Vec<Statement>) {
|
||||||
@ -128,7 +128,7 @@ impl<'a> Transformer<'a> {
|
|||||||
let len = u32::try_from(self.living.len()).unwrap();
|
let len = u32::try_from(self.living.len()).unwrap();
|
||||||
let result = len..len + arity.num_result;
|
let result = len..len + arity.num_result;
|
||||||
|
|
||||||
self.gen_push_recall(arity.num_result);
|
self.push_recall(arity.num_result);
|
||||||
self.gen_leak_pending(stat);
|
self.gen_leak_pending(stat);
|
||||||
stat.push(Statement::Call(Call {
|
stat.push(Statement::Call(Call {
|
||||||
func,
|
func,
|
||||||
@ -149,7 +149,7 @@ impl<'a> Transformer<'a> {
|
|||||||
let len = u32::try_from(self.living.len()).unwrap();
|
let len = u32::try_from(self.living.len()).unwrap();
|
||||||
let result = len..len + arity.num_result;
|
let result = len..len + arity.num_result;
|
||||||
|
|
||||||
self.gen_push_recall(arity.num_result);
|
self.push_recall(arity.num_result);
|
||||||
self.gen_leak_pending(stat);
|
self.gen_leak_pending(stat);
|
||||||
stat.push(Statement::CallIndirect(CallIndirect {
|
stat.push(Statement::CallIndirect(CallIndirect {
|
||||||
table,
|
table,
|
||||||
@ -224,27 +224,30 @@ impl<'a> Transformer<'a> {
|
|||||||
self.gen_leak_pending(&mut stat);
|
self.gen_leak_pending(&mut stat);
|
||||||
stat.push(Statement::Unreachable);
|
stat.push(Statement::Unreachable);
|
||||||
}
|
}
|
||||||
Inst::Block(_) => {
|
Inst::Block(t) => {
|
||||||
self.gen_leak_pending(&mut stat);
|
self.gen_leak_pending(&mut stat);
|
||||||
|
|
||||||
let data = self.new_forward(list);
|
let data = self.new_forward(list);
|
||||||
|
|
||||||
|
self.push_block_result(*t);
|
||||||
stat.push(Statement::Forward(data));
|
stat.push(Statement::Forward(data));
|
||||||
}
|
}
|
||||||
Inst::Loop(_) => {
|
Inst::Loop(t) => {
|
||||||
self.gen_leak_pending(&mut stat);
|
self.gen_leak_pending(&mut stat);
|
||||||
|
|
||||||
let data = self.new_backward(list);
|
let data = self.new_backward(list);
|
||||||
|
|
||||||
|
self.push_block_result(*t);
|
||||||
stat.push(Statement::Backward(data));
|
stat.push(Statement::Backward(data));
|
||||||
}
|
}
|
||||||
Inst::If(_) => {
|
Inst::If(t) => {
|
||||||
let cond = self.living.pop().unwrap();
|
let cond = self.living.pop().unwrap();
|
||||||
|
|
||||||
self.gen_leak_pending(&mut stat);
|
self.gen_leak_pending(&mut stat);
|
||||||
|
|
||||||
let data = self.new_if(cond, list);
|
let data = self.new_if(cond, list);
|
||||||
|
|
||||||
|
self.push_block_result(*t);
|
||||||
stat.push(Statement::If(data));
|
stat.push(Statement::If(data));
|
||||||
}
|
}
|
||||||
Inst::Else => {
|
Inst::Else => {
|
||||||
@ -263,7 +266,6 @@ impl<'a> Transformer<'a> {
|
|||||||
}
|
}
|
||||||
Inst::Br(i) => {
|
Inst::Br(i) => {
|
||||||
self.gen_leak_pending(&mut stat);
|
self.gen_leak_pending(&mut stat);
|
||||||
|
|
||||||
stat.push(Statement::Br(Br { target: *i }));
|
stat.push(Statement::Br(Br { target: *i }));
|
||||||
}
|
}
|
||||||
Inst::BrIf(i) => {
|
Inst::BrIf(i) => {
|
||||||
@ -383,7 +385,7 @@ impl<'a> Transformer<'a> {
|
|||||||
|
|
||||||
fn new_if(&mut self, cond: Expression, list: &mut &[Instruction]) -> If {
|
fn new_if(&mut self, cond: Expression, list: &mut &[Instruction]) -> If {
|
||||||
let body = self.new_stored_body(list);
|
let body = self.new_stored_body(list);
|
||||||
let other = is_now_else(list).then(|| {
|
let other = is_else_stat(list).then(|| {
|
||||||
*list = &list[1..];
|
*list = &list[1..];
|
||||||
self.new_stored_body(list)
|
self.new_stored_body(list)
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user