Skip to content

Commit

Permalink
Expose a FunctionBuilder through LocalFunction
Browse files Browse the repository at this point in the history
This should allow to continue to build expressions for a function even
after it exists
  • Loading branch information
alexcrichton committed Feb 15, 2019
1 parent abe5b19 commit 93dfa67
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 31 deletions.
2 changes: 1 addition & 1 deletion crates/macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ fn create_matchers(variants: &[WalrusVariant]) -> impl quote::ToTokens {
true #(
&& #self_args.is_match(
local_func,
&local_func.exprs[*#args]
local_func.get(*#args)
)
)*
}
Expand Down
4 changes: 2 additions & 2 deletions src/function_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::ops::{Deref, DerefMut, Drop};
/// A helpful struct used for building instances of `LocalFunction`
#[derive(Default, Debug)]
pub struct FunctionBuilder {
arena: Arena<Expr>,
pub(crate) arena: Arena<Expr>,
}

impl FunctionBuilder {
Expand Down Expand Up @@ -127,7 +127,7 @@ impl FunctionBuilder {
results: ty.results().to_vec().into_boxed_slice(),
exprs,
});
let func = LocalFunction::new(ty_id, args, self.arena, entry);
let func = LocalFunction::new(ty_id, args, self, entry);
module.funcs.add_local(func)
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/ir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -990,7 +990,7 @@ impl<'expr> Visit<'expr> for ExprId {
where
V: Visitor<'expr>,
{
visitor.visit_expr(&visitor.local_function().exprs[*self])
visitor.visit_expr(&visitor.local_function().get(*self))
}
}

Expand All @@ -1004,11 +1004,11 @@ impl VisitMut for ExprId {
// use graph traversal instead of a simple tree walk like we have today
// when that comes about.
let mut expr = mem::replace(
&mut visitor.local_function_mut().exprs[*self],
visitor.local_function_mut().get_mut(*self),
Expr::Unreachable(Unreachable {}),
);
visitor.visit_expr_mut(&mut expr);
visitor.local_function_mut().exprs[*self] = expr;
*visitor.local_function_mut().get_mut(*self) = expr;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub mod passes;
mod ty;

pub use crate::error::{ErrorKind, Result};
pub use crate::function_builder::FunctionBuilder;
pub use crate::function_builder::{FunctionBuilder, BlockBuilder};
pub use crate::init_expr::InitExpr;
pub use crate::ir::{Local, LocalId};
pub use crate::module::*;
Expand Down
9 changes: 4 additions & 5 deletions src/module/functions/local_function/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ impl<'a> FunctionContext<'a> {
}
}

