WIP.
This commit is contained in:
parent
91a2c11f67
commit
c2db0ad4b9
|
@ -1,5 +1,7 @@
|
||||||
//! Binaryen bindings.
|
//! Binaryen bindings.
|
||||||
|
|
||||||
|
use crate::entity::EntityRef;
|
||||||
|
use crate::ir;
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use libc::{c_char, c_void};
|
use libc::{c_char, c_void};
|
||||||
|
@ -118,14 +120,14 @@ impl Function {
|
||||||
|
|
||||||
pub fn create(
|
pub fn create(
|
||||||
module: &mut Module,
|
module: &mut Module,
|
||||||
params: impl Iterator<Item = wasmparser::Type>,
|
params: impl Iterator<Item = ir::Type>,
|
||||||
results: impl Iterator<Item = wasmparser::Type>,
|
results: impl Iterator<Item = ir::Type>,
|
||||||
locals: impl Iterator<Item = wasmparser::Type>,
|
locals: impl Iterator<Item = ir::Type>,
|
||||||
body: Expression,
|
body: Expression,
|
||||||
) -> 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_binaryen()).collect();
|
||||||
let ptr = unsafe {
|
let ptr = unsafe {
|
||||||
BinaryenAddFunc(
|
BinaryenAddFunc(
|
||||||
module.0,
|
module.0,
|
||||||
|
@ -140,8 +142,8 @@ impl Function {
|
||||||
Function(module.0, ptr)
|
Function(module.0, ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_local(&mut self, ty: wasmparser::Type) -> usize {
|
pub fn add_local(&mut self, ty: ir::Type) -> usize {
|
||||||
(unsafe { BinaryenFunctionAddVar(self.1, Type::from(ty).to_kind()) }) as usize
|
(unsafe { BinaryenFunctionAddVar(self.1, Type::from(ty).to_binaryen()) }) as usize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +266,7 @@ pub enum Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Type {
|
impl Type {
|
||||||
fn from_kind(kind: BinaryenType) -> Option<Type> {
|
fn from_binaryen(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)
|
||||||
|
@ -281,7 +283,7 @@ impl Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn to_kind(&self) -> BinaryenType {
|
pub(crate) fn to_binaryen(&self) -> BinaryenType {
|
||||||
let tys = &*TYPE_IDS;
|
let tys = &*TYPE_IDS;
|
||||||
match self {
|
match self {
|
||||||
&Type::None => tys.none_t,
|
&Type::None => tys.none_t,
|
||||||
|
@ -294,21 +296,21 @@ impl Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<wasmparser::Type> for Type {
|
impl From<ir::Type> for Type {
|
||||||
fn from(ty: wasmparser::Type) -> Self {
|
fn from(ty: ir::Type) -> Self {
|
||||||
match ty {
|
match ty {
|
||||||
wasmparser::Type::I32 => Type::I32,
|
ir::Type::I32 => Type::I32,
|
||||||
wasmparser::Type::I64 => Type::I64,
|
ir::Type::I64 => Type::I64,
|
||||||
wasmparser::Type::F32 => Type::F32,
|
ir::Type::F32 => Type::F32,
|
||||||
wasmparser::Type::F64 => Type::F64,
|
ir::Type::F64 => Type::F64,
|
||||||
wasmparser::Type::V128 => Type::V128,
|
ir::Type::V128 => Type::V128,
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tys_to_binaryen(tys: impl Iterator<Item = wasmparser::Type>) -> BinaryenType {
|
pub fn tys_to_binaryen(tys: impl Iterator<Item = ir::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_binaryen()).collect();
|
||||||
unsafe { BinaryenTypeCreate(tys.as_ptr(), tys.len() as BinaryenIndex) }
|
unsafe { BinaryenTypeCreate(tys.as_ptr(), tys.len() as BinaryenIndex) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,7 +324,7 @@ fn name_to_string(name: *const c_char) -> Option<String> {
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
pub fn ty(&self) -> Type {
|
pub fn ty(&self) -> Type {
|
||||||
Type::from_kind(unsafe { BinaryenExpressionGetType(self.1) }).unwrap()
|
Type::from_binaryen(unsafe { BinaryenExpressionGetType(self.1) }).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deep_clone(&self) -> Self {
|
pub fn deep_clone(&self) -> Self {
|
||||||
|
@ -345,6 +347,44 @@ impl Expression {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn block_append_child(&mut self, child: Expression) {
|
||||||
|
unsafe {
|
||||||
|
BinaryenBlockAppendChild(self.1, child.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unreachable(module: &Module) -> Expression {
|
||||||
|
Expression(module.0, unsafe { BinaryenUnreachable(module.0) })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn local_get(module: &Module, local: ir::Local, ty: ir::Type) -> Expression {
|
||||||
|
let local = local.index() as BinaryenIndex;
|
||||||
|
let ty = Type::from(ty).to_binaryen();
|
||||||
|
let expr = unsafe { BinaryenLocalGet(module.0, local, ty) };
|
||||||
|
Expression(module.0, expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn local_set(module: &Module, local: ir::Local, value: Expression) -> Expression {
|
||||||
|
let local = local.index() as BinaryenIndex;
|
||||||
|
let expr = unsafe { BinaryenLocalSet(module.0, local, value.1) };
|
||||||
|
Expression(module.0, expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ret(module: &Module, values: &[Expression]) -> Expression {
|
||||||
|
let expr = if values.len() == 0 {
|
||||||
|
unsafe { BinaryenReturn(module.0, std::ptr::null()) }
|
||||||
|
} else if values.len() == 1 {
|
||||||
|
unsafe { BinaryenReturn(module.0, values[0].1) }
|
||||||
|
} else {
|
||||||
|
let exprs = values.iter().map(|e| e.1).collect::<Vec<_>>();
|
||||||
|
let tuple = unsafe {
|
||||||
|
BinaryenTupleMake(module.0, exprs.as_ptr(), exprs.len() as BinaryenIndex)
|
||||||
|
};
|
||||||
|
unsafe { BinaryenReturn(module.0, tuple) }
|
||||||
|
};
|
||||||
|
Expression(module.0, expr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
@ -387,13 +427,13 @@ lazy_static! {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UnaryOp {
|
impl UnaryOp {
|
||||||
fn from_kind(kind: u32) -> UnaryOp {
|
fn from_binaryen(kind: u32) -> UnaryOp {
|
||||||
UnaryOp::Other(kind)
|
UnaryOp::Other(kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BinaryOp {
|
impl BinaryOp {
|
||||||
fn from_kind(kind: u32) -> BinaryOp {
|
fn from_binaryen(kind: u32) -> BinaryOp {
|
||||||
let ids = &*OP_IDS;
|
let ids = &*OP_IDS;
|
||||||
if kind == ids.i32_add {
|
if kind == ids.i32_add {
|
||||||
BinaryOp::I32Add
|
BinaryOp::I32Add
|
||||||
|
@ -447,9 +487,6 @@ pub struct Relooper(BinaryenModule, BinaryenRelooper);
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct RelooperBlock(BinaryenRelooperBlock);
|
pub struct RelooperBlock(BinaryenRelooperBlock);
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct RelooperBlockWithSwitch(BinaryenRelooperBlock);
|
|
||||||
|
|
||||||
impl Relooper {
|
impl Relooper {
|
||||||
pub fn new(module: &Module) -> Relooper {
|
pub fn new(module: &Module) -> Relooper {
|
||||||
let ptr = unsafe { RelooperCreate(module.0) };
|
let ptr = unsafe { RelooperCreate(module.0) };
|
||||||
|
@ -467,12 +504,8 @@ impl Relooper {
|
||||||
RelooperBlock(unsafe { RelooperAddBlock(self.1, expr.1) })
|
RelooperBlock(unsafe { RelooperAddBlock(self.1, expr.1) })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_block_with_switch(
|
pub fn add_block_with_switch(&mut self, expr: Expression, sel: Expression) -> RelooperBlock {
|
||||||
&mut self,
|
RelooperBlock(unsafe { RelooperAddBlockWithSwitch(self.1, expr.1, sel.1) })
|
||||||
expr: Expression,
|
|
||||||
sel: Expression,
|
|
||||||
) -> RelooperBlockWithSwitch {
|
|
||||||
RelooperBlockWithSwitch(unsafe { RelooperAddBlockWithSwitch(self.1, expr.1, sel.1) })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,9 +521,7 @@ impl RelooperBlock {
|
||||||
RelooperAddBranch(self.0, to.0, std::ptr::null(), edge.1);
|
RelooperAddBranch(self.0, to.0, std::ptr::null(), edge.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl RelooperBlockWithSwitch {
|
|
||||||
pub fn switch(&self, to: RelooperBlock, edge: Expression, indices: &[BinaryenIndex]) {
|
pub fn switch(&self, to: RelooperBlock, edge: Expression, indices: &[BinaryenIndex]) {
|
||||||
unsafe {
|
unsafe {
|
||||||
RelooperAddBranchForSwitch(
|
RelooperAddBranchForSwitch(
|
||||||
|
@ -548,6 +579,10 @@ extern "C" {
|
||||||
fn BinaryenBlockGetNumChildren(ptr: BinaryenExpression) -> u32;
|
fn BinaryenBlockGetNumChildren(ptr: BinaryenExpression) -> u32;
|
||||||
fn BinaryenBlockGetChildAt(ptr: BinaryenExpression, index: u32) -> BinaryenExpression;
|
fn BinaryenBlockGetChildAt(ptr: BinaryenExpression, index: u32) -> BinaryenExpression;
|
||||||
fn BinaryenBlockGetName(ptr: BinaryenExpression) -> *const c_char;
|
fn BinaryenBlockGetName(ptr: BinaryenExpression) -> *const c_char;
|
||||||
|
fn BinaryenBlockAppendChild(
|
||||||
|
ptr: BinaryenExpression,
|
||||||
|
child: BinaryenExpression,
|
||||||
|
) -> BinaryenIndex;
|
||||||
|
|
||||||
fn BinaryenLoopGetBody(ptr: BinaryenExpression) -> BinaryenExpression;
|
fn BinaryenLoopGetBody(ptr: BinaryenExpression) -> BinaryenExpression;
|
||||||
fn BinaryenLoopGetName(ptr: BinaryenExpression) -> *const c_char;
|
fn BinaryenLoopGetName(ptr: BinaryenExpression) -> *const c_char;
|
||||||
|
@ -654,6 +689,12 @@ extern "C" {
|
||||||
fn BinaryenShrSInt32() -> u32;
|
fn BinaryenShrSInt32() -> u32;
|
||||||
|
|
||||||
fn BinaryenConst(module: BinaryenModule, lit: BinaryenLiteral) -> BinaryenExpression;
|
fn BinaryenConst(module: BinaryenModule, lit: BinaryenLiteral) -> BinaryenExpression;
|
||||||
|
fn BinaryenUnreachable(module: BinaryenModule) -> BinaryenExpression;
|
||||||
|
fn BinaryenLocalGet(
|
||||||
|
module: BinaryenModule,
|
||||||
|
local: BinaryenIndex,
|
||||||
|
ty: BinaryenType,
|
||||||
|
) -> BinaryenExpression;
|
||||||
fn BinaryenLocalSet(
|
fn BinaryenLocalSet(
|
||||||
module: BinaryenModule,
|
module: BinaryenModule,
|
||||||
index: u32,
|
index: u32,
|
||||||
|
@ -666,6 +707,12 @@ extern "C" {
|
||||||
n_children: BinaryenIndex,
|
n_children: BinaryenIndex,
|
||||||
ty: BinaryenType,
|
ty: BinaryenType,
|
||||||
) -> BinaryenExpression;
|
) -> BinaryenExpression;
|
||||||
|
fn BinaryenTupleMake(
|
||||||
|
module: BinaryenModule,
|
||||||
|
operands: *const BinaryenExpression,
|
||||||
|
n_operands: BinaryenIndex,
|
||||||
|
) -> BinaryenExpression;
|
||||||
|
fn BinaryenReturn(module: BinaryenModule, expr: BinaryenExpression) -> BinaryenExpression;
|
||||||
|
|
||||||
fn BinaryenAddFunc(
|
fn BinaryenAddFunc(
|
||||||
module: BinaryenModule,
|
module: BinaryenModule,
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
/*
|
|
||||||
use crate::backend::binaryen;
|
use crate::backend::binaryen;
|
||||||
use crate::entity::EntityRef;
|
use crate::entity::EntityRef;
|
||||||
use crate::ir::*;
|
use crate::ir::*;
|
||||||
use crate::Operator;
|
use crate::Operator;
|
||||||
use fxhash::FxHashMap;
|
use fxhash::FxHashMap;
|
||||||
use wasmparser::Type;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
/// Creates a body expression for a function. Returns that expression,
|
/// Creates a body expression for a function. Returns that expression,
|
||||||
/// and new locals (as their types) that were created as temporaries
|
/// and new locals (as their types) that were created as temporaries
|
||||||
|
@ -16,36 +15,133 @@ pub(crate) fn generate_body(
|
||||||
let mut ctx = ElabCtx::new(body, into_mod);
|
let mut ctx = ElabCtx::new(body, into_mod);
|
||||||
|
|
||||||
// For each block, generate an expr.
|
// For each block, generate an expr.
|
||||||
let mut block_exprs: FxHashMap<Block, binaryen::Expression> = FxHashMap::default();
|
let mut block_exprs: BTreeMap<Block, binaryen::Expression> = BTreeMap::default();
|
||||||
for (block_id, block) in body.blocks.entries() {
|
for (block_id, block) in body.blocks.entries() {
|
||||||
let exprs = block
|
let mut exprs = vec![];
|
||||||
.insts
|
for (i, (ty, _param)) in block.params.iter().enumerate() {
|
||||||
.iter()
|
let val = binaryen::Expression::local_get(
|
||||||
.flat_map(|&inst| {
|
into_mod,
|
||||||
let inst = body.resolve_alias(inst);
|
*ctx.block_param_next_locals.get(&(block_id, i)).unwrap(),
|
||||||
ctx.elaborate_value(into_mod, inst)
|
*ty,
|
||||||
})
|
);
|
||||||
.collect::<Vec<binaryen::Expression>>();
|
let set = binaryen::Expression::local_set(
|
||||||
|
into_mod,
|
||||||
|
*ctx.block_param_locals.get(&(block_id, i)).unwrap(),
|
||||||
|
val,
|
||||||
|
);
|
||||||
|
exprs.push(set);
|
||||||
|
}
|
||||||
|
for &inst in &block.insts {
|
||||||
|
let inst = body.resolve_alias(inst);
|
||||||
|
if let Some(expr) = ctx.elaborate_value(into_mod, inst) {
|
||||||
|
exprs.push(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
block_exprs.insert(block_id, binaryen::Expression::block(into_mod, &exprs[..]));
|
block_exprs.insert(block_id, binaryen::Expression::block(into_mod, &exprs[..]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Combine blocks into a single body expression, using the
|
// Combine blocks into a single body expression, using the
|
||||||
// relooper/stackifier support built into Binaryen.
|
// relooper/stackifier support built into Binaryen.
|
||||||
let mut relooper = binaryen::Relooper::new(into_mod);
|
let mut relooper = binaryen::Relooper::new(into_mod);
|
||||||
let mut entry = None;
|
|
||||||
let mut relooper_blocks: FxHashMap<Block, binaryen::RelooperBlock> = FxHashMap::default();
|
// Create the blocks.
|
||||||
for (block_id, block_expr) in block_exprs {}
|
let mut relooper_blocks: FxHashMap<Block, (binaryen::Expression, binaryen::RelooperBlock)> =
|
||||||
|
FxHashMap::default();
|
||||||
|
for (block_id, block_expr) in &mut block_exprs {
|
||||||
|
let block = match &body.blocks[*block_id].terminator {
|
||||||
|
&Terminator::Select { value, .. } => {
|
||||||
|
let sel = ctx.get_val(value, into_mod);
|
||||||
|
relooper.add_block_with_switch(block_expr.clone(), sel)
|
||||||
|
}
|
||||||
|
_ => relooper.add_block(block_expr.clone()),
|
||||||
|
};
|
||||||
|
relooper_blocks.insert(*block_id, (block_expr.clone(), block));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add edges.
|
||||||
|
for &block_id in block_exprs.keys() {
|
||||||
|
let (mut block_expr, block) = relooper_blocks.get(&block_id).unwrap().clone();
|
||||||
|
match &body.blocks[block_id].terminator {
|
||||||
|
&Terminator::Br { ref target } => {
|
||||||
|
let (target_block, edge) = build_ssa_edge(&ctx, target, &relooper_blocks, into_mod);
|
||||||
|
block.branch(target_block, edge);
|
||||||
|
}
|
||||||
|
&Terminator::CondBr {
|
||||||
|
cond,
|
||||||
|
ref if_true,
|
||||||
|
ref if_false,
|
||||||
|
} => {
|
||||||
|
let (true_block, true_edge) =
|
||||||
|
build_ssa_edge(&ctx, if_true, &relooper_blocks, into_mod);
|
||||||
|
let (false_block, false_edge) =
|
||||||
|
build_ssa_edge(&ctx, if_false, &relooper_blocks, into_mod);
|
||||||
|
let cond = ctx.get_val(cond, into_mod);
|
||||||
|
block.cond_branch(true_block, cond, true_edge);
|
||||||
|
block.branch(false_block, false_edge);
|
||||||
|
}
|
||||||
|
&Terminator::Select {
|
||||||
|
value: _,
|
||||||
|
ref targets,
|
||||||
|
ref default,
|
||||||
|
} => {
|
||||||
|
for (i, target) in targets.iter().enumerate() {
|
||||||
|
let (target_block, edge) =
|
||||||
|
build_ssa_edge(&ctx, target, &relooper_blocks, into_mod);
|
||||||
|
block.switch(target_block, edge, &[i as u32]);
|
||||||
|
}
|
||||||
|
let (target_block, edge) =
|
||||||
|
build_ssa_edge(&ctx, default, &relooper_blocks, into_mod);
|
||||||
|
block.switch(target_block, edge, &[]);
|
||||||
|
}
|
||||||
|
&Terminator::Return { ref values } => {
|
||||||
|
let values = values
|
||||||
|
.iter()
|
||||||
|
.map(|value| ctx.get_val(*value, into_mod))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
block_expr.block_append_child(binaryen::Expression::ret(into_mod, &values[..]));
|
||||||
|
}
|
||||||
|
&Terminator::Unreachable | &Terminator::None => {
|
||||||
|
block_expr.block_append_child(binaryen::Expression::unreachable(into_mod));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let index_var = ctx.new_local(Type::I32);
|
let index_var = ctx.new_local(Type::I32);
|
||||||
let expr = relooper.construct(entry.unwrap(), index_var.index());
|
let entry = relooper_blocks.get(&ctx.body.entry).unwrap().1.clone();
|
||||||
|
let expr = relooper.construct(entry, index_var.index());
|
||||||
(ctx.new_locals, expr)
|
(ctx.new_locals, expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_ssa_edge(
|
||||||
|
ctx: &ElabCtx<'_>,
|
||||||
|
target: &BlockTarget,
|
||||||
|
blocks: &FxHashMap<Block, (binaryen::Expression, binaryen::RelooperBlock)>,
|
||||||
|
into_mod: &mut binaryen::Module,
|
||||||
|
) -> (binaryen::RelooperBlock, binaryen::Expression) {
|
||||||
|
// Copy all block args to the "next" locals. Build an edge block
|
||||||
|
// with these get-set pairs.
|
||||||
|
let mut sets = vec![];
|
||||||
|
for (i, arg) in target.args.iter().enumerate() {
|
||||||
|
let value = ctx.get_val(*arg, into_mod);
|
||||||
|
let set = binaryen::Expression::local_set(
|
||||||
|
into_mod,
|
||||||
|
*ctx.block_param_next_locals.get(&(target.block, i)).unwrap(),
|
||||||
|
value,
|
||||||
|
);
|
||||||
|
sets.push(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
let edge_block = binaryen::Expression::block(into_mod, &sets[..]);
|
||||||
|
let block = blocks.get(&target.block).unwrap().1.clone();
|
||||||
|
(block, edge_block)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct ElabCtx<'a> {
|
struct ElabCtx<'a> {
|
||||||
body: &'a FunctionBody,
|
body: &'a FunctionBody,
|
||||||
op_result_locals: FxHashMap<(Value, usize), Local>,
|
op_result_locals: FxHashMap<(Value, usize), Local>,
|
||||||
block_param_locals: FxHashMap<(Block, usize), Local>,
|
block_param_locals: FxHashMap<(Block, usize), Local>,
|
||||||
|
block_param_next_locals: FxHashMap<(Block, usize), Local>,
|
||||||
new_locals: Vec<Type>,
|
new_locals: Vec<Type>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +189,6 @@ impl<'a> ElabCtx<'a> {
|
||||||
|
|
||||||
fn get_val_local(&self, value: Value) -> Local {
|
fn get_val_local(&self, value: Value) -> Local {
|
||||||
match &self.body.values[value] {
|
match &self.body.values[value] {
|
||||||
&ValueDef::Arg(idx, _) => Local::new(idx),
|
|
||||||
&ValueDef::BlockParam(block, idx, _) => {
|
&ValueDef::BlockParam(block, idx, _) => {
|
||||||
self.block_param_locals.get(&(block, idx)).copied().unwrap()
|
self.block_param_locals.get(&(block, idx)).copied().unwrap()
|
||||||
}
|
}
|
||||||
|
@ -102,10 +197,15 @@ impl<'a> ElabCtx<'a> {
|
||||||
self.op_result_locals.get(&(value, idx)).copied().unwrap()
|
self.op_result_locals.get(&(value, idx)).copied().unwrap()
|
||||||
}
|
}
|
||||||
&ValueDef::Alias(val) => self.get_val_local(val),
|
&ValueDef::Alias(val) => self.get_val_local(val),
|
||||||
&ValueDef::Placeholder(_) => unreachable!(),
|
&ValueDef::Placeholder(_) | &ValueDef::None => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_val(&self, value: Value, into_mod: &mut binaryen::Module) -> binaryen::Expression {
|
||||||
|
let local = self.get_val_local(value);
|
||||||
|
binaryen::Expression::local_get(into_mod, local, self.body.values[value].ty().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
fn new_local(&mut self, ty: Type) -> Local {
|
fn new_local(&mut self, ty: Type) -> Local {
|
||||||
let index = Local::new(self.body.locals.len() + self.new_locals.len());
|
let index = Local::new(self.body.locals.len() + self.new_locals.len());
|
||||||
self.new_locals.push(ty);
|
self.new_locals.push(ty);
|
||||||
|
@ -152,4 +252,3 @@ pub(crate) fn create_new_func(
|
||||||
body_expr,
|
body_expr,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
|
@ -13,6 +13,17 @@ pub enum ValueDef {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValueDef {
|
impl ValueDef {
|
||||||
|
pub fn ty(&self) -> Option<Type> {
|
||||||
|
match self {
|
||||||
|
&ValueDef::BlockParam(_, _, ty) => Some(ty),
|
||||||
|
&ValueDef::Operator(_, _, ref tys) if tys.len() == 0 => None,
|
||||||
|
&ValueDef::Operator(_, _, ref tys) if tys.len() == 1 => Some(tys[0]),
|
||||||
|
&ValueDef::PickOutput(_, _, ty) => Some(ty),
|
||||||
|
&ValueDef::Placeholder(ty) => Some(ty),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn visit_uses<F: FnMut(Value)>(&self, mut f: F) {
|
pub fn visit_uses<F: FnMut(Value)>(&self, mut f: F) {
|
||||||
match self {
|
match self {
|
||||||
&ValueDef::BlockParam { .. } => {}
|
&ValueDef::BlockParam { .. } => {}
|
||||||
|
|
Loading…
Reference in a new issue