Seems to be fuzz-clean in wasm-to-IR step now; complete for Wasm-MVP
This commit is contained in:
parent
d8a4340743
commit
0eb41cb0a3
271
src/frontend.rs
271
src/frontend.rs
|
@ -100,6 +100,11 @@ fn parse_body<'a, 'b>(
|
||||||
body: wasmparser::FunctionBody<'a>,
|
body: wasmparser::FunctionBody<'a>,
|
||||||
) -> Result<FunctionBody<'a>> {
|
) -> Result<FunctionBody<'a>> {
|
||||||
let mut ret: FunctionBody<'a> = FunctionBody::default();
|
let mut ret: FunctionBody<'a> = FunctionBody::default();
|
||||||
|
|
||||||
|
for ¶m in &module.signatures[my_sig].params[..] {
|
||||||
|
ret.locals.push(param);
|
||||||
|
}
|
||||||
|
|
||||||
let mut locals = body.get_locals_reader()?;
|
let mut locals = body.get_locals_reader()?;
|
||||||
for _ in 0..locals.get_count() {
|
for _ in 0..locals.get_count() {
|
||||||
let (count, ty) = locals.read()?;
|
let (count, ty) = locals.read()?;
|
||||||
|
@ -197,6 +202,15 @@ impl Frame {
|
||||||
Frame::If { out, .. } | Frame::Else { out, .. } => *out,
|
Frame::If { out, .. } | Frame::Else { out, .. } => *out,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn out(&self) -> BlockId {
|
||||||
|
match self {
|
||||||
|
Frame::Block { out, .. }
|
||||||
|
| Frame::Loop { out, .. }
|
||||||
|
| Frame::If { out, .. }
|
||||||
|
| Frame::Else { out, .. } => *out,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
|
@ -212,13 +226,13 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Push initial implicit Block.
|
// Push initial implicit Block.
|
||||||
let params = module.signatures[my_sig].params.to_vec();
|
let results = module.signatures[my_sig].returns.to_vec();
|
||||||
let results = module.signatures[my_sig].params.to_vec();
|
|
||||||
let out = ret.create_block();
|
let out = ret.create_block();
|
||||||
|
ret.add_block_params(out, &results[..]);
|
||||||
ret.ctrl_stack.push(Frame::Block {
|
ret.ctrl_stack.push(Frame::Block {
|
||||||
start_depth: 0,
|
start_depth: 0,
|
||||||
out,
|
out,
|
||||||
params,
|
params: vec![],
|
||||||
results,
|
results,
|
||||||
});
|
});
|
||||||
ret
|
ret
|
||||||
|
@ -229,11 +243,13 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop_n(&mut self, n: usize) -> Vec<ValueId> {
|
fn pop_n(&mut self, n: usize) -> Vec<ValueId> {
|
||||||
self.op_stack
|
let new_top = self.op_stack.len() - n;
|
||||||
.split_off(n)
|
let ret = self.op_stack[new_top..]
|
||||||
.into_iter()
|
.iter()
|
||||||
.map(|(_ty, value)| value)
|
.map(|(_ty, value)| *value)
|
||||||
.collect()
|
.collect::<Vec<_>>();
|
||||||
|
self.op_stack.truncate(new_top);
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop_1(&mut self) -> ValueId {
|
fn pop_1(&mut self) -> ValueId {
|
||||||
|
@ -242,9 +258,17 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
|
|
||||||
fn handle_op(&mut self, op: Operator<'a>) -> Result<()> {
|
fn handle_op(&mut self, op: Operator<'a>) -> Result<()> {
|
||||||
trace!("handle_op: {:?}", op);
|
trace!("handle_op: {:?}", op);
|
||||||
|
trace!("op_stack = {:?}", self.op_stack);
|
||||||
|
trace!("ctrl_stack = {:?}", self.ctrl_stack);
|
||||||
match &op {
|
match &op {
|
||||||
Operator::Unreachable
|
Operator::Unreachable => {
|
||||||
| Operator::LocalGet { .. }
|
if let Some(block) = self.cur_block {
|
||||||
|
self.body.blocks[block].terminator = Terminator::None;
|
||||||
|
}
|
||||||
|
self.cur_block = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operator::LocalGet { .. }
|
||||||
| Operator::LocalSet { .. }
|
| Operator::LocalSet { .. }
|
||||||
| Operator::LocalTee { .. }
|
| Operator::LocalTee { .. }
|
||||||
| Operator::Call { .. }
|
| Operator::Call { .. }
|
||||||
|
@ -414,6 +438,10 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
| Operator::I64TruncSatF32U
|
| Operator::I64TruncSatF32U
|
||||||
| Operator::I64TruncSatF64S
|
| Operator::I64TruncSatF64S
|
||||||
| Operator::I64TruncSatF64U
|
| Operator::I64TruncSatF64U
|
||||||
|
| Operator::F32ReinterpretI32
|
||||||
|
| Operator::F64ReinterpretI64
|
||||||
|
| Operator::I32ReinterpretF32
|
||||||
|
| Operator::I64ReinterpretF64
|
||||||
| Operator::TableGet { .. }
|
| Operator::TableGet { .. }
|
||||||
| Operator::TableSet { .. }
|
| Operator::TableSet { .. }
|
||||||
| Operator::TableGrow { .. }
|
| Operator::TableGrow { .. }
|
||||||
|
@ -425,71 +453,88 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
let _ = self.pop_1();
|
let _ = self.pop_1();
|
||||||
}
|
}
|
||||||
|
|
||||||
Operator::End => match self.ctrl_stack.pop() {
|
Operator::End if self.cur_block.is_none() => {
|
||||||
None => {
|
let frame = self.ctrl_stack.pop().unwrap();
|
||||||
self.emit(Operator::Return)?;
|
self.op_stack.truncate(frame.start_depth());
|
||||||
|
self.cur_block = Some(frame.out());
|
||||||
|
self.push_block_params();
|
||||||
|
}
|
||||||
|
|
||||||
|
Operator::End => {
|
||||||
|
let frame = self.ctrl_stack.pop();
|
||||||
|
match frame {
|
||||||
|
None => {
|
||||||
|
self.emit(Operator::Return)?;
|
||||||
|
}
|
||||||
|
Some(Frame::Block {
|
||||||
|
start_depth,
|
||||||
|
out,
|
||||||
|
results,
|
||||||
|
..
|
||||||
|
})
|
||||||
|
| Some(Frame::Loop {
|
||||||
|
start_depth,
|
||||||
|
out,
|
||||||
|
results,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
// Generate a branch to the out-block with
|
||||||
|
// blockparams for the results.
|
||||||
|
if self.cur_block.is_some() {
|
||||||
|
let result_values = self.pop_n(results.len());
|
||||||
|
self.emit_branch(out, &result_values[..]);
|
||||||
|
}
|
||||||
|
self.op_stack.truncate(start_depth);
|
||||||
|
self.cur_block = Some(out);
|
||||||
|
self.push_block_params();
|
||||||
|
}
|
||||||
|
Some(Frame::If {
|
||||||
|
start_depth,
|
||||||
|
out,
|
||||||
|
el,
|
||||||
|
param_values,
|
||||||
|
results,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
// Generate a branch to the out-block with
|
||||||
|
// blockparams for the results.
|
||||||
|
if self.cur_block.is_some() {
|
||||||
|
let result_values = self.pop_n(results.len());
|
||||||
|
self.emit_branch(out, &result_values[..]);
|
||||||
|
}
|
||||||
|
self.op_stack.truncate(start_depth);
|
||||||
|
// No `else`, so we need to generate a trivial
|
||||||
|
// branch in the else-block. If the if-block-type
|
||||||
|
// has results, they must be exactly the params.
|
||||||
|
let else_result_values = param_values;
|
||||||
|
assert_eq!(else_result_values.len(), results.len());
|
||||||
|
let else_result_values = else_result_values
|
||||||
|
.iter()
|
||||||
|
.map(|(_ty, value)| *value)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
self.emit_branch(el, &else_result_values[..]);
|
||||||
|
assert_eq!(self.op_stack.len(), start_depth);
|
||||||
|
self.cur_block = Some(out);
|
||||||
|
self.push_block_params();
|
||||||
|
}
|
||||||
|
Some(Frame::Else {
|
||||||
|
out,
|
||||||
|
results,
|
||||||
|
start_depth,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
// Generate a branch to the out-block with
|
||||||
|
// blockparams for the results.
|
||||||
|
if self.cur_block.is_some() {
|
||||||
|
let result_values = self.pop_n(results.len());
|
||||||
|
self.emit_branch(out, &result_values[..]);
|
||||||
|
}
|
||||||
|
self.op_stack.truncate(start_depth);
|
||||||
|
self.cur_block = Some(out);
|
||||||
|
self.push_block_params();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(Frame::Block {
|
}
|
||||||
start_depth,
|
|
||||||
out,
|
|
||||||
results,
|
|
||||||
..
|
|
||||||
})
|
|
||||||
| Some(Frame::Loop {
|
|
||||||
start_depth,
|
|
||||||
out,
|
|
||||||
results,
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
// Generate a branch to the out-block with
|
|
||||||
// blockparams for the results.
|
|
||||||
let result_values = self.pop_n(results.len());
|
|
||||||
self.emit_branch(out, &result_values[..]);
|
|
||||||
assert_eq!(self.op_stack.len(), start_depth);
|
|
||||||
self.cur_block = Some(out);
|
|
||||||
self.push_block_params(&results[..]);
|
|
||||||
}
|
|
||||||
Some(Frame::If {
|
|
||||||
start_depth,
|
|
||||||
out,
|
|
||||||
el,
|
|
||||||
param_values,
|
|
||||||
results,
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
// Generate a branch to the out-block with
|
|
||||||
// blockparams for the results.
|
|
||||||
let result_values = self.pop_n(results.len());
|
|
||||||
self.emit_branch(out, &result_values[..]);
|
|
||||||
// No `else`, so we need to generate a trivial
|
|
||||||
// branch in the else-block. If the if-block-type
|
|
||||||
// has results, they must be exactly the params.
|
|
||||||
let else_result_values = param_values;
|
|
||||||
assert_eq!(else_result_values.len(), results.len());
|
|
||||||
let else_result_values = else_result_values
|
|
||||||
.iter()
|
|
||||||
.map(|(_ty, value)| *value)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
self.emit_branch(el, &else_result_values[..]);
|
|
||||||
assert_eq!(self.op_stack.len(), start_depth);
|
|
||||||
self.cur_block = Some(out);
|
|
||||||
self.push_block_params(&results[..]);
|
|
||||||
}
|
|
||||||
Some(Frame::Else {
|
|
||||||
out,
|
|
||||||
results,
|
|
||||||
start_depth,
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
// Generate a branch to the out-block with
|
|
||||||
// blockparams for the results.
|
|
||||||
let result_values = self.pop_n(results.len());
|
|
||||||
assert_eq!(self.op_stack.len(), start_depth);
|
|
||||||
self.emit_branch(out, &result_values[..]);
|
|
||||||
self.cur_block = Some(out);
|
|
||||||
self.push_block_params(&results[..]);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
Operator::Block { ty } => {
|
Operator::Block { ty } => {
|
||||||
let (params, results) = self.block_params_and_results(*ty);
|
let (params, results) = self.block_params_and_results(*ty);
|
||||||
|
@ -512,8 +557,9 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
let start_depth = self.op_stack.len();
|
let start_depth = self.op_stack.len();
|
||||||
self.emit_branch(header, &initial_args[..]);
|
self.emit_branch(header, &initial_args[..]);
|
||||||
self.cur_block = Some(header);
|
self.cur_block = Some(header);
|
||||||
self.push_block_params(¶ms[..]);
|
self.push_block_params();
|
||||||
let out = self.create_block();
|
let out = self.create_block();
|
||||||
|
self.add_block_params(out, &results[..]);
|
||||||
self.ctrl_stack.push(Frame::Loop {
|
self.ctrl_stack.push(Frame::Loop {
|
||||||
start_depth,
|
start_depth,
|
||||||
header,
|
header,
|
||||||
|
@ -531,7 +577,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
self.add_block_params(join, &results[..]);
|
self.add_block_params(join, &results[..]);
|
||||||
let cond = self.pop_1();
|
let cond = self.pop_1();
|
||||||
let param_values = self.op_stack[self.op_stack.len() - params.len()..].to_vec();
|
let param_values = self.op_stack[self.op_stack.len() - params.len()..].to_vec();
|
||||||
let start_depth = self.op_stack.len();
|
let start_depth = self.op_stack.len() - params.len();
|
||||||
self.ctrl_stack.push(Frame::If {
|
self.ctrl_stack.push(Frame::If {
|
||||||
start_depth,
|
start_depth,
|
||||||
out: join,
|
out: join,
|
||||||
|
@ -554,8 +600,11 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
results,
|
results,
|
||||||
} = self.ctrl_stack.pop().unwrap()
|
} = self.ctrl_stack.pop().unwrap()
|
||||||
{
|
{
|
||||||
let if_results = self.pop_n(results.len());
|
if self.cur_block.is_some() {
|
||||||
self.emit_branch(out, &if_results[..]);
|
let if_results = self.pop_n(results.len());
|
||||||
|
self.emit_branch(out, &if_results[..]);
|
||||||
|
}
|
||||||
|
self.op_stack.truncate(start_depth);
|
||||||
self.op_stack.extend(param_values);
|
self.op_stack.extend(param_values);
|
||||||
self.ctrl_stack.push(Frame::Else {
|
self.ctrl_stack.push(Frame::Else {
|
||||||
start_depth,
|
start_depth,
|
||||||
|
@ -577,16 +626,21 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
};
|
};
|
||||||
// Get the frame we're branching to.
|
// Get the frame we're branching to.
|
||||||
let frame = self.relative_frame(*relative_depth).clone();
|
let frame = self.relative_frame(*relative_depth).clone();
|
||||||
// Get the args off the stack.
|
|
||||||
let args = self.pop_n(frame.br_args().len());
|
|
||||||
// Finally, generate the branch itself.
|
// Finally, generate the branch itself.
|
||||||
match cond {
|
match cond {
|
||||||
None => {
|
None => {
|
||||||
|
// Get the args off the stack unconditionally.
|
||||||
|
let args = self.pop_n(frame.br_args().len());
|
||||||
self.emit_branch(frame.br_target(), &args[..]);
|
self.emit_branch(frame.br_target(), &args[..]);
|
||||||
self.cur_block = None;
|
self.cur_block = None;
|
||||||
}
|
}
|
||||||
Some(cond) => {
|
Some(cond) => {
|
||||||
let cont = self.create_block();
|
let cont = self.create_block();
|
||||||
|
// Get the args off the stack but leave for the fallthrough.
|
||||||
|
let args = self.op_stack[self.op_stack.len() - frame.br_args().len()..]
|
||||||
|
.iter()
|
||||||
|
.map(|(_ty, value)| *value)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
self.emit_cond_branch(cond, frame.br_target(), &args[..], cont, &[]);
|
self.emit_cond_branch(cond, frame.br_target(), &args[..], cont, &[]);
|
||||||
self.cur_block = Some(cont);
|
self.cur_block = Some(cont);
|
||||||
}
|
}
|
||||||
|
@ -637,6 +691,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
|
|
||||||
fn block_params_and_results(&self, ty: TypeOrFuncType) -> (Vec<Type>, Vec<Type>) {
|
fn block_params_and_results(&self, ty: TypeOrFuncType) -> (Vec<Type>, Vec<Type>) {
|
||||||
match ty {
|
match ty {
|
||||||
|
TypeOrFuncType::Type(Type::EmptyBlockType) => (vec![], vec![]),
|
||||||
TypeOrFuncType::Type(ret_ty) => (vec![], vec![ret_ty]),
|
TypeOrFuncType::Type(ret_ty) => (vec![], vec![ret_ty]),
|
||||||
TypeOrFuncType::FuncType(sig_idx) => {
|
TypeOrFuncType::FuncType(sig_idx) => {
|
||||||
let sig = &self.module.signatures[sig_idx as SignatureId];
|
let sig = &self.module.signatures[sig_idx as SignatureId];
|
||||||
|
@ -729,8 +784,9 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_block_params(&mut self, tys: &[Type]) {
|
fn push_block_params(&mut self) {
|
||||||
assert_eq!(tys, self.body.blocks[self.cur_block.unwrap()].params);
|
let tys = &self.body.blocks[self.cur_block.unwrap()].params[..];
|
||||||
|
|
||||||
for (i, &ty) in tys.iter().enumerate() {
|
for (i, &ty) in tys.iter().enumerate() {
|
||||||
let value_id = self.body.values.len() as ValueId;
|
let value_id = self.body.values.len() as ValueId;
|
||||||
self.body.values.push(ValueDef {
|
self.body.values.push(ValueDef {
|
||||||
|
@ -742,32 +798,30 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit(&mut self, op: Operator<'a>) -> Result<()> {
|
fn emit(&mut self, op: Operator<'a>) -> Result<()> {
|
||||||
|
let inputs = op_inputs(
|
||||||
|
self.module,
|
||||||
|
self.my_sig,
|
||||||
|
&self.body.locals[..],
|
||||||
|
&self.op_stack[..],
|
||||||
|
&op,
|
||||||
|
)?;
|
||||||
|
let outputs = op_outputs(self.module, &self.body.locals[..], &self.op_stack[..], &op)?;
|
||||||
|
|
||||||
if let Some(block) = self.cur_block {
|
if let Some(block) = self.cur_block {
|
||||||
let inst = self.body.blocks[block].insts.len() as InstId;
|
let inst = self.body.blocks[block].insts.len() as InstId;
|
||||||
|
|
||||||
let mut inputs = vec![];
|
let mut input_operands = vec![];
|
||||||
for input in op_inputs(
|
for input in inputs.into_iter().rev() {
|
||||||
self.module,
|
|
||||||
self.my_sig,
|
|
||||||
&self.body.locals[..],
|
|
||||||
&self.op_stack[..],
|
|
||||||
&op,
|
|
||||||
)?
|
|
||||||
.into_iter()
|
|
||||||
.rev()
|
|
||||||
{
|
|
||||||
let (stack_top_ty, stack_top) = self.op_stack.pop().unwrap();
|
let (stack_top_ty, stack_top) = self.op_stack.pop().unwrap();
|
||||||
assert_eq!(stack_top_ty, input);
|
assert_eq!(stack_top_ty, input);
|
||||||
inputs.push(Operand::value(stack_top));
|
input_operands.push(Operand::value(stack_top));
|
||||||
}
|
}
|
||||||
inputs.reverse();
|
input_operands.reverse();
|
||||||
|
|
||||||
let mut outputs = vec![];
|
let mut output_operands = vec![];
|
||||||
for output_ty in
|
for output_ty in outputs.into_iter() {
|
||||||
op_outputs(self.module, &self.body.locals[..], &self.op_stack[..], &op)?.into_iter()
|
|
||||||
{
|
|
||||||
let val = self.body.values.len() as ValueId;
|
let val = self.body.values.len() as ValueId;
|
||||||
outputs.push(val);
|
output_operands.push(val);
|
||||||
self.body.values.push(ValueDef {
|
self.body.values.push(ValueDef {
|
||||||
kind: ValueKind::Inst(block, inst),
|
kind: ValueKind::Inst(block, inst),
|
||||||
ty: output_ty,
|
ty: output_ty,
|
||||||
|
@ -777,21 +831,12 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
|
|
||||||
self.body.blocks[block].insts.push(Inst {
|
self.body.blocks[block].insts.push(Inst {
|
||||||
operator: op,
|
operator: op,
|
||||||
outputs,
|
outputs: output_operands,
|
||||||
inputs,
|
inputs: input_operands,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
let _ = self.pop_n(
|
let _ = self.pop_n(inputs.len());
|
||||||
op_inputs(
|
for ty in outputs {
|
||||||
self.module,
|
|
||||||
self.my_sig,
|
|
||||||
&self.body.locals[..],
|
|
||||||
&self.op_stack[..],
|
|
||||||
&op,
|
|
||||||
)?
|
|
||||||
.len(),
|
|
||||||
);
|
|
||||||
for ty in op_outputs(self.module, &self.body.locals[..], &self.op_stack[..], &op)? {
|
|
||||||
self.op_stack.push((ty, NO_VALUE));
|
self.op_stack.push((ty, NO_VALUE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@ pub fn op_inputs(
|
||||||
Ok(Vec::from(module.signatures[sig].params.clone()))
|
Ok(Vec::from(module.signatures[sig].params.clone()))
|
||||||
}
|
}
|
||||||
&Operator::CallIndirect { index, .. } => {
|
&Operator::CallIndirect { index, .. } => {
|
||||||
let mut params = vec![Type::I32];
|
let mut params = module.signatures[index as usize].params.to_vec();
|
||||||
params.extend_from_slice(&module.signatures[index as usize].params[..]);
|
params.push(Type::I32);
|
||||||
Ok(params)
|
Ok(params)
|
||||||
}
|
}
|
||||||
&Operator::Return => Ok(Vec::from(module.signatures[my_sig].returns.clone())),
|
&Operator::Return => Ok(Vec::from(module.signatures[my_sig].returns.clone())),
|
||||||
|
@ -210,10 +210,16 @@ pub fn op_inputs(
|
||||||
Operator::I64TruncSatF32U => Ok(vec![Type::F32]),
|
Operator::I64TruncSatF32U => Ok(vec![Type::F32]),
|
||||||
Operator::I64TruncSatF64S => Ok(vec![Type::F64]),
|
Operator::I64TruncSatF64S => Ok(vec![Type::F64]),
|
||||||
Operator::I64TruncSatF64U => Ok(vec![Type::F64]),
|
Operator::I64TruncSatF64U => Ok(vec![Type::F64]),
|
||||||
|
Operator::F32ReinterpretI32 => Ok(vec![Type::I32]),
|
||||||
|
Operator::F64ReinterpretI64 => Ok(vec![Type::I64]),
|
||||||
|
Operator::I32ReinterpretF32 => Ok(vec![Type::F32]),
|
||||||
|
Operator::I64ReinterpretF64 => Ok(vec![Type::F64]),
|
||||||
Operator::TableGet { .. } => Ok(vec![Type::I32]),
|
Operator::TableGet { .. } => Ok(vec![Type::I32]),
|
||||||
Operator::TableSet { table } => Ok(vec![Type::I32, module.tables[*table as usize]]),
|
Operator::TableSet { table } => Ok(vec![Type::I32, module.tables[*table as usize]]),
|
||||||
Operator::TableGrow { .. } => Ok(vec![Type::I32]),
|
Operator::TableGrow { .. } => Ok(vec![Type::I32]),
|
||||||
Operator::TableSize { .. } => Ok(vec![]),
|
Operator::TableSize { .. } => Ok(vec![]),
|
||||||
|
Operator::MemorySize { .. } => Ok(vec![]),
|
||||||
|
Operator::MemoryGrow { .. } => Ok(vec![Type::I32]),
|
||||||
|
|
||||||
_ => bail!("Unknown operator in op_inputs(): {:?}", op),
|
_ => bail!("Unknown operator in op_inputs(): {:?}", op),
|
||||||
}
|
}
|
||||||
|
@ -236,8 +242,10 @@ pub fn op_outputs(
|
||||||
Ok(Vec::from(module.signatures[index as usize].returns.clone()))
|
Ok(Vec::from(module.signatures[index as usize].returns.clone()))
|
||||||
}
|
}
|
||||||
&Operator::Return => Ok(vec![]),
|
&Operator::Return => Ok(vec![]),
|
||||||
&Operator::LocalSet { .. } | &Operator::LocalTee { .. } => Ok(vec![]),
|
&Operator::LocalSet { .. } => Ok(vec![]),
|
||||||
&Operator::LocalGet { local_index } => Ok(vec![my_locals[local_index as usize]]),
|
&Operator::LocalGet { local_index } | &Operator::LocalTee { local_index } => {
|
||||||
|
Ok(vec![my_locals[local_index as usize]])
|
||||||
|
}
|
||||||
|
|
||||||
&Operator::Select => {
|
&Operator::Select => {
|
||||||
let val_ty = op_stack[op_stack.len() - 2].0;
|
let val_ty = op_stack[op_stack.len() - 2].0;
|
||||||
|
@ -248,19 +256,19 @@ pub fn op_outputs(
|
||||||
&Operator::GlobalSet { .. } => Ok(vec![]),
|
&Operator::GlobalSet { .. } => Ok(vec![]),
|
||||||
|
|
||||||
Operator::I32Load { .. }
|
Operator::I32Load { .. }
|
||||||
| Operator::I64Load { .. }
|
|
||||||
| Operator::F32Load { .. }
|
|
||||||
| Operator::F64Load { .. }
|
|
||||||
| Operator::I32Load8S { .. }
|
| Operator::I32Load8S { .. }
|
||||||
| Operator::I32Load8U { .. }
|
| Operator::I32Load8U { .. }
|
||||||
| Operator::I32Load16S { .. }
|
| Operator::I32Load16S { .. }
|
||||||
| Operator::I32Load16U { .. } => Ok(vec![Type::I32]),
|
| Operator::I32Load16U { .. } => Ok(vec![Type::I32]),
|
||||||
Operator::I64Load8S { .. }
|
Operator::I64Load { .. }
|
||||||
|
| Operator::I64Load8S { .. }
|
||||||
| Operator::I64Load8U { .. }
|
| Operator::I64Load8U { .. }
|
||||||
| Operator::I64Load16S { .. }
|
| Operator::I64Load16S { .. }
|
||||||
| Operator::I64Load16U { .. }
|
| Operator::I64Load16U { .. }
|
||||||
| Operator::I64Load32S { .. }
|
| Operator::I64Load32S { .. }
|
||||||
| Operator::I64Load32U { .. } => Ok(vec![Type::I64]),
|
| Operator::I64Load32U { .. } => Ok(vec![Type::I64]),
|
||||||
|
Operator::F32Load { .. } => Ok(vec![Type::F32]),
|
||||||
|
Operator::F64Load { .. } => Ok(vec![Type::F64]),
|
||||||
|
|
||||||
Operator::I32Store { .. } => Ok(vec![]),
|
Operator::I32Store { .. } => Ok(vec![]),
|
||||||
Operator::I64Store { .. } => Ok(vec![]),
|
Operator::I64Store { .. } => Ok(vec![]),
|
||||||
|
@ -414,10 +422,16 @@ pub fn op_outputs(
|
||||||
Operator::I64TruncSatF32U => Ok(vec![Type::I64]),
|
Operator::I64TruncSatF32U => Ok(vec![Type::I64]),
|
||||||
Operator::I64TruncSatF64S => Ok(vec![Type::I64]),
|
Operator::I64TruncSatF64S => Ok(vec![Type::I64]),
|
||||||
Operator::I64TruncSatF64U => Ok(vec![Type::I64]),
|
Operator::I64TruncSatF64U => Ok(vec![Type::I64]),
|
||||||
|
Operator::F32ReinterpretI32 => Ok(vec![Type::F32]),
|
||||||
|
Operator::F64ReinterpretI64 => Ok(vec![Type::F64]),
|
||||||
|
Operator::I32ReinterpretF32 => Ok(vec![Type::I32]),
|
||||||
|
Operator::I64ReinterpretF64 => Ok(vec![Type::I64]),
|
||||||
Operator::TableGet { table } => Ok(vec![module.tables[*table as usize]]),
|
Operator::TableGet { table } => Ok(vec![module.tables[*table as usize]]),
|
||||||
Operator::TableSet { .. } => Ok(vec![]),
|
Operator::TableSet { .. } => Ok(vec![]),
|
||||||
Operator::TableGrow { .. } => Ok(vec![]),
|
Operator::TableGrow { .. } => Ok(vec![]),
|
||||||
Operator::TableSize { .. } => Ok(vec![Type::I32]),
|
Operator::TableSize { .. } => Ok(vec![Type::I32]),
|
||||||
|
Operator::MemorySize { .. } => Ok(vec![Type::I32]),
|
||||||
|
Operator::MemoryGrow { .. } => Ok(vec![Type::I32]),
|
||||||
|
|
||||||
_ => bail!("Unknown operator in op_outputs(): {:?}", op),
|
_ => bail!("Unknown operator in op_outputs(): {:?}", op),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue