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 {
let params = tys_to_binaryen(params);
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 {
BinaryenAddFunc(
module.0,
@ -139,6 +139,10 @@ impl Function {
};
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 {
@ -224,12 +228,12 @@ lazy_static! {
}
struct TypeIds {
none_t: u32,
i32_t: u32,
i64_t: u32,
f32_t: u32,
f64_t: u32,
v128_t: u32,
none_t: BinaryenType,
i32_t: BinaryenType,
i64_t: BinaryenType,
f32_t: BinaryenType,
f64_t: BinaryenType,
v128_t: BinaryenType,
}
impl TypeIds {
@ -260,7 +264,7 @@ pub enum Type {
}
impl Type {
fn from_kind(kind: u32) -> Option<Type> {
fn from_kind(kind: BinaryenType) -> Option<Type> {
let tys = &*TYPE_IDS;
if kind == tys.none_t {
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 {
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) }
}
@ -450,6 +454,7 @@ extern "C" {
fn BinaryenFunctionGetBody(ptr: BinaryenFunction) -> BinaryenExpression;
fn BinaryenFunctionSetBody(ptr: BinaryenFunction, body: BinaryenExpression);
fn BinaryenFunctionGetName(ptr: BinaryenFunction) -> *const c_char;
fn BinaryenFunctionAddVar(ptr: BinaryenFunction, ty: BinaryenType) -> BinaryenIndex;
fn BinaryenGetExport(ptr: BinaryenModule, name: *const c_char) -> BinaryenExport;
fn BinaryenGetNumExports(ptr: BinaryenModule) -> u32;
fn BinaryenGetExportByIndex(ptr: BinaryenModule, index: u32) -> BinaryenExport;
@ -459,7 +464,7 @@ extern "C" {
fn BinaryenExternalFunction() -> u32;
fn BinaryenExpressionGetId(ptr: BinaryenExpression) -> u32;
fn BinaryenExpressionGetType(ptr: BinaryenExpression) -> u32;
fn BinaryenExpressionGetType(ptr: BinaryenExpression) -> BinaryenType;
fn BinaryenExpressionCopy(
ptr: BinaryenExpression,
module: BinaryenModule,

View file

@ -1,14 +1,18 @@
use crate::backend::binaryen;
use crate::ir::*;
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(
body: &FunctionBody,
into_mod: &mut binaryen::Module,
) -> binaryen::Expression {
) -> (Vec<Type>, binaryen::Expression) {
// For each block, generate an expr.
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() {
let exprs = body[block]
.insts
@ -24,22 +28,33 @@ pub(crate) fn generate_body(
todo!()
}
#[derive(Clone, Debug, Default)]
#[derive(Clone, Debug)]
struct ElabCtx {
value_to_expr: FxHashMap<Value, binaryen::Expression>,
block_params: FxHashMap<Value, LocalId>,
args: FxHashMap<Value, LocalId>,
block_params: FxHashMap<(Block, usize), LocalId>,
new_locals: Vec<Type>,
}
impl ElabCtx {
fn for_func(module: &Module, func: FuncId) -> ElabCtx {
let sig = module.func(func).sig();
let sig = module.signature(sig);
let body = module.func(func).body().unwrap();
fn new(body: &FunctionBody, into_mod: &mut binaryen::Module) -> ElabCtx {
// Create locals for each blockparam.
let mut block_params = FxHashMap::default();
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();
// TODO
ElabCtx {
value_to_expr: FxHashMap::default(),
block_params,
new_locals,
}
}
}
@ -73,6 +88,7 @@ pub(crate) fn create_new_func(
body: &FunctionBody,
into_mod: &mut binaryen::Module,
body_expr: binaryen::Expression,
new_locals: Vec<Type>,
) {
// Create param types.
let sig = module.signature(sig);
@ -80,7 +96,11 @@ pub(crate) fn create_new_func(
into_mod,
sig.params.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,
);
}

View file

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