This commit is contained in:
Chris Fallin 2022-10-28 14:39:38 -07:00
parent 8e8464f76a
commit 676ee3a1d2
3 changed files with 157 additions and 6 deletions

View file

@ -115,6 +115,30 @@ impl Function {
let s = unsafe { CStr::from_ptr(BinaryenFunctionGetName(self.1)) };
s.to_str().unwrap()
}
pub fn create(
module: &mut Module,
params: impl Iterator<Item = wasmparser::Type>,
results: impl Iterator<Item = wasmparser::Type>,
locals: impl Iterator<Item = wasmparser::Type>,
body: Expression,
) -> 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 ptr = unsafe {
BinaryenAddFunc(
module.0,
/* name = */ std::ptr::null(),
params,
results,
locals.as_ptr(),
locals.len() as BinaryenIndex,
body.1,
)
};
Function(module.0, ptr)
}
}
impl Export {
@ -205,6 +229,7 @@ struct TypeIds {
i64_t: u32,
f32_t: u32,
f64_t: u32,
v128_t: u32,
}
impl TypeIds {
@ -215,6 +240,7 @@ impl TypeIds {
i64_t: unsafe { BinaryenTypeInt64() },
f32_t: unsafe { BinaryenTypeFloat32() },
f64_t: unsafe { BinaryenTypeFloat64() },
v128_t: unsafe { BinaryenTypeVec128() },
}
}
}
@ -230,6 +256,7 @@ pub enum Type {
I64,
F32,
F64,
V128,
}
impl Type {
@ -250,7 +277,7 @@ impl Type {
}
}
fn to_kind(&self) -> u32 {
pub(crate) fn to_kind(&self) -> BinaryenType {
let tys = &*TYPE_IDS;
match self {
&Type::None => tys.none_t,
@ -258,10 +285,29 @@ impl Type {
&Type::I64 => tys.i64_t,
&Type::F32 => tys.f32_t,
&Type::F64 => tys.f64_t,
&Type::V128 => tys.v128_t,
}
}
}
impl From<wasmparser::Type> for Type {
fn from(ty: wasmparser::Type) -> Self {
match ty {
wasmparser::Type::I32 => Type::I32,
wasmparser::Type::I64 => Type::I64,
wasmparser::Type::F32 => Type::F32,
wasmparser::Type::F64 => Type::F64,
wasmparser::Type::V128 => Type::V128,
_ => unimplemented!(),
}
}
}
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();
unsafe { BinaryenTypeCreate(tys.as_ptr(), tys.len() as BinaryenIndex) }
}
fn name_to_string(name: *const c_char) -> Option<String> {
if name.is_null() {
None
@ -517,11 +563,14 @@ extern "C" {
fn BinaryenUnreachableId() -> u32;
fn BinaryenPopId() -> u32;
fn BinaryenTypeNone() -> u32;
fn BinaryenTypeInt32() -> u32;
fn BinaryenTypeInt64() -> u32;
fn BinaryenTypeFloat32() -> u32;
fn BinaryenTypeFloat64() -> u32;
fn BinaryenTypeNone() -> BinaryenType;
fn BinaryenTypeInt32() -> BinaryenType;
fn BinaryenTypeInt64() -> BinaryenType;
fn BinaryenTypeFloat32() -> BinaryenType;
fn BinaryenTypeFloat64() -> BinaryenType;
fn BinaryenTypeVec128() -> BinaryenType;
fn BinaryenTypeCreate(tys: *const BinaryenType, n_tys: BinaryenIndex) -> BinaryenType;
fn BinaryenAddInt32() -> u32;
fn BinaryenSubInt32() -> u32;
@ -543,6 +592,16 @@ extern "C" {
ty: BinaryenType,
) -> BinaryenExpression;
fn BinaryenAddFunc(
module: BinaryenModule,
name: *const c_char,
params: BinaryenType,
results: BinaryenType,
vars: *const BinaryenType,
n_vars: BinaryenIndex,
body: BinaryenExpression,
) -> BinaryenFunction;
fn BinaryenUndefined() -> BinaryenType;
fn BinaryenLiteralInt32(x: i32) -> BinaryenLiteral;

86
src/backend/lower.rs Normal file
View file

@ -0,0 +1,86 @@
use crate::backend::binaryen;
use crate::ir::*;
use fxhash::FxHashMap;
pub(crate) fn generate_body(
body: &FunctionBody,
into_mod: &mut binaryen::Module,
) -> binaryen::Expression {
// For each block, generate an expr.
let mut block_exprs: FxHashMap<BlockId, binaryen::Expression> = FxHashMap::default();
let mut ctx = ElabCtx::default();
for block in body.blocks() {
let exprs = body[block]
.insts
.iter()
.map(|&inst| {
let inst = body.resolve_alias(inst);
elaborate_value(body, into_mod, &mut ctx, inst)
})
.collect::<Vec<_>>();
block_exprs.insert(block, binaryen::Expression::block(into_mod, &exprs[..]));
}
todo!()
}
#[derive(Clone, Debug, Default)]
struct ElabCtx {
value_to_expr: FxHashMap<Value, binaryen::Expression>,
block_params: FxHashMap<Value, LocalId>,
args: FxHashMap<Value, LocalId>,
}
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();
let mut ctx = ElabCtx::default();
// TODO
}
}
fn elaborate_value(
body: &FunctionBody,
into_mod: &binaryen::Module,
ctx: &mut ElabCtx,
value: Value,
) -> binaryen::Expression {
let value = body.resolve_alias(value);
if let Some(expr) = ctx.value_to_expr.get(&value) {
return *expr;
}
match &body[value] {
&ValueDef::BlockParam(block, idx) => {}
&ValueDef::Arg(idx) => {}
&ValueDef::PickOutput(value, idx) => {}
&ValueDef::Operator(op, ref args) => {}
&ValueDef::Alias(_) => unreachable!(),
&ValueDef::Placeholder => unreachable!(),
}
todo!()
}
pub(crate) fn create_new_func(
module: &Module,
sig: SignatureId,
body: &FunctionBody,
into_mod: &mut binaryen::Module,
body_expr: binaryen::Expression,
) {
// Create param types.
let sig = module.signature(sig);
let _func = binaryen::Function::create(
into_mod,
sig.params.iter().copied(),
sig.returns.iter().copied(),
body.locals.iter().copied(),
body_expr,
);
}

View file

@ -521,6 +521,12 @@ impl<'a> Module<'a> {
pub fn to_wasm_bytes(&self) -> Result<Vec<u8>> {
let mut binaryen_module = binaryen::Module::read(self.orig_bytes)?;
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);
}
for &func in &self.dirty_funcs {
if let Some(body) = self.func(func).body() {
let mut binaryen_func = binaryen_module.func(func);