This commit is contained in:
Chris Fallin 2022-10-29 15:19:26 -07:00
parent 676ee3a1d2
commit 589729566f
3 changed files with 72 additions and 29 deletions

View file

@ -125,7 +125,7 @@ impl Function {
) -> Function { ) -> Function {
let params = tys_to_binaryen(params); let params = tys_to_binaryen(params);
let results = tys_to_binaryen(results); let results = tys_to_binaryen(results);
let locals: Vec<BinaryenType> = locals.map(|&ty| Type::from(ty).to_kind()).collect(); let locals: Vec<BinaryenType> = locals.map(|ty| Type::from(ty).to_kind()).collect();
let ptr = unsafe { let ptr = unsafe {
BinaryenAddFunc( BinaryenAddFunc(
module.0, module.0,
@ -139,6 +139,10 @@ impl Function {
}; };
Function(module.0, ptr) Function(module.0, ptr)
} }
pub fn add_local(&mut self, ty: wasmparser::Type) -> usize {
(unsafe { BinaryenFunctionAddVar(self.1, Type::from(ty).to_kind()) }) as usize
}
} }
impl Export { impl Export {
@ -224,12 +228,12 @@ lazy_static! {
} }
struct TypeIds { struct TypeIds {
none_t: u32, none_t: BinaryenType,
i32_t: u32, i32_t: BinaryenType,
i64_t: u32, i64_t: BinaryenType,
f32_t: u32, f32_t: BinaryenType,
f64_t: u32, f64_t: BinaryenType,
v128_t: u32, v128_t: BinaryenType,
} }
impl TypeIds { impl TypeIds {
@ -260,7 +264,7 @@ pub enum Type {
} }
impl Type { impl Type {
fn from_kind(kind: u32) -> Option<Type> { fn from_kind(kind: BinaryenType) -> Option<Type> {
let tys = &*TYPE_IDS; let tys = &*TYPE_IDS;
if kind == tys.none_t { if kind == tys.none_t {
Some(Type::None) Some(Type::None)
@ -304,7 +308,7 @@ impl From<wasmparser::Type> for Type {
} }
pub fn tys_to_binaryen(tys: impl Iterator<Item = wasmparser::Type>) -> BinaryenType { pub fn tys_to_binaryen(tys: impl Iterator<Item = wasmparser::Type>) -> BinaryenType {
let tys: Vec<BinaryenType> = tys.map(|&ty| Type::from(ty).to_kind()).collect(); let tys: Vec<BinaryenType> = tys.map(|ty| Type::from(ty).to_kind()).collect();
unsafe { BinaryenTypeCreate(tys.as_ptr(), tys.len() as BinaryenIndex) } unsafe { BinaryenTypeCreate(tys.as_ptr(), tys.len() as BinaryenIndex) }
} }
@ -450,6 +454,7 @@ extern "C" {
fn BinaryenFunctionGetBody(ptr: BinaryenFunction) -> BinaryenExpression; fn BinaryenFunctionGetBody(ptr: BinaryenFunction) -> BinaryenExpression;
fn BinaryenFunctionSetBody(ptr: BinaryenFunction, body: BinaryenExpression); fn BinaryenFunctionSetBody(ptr: BinaryenFunction, body: BinaryenExpression);
fn BinaryenFunctionGetName(ptr: BinaryenFunction) -> *const c_char; fn BinaryenFunctionGetName(ptr: BinaryenFunction) -> *const c_char;
fn BinaryenFunctionAddVar(ptr: BinaryenFunction, ty: BinaryenType) -> BinaryenIndex;
fn BinaryenGetExport(ptr: BinaryenModule, name: *const c_char) -> BinaryenExport; fn BinaryenGetExport(ptr: BinaryenModule, name: *const c_char) -> BinaryenExport;
fn BinaryenGetNumExports(ptr: BinaryenModule) -> u32; fn BinaryenGetNumExports(ptr: BinaryenModule) -> u32;
fn BinaryenGetExportByIndex(ptr: BinaryenModule, index: u32) -> BinaryenExport; fn BinaryenGetExportByIndex(ptr: BinaryenModule, index: u32) -> BinaryenExport;
@ -459,7 +464,7 @@ extern "C" {
fn BinaryenExternalFunction() -> u32; fn BinaryenExternalFunction() -> u32;
fn BinaryenExpressionGetId(ptr: BinaryenExpression) -> u32; fn BinaryenExpressionGetId(ptr: BinaryenExpression) -> u32;
fn BinaryenExpressionGetType(ptr: BinaryenExpression) -> u32; fn BinaryenExpressionGetType(ptr: BinaryenExpression) -> BinaryenType;
fn BinaryenExpressionCopy( fn BinaryenExpressionCopy(
ptr: BinaryenExpression, ptr: BinaryenExpression,
module: BinaryenModule, module: BinaryenModule,

View file

@ -1,14 +1,18 @@
use crate::backend::binaryen; use crate::backend::binaryen;
use crate::ir::*; use crate::ir::*;
use fxhash::FxHashMap; use fxhash::FxHashMap;
use wasmparser::Type;
/// Creates a body expression for a function. Returns that expression,
/// and new locals (as their types) that were created as temporaries
/// and need to be appended to `body.locals`.
pub(crate) fn generate_body( pub(crate) fn generate_body(
body: &FunctionBody, body: &FunctionBody,
into_mod: &mut binaryen::Module, into_mod: &mut binaryen::Module,
) -> binaryen::Expression { ) -> (Vec<Type>, binaryen::Expression) {
// For each block, generate an expr. // For each block, generate an expr.
let mut block_exprs: FxHashMap<BlockId, binaryen::Expression> = FxHashMap::default(); let mut block_exprs: FxHashMap<BlockId, binaryen::Expression> = FxHashMap::default();
let mut ctx = ElabCtx::default(); let mut ctx = ElabCtx::new(body, into_mod);
for block in body.blocks() { for block in body.blocks() {
let exprs = body[block] let exprs = body[block]
.insts .insts
@ -24,22 +28,33 @@ pub(crate) fn generate_body(
todo!() todo!()
} }
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug)]
struct ElabCtx { struct ElabCtx {
value_to_expr: FxHashMap<Value, binaryen::Expression>, value_to_expr: FxHashMap<Value, binaryen::Expression>,
block_params: FxHashMap<Value, LocalId>, block_params: FxHashMap<(Block, usize), LocalId>,
args: FxHashMap<Value, LocalId>, new_locals: Vec<Type>,
} }
impl ElabCtx { impl ElabCtx {
fn for_func(module: &Module, func: FuncId) -> ElabCtx { fn new(body: &FunctionBody, into_mod: &mut binaryen::Module) -> ElabCtx {
let sig = module.func(func).sig(); // Create locals for each blockparam.
let sig = module.signature(sig); let mut block_params = FxHashMap::default();
let body = module.func(func).body().unwrap(); let mut next_local = body.locals.len() as LocalId;
let mut new_locals = vec![];
for block in body.blocks() {
for &(ty, param) in &body[block].params {
let new_local = next_local;
next_local += 1;
block_params.insert((ty, param), new_local);
new_locals.push(ty);
}
}
let mut ctx = ElabCtx::default(); ElabCtx {
value_to_expr: FxHashMap::default(),
// TODO block_params,
new_locals,
}
} }
} }
@ -73,6 +88,7 @@ pub(crate) fn create_new_func(
body: &FunctionBody, body: &FunctionBody,
into_mod: &mut binaryen::Module, into_mod: &mut binaryen::Module,
body_expr: binaryen::Expression, body_expr: binaryen::Expression,
new_locals: Vec<Type>,
) { ) {
// Create param types. // Create param types.
let sig = module.signature(sig); let sig = module.signature(sig);
@ -80,7 +96,11 @@ pub(crate) fn create_new_func(
into_mod, into_mod,
sig.params.iter().copied(), sig.params.iter().copied(),
sig.returns.iter().copied(), sig.returns.iter().copied(),
body.locals.iter().copied(), body.locals
.iter()
.copied()
.skip(body.n_params)
.chain(new_locals.into_iter()),
body_expr, body_expr,
); );
} }

View file

@ -99,14 +99,20 @@ impl FuncDecl {
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct FunctionBody { pub struct FunctionBody {
/// How many parameters the function has. (Their types are the
/// first `n_params` values in `locals`.)
pub n_params: usize, pub n_params: usize,
/// Return types of the function.
pub rets: Vec<Type>, pub rets: Vec<Type>,
/// Local types, *including* args.
pub locals: Vec<Type>, pub locals: Vec<Type>,
/// Block bodies, indexed by `BlockId`.
pub blocks: Vec<Block>, pub blocks: Vec<Block>,
/// Value definitions, indexed by `Value`.
pub values: Vec<ValueDef>, pub values: Vec<ValueDef>,
/// A single value can have multiple types if multi-value (e.g. a /// Types, indexed by `Value`. A single value can have multiple
/// call). /// types if multi-value (e.g. a call).
pub types: Vec</* Value, */ Vec<Type>>, pub types: Vec<Vec<Type>>,
} }
impl FunctionBody { impl FunctionBody {
@ -524,13 +530,25 @@ impl<'a> Module<'a> {
for new_func_idx in self.funcs.len()..binaryen_module.num_funcs() { for new_func_idx in self.funcs.len()..binaryen_module.num_funcs() {
let sig = self.func(new_func_idx).sig(); let sig = self.func(new_func_idx).sig();
let body = self.func(new_func_idx).body().unwrap(); let body = self.func(new_func_idx).body().unwrap();
let binaryen_expr = backend::lower::generate_body(body, &mut binaryen_module); let (new_locals, binaryen_expr) =
backend::lower::create_new_func(self, sig, body, &mut binaryen_module, binaryen_expr); backend::lower::generate_body(body, &mut binaryen_module);
backend::lower::create_new_func(
self,
sig,
body,
&mut binaryen_module,
binaryen_expr,
new_locals,
);
} }
for &func in &self.dirty_funcs { for &func in &self.dirty_funcs {
if let Some(body) = self.func(func).body() { if let Some(body) = self.func(func).body() {
let mut binaryen_func = binaryen_module.func(func); let mut binaryen_func = binaryen_module.func(func);
let binaryen_expr = backend::lower::generate_body(body, &mut binaryen_module); let (new_locals, binaryen_expr) =
backend::lower::generate_body(body, &mut binaryen_module);
for ty in new_locals {
binaryen_func.add_local(ty);
}
binaryen_func.set_body(binaryen_expr); binaryen_func.set_body(binaryen_expr);
} }
} }