let block = self.func.exprs[frame.block.into()].unwrap_block_mut();
let block = self.func.block_mut(frame.block);
block.exprs.extend(extra_exprs);
block.exprs.push(expr);
}
Expand All @@ -192,8 +192,7 @@ impl<'a> FunctionContext<'a> {
where
E: Into<ExprId>,
{
let block = self.func.exprs[block.into()].unwrap_block_mut();
block.exprs.push(expr.into());
self.func.block_mut(block).exprs.push(expr.into());
}

pub fn add_to_frame_block<E>(&mut self, control_frame: usize, expr: E)
Expand Down Expand Up @@ -228,8 +227,8 @@ impl<'a> FunctionContext<'a> {

pub fn add_side_effect(&mut self, value: ExprId, side_effect: ExprId) -> ExprId {
// If we can add it to an existing `WithSideEffects` expr for this value, then do that.
if let Some(Expr::WithSideEffects(WithSideEffects { side_effects, .. })) =
self.func.exprs.get_mut(value)
if let Expr::WithSideEffects(WithSideEffects { side_effects, .. }) =
self.func.get_mut(value)
{
side_effects.push(side_effect);
return value;
Expand Down
2 changes: 1 addition & 1 deletion src/module/functions/local_function/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ impl Emit<'_, '_> {
let old = self.id;
self.id = id;

match &self.func.exprs[id] {
match &self.func.get(id) {
Const(e) => e.value.emit(self.encoder),
Block(e) => self.visit_block(e),
BrTable(e) => self.visit_br_table(e),
Expand Down
44 changes: 26 additions & 18 deletions src/module/functions/local_function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ use crate::ir::*;
use crate::map::{IdHashMap, IdHashSet};
use crate::parse::IndicesToIds;
use crate::passes::Used;
use crate::{FunctionId, Module, Result, TypeId, ValType, TableKind};
use crate::{FunctionId, Module, Result, TypeId, ValType, FunctionBuilder, TableKind};
use failure::{bail, ResultExt};
use id_arena::{Arena, Id};
use id_arena::Id;
use std::collections::BTreeMap;
use std::fmt;
use std::mem;
Expand All @@ -27,8 +27,8 @@ pub struct LocalFunction {
/// This function's type.
pub ty: TypeId,

/// The arena that contains this function's expressions.
pub(crate) exprs: Arena<Expr>,
/// All of this function's expressions, contained in the arena.
exprs: FunctionBuilder,

/// Arguments to this function, and the locals that they're assigned to
pub args: Vec<LocalId>,
Expand All @@ -46,7 +46,7 @@ impl LocalFunction {
pub(crate) fn new(
ty: TypeId,
args: Vec<LocalId>,
exprs: Arena<Expr>,
exprs: FunctionBuilder,
entry: BlockId,
) -> LocalFunction {
LocalFunction {
Expand All @@ -71,7 +71,7 @@ impl LocalFunction {
) -> Result<LocalFunction> {
let mut func = LocalFunction {
ty,
exprs: Arena::new(),
exprs: FunctionBuilder::new(),
args,
entry: None,
};
Expand Down Expand Up @@ -101,12 +101,11 @@ impl LocalFunction {
Ok(func)
}

fn alloc<T>(&mut self, val: T) -> T::Id
pub(crate) fn alloc<T>(&mut self, val: T) -> T::Id
where
T: Ast,
{
let id = self.exprs.alloc(val.into());
T::new_id(id)
self.exprs.alloc(val)
}

/// Get the id of this function's entry block.
Expand All @@ -116,22 +115,34 @@ impl LocalFunction {

/// Get the block associated with the given id.
pub fn block(&self, block: BlockId) -> &Block {
self.exprs[block.into()].unwrap_block()
self.get(block.into()).unwrap_block()
}

/// Get the block associated with the given id.
pub fn block_mut(&mut self, block: BlockId) -> &mut Block {
self.exprs[block.into()].unwrap_block_mut()
self.get_mut(block.into()).unwrap_block_mut()
}

/// Get the expression associated with the given id
pub fn get(&self, id: ExprId) -> &Expr {
&self.exprs[id]
&self.exprs.arena[id]
}

/// Get the expression associated with the given id
pub fn get_mut(&mut self, id: ExprId) -> &mut Expr {
&mut self.exprs[id]
&mut self.exprs.arena[id]
}

/// Get access to a `FunctionBuilder` to continue adding expressions to
/// this function.
pub fn builder(&self) -> &FunctionBuilder {
&self.exprs
}

/// Get access to a `FunctionBuilder` to continue adding expressions to
/// this function.
pub fn builder_mut(&mut self) -> &mut FunctionBuilder {
&mut self.exprs
}

/// Get the size of this function, in number of expressions.
Expand Down Expand Up @@ -163,15 +174,12 @@ impl LocalFunction {
/// Is this function's body a [constant
/// expression](https://webassembly.github.io/spec/core/valid/instructions.html#constant-expressions)?
pub fn is_const(&self) -> bool {
let entry = match &self.exprs[self.entry_block().into()] {
Expr::Block(b) => b,
_ => unreachable!(),
};
let entry = self.block(self.entry_block());
let matcher = ConstMatcher::new();
entry
.exprs
.iter()
.all(|e| matcher.is_match(self, &self.exprs[*e]))
.all(|e| matcher.is_match(self, &self.get(*e)))
}

/// Emit this function's compact locals declarations.
Expand Down

0 comments on commit 93dfa67

Please sign in to comment.