This commit is contained in:
Chris Fallin 2021-11-13 14:23:22 -08:00
parent e6024c4ffd
commit bc245b581a
3 changed files with 38 additions and 8 deletions

View file

@ -189,7 +189,8 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
| Operator::Call { .. } | Operator::Call { .. }
| Operator::LocalGet { .. } | Operator::LocalGet { .. }
| Operator::LocalSet { .. } | Operator::LocalSet { .. }
| Operator::LocalTee { .. } => self.emit(op.clone())?, | Operator::LocalTee { .. }
| Operator::I32Eqz => self.emit(op.clone())?,
Operator::End => match self.ctrl_stack.pop() { Operator::End => match self.ctrl_stack.pop() {
None => { None => {
@ -409,7 +410,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
fn emit_branch(&mut self, target: BlockId, args: &[ValueId]) { fn emit_branch(&mut self, target: BlockId, args: &[ValueId]) {
if let Some(block) = self.cur_block { if let Some(block) = self.cur_block {
let args = args.iter().map(|&val| Operand::Value(val)).collect(); let args = args.iter().map(|&val| Operand::value(val)).collect();
let target = BlockTarget { let target = BlockTarget {
block: target, block: target,
args, args,
@ -429,14 +430,14 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
if let Some(block) = self.cur_block { if let Some(block) = self.cur_block {
let if_true_args = if_true_args let if_true_args = if_true_args
.iter() .iter()
.map(|&val| Operand::Value(val)) .map(|&val| Operand::value(val))
.collect(); .collect();
let if_false_args = if_false_args let if_false_args = if_false_args
.iter() .iter()
.map(|&val| Operand::Value(val)) .map(|&val| Operand::value(val))
.collect(); .collect();
self.body.blocks[block].terminator = Terminator::CondBr { self.body.blocks[block].terminator = Terminator::CondBr {
cond: Operand::Value(cond), cond: Operand::value(cond),
if_true: BlockTarget { if_true: BlockTarget {
block: if_true, block: if_true,
args: if_true_args, args: if_true_args,
@ -457,7 +458,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
args: &[ValueId], args: &[ValueId],
) { ) {
if let Some(block) = self.cur_block { if let Some(block) = self.cur_block {
let args: Vec<Operand<'a>> = args.iter().map(|&arg| Operand::Value(arg)).collect(); let args: Vec<Operand<'a>> = args.iter().map(|&arg| Operand::value(arg)).collect();
let targets = indexed_targets let targets = indexed_targets
.iter() .iter()
.map(|&block| BlockTarget { .map(|&block| BlockTarget {
@ -470,7 +471,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
args: args.clone(), args: args.clone(),
}; };
self.body.blocks[block].terminator = Terminator::Select { self.body.blocks[block].terminator = Terminator::Select {
value: Operand::Value(index), value: Operand::value(index),
targets, targets,
default, default,
}; };
@ -500,7 +501,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
{ {
let stack_top = self.op_stack.pop().unwrap(); let stack_top = self.op_stack.pop().unwrap();
assert_eq!(self.body.values[stack_top].ty, input); assert_eq!(self.body.values[stack_top].ty, input);
inputs.push(Operand::Value(stack_top)); inputs.push(Operand::value(stack_top));
} }
inputs.reverse(); inputs.reverse();
@ -520,6 +521,13 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
outputs, outputs,
inputs, inputs,
}); });
} else {
let _ = self
.op_stack
.split_off(op_inputs(self.module, self.my_sig, &self.body.locals[..], &op)?.len());
for _ in 0..op_outputs(self.module, &self.body.locals[..], &op)?.len() {
self.op_stack.push(NO_VALUE);
}
} }
Ok(()) Ok(())

View file

@ -8,6 +8,8 @@ pub type BlockId = usize;
pub type InstId = usize; pub type InstId = usize;
pub type ValueId = usize; pub type ValueId = usize;
pub const NO_VALUE: ValueId = usize::MAX;
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct Module<'a> { pub struct Module<'a> {
pub funcs: Vec<FuncDecl<'a>>, pub funcs: Vec<FuncDecl<'a>>,
@ -64,8 +66,23 @@ pub struct Inst<'a> {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Operand<'a> { pub enum Operand<'a> {
/// An SSA value.
Value(ValueId), Value(ValueId),
/// Tree-ified instructions for Wasm emission.
Sub(Box<Inst<'a>>), Sub(Box<Inst<'a>>),
/// Undef values are produced when code is unreachable and thus
/// removed/never executed.
Undef,
}
impl<'a> Operand<'a> {
pub fn value(value: ValueId) -> Self {
if value == NO_VALUE {
Operand::Undef
} else {
Operand::Value(value)
}
}
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]

View file

@ -24,6 +24,9 @@ pub fn op_inputs(
} }
&Operator::LocalGet { .. } => Ok(vec![]), &Operator::LocalGet { .. } => Ok(vec![]),
&Operator::I32Eqz => Ok(vec![Type::I32]),
&Operator::I32Eq => Ok(vec![Type::I32, Type::I32]),
_ => bail!("Unknown operator in op_inputs(): {:?}", op), _ => bail!("Unknown operator in op_inputs(): {:?}", op),
} }
} }
@ -40,6 +43,8 @@ pub fn op_outputs(module: &Module, my_locals: &[Type], op: &Operator<'_>) -> Res
&Operator::LocalSet { .. } | &Operator::LocalTee { .. } => Ok(vec![]), &Operator::LocalSet { .. } | &Operator::LocalTee { .. } => Ok(vec![]),
&Operator::LocalGet { local_index } => Ok(vec![my_locals[local_index as usize]]), &Operator::LocalGet { local_index } => Ok(vec![my_locals[local_index as usize]]),
&Operator::I32Eqz | &Operator::I32Eq => Ok(vec![Type::I32]),
_ => bail!("Unknown operator in op_outputs(): {:?}", op), _ => bail!("Unknown operator in op_outputs(): {:?}", op),
} }
} }