Skip to content

Commit

Permalink
Merge pull request #27 from alexcrichton/parser-improvements
Browse files Browse the repository at this point in the history
A few minor improvements to the parser
  • Loading branch information
alexcrichton authored Jan 25, 2019
2 parents 8db4a1c + c284bec commit 637f146
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 278 deletions.
102 changes: 0 additions & 102 deletions src/chunk_list.rs

This file was deleted.

2 changes: 0 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#![deny(missing_docs)]

mod arena_set;
mod chunk_list;
pub mod const_value;
pub mod dot;
mod emit;
Expand All @@ -14,4 +13,3 @@ pub mod module;
mod parse;
pub mod passes;
pub mod ty;
pub mod validation_context;
31 changes: 8 additions & 23 deletions src/module/functions/local_function/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use crate::module::functions::{FunctionId, LocalFunction};
use crate::module::Module;
use crate::parse::IndicesToIds;
use crate::ty::ValType;
use crate::validation_context::ValidationContext;
use failure::Fail;

#[derive(Debug)]
Expand Down Expand Up @@ -44,7 +43,7 @@ pub type ControlStack = Vec<ControlFrame>;
#[derive(Debug)]
pub struct FunctionContext<'a> {
/// The module that we're adding a function for.
pub module: &'a mut Module,
pub module: &'a Module,

/// Mapping of indexes back to ids.
pub indices: &'a IndicesToIds,
Expand All @@ -55,9 +54,6 @@ pub struct FunctionContext<'a> {
/// The function being validated/constructed.
pub func: &'a mut LocalFunction,

/// The context under which the function is being validated/constructed.
pub validation: &'a ValidationContext<'a>,

/// The operands stack.
pub operands: &'a mut OperandStack,

Expand All @@ -68,11 +64,10 @@ pub struct FunctionContext<'a> {
impl<'a> FunctionContext<'a> {
/// Create a new function context.
pub fn new(
module: &'a mut Module,
module: &'a Module,
indices: &'a IndicesToIds,
func_id: FunctionId,
func: &'a mut LocalFunction,
validation: &'a ValidationContext<'a>,
operands: &'a mut OperandStack,
controls: &'a mut ControlStack,
) -> FunctionContext<'a> {
Expand All @@ -81,24 +76,11 @@ impl<'a> FunctionContext<'a> {
indices,
func_id,
func,
validation,
operands,
controls,
}
}

pub fn nested<'b>(&'b mut self, validation: &'b ValidationContext<'b>) -> FunctionContext<'b> {
FunctionContext {
module: self.module,
indices: self.indices,
func_id: self.func_id,
func: self.func,
validation,
operands: self.operands,
controls: self.controls,
}
}

pub fn push_operand<E>(&mut self, op: Option<ValType>, expr: E)
where
E: Copy + Into<ExprId>,
Expand Down Expand Up @@ -165,9 +147,12 @@ impl<'a> FunctionContext<'a> {
impl_unreachable(&mut self.operands, &mut self.controls, expr);
}

