Refactor Builder
behavior and stack emulation
This commit is contained in:
parent
22ea8910ad
commit
460f363c91
@ -99,103 +99,16 @@ impl Arities {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Builder<'a> {
|
||||
// target state
|
||||
wasm: &'a Module,
|
||||
other: &'a Arities,
|
||||
num_result: u32,
|
||||
|
||||
// translation state
|
||||
pending: Vec<Vec<Expression>>,
|
||||
#[derive(Default)]
|
||||
struct Stacked {
|
||||
pending_list: Vec<Vec<Expression>>,
|
||||
stack: Vec<Expression>,
|
||||
last_stack: usize,
|
||||
}
|
||||
|
||||
fn is_else_stat(inst: &Instruction) -> bool {
|
||||
inst == &Instruction::Else
|
||||
}
|
||||
|
||||
fn is_dead_precursor(inst: &Instruction) -> bool {
|
||||
matches!(
|
||||
inst,
|
||||
Instruction::Unreachable | Instruction::Br(_) | Instruction::Return
|
||||
)
|
||||
}
|
||||
|
||||
fn flat_local_list(local: Local) -> impl Iterator<Item = ValueType> {
|
||||
std::iter::repeat(local.value_type()).take(local.count().try_into().unwrap())
|
||||
}
|
||||
|
||||
fn load_local_list(func: &FuncBody) -> Vec<ValueType> {
|
||||
func.locals()
|
||||
.iter()
|
||||
.copied()
|
||||
.flat_map(flat_local_list)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn load_func_at(wasm: &Module, index: usize) -> &FuncBody {
|
||||
&wasm.code_section().unwrap().bodies()[index]
|
||||
}
|
||||
|
||||
impl<'a> Builder<'a> {
|
||||
#[must_use]
|
||||
pub fn new(wasm: &'a Module, other: &'a Arities) -> Builder<'a> {
|
||||
Builder {
|
||||
wasm,
|
||||
other,
|
||||
num_result: 0,
|
||||
pending: Vec::new(),
|
||||
stack: Vec::new(),
|
||||
last_stack: 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn consume(mut self, index: usize) -> Function {
|
||||
let func = load_func_at(self.wasm, index);
|
||||
let arity = &self.other.in_arity[index];
|
||||
|
||||
let local_list = load_local_list(func);
|
||||
let num_param = arity.num_param;
|
||||
|
||||
self.num_result = arity.num_result;
|
||||
|
||||
let body = self.new_forward(&mut func.code().elements());
|
||||
let num_stack = self.last_stack.try_into().unwrap();
|
||||
|
||||
Function {
|
||||
local_list,
|
||||
num_param,
|
||||
num_stack,
|
||||
body,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_type_of(&self, index: u32) -> Arity {
|
||||
let types = self.wasm.type_section().unwrap().types();
|
||||
|
||||
Arity::from_index(types, index)
|
||||
}
|
||||
|
||||
fn push_recall(&mut self, num: u32) {
|
||||
let len = self.stack.len();
|
||||
|
||||
for var in len..len + num as usize {
|
||||
self.stack.push(Expression::Recall(Recall { var }));
|
||||
}
|
||||
}
|
||||
|
||||
fn push_block_result(&mut self, typ: BlockType) {
|
||||
let num = match typ {
|
||||
BlockType::NoResult => {
|
||||
return;
|
||||
}
|
||||
BlockType::Value(_) => 1,
|
||||
BlockType::TypeIndex(i) => self.get_type_of(i).num_result,
|
||||
};
|
||||
|
||||
self.push_recall(num);
|
||||
impl Stacked {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
// If any expressions are still pending at the start of
|
||||
@ -226,63 +139,35 @@ impl<'a> Builder<'a> {
|
||||
fn save_pending(&mut self) {
|
||||
let cloned = self.stack.iter().map(Expression::clone_recall).collect();
|
||||
|
||||
self.pending.push(cloned);
|
||||
self.pending_list.push(cloned);
|
||||
}
|
||||
|
||||
fn load_pending(&mut self) {
|
||||
self.stack = self.pending.pop().unwrap();
|
||||
self.stack = self.pending_list.pop().unwrap();
|
||||
}
|
||||
|
||||
fn gen_return(&mut self, stat: &mut Vec<Statement>) {
|
||||
let num = self.num_result as usize;
|
||||
let list = self.stack.split_off(self.stack.len() - num);
|
||||
|
||||
self.gen_leak_pending(stat);
|
||||
stat.push(Statement::Return(Return { list }));
|
||||
fn pop(&mut self) -> Expression {
|
||||
self.stack.pop().unwrap()
|
||||
}
|
||||
|
||||
fn gen_call(&mut self, func: u32, stat: &mut Vec<Statement>) {
|
||||
let arity = self.other.arity_of(func as usize);
|
||||
|
||||
let param_list = self
|
||||
.stack
|
||||
.split_off(self.stack.len() - arity.num_param as usize);
|
||||
|
||||
let len = u32::try_from(self.stack.len()).unwrap();
|
||||
let result = len..len + arity.num_result;
|
||||
|
||||
self.push_recall(arity.num_result);
|
||||
self.gen_leak_pending(stat);
|
||||
stat.push(Statement::Call(Call {
|
||||
func,
|
||||
result,
|
||||
param_list,
|
||||
}));
|
||||
fn push(&mut self, value: Expression) {
|
||||
self.stack.push(value);
|
||||
}
|
||||
|
||||
fn gen_call_indirect(&mut self, typ: u32, table: u8, stat: &mut Vec<Statement>) {
|
||||
let arity = self.get_type_of(typ);
|
||||
fn push_constant(&mut self, value: Value) {
|
||||
self.stack.push(Expression::Value(value));
|
||||
}
|
||||
|
||||
let index = self.stack.pop().unwrap();
|
||||
let param_list = self
|
||||
.stack
|
||||
.split_off(self.stack.len() - arity.num_param as usize);
|
||||
fn push_recall(&mut self, num: u32) {
|
||||
let len = self.stack.len();
|
||||
|
||||
let len = u32::try_from(self.stack.len()).unwrap();
|
||||
let result = len..len + arity.num_result;
|
||||
|
||||
self.push_recall(arity.num_result);
|
||||
self.gen_leak_pending(stat);
|
||||
stat.push(Statement::CallIndirect(CallIndirect {
|
||||
table,
|
||||
index,
|
||||
result,
|
||||
param_list,
|
||||
}));
|
||||
for var in len..len + num as usize {
|
||||
self.stack.push(Expression::Recall(Recall { var }));
|
||||
}
|
||||
}
|
||||
|
||||
fn push_load(&mut self, op: Load, offset: u32) {
|
||||
let pointer = Box::new(self.stack.pop().unwrap());
|
||||
let pointer = Box::new(self.pop());
|
||||
|
||||
self.stack.push(Expression::AnyLoad(AnyLoad {
|
||||
op,
|
||||
@ -292,10 +177,11 @@ impl<'a> Builder<'a> {
|
||||
}
|
||||
|
||||
fn gen_store(&mut self, op: Store, offset: u32, stat: &mut Vec<Statement>) {
|
||||
let value = self.stack.pop().unwrap();
|
||||
let pointer = self.stack.pop().unwrap();
|
||||
let value = self.pop();
|
||||
let pointer = self.pop();
|
||||
|
||||
self.gen_leak_pending(stat);
|
||||
|
||||
stat.push(Statement::AnyStore(AnyStore {
|
||||
op,
|
||||
offset,
|
||||
@ -304,27 +190,23 @@ impl<'a> Builder<'a> {
|
||||
}));
|
||||
}
|
||||
|
||||
fn push_constant(&mut self, value: Value) {
|
||||
self.stack.push(Expression::Value(value));
|
||||
}
|
||||
|
||||
fn push_un_op(&mut self, op: UnOp) {
|
||||
let rhs = Box::new(self.stack.pop().unwrap());
|
||||
let rhs = Box::new(self.pop());
|
||||
|
||||
self.stack.push(Expression::AnyUnOp(AnyUnOp { op, rhs }));
|
||||
}
|
||||
|
||||
fn push_bin_op(&mut self, op: BinOp) {
|
||||
let rhs = Box::new(self.stack.pop().unwrap());
|
||||
let lhs = Box::new(self.stack.pop().unwrap());
|
||||
let rhs = Box::new(self.pop());
|
||||
let lhs = Box::new(self.pop());
|
||||
|
||||
self.stack
|
||||
.push(Expression::AnyBinOp(AnyBinOp { op, lhs, rhs }));
|
||||
}
|
||||
|
||||
fn push_cmp_op(&mut self, op: CmpOp) {
|
||||
let rhs = Box::new(self.stack.pop().unwrap());
|
||||
let lhs = Box::new(self.stack.pop().unwrap());
|
||||
let rhs = Box::new(self.pop());
|
||||
let lhs = Box::new(self.pop());
|
||||
|
||||
self.stack
|
||||
.push(Expression::AnyCmpOp(AnyCmpOp { op, lhs, rhs }));
|
||||
@ -367,6 +249,142 @@ impl<'a> Builder<'a> {
|
||||
self.from_equal_zero(inst)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Builder<'a> {
|
||||
// target state
|
||||
wasm: &'a Module,
|
||||
other: &'a Arities,
|
||||
num_result: u32,
|
||||
|
||||
// translation state
|
||||
data: Stacked,
|
||||
}
|
||||
|
||||
fn is_else_stat(inst: &Instruction) -> bool {
|
||||
inst == &Instruction::Else
|
||||
}
|
||||
|
||||
fn is_dead_precursor(inst: &Instruction) -> bool {
|
||||
matches!(
|
||||
inst,
|
||||
Instruction::Unreachable | Instruction::Br(_) | Instruction::Return
|
||||
)
|
||||
}
|
||||
|
||||
fn flat_local_list(local: Local) -> impl Iterator<Item = ValueType> {
|
||||
std::iter::repeat(local.value_type()).take(local.count().try_into().unwrap())
|
||||
}
|
||||
|
||||
fn load_local_list(func: &FuncBody) -> Vec<ValueType> {
|
||||
func.locals()
|
||||
.iter()
|
||||
.copied()
|
||||
.flat_map(flat_local_list)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn load_func_at(wasm: &Module, index: usize) -> &FuncBody {
|
||||
&wasm.code_section().unwrap().bodies()[index]
|
||||
}
|
||||
|
||||
impl<'a> Builder<'a> {
|
||||
#[must_use]
|
||||
pub fn new(wasm: &'a Module, other: &'a Arities) -> Builder<'a> {
|
||||
Builder {
|
||||
wasm,
|
||||
other,
|
||||
num_result: 0,
|
||||
data: Stacked::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn consume(mut self, index: usize) -> Function {
|
||||
let func = load_func_at(self.wasm, index);
|
||||
let arity = &self.other.in_arity[index];
|
||||
|
||||
let local_list = load_local_list(func);
|
||||
let num_param = arity.num_param;
|
||||
|
||||
self.num_result = arity.num_result;
|
||||
|
||||
let body = self.new_forward(&mut func.code().elements());
|
||||
let num_stack = self.data.last_stack.try_into().unwrap();
|
||||
|
||||
Function {
|
||||
local_list,
|
||||
num_param,
|
||||
num_stack,
|
||||
body,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_type_of(&self, index: u32) -> Arity {
|
||||
let types = self.wasm.type_section().unwrap().types();
|
||||
|
||||
Arity::from_index(types, index)
|
||||
}
|
||||
|
||||
fn push_block_result(&mut self, typ: BlockType) {
|
||||
let num = match typ {
|
||||
BlockType::NoResult => {
|
||||
return;
|
||||
}
|
||||
BlockType::Value(_) => 1,
|
||||
BlockType::TypeIndex(i) => self.get_type_of(i).num_result,
|
||||
};
|
||||
|
||||
self.data.push_recall(num);
|
||||
}
|
||||
|
||||
fn gen_return(&mut self, stat: &mut Vec<Statement>) {
|
||||
let num = self.num_result as usize;
|
||||
let list = self.data.stack.split_off(self.data.stack.len() - num);
|
||||
|
||||
self.data.gen_leak_pending(stat);
|
||||
|
||||
stat.push(Statement::Return(Return { list }));
|
||||
}
|
||||
|
||||
fn gen_call(&mut self, func: u32, stat: &mut Vec<Statement>) {
|
||||
let arity = self.other.arity_of(func as usize);
|
||||
let len = self.data.stack.len();
|
||||
|
||||
let first = u32::try_from(len).unwrap();
|
||||
let result = first..first + arity.num_result;
|
||||
let param_list = self.data.stack.split_off(len - arity.num_param as usize);
|
||||
|
||||
self.data.push_recall(arity.num_result);
|
||||
self.data.gen_leak_pending(stat);
|
||||
|
||||
stat.push(Statement::Call(Call {
|
||||
func,
|
||||
result,
|
||||
param_list,
|
||||
}));
|
||||
}
|
||||
|
||||
fn gen_call_indirect(&mut self, typ: u32, table: u8, stat: &mut Vec<Statement>) {
|
||||
let arity = self.get_type_of(typ);
|
||||
let len = self.data.stack.len();
|
||||
|
||||
let index = self.data.pop();
|
||||
let param_list = self.data.stack.split_off(len - arity.num_param as usize);
|
||||
|
||||
let first = u32::try_from(len).unwrap();
|
||||
let result = first..first + arity.num_result;
|
||||
|
||||
self.data.push_recall(arity.num_result);
|
||||
self.data.gen_leak_pending(stat);
|
||||
|
||||
stat.push(Statement::CallIndirect(CallIndirect {
|
||||
table,
|
||||
index,
|
||||
result,
|
||||
param_list,
|
||||
}));
|
||||
}
|
||||
|
||||
fn drop_unreachable(list: &mut &[Instruction]) {
|
||||
use Instruction as Inst;
|
||||
@ -405,14 +423,14 @@ impl<'a> Builder<'a> {
|
||||
|
||||
let mut stat = Vec::new();
|
||||
|
||||
self.save_pending();
|
||||
self.data.save_pending();
|
||||
|
||||
loop {
|
||||
let inst = &list[0];
|
||||
|
||||
*list = &list[1..];
|
||||
|
||||
if self.from_operation(inst) {
|
||||
if self.data.from_operation(inst) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -422,7 +440,7 @@ impl<'a> Builder<'a> {
|
||||
stat.push(Statement::Unreachable);
|
||||
}
|
||||
Inst::Block(t) => {
|
||||
self.gen_leak_pending(&mut stat);
|
||||
self.data.gen_leak_pending(&mut stat);
|
||||
|
||||
let data = self.new_forward(list);
|
||||
|
||||
@ -430,7 +448,7 @@ impl<'a> Builder<'a> {
|
||||
stat.push(Statement::Forward(data));
|
||||
}
|
||||
Inst::Loop(t) => {
|
||||
self.gen_leak_pending(&mut stat);
|
||||
self.data.gen_leak_pending(&mut stat);
|
||||
|
||||
let data = self.new_backward(list);
|
||||
|
||||
@ -438,9 +456,9 @@ impl<'a> Builder<'a> {
|
||||
stat.push(Statement::Backward(data));
|
||||
}
|
||||
Inst::If(t) => {
|
||||
let cond = self.stack.pop().unwrap();
|
||||
let cond = self.data.pop();
|
||||
|
||||
self.gen_leak_pending(&mut stat);
|
||||
self.data.gen_leak_pending(&mut stat);
|
||||
|
||||
let data = self.new_if(cond, list);
|
||||
|
||||
@ -448,7 +466,7 @@ impl<'a> Builder<'a> {
|
||||
stat.push(Statement::If(data));
|
||||
}
|
||||
Inst::Else => {
|
||||
self.gen_leak_pending(&mut stat);
|
||||
self.data.gen_leak_pending(&mut stat);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -456,25 +474,25 @@ impl<'a> Builder<'a> {
|
||||
if list.is_empty() && self.num_result != 0 {
|
||||
self.gen_return(&mut stat);
|
||||
} else {
|
||||
self.gen_leak_pending(&mut stat);
|
||||
self.data.gen_leak_pending(&mut stat);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
Inst::Br(i) => {
|
||||
self.gen_leak_pending(&mut stat);
|
||||
self.data.gen_leak_pending(&mut stat);
|
||||
stat.push(Statement::Br(Br { target: *i }));
|
||||
}
|
||||
Inst::BrIf(i) => {
|
||||
let cond = self.stack.pop().unwrap();
|
||||
let cond = self.data.pop();
|
||||
|
||||
self.gen_leak_pending(&mut stat);
|
||||
self.data.gen_leak_pending(&mut stat);
|
||||
stat.push(Statement::BrIf(BrIf { cond, target: *i }));
|
||||
}
|
||||
Inst::BrTable(t) => {
|
||||
let cond = self.stack.pop().unwrap();
|
||||
let cond = self.data.pop();
|
||||
|
||||
self.gen_leak_pending(&mut stat);
|
||||
self.data.gen_leak_pending(&mut stat);
|
||||
stat.push(Statement::BrTable(BrTable {
|
||||
cond,
|
||||
data: *t.clone(),
|
||||
@ -490,80 +508,80 @@ impl<'a> Builder<'a> {
|
||||
self.gen_call_indirect(*i, *t, &mut stat);
|
||||
}
|
||||
Inst::Drop => {
|
||||
self.stack.pop().unwrap();
|
||||
self.data.pop();
|
||||
}
|
||||
Inst::Select => {
|
||||
let cond = Box::new(self.stack.pop().unwrap());
|
||||
let b = Box::new(self.stack.pop().unwrap());
|
||||
let a = Box::new(self.stack.pop().unwrap());
|
||||
let cond = Box::new(self.data.pop());
|
||||
let b = Box::new(self.data.pop());
|
||||
let a = Box::new(self.data.pop());
|
||||
|
||||
self.stack.push(Expression::Select(Select { cond, a, b }));
|
||||
self.data.push(Expression::Select(Select { cond, a, b }));
|
||||
}
|
||||
Inst::GetLocal(i) => {
|
||||
self.stack.push(Expression::GetLocal(GetLocal { var: *i }));
|
||||
self.data.push(Expression::GetLocal(GetLocal { var: *i }));
|
||||
}
|
||||
Inst::SetLocal(i) => {
|
||||
let value = self.stack.pop().unwrap();
|
||||
let value = self.data.pop();
|
||||
|
||||
self.gen_leak_pending(&mut stat);
|
||||
self.data.gen_leak_pending(&mut stat);
|
||||
stat.push(Statement::SetLocal(SetLocal { var: *i, value }));
|
||||
}
|
||||
Inst::TeeLocal(i) => {
|
||||
self.gen_leak_pending(&mut stat);
|
||||
self.data.gen_leak_pending(&mut stat);
|
||||
|
||||
let value = self.stack.last().unwrap().clone_recall();
|
||||
let value = self.data.pop();
|
||||
|
||||
self.data.push(value.clone_recall());
|
||||
stat.push(Statement::SetLocal(SetLocal { var: *i, value }));
|
||||
}
|
||||
Inst::GetGlobal(i) => {
|
||||
self.stack
|
||||
.push(Expression::GetGlobal(GetGlobal { var: *i }));
|
||||
self.data.push(Expression::GetGlobal(GetGlobal { var: *i }));
|
||||
}
|
||||
Inst::SetGlobal(i) => {
|
||||
let value = self.stack.pop().unwrap();
|
||||
let value = self.data.pop();
|
||||
|
||||
stat.push(Statement::SetGlobal(SetGlobal { var: *i, value }));
|
||||
}
|
||||
Inst::I32Load(_, o) => self.push_load(Load::I32, *o),
|
||||
Inst::I64Load(_, o) => self.push_load(Load::I64, *o),
|
||||
Inst::F32Load(_, o) => self.push_load(Load::F32, *o),
|
||||
Inst::F64Load(_, o) => self.push_load(Load::F64, *o),
|
||||
Inst::I32Load8S(_, o) => self.push_load(Load::I32_I8, *o),
|
||||
Inst::I32Load8U(_, o) => self.push_load(Load::I32_U8, *o),
|
||||
Inst::I32Load16S(_, o) => self.push_load(Load::I32_I16, *o),
|
||||
Inst::I32Load16U(_, o) => self.push_load(Load::I32_U16, *o),
|
||||
Inst::I64Load8S(_, o) => self.push_load(Load::I64_I8, *o),
|
||||
Inst::I64Load8U(_, o) => self.push_load(Load::I64_U8, *o),
|
||||
Inst::I64Load16S(_, o) => self.push_load(Load::I64_I16, *o),
|
||||
Inst::I64Load16U(_, o) => self.push_load(Load::I64_U16, *o),
|
||||
Inst::I64Load32S(_, o) => self.push_load(Load::I64_I32, *o),
|
||||
Inst::I64Load32U(_, o) => self.push_load(Load::I64_U32, *o),
|
||||
Inst::I32Store(_, o) => self.gen_store(Store::I32, *o, &mut stat),
|
||||
Inst::I64Store(_, o) => self.gen_store(Store::I64, *o, &mut stat),
|
||||
Inst::F32Store(_, o) => self.gen_store(Store::F32, *o, &mut stat),
|
||||
Inst::F64Store(_, o) => self.gen_store(Store::F64, *o, &mut stat),
|
||||
Inst::I32Store8(_, o) => self.gen_store(Store::I32_N8, *o, &mut stat),
|
||||
Inst::I32Store16(_, o) => self.gen_store(Store::I32_N16, *o, &mut stat),
|
||||
Inst::I64Store8(_, o) => self.gen_store(Store::I64_N8, *o, &mut stat),
|
||||
Inst::I64Store16(_, o) => self.gen_store(Store::I64_N16, *o, &mut stat),
|
||||
Inst::I64Store32(_, o) => self.gen_store(Store::I64_N32, *o, &mut stat),
|
||||
Inst::I32Load(_, o) => self.data.push_load(Load::I32, *o),
|
||||
Inst::I64Load(_, o) => self.data.push_load(Load::I64, *o),
|
||||
Inst::F32Load(_, o) => self.data.push_load(Load::F32, *o),
|
||||
Inst::F64Load(_, o) => self.data.push_load(Load::F64, *o),
|
||||
Inst::I32Load8S(_, o) => self.data.push_load(Load::I32_I8, *o),
|
||||
Inst::I32Load8U(_, o) => self.data.push_load(Load::I32_U8, *o),
|
||||
Inst::I32Load16S(_, o) => self.data.push_load(Load::I32_I16, *o),
|
||||
Inst::I32Load16U(_, o) => self.data.push_load(Load::I32_U16, *o),
|
||||
Inst::I64Load8S(_, o) => self.data.push_load(Load::I64_I8, *o),
|
||||
Inst::I64Load8U(_, o) => self.data.push_load(Load::I64_U8, *o),
|
||||
Inst::I64Load16S(_, o) => self.data.push_load(Load::I64_I16, *o),
|
||||
Inst::I64Load16U(_, o) => self.data.push_load(Load::I64_U16, *o),
|
||||
Inst::I64Load32S(_, o) => self.data.push_load(Load::I64_I32, *o),
|
||||
Inst::I64Load32U(_, o) => self.data.push_load(Load::I64_U32, *o),
|
||||
Inst::I32Store(_, o) => self.data.gen_store(Store::I32, *o, &mut stat),
|
||||
Inst::I64Store(_, o) => self.data.gen_store(Store::I64, *o, &mut stat),
|
||||
Inst::F32Store(_, o) => self.data.gen_store(Store::F32, *o, &mut stat),
|
||||
Inst::F64Store(_, o) => self.data.gen_store(Store::F64, *o, &mut stat),
|
||||
Inst::I32Store8(_, o) => self.data.gen_store(Store::I32_N8, *o, &mut stat),
|
||||
Inst::I32Store16(_, o) => self.data.gen_store(Store::I32_N16, *o, &mut stat),
|
||||
Inst::I64Store8(_, o) => self.data.gen_store(Store::I64_N8, *o, &mut stat),
|
||||
Inst::I64Store16(_, o) => self.data.gen_store(Store::I64_N16, *o, &mut stat),
|
||||
Inst::I64Store32(_, o) => self.data.gen_store(Store::I64_N32, *o, &mut stat),
|
||||
Inst::CurrentMemory(i) => {
|
||||
self.stack
|
||||
self.data
|
||||
.push(Expression::MemorySize(MemorySize { memory: *i }));
|
||||
}
|
||||
Inst::GrowMemory(i) => {
|
||||
let value = Box::new(self.stack.pop().unwrap());
|
||||
let value = Box::new(self.data.pop());
|
||||
|
||||
// `MemoryGrow` is an expression *but* it has side effects
|
||||
self.stack
|
||||
self.data
|
||||
.push(Expression::MemoryGrow(MemoryGrow { memory: *i, value }));
|
||||
|
||||
self.gen_leak_pending(&mut stat);
|
||||
self.data.gen_leak_pending(&mut stat);
|
||||
}
|
||||
Inst::I32Const(v) => self.push_constant(Value::I32(*v)),
|
||||
Inst::I64Const(v) => self.push_constant(Value::I64(*v)),
|
||||
Inst::F32Const(v) => self.push_constant(Value::F32(f32::from_bits(*v))),
|
||||
Inst::F64Const(v) => self.push_constant(Value::F64(f64::from_bits(*v))),
|
||||
Inst::I32Const(v) => self.data.push_constant(Value::I32(*v)),
|
||||
Inst::I64Const(v) => self.data.push_constant(Value::I64(*v)),
|
||||
Inst::F32Const(v) => self.data.push_constant(Value::F32(f32::from_bits(*v))),
|
||||
Inst::F64Const(v) => self.data.push_constant(Value::F64(f64::from_bits(*v))),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
@ -574,7 +592,7 @@ impl<'a> Builder<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
self.load_pending();
|
||||
self.data.load_pending();
|
||||
|
||||
stat
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user