WIP.
This commit is contained in:
parent
676ee3a1d2
commit
589729566f
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
30
src/ir.rs
30
src/ir.rs
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue