fuzzbug fix and more robust undef handling

This commit is contained in:
Chris Fallin 2021-12-24 14:00:58 -08:00
parent 63aa7e4cb6
commit f33aab4216
6 changed files with 24 additions and 56 deletions

View file

@ -169,11 +169,6 @@ pub fn produce_func_wasm<FT: FuncTypeSink>(
for operator in &body.operators {
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
}

View file

@ -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,

View file

@ -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());

View file

@ -23,22 +23,18 @@ 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) {
workqueue.push_back(value);
}
counts.toplevel.insert(value);
let value = f.resolve_alias(value);
counts.add(value);
if workqueue_set.insert(value) {
workqueue.push_back(value);
}
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);
}
let value = f.resolve_alias(value);
counts.add(value);
if workqueue_set.insert(value) {
workqueue.push_back(value);
}
});
@ -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 {

View file

@ -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,16 +574,12 @@ 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);
}
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);
}
self.locals.set(*local_index, value);
}
wasmparser::Operator::Call { .. }
@ -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);

View file

@ -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),