fuzzbug fix and more robust undef handling
This commit is contained in:
parent
63aa7e4cb6
commit
f33aab4216
|
@ -170,10 +170,5 @@ pub fn produce_func_wasm<FT: FuncTypeSink>(
|
|||
ctx.translate(operator, locations);
|
||||
}
|
||||
|
||||
// Fixup: add unreachable just before last `end`; there must be an explicit return.
|
||||
// assert!(matches!(wasm.operators.pop(), Some(wasm_encoder::Instruction::End)));
|
||||
// wasm.operators.push(wasm_encoder::Instruction::Unreachable);
|
||||
// wasm.operators.push(wasm_encoder::Instruction::End);
|
||||
|
||||
wasm
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ pub struct Allocator<'a> {
|
|||
freelist: FxHashMap<wasmparser::Type, Vec<LocalId>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct ValueSpan {
|
||||
value: Value,
|
||||
multi_value_index: usize,
|
||||
|
|
|
@ -82,10 +82,6 @@ impl Schedule {
|
|||
}
|
||||
match value_def {
|
||||
&ValueDef::Operator(op, ref operands) => {
|
||||
if operands.iter().any(|&value| value == Value::undef()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if operands.len() == 0 {
|
||||
if !op_rematerialize(&op) {
|
||||
log::trace!("immediately ready: v{}", value.index());
|
||||
|
|
|
@ -23,7 +23,6 @@ impl UseCountAnalysis {
|
|||
let mut workqueue_set = FxHashSet::default();
|
||||
for block in 0..f.blocks.len() {
|
||||
for &value in &f.blocks[block].insts {
|
||||
if value != Value::undef() {
|
||||
let value = f.resolve_alias(value);
|
||||
counts.add(value);
|
||||
if workqueue_set.insert(value) {
|
||||
|
@ -31,15 +30,12 @@ impl UseCountAnalysis {
|
|||
}
|
||||
counts.toplevel.insert(value);
|
||||
}
|
||||
}
|
||||
f.blocks[block].terminator.visit_uses(|value| {
|
||||
if value != Value::undef() {
|
||||
let value = f.resolve_alias(value);
|
||||
counts.add(value);
|
||||
if workqueue_set.insert(value) {
|
||||
workqueue.push_back(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
while let Some(value) = workqueue.pop_front() {
|
||||
|
@ -48,9 +44,6 @@ impl UseCountAnalysis {
|
|||
&ValueDef::Alias(..) | &ValueDef::Arg(..) | &ValueDef::BlockParam(..) => {}
|
||||
&ValueDef::Operator(_op, ref args) => {
|
||||
for &arg in args {
|
||||
if arg == Value::undef() {
|
||||
continue;
|
||||
}
|
||||
let arg = f.resolve_alias(arg);
|
||||
counts.add(arg);
|
||||
if counts.use_count[arg.index()] == 1 {
|
||||
|
@ -61,9 +54,6 @@ impl UseCountAnalysis {
|
|||
}
|
||||
}
|
||||
&ValueDef::PickOutput(value, _) => {
|
||||
if value == Value::undef() {
|
||||
continue;
|
||||
}
|
||||
let value = f.resolve_alias(value);
|
||||
counts.add(value);
|
||||
if counts.use_count[value.index()] == 1 {
|
||||
|
|
|
@ -290,7 +290,8 @@ impl LocalTracker {
|
|||
assert!((local as usize) < body.locals.len());
|
||||
self.get_in_block(body, block, local)
|
||||
} else {
|
||||
Value::undef()
|
||||
let ty = body.locals[local as usize];
|
||||
self.create_default_value(body, ty)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -541,11 +542,13 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
|||
self.op_stack.pop().unwrap().1
|
||||
}
|
||||
|
||||
fn block_results(&mut self, n: usize, start_depth: usize) -> Vec<Value> {
|
||||
if self.op_stack.len() < start_depth + n {
|
||||
vec![Value::undef(); n]
|
||||
fn block_results(&mut self, tys: &[Type], start_depth: usize) -> Vec<Value> {
|
||||
if self.op_stack.len() < start_depth + tys.len() {
|
||||
tys.iter()
|
||||
.map(|&ty| self.locals.create_default_value(&mut self.body, ty))
|
||||
.collect()
|
||||
} else {
|
||||
self.pop_n(n)
|
||||
self.pop_n(tys.len())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -571,17 +574,13 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
|||
|
||||
wasmparser::Operator::LocalSet { local_index } => {
|
||||
let (_, value) = self.op_stack.pop().unwrap();
|
||||
if value != Value::undef() {
|
||||
self.locals.set(*local_index, value);
|
||||
}
|
||||
}
|
||||
|
||||
wasmparser::Operator::LocalTee { local_index } => {
|
||||
let (_ty, value) = *self.op_stack.last().unwrap();
|
||||
if value != Value::undef() {
|
||||
self.locals.set(*local_index, value);
|
||||
}
|
||||
}
|
||||
|
||||
wasmparser::Operator::Call { .. }
|
||||
| wasmparser::Operator::CallIndirect { .. }
|
||||
|
@ -787,7 +786,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
|||
}) => {
|
||||
// Generate a branch to the out-block with
|
||||
// blockparams for the results.
|
||||
let result_values = self.block_results(results.len(), *start_depth);
|
||||
let result_values = self.block_results(&results[..], *start_depth);
|
||||
self.emit_branch(*out, &result_values[..]);
|
||||
self.op_stack.truncate(*start_depth);
|
||||
// Seal the out-block: no more edges will be
|
||||
|
@ -812,7 +811,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
|||
}) => {
|
||||
// Generate a branch to the out-block with
|
||||
// blockparams for the results.
|
||||
let result_values = self.block_results(results.len(), *start_depth);
|
||||
let result_values = self.block_results(&results[..], *start_depth);
|
||||
self.emit_branch(*out, &result_values[..]);
|
||||
self.op_stack.truncate(*start_depth);
|
||||
// No `else`, so we need to generate a trivial
|
||||
|
@ -841,7 +840,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
|||
}) => {
|
||||
// Generate a branch to the out-block with
|
||||
// blockparams for the results.
|
||||
let result_values = self.block_results(results.len(), *start_depth);
|
||||
let result_values = self.block_results(&results[..], *start_depth);
|
||||
self.emit_branch(*out, &result_values[..]);
|
||||
self.op_stack.truncate(*start_depth);
|
||||
self.cur_block = Some(*out);
|
||||
|
@ -920,7 +919,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
|||
results,
|
||||
} = self.ctrl_stack.pop().unwrap()
|
||||
{
|
||||
let if_results = self.block_results(results.len(), start_depth);
|
||||
let if_results = self.block_results(&results[..], start_depth);
|
||||
self.emit_branch(out, &if_results[..]);
|
||||
self.op_stack.truncate(start_depth);
|
||||
self.op_stack.extend(param_values);
|
||||
|
|
12
src/ir.rs
12
src/ir.rs
|
@ -100,7 +100,6 @@ impl FunctionBody {
|
|||
}
|
||||
|
||||
pub fn set_alias(&mut self, value: Value, to: Value) {
|
||||
assert_ne!(to, Value::undef());
|
||||
log::trace!("set_alias: value {:?} to {:?}", value, to);
|
||||
// Resolve the `to` value through all existing aliases.
|
||||
let to = self.resolve_and_update_alias(to);
|
||||
|
@ -112,7 +111,6 @@ impl FunctionBody {
|
|||
}
|
||||
|
||||
pub fn resolve_alias(&self, value: Value) -> Value {
|
||||
assert_ne!(value, Value::undef());
|
||||
let mut result = value;
|
||||
loop {
|
||||
if let &ValueDef::Alias(to) = &self.values[result.index()] {
|
||||
|
@ -238,10 +236,6 @@ impl std::fmt::Display for Value {
|
|||
}
|
||||
|
||||
impl Value {
|
||||
pub fn undef() -> Self {
|
||||
Value(u32::MAX)
|
||||
}
|
||||
|
||||
pub fn index(self) -> usize {
|
||||
self.0 as usize
|
||||
}
|
||||
|
@ -251,12 +245,6 @@ impl Value {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::default::Default for Value {
|
||||
fn default() -> Self {
|
||||
Value::undef()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum ValueDef {
|
||||
Arg(usize),
|
||||
|
|
Loading…
Reference in a new issue