pub fn control(&self, n: usize) -> &ControlFrame {
pub fn control(&self, n: usize) -> Result<&ControlFrame> {
if n >= self.controls.len() {
failure::bail!("jump to nonexistent control block");
}
let idx = self.controls.len() - n - 1;
&self.controls[idx]
Ok(&self.controls[idx])
}

pub fn add_to_block<E>(&mut self, block: BlockId, expr: E)
Expand All @@ -182,7 +167,7 @@ impl<'a> FunctionContext<'a> {
where
E: Into<ExprId>,
{
let ctrl = self.control(control_frame);
let ctrl = self.control(control_frame).unwrap();
if ctrl.unreachable.is_some() {
return;
}
Expand Down
77 changes: 16 additions & 61 deletions src/module/functions/local_function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use crate::module::locals::ModuleLocals;
use crate::module::Module;
use crate::parse::IndicesToIds;
use crate::ty::{TypeId, ValType};
use crate::validation_context::ValidationContext;
use failure::{bail, Fail, ResultExt};
use id_arena::{Arena, Id};
use parity_wasm::elements;
Expand Down Expand Up @@ -53,11 +52,8 @@ impl LocalFunction {
indices: &mut IndicesToIds,
id: FunctionId,
ty: TypeId,
validation: &ValidationContext,
body: wasmparser::FunctionBody,
) -> Result<LocalFunction> {
let validation = validation.for_function(&module.types.get(ty));

// First up, implicitly add locals for all function arguments. We also
// record these in the function itself for later processing.
let mut args = Vec::new();
Expand Down Expand Up @@ -108,7 +104,6 @@ impl LocalFunction {
indices,
id,
&mut func,
&validation,
operands,
controls,
);
Expand Down Expand Up @@ -455,7 +450,7 @@ fn validate_instruction(
.get_func(function_index)
.context("invalid call")?;
let ty_id = ctx.module.funcs.get(func).ty();
let fun_ty = ctx.module.types.get(ty_id).clone();
let fun_ty = ctx.module.types.get(ty_id);
let mut args = ctx.pop_operands(fun_ty.params())?.into_boxed_slice();
args.reverse();
let expr = ctx.func.alloc(Call { func, args });
Expand All @@ -466,7 +461,7 @@ fn validate_instruction(
.indices
.get_type(index)
.context("invalid call_indirect")?;
let ty = ctx.module.types.get(type_id).clone();
let ty = ctx.module.types.get(type_id);
let table = ctx
.indices
.get_table(table_index)
Expand Down Expand Up @@ -707,13 +702,9 @@ fn validate_instruction(
ctx.push_operand(t2, expr);
}
Operator::Return => {
let expected: Vec<_> = ctx
.validation
.return_
.iter()
.flat_map(|b| b.iter().cloned())
.collect();
let values = ctx.pop_operands(&expected)?.into_boxed_slice();
let fn_ty = ctx.module.funcs.get(ctx.func_id).ty();
let expected = ctx.module.types.get(fn_ty).results();
let values = ctx.pop_operands(expected)?.into_boxed_slice();
let expr = ctx.func.alloc(Return { values });
ctx.unreachable(expr);
}
Expand All @@ -723,31 +714,24 @@ fn validate_instruction(
}
Operator::Block { ty } => {
let results = ValType::from_block_ty(ty)?;
let validation = ctx.validation.for_block(results.clone());
let mut ctx = ctx.nested(&validation);
ctx.push_control(BlockKind::Block, results.clone(), results);
validate_instruction_sequence_until_end(&mut ctx, ops)?;
validate_end(&mut ctx)?;
validate_instruction_sequence_until_end(ctx, ops)?;
validate_end(ctx)?;
}
Operator::Loop { ty } => {
let validation = ctx.validation.for_loop();
let mut ctx = ctx.nested(&validation);
let t = ValType::from_block_ty(ty)?;
ctx.push_control(BlockKind::Loop, vec![].into_boxed_slice(), t);
validate_instruction_sequence_until_end(&mut ctx, ops)?;
validate_end(&mut ctx)?;
validate_instruction_sequence_until_end(ctx, ops)?;
validate_end(ctx)?;
}
Operator::If { ty } => {
let ty = ValType::from_block_ty(ty)?;
let validation = ctx.validation.for_if_else(ty.clone());
let mut ctx = ctx.nested(&validation);

let (_, condition) = ctx.pop_operand_expected(Some(ValType::I32))?;

let consequent = ctx.push_control(BlockKind::IfElse, ty.clone(), ty.clone());

let mut else_found = false;
validate_instruction_sequence_until(&mut ctx, ops, |i| match i {
validate_instruction_sequence_until(ctx, ops, |i| match i {
Operator::Else => {
else_found = true;
true
Expand All @@ -760,7 +744,7 @@ fn validate_instruction(
let alternative = ctx.push_control(BlockKind::IfElse, results.clone(), results);

if else_found {
validate_instruction_sequence_until_end(&mut ctx, ops)?;
validate_instruction_sequence_until_end(ctx, ops)?;
}
let (results, _block) = ctx.pop_control()?;

Expand All @@ -782,45 +766,25 @@ fn validate_instruction(
.into());
}
Operator::Br { relative_depth } => {
ctx.validation
.label(relative_depth)
.context("`br` to out-of-bounds block")?;

let n = relative_depth as usize;
if ctx.controls.len() <= n {
return Err(ErrorKind::InvalidWasm
.context("attempt to branch to out-of-bounds block")
.into());
}

let expected = ctx.control(n).label_types.clone();
let expected = ctx.control(n)?.label_types.clone();
let args = ctx.pop_operands(&expected)?.into_boxed_slice();

let to_block = ctx.control(n).block;
let to_block = ctx.control(n)?.block;
let expr = ctx.func.alloc(Br {
block: to_block,
args,
});
ctx.unreachable(expr);
}
Operator::BrIf { relative_depth } => {
ctx.validation
.label(relative_depth)
.context("`br_if` to out-of-bounds block")?;

let n = relative_depth as usize;
if ctx.controls.len() <= n {
return Err(ErrorKind::InvalidWasm
.context("attempt to branch to out-of-bounds block")
.into());
}

let (_, condition) = ctx.pop_operand_expected(Some(ValType::I32))?;

let expected = ctx.control(n).label_types.clone();
let expected = ctx.control(n)?.label_types.clone();
let args = ctx.pop_operands(&expected)?.into_boxed_slice();

let to_block = ctx.control(n).block;
let to_block = ctx.control(n)?.block;
let expr = ctx.func.alloc(BrIf {
condition,
block: to_block,
Expand All @@ -838,16 +802,7 @@ fn validate_instruction(
Some(n) => n,
None => bail!("malformed `br_table"),
};
ctx.validation
.label(n)
.context("`br_table` with out-of-bounds block")?;
let n = n as usize;
if ctx.controls.len() < n {
return Err(ErrorKind::InvalidWasm
.context("attempt to jump to an out-of-bounds block from a table entry")
.into());
}
let control = ctx.control(n);
let control = ctx.control(n as usize)?;
match label_types {
None => label_types = Some(&control.label_types),
Some(n) => {
Expand Down
Loading

0 comments on commit 637f146

Please sign in to comment.