WIP.
This commit is contained in:
parent
589729566f
commit
1da150823d
|
@ -14,8 +14,8 @@ pub struct Expression(BinaryenModule, BinaryenExpression);
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct Export(BinaryenModule, BinaryenExport);
|
pub struct Export(BinaryenModule, BinaryenExport);
|
||||||
|
|
||||||
type BinaryenIndex = u32;
|
pub type BinaryenIndex = u32;
|
||||||
type BinaryenType = usize;
|
pub type BinaryenType = usize;
|
||||||
|
|
||||||
impl Module {
|
impl Module {
|
||||||
pub fn read(data: &[u8]) -> Result<Module> {
|
pub fn read(data: &[u8]) -> Result<Module> {
|
||||||
|
@ -423,6 +423,8 @@ pub type BinaryenModule = *const c_void;
|
||||||
type BinaryenFunction = *const c_void;
|
type BinaryenFunction = *const c_void;
|
||||||
type BinaryenExpression = *const c_void;
|
type BinaryenExpression = *const c_void;
|
||||||
type BinaryenExport = *const c_void;
|
type BinaryenExport = *const c_void;
|
||||||
|
type BinaryenRelooper = *const c_void;
|
||||||
|
type BinaryenRelooperBlock = *const c_void;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct BinaryenModuleAllocateAndWriteResult {
|
struct BinaryenModuleAllocateAndWriteResult {
|
||||||
|
@ -440,6 +442,74 @@ impl Drop for BinaryenModuleAllocateAndWriteResult {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Relooper(BinaryenModule, BinaryenRelooper);
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct RelooperBlock(BinaryenRelooperBlock);
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct RelooperBlockWithSwitch(BinaryenRelooperBlock);
|
||||||
|
|
||||||
|
impl Relooper {
|
||||||
|
pub fn new(module: &Module) -> Relooper {
|
||||||
|
let ptr = unsafe { RelooperCreate(module.0) };
|
||||||
|
Relooper(module.0, ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn construct(self, entry: RelooperBlock, index_var: usize) -> Expression {
|
||||||
|
let module = self.0;
|
||||||
|
let expr = unsafe { RelooperRenderAndDispose(self.1, entry.0, index_var as BinaryenIndex) };
|
||||||
|
std::mem::forget(self);
|
||||||
|
Expression(module, expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_block(&mut self, expr: Expression) -> RelooperBlock {
|
||||||
|
RelooperBlock(unsafe { RelooperAddBlock(self.1, expr.1) })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_block_with_switch(
|
||||||
|
&mut self,
|
||||||
|
expr: Expression,
|
||||||
|
sel: Expression,
|
||||||
|
) -> RelooperBlockWithSwitch {
|
||||||
|
RelooperBlockWithSwitch(unsafe { RelooperAddBlockWithSwitch(self.1, expr.1, sel.1) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelooperBlock {
|
||||||
|
pub fn cond_branch(&self, to: RelooperBlock, cond: Expression, edge: Expression) {
|
||||||
|
unsafe {
|
||||||
|
RelooperAddBranch(self.0, to.0, cond.1, edge.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn branch(&self, to: RelooperBlock, edge: Expression) {
|
||||||
|
unsafe {
|
||||||
|
RelooperAddBranch(self.0, to.0, std::ptr::null(), edge.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelooperBlockWithSwitch {
|
||||||
|
pub fn switch(&self, to: RelooperBlock, edge: Expression, indices: &[BinaryenIndex]) {
|
||||||
|
unsafe {
|
||||||
|
RelooperAddBranchForSwitch(
|
||||||
|
self.0,
|
||||||
|
to.0,
|
||||||
|
indices.as_ptr(),
|
||||||
|
indices.len() as BinaryenIndex,
|
||||||
|
edge.1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Relooper {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
panic!("Relooper dropped without constructing/disposing");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[link(name = "binaryen")]
|
#[link(name = "binaryen")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn BinaryenModuleRead(data: *const u8, len: usize) -> BinaryenModule;
|
fn BinaryenModuleRead(data: *const u8, len: usize) -> BinaryenModule;
|
||||||
|
@ -613,6 +683,32 @@ extern "C" {
|
||||||
fn BinaryenLiteralInt64(x: i64) -> BinaryenLiteral;
|
fn BinaryenLiteralInt64(x: i64) -> BinaryenLiteral;
|
||||||
fn BinaryenLiteralFloat32Bits(x: i32) -> BinaryenLiteral;
|
fn BinaryenLiteralFloat32Bits(x: i32) -> BinaryenLiteral;
|
||||||
fn BinaryenLiteralFloat64Bits(x: i64) -> BinaryenLiteral;
|
fn BinaryenLiteralFloat64Bits(x: i64) -> BinaryenLiteral;
|
||||||
|
|
||||||
|
fn RelooperCreate(module: BinaryenModule) -> BinaryenRelooper;
|
||||||
|
fn RelooperRenderAndDispose(
|
||||||
|
r: BinaryenRelooper,
|
||||||
|
entry: BinaryenRelooperBlock,
|
||||||
|
labelVar: BinaryenIndex,
|
||||||
|
) -> BinaryenExpression;
|
||||||
|
fn RelooperAddBlock(r: BinaryenRelooper, code: BinaryenExpression) -> BinaryenRelooperBlock;
|
||||||
|
fn RelooperAddBranch(
|
||||||
|
from: BinaryenRelooperBlock,
|
||||||
|
to: BinaryenRelooperBlock,
|
||||||
|
cond: BinaryenExpression,
|
||||||
|
edge_code: BinaryenExpression,
|
||||||
|
);
|
||||||
|
fn RelooperAddBlockWithSwitch(
|
||||||
|
r: BinaryenRelooper,
|
||||||
|
code: BinaryenExpression,
|
||||||
|
selector: BinaryenExpression,
|
||||||
|
) -> BinaryenRelooperBlock;
|
||||||
|
fn RelooperAddBranchForSwitch(
|
||||||
|
from: BinaryenRelooperBlock,
|
||||||
|
to: BinaryenRelooperBlock,
|
||||||
|
indices: *const BinaryenIndex,
|
||||||
|
n_indices: BinaryenIndex,
|
||||||
|
edge_code: BinaryenExpression,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::backend::binaryen;
|
use crate::backend::binaryen;
|
||||||
use crate::ir::*;
|
use crate::ir::*;
|
||||||
|
use crate::Operator;
|
||||||
use fxhash::FxHashMap;
|
use fxhash::FxHashMap;
|
||||||
use wasmparser::Type;
|
use wasmparser::Type;
|
||||||
|
|
||||||
|
@ -10,76 +11,148 @@ pub(crate) fn generate_body(
|
||||||
body: &FunctionBody,
|
body: &FunctionBody,
|
||||||
into_mod: &mut binaryen::Module,
|
into_mod: &mut binaryen::Module,
|
||||||
) -> (Vec<Type>, binaryen::Expression) {
|
) -> (Vec<Type>, binaryen::Expression) {
|
||||||
|
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<BlockId, binaryen::Expression> = FxHashMap::default();
|
let mut block_exprs: FxHashMap<BlockId, binaryen::Expression> = FxHashMap::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
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&inst| {
|
.flat_map(|&inst| {
|
||||||
let inst = body.resolve_alias(inst);
|
let inst = body.resolve_alias(inst);
|
||||||
elaborate_value(body, into_mod, &mut ctx, inst)
|
ctx.elaborate_value(into_mod, inst)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<binaryen::Expression>>();
|
||||||
block_exprs.insert(block, binaryen::Expression::block(into_mod, &exprs[..]));
|
block_exprs.insert(block, binaryen::Expression::block(into_mod, &exprs[..]));
|
||||||
}
|
}
|
||||||
|
|
||||||
todo!()
|
// Combine blocks into a single body expression, using the
|
||||||
|
// relooper/stackifier support built into Binaryen.
|
||||||
|
let mut relooper = binaryen::Relooper::new(into_mod);
|
||||||
|
let mut entry = None;
|
||||||
|
let mut relooper_blocks: FxHashMap<BlockId, binaryen::RelooperBlock> = FxHashMap::default();
|
||||||
|
for (block_id, block_expr) in block_exprs {}
|
||||||
|
|
||||||
|
let index_var = ctx.new_local(Type::I32);
|
||||||
|
let expr = relooper.construct(entry.unwrap(), index_var as usize);
|
||||||
|
(ctx.new_locals, expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct ElabCtx {
|
struct ElabCtx<'a> {
|
||||||
value_to_expr: FxHashMap<Value, binaryen::Expression>,
|
body: &'a FunctionBody,
|
||||||
block_params: FxHashMap<(Block, usize), LocalId>,
|
op_result_locals: FxHashMap<(Value, usize), LocalId>,
|
||||||
|
block_param_locals: FxHashMap<(BlockId, usize), LocalId>,
|
||||||
new_locals: Vec<Type>,
|
new_locals: Vec<Type>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ElabCtx {
|
impl<'a> ElabCtx<'a> {
|
||||||
fn new(body: &FunctionBody, into_mod: &mut binaryen::Module) -> ElabCtx {
|
fn new(body: &'a FunctionBody, into_mod: &mut binaryen::Module) -> ElabCtx<'a> {
|
||||||
// Create locals for each blockparam.
|
// Create locals for each blockparam.
|
||||||
let mut block_params = FxHashMap::default();
|
let mut this = ElabCtx {
|
||||||
let mut next_local = body.locals.len() as LocalId;
|
body,
|
||||||
let mut new_locals = vec![];
|
op_result_locals: FxHashMap::default(),
|
||||||
|
block_param_locals: FxHashMap::default(),
|
||||||
|
new_locals: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
for block in body.blocks() {
|
for block in body.blocks() {
|
||||||
for &(ty, param) in &body[block].params {
|
for &(ty, param) in &body[block].params {}
|
||||||
let new_local = next_local;
|
}
|
||||||
next_local += 1;
|
|
||||||
block_params.insert((ty, param), new_local);
|
// Create locals for each Operator value and each blockparam.
|
||||||
new_locals.push(ty);
|
for (value, def) in body.values() {
|
||||||
|
match def {
|
||||||
|
&ValueDef::Operator(_, _, ref tys) => {
|
||||||
|
for (i, ty) in tys.iter().copied().enumerate() {
|
||||||
|
let local = this.new_local(ty);
|
||||||
|
this.op_result_locals.insert((value, i), local);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&ValueDef::BlockParam(block, index, ty) => {
|
||||||
|
let local = this.new_local(ty);
|
||||||
|
this.block_param_locals.insert((block, index), local);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElabCtx {
|
this
|
||||||
value_to_expr: FxHashMap::default(),
|
|
||||||
block_params,
|
|
||||||
new_locals,
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn elaborate_value(
|
fn elaborate_value(
|
||||||
body: &FunctionBody,
|
&mut self,
|
||||||
into_mod: &binaryen::Module,
|
into_mod: &binaryen::Module,
|
||||||
ctx: &mut ElabCtx,
|
|
||||||
value: Value,
|
value: Value,
|
||||||
) -> binaryen::Expression {
|
) -> Option<binaryen::Expression> {
|
||||||
let value = body.resolve_alias(value);
|
let value = self.body.resolve_alias(value);
|
||||||
if let Some(expr) = ctx.value_to_expr.get(&value) {
|
|
||||||
return *expr;
|
match &self.body[value] {
|
||||||
|
&ValueDef::Operator(op, ref args, ref tys) => {
|
||||||
|
// Get expressions for each arg.
|
||||||
|
let args = args.iter().map(|&arg| self.get_val_local(arg));
|
||||||
|
// Create `get_local` expressions for each arg.
|
||||||
|
let binaryen_args = args
|
||||||
|
.map(|arg_local| into_mod.expr_local_get(arg_local, self.local_ty(arg_local)))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
// Create operator.
|
||||||
|
let expr = self.create_binaryen_op(op, binaryen_args, tys);
|
||||||
|
|
||||||
|
// Set local(s) as appropriate.
|
||||||
|
if tys.len() == 0 {
|
||||||
|
// Nothing. Create a `drop` expr that wraps the actual operator.
|
||||||
|
Some(into_mod.expr_drop(expr))
|
||||||
|
} else if tys.len() == 1 {
|
||||||
|
// Set value directly.
|
||||||
|
let local = self.get_val_local(value);
|
||||||
|
Some(into_mod.expr_local_set(local, expr))
|
||||||
|
} else {
|
||||||
|
todo!("support multivalue")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match &body[value] {
|
fn get_val_local(&self, value: Value) -> LocalId {
|
||||||
&ValueDef::BlockParam(block, idx) => {}
|
match &self.body[value] {
|
||||||
&ValueDef::Arg(idx) => {}
|
&ValueDef::Arg(idx, _) => idx as LocalId,
|
||||||
&ValueDef::PickOutput(value, idx) => {}
|
&ValueDef::BlockParam(block, idx, _) => {
|
||||||
&ValueDef::Operator(op, ref args) => {}
|
self.block_param_locals.get(&(block, idx)).copied().unwrap()
|
||||||
|
}
|
||||||
&ValueDef::Alias(_) => unreachable!(),
|
&ValueDef::Operator(..) => self.op_result_locals.get(&(value, 0)).copied().unwrap(),
|
||||||
&ValueDef::Placeholder => unreachable!(),
|
&ValueDef::PickOutput(value, idx, _) => {
|
||||||
|
self.op_result_locals.get(&(value, idx)).copied().unwrap()
|
||||||
|
}
|
||||||
|
&ValueDef::Alias(val) => self.get_val_local(val),
|
||||||
|
&ValueDef::Placeholder(_) => unreachable!(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn new_local(&mut self, ty: Type) -> LocalId {
|
||||||
|
let index = (self.body.locals.len() + self.new_locals.len()) as LocalId;
|
||||||
|
self.new_locals.push(ty);
|
||||||
|
index
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_binaryen_op(
|
||||||
|
&mut self,
|
||||||
|
op: Operator,
|
||||||
|
args: Vec<binaryen::Expression>,
|
||||||
|
tys: &[Type],
|
||||||
|
) -> binaryen::Expression {
|
||||||
todo!()
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn local_ty(&self, local: LocalId) -> Type {
|
||||||
|
let index = local as usize;
|
||||||
|
self.body
|
||||||
|
.locals
|
||||||
|
.get(index)
|
||||||
|
.copied()
|
||||||
|
.unwrap_or_else(|| self.new_locals[index - self.body.locals.len()])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn create_new_func(
|
pub(crate) fn create_new_func(
|
||||||
|
|
|
@ -128,7 +128,7 @@ fn parse_body<'a>(
|
||||||
|
|
||||||
for (arg_idx, &arg_ty) in module.signature(my_sig).params.iter().enumerate() {
|
for (arg_idx, &arg_ty) in module.signature(my_sig).params.iter().enumerate() {
|
||||||
let local_idx = arg_idx as LocalId;
|
let local_idx = arg_idx as LocalId;
|
||||||
let value = builder.body.add_value(ValueDef::Arg(arg_idx), vec![arg_ty]);
|
let value = builder.body.add_value(ValueDef::Arg(arg_idx, arg_ty));
|
||||||
trace!("defining local {} to value {}", local_idx, value);
|
trace!("defining local {} to value {}", local_idx, value);
|
||||||
builder.locals.declare(local_idx, arg_ty);
|
builder.locals.declare(local_idx, arg_ty);
|
||||||
builder.locals.set(local_idx, value);
|
builder.locals.set(local_idx, value);
|
||||||
|
@ -155,7 +155,7 @@ fn parse_body<'a>(
|
||||||
assert!(builder.locals.is_sealed(block));
|
assert!(builder.locals.is_sealed(block));
|
||||||
}
|
}
|
||||||
for value in &builder.body.values {
|
for value in &builder.body.values {
|
||||||
assert!(value != &ValueDef::Placeholder);
|
assert!(!matches!(value, &ValueDef::Placeholder(_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!("Final function body:{:?}", ret);
|
trace!("Final function body:{:?}", ret);
|
||||||
|
@ -291,32 +291,30 @@ impl LocalTracker {
|
||||||
|
|
||||||
fn create_default_value(&mut self, body: &mut FunctionBody, ty: Type) -> Value {
|
fn create_default_value(&mut self, body: &mut FunctionBody, ty: Type) -> Value {
|
||||||
match ty {
|
match ty {
|
||||||
Type::I32 => body.add_value(
|
Type::I32 => body.add_value(ValueDef::Operator(
|
||||||
ValueDef::Operator(Operator::I32Const { value: 0 }, vec![]),
|
Operator::I32Const { value: 0 },
|
||||||
|
vec![],
|
||||||
vec![ty],
|
vec![ty],
|
||||||
),
|
)),
|
||||||
Type::I64 => body.add_value(
|
Type::I64 => body.add_value(ValueDef::Operator(
|
||||||
ValueDef::Operator(Operator::I64Const { value: 0 }, vec![]),
|
Operator::I64Const { value: 0 },
|
||||||
|
vec![],
|
||||||
vec![ty],
|
vec![ty],
|
||||||
),
|
)),
|
||||||
Type::F32 => body.add_value(
|
Type::F32 => body.add_value(ValueDef::Operator(
|
||||||
ValueDef::Operator(
|
|
||||||
Operator::F32Const {
|
Operator::F32Const {
|
||||||
value: Ieee32::from_bits(0),
|
value: Ieee32::from_bits(0),
|
||||||
},
|
},
|
||||||
vec![],
|
vec![],
|
||||||
),
|
|
||||||
vec![ty],
|
vec![ty],
|
||||||
),
|
)),
|
||||||
Type::F64 => body.add_value(
|
Type::F64 => body.add_value(ValueDef::Operator(
|
||||||
ValueDef::Operator(
|
|
||||||
Operator::F64Const {
|
Operator::F64Const {
|
||||||
value: Ieee64::from_bits(0),
|
value: Ieee64::from_bits(0),
|
||||||
},
|
},
|
||||||
vec![],
|
vec![],
|
||||||
),
|
|
||||||
vec![ty],
|
vec![ty],
|
||||||
),
|
)),
|
||||||
_ => todo!("unsupported type: {:?}", ty),
|
_ => todo!("unsupported type: {:?}", ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1180,7 +1178,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
|
|
||||||
let value = self
|
let value = self
|
||||||
.body
|
.body
|
||||||
.add_value(ValueDef::Operator(op, input_operands), outputs.clone());
|
.add_value(ValueDef::Operator(op, input_operands, outputs.clone()));
|
||||||
log::trace!(" -> value: {:?}", value);
|
log::trace!(" -> value: {:?}", value);
|
||||||
|
|
||||||
if let Some(block) = self.cur_block {
|
if let Some(block) = self.cur_block {
|
||||||
|
@ -1194,7 +1192,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
for (i, output_ty) in outputs.into_iter().enumerate() {
|
for (i, output_ty) in outputs.into_iter().enumerate() {
|
||||||
let pick = self
|
let pick = self
|
||||||
.body
|
.body
|
||||||
.add_value(ValueDef::PickOutput(value, i), vec![output_ty]);
|
.add_value(ValueDef::PickOutput(value, i, output_ty));
|
||||||
self.op_stack.push((output_ty, pick));
|
self.op_stack.push((output_ty, pick));
|
||||||
log::trace!(" -> pick {}: {:?} ty {:?}", i, pick, output_ty);
|
log::trace!(" -> pick {}: {:?} ty {:?}", i, pick, output_ty);
|
||||||
}
|
}
|
||||||
|
|
41
src/ir.rs
41
src/ir.rs
|
@ -110,9 +110,6 @@ pub struct FunctionBody {
|
||||||
pub blocks: Vec<Block>,
|
pub blocks: Vec<Block>,
|
||||||
/// Value definitions, indexed by `Value`.
|
/// Value definitions, indexed by `Value`.
|
||||||
pub values: Vec<ValueDef>,
|
pub values: Vec<ValueDef>,
|
||||||
/// 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 {
|
impl FunctionBody {
|
||||||
|
@ -134,12 +131,11 @@ impl FunctionBody {
|
||||||
log::trace!("add_edge: from {} to {}", from, to);
|
log::trace!("add_edge: from {} to {}", from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_value(&mut self, value: ValueDef, tys: Vec<Type>) -> Value {
|
pub fn add_value(&mut self, value: ValueDef) -> Value {
|
||||||
log::trace!("add_value: def {:?} ty {:?}", value, tys);
|
log::trace!("add_value: def {:?}", value);
|
||||||
let id = Value(self.values.len() as u32);
|
let id = Value(self.values.len() as u32);
|
||||||
log::trace!(" -> value {:?}", id);
|
log::trace!(" -> value {:?}", id);
|
||||||
self.values.push(value.clone());
|
self.values.push(value.clone());
|
||||||
self.types.push(tys);
|
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,30 +162,31 @@ impl FunctionBody {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_mutable_inst(&mut self, tys: Vec<Type>, def: ValueDef) -> Value {
|
pub fn add_mutable_inst(&mut self, def: ValueDef) -> Value {
|
||||||
let value = Value(self.values.len() as u32);
|
let value = Value(self.values.len() as u32);
|
||||||
self.types.push(tys);
|
|
||||||
self.values.push(def);
|
self.values.push(def);
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_blockparam(&mut self, block: BlockId, ty: Type) -> Value {
|
pub fn add_blockparam(&mut self, block: BlockId, ty: Type) -> Value {
|
||||||
let index = self.blocks[block].params.len();
|
let index = self.blocks[block].params.len();
|
||||||
let value = self.add_value(ValueDef::BlockParam(block, index), vec![ty]);
|
let value = self.add_value(ValueDef::BlockParam(block, index, ty));
|
||||||
self.blocks[block].params.push((ty, value));
|
self.blocks[block].params.push((ty, value));
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_placeholder(&mut self, ty: Type) -> Value {
|
pub fn add_placeholder(&mut self, ty: Type) -> Value {
|
||||||
self.add_mutable_inst(vec![ty], ValueDef::Placeholder)
|
self.add_mutable_inst(ValueDef::Placeholder(ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn replace_placeholder_with_blockparam(&mut self, block: BlockId, value: Value) {
|
pub fn replace_placeholder_with_blockparam(&mut self, block: BlockId, value: Value) {
|
||||||
assert!(self.values[value.index()] == ValueDef::Placeholder);
|
|
||||||
let ty = self.types[value.index()].get(0).cloned().unwrap();
|
|
||||||
let index = self.blocks[block].params.len();
|
let index = self.blocks[block].params.len();
|
||||||
|
let ty = match &self.values[value.index()] {
|
||||||
|
&ValueDef::Placeholder(ty) => ty,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
self.blocks[block].params.push((ty, value));
|
self.blocks[block].params.push((ty, value));
|
||||||
self.values[value.index()] = ValueDef::BlockParam(block, index);
|
self.values[value.index()] = ValueDef::BlockParam(block, index, ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_and_update_alias(&mut self, value: Value) -> Value {
|
pub fn resolve_and_update_alias(&mut self, value: Value) -> Value {
|
||||||
|
@ -295,12 +292,12 @@ impl Value {
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum ValueDef {
|
pub enum ValueDef {
|
||||||
Arg(usize),
|
Arg(usize, Type),
|
||||||
BlockParam(BlockId, usize),
|
BlockParam(BlockId, usize, Type),
|
||||||
Operator(Operator, Vec<Value>),
|
Operator(Operator, Vec<Value>, Vec<Type>),
|
||||||
PickOutput(Value, usize),
|
PickOutput(Value, usize, Type),
|
||||||
Alias(Value),
|
Alias(Value),
|
||||||
Placeholder,
|
Placeholder(Type),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValueDef {
|
impl ValueDef {
|
||||||
|
@ -308,14 +305,14 @@ impl ValueDef {
|
||||||
match self {
|
match self {
|
||||||
&ValueDef::Arg { .. } => {}
|
&ValueDef::Arg { .. } => {}
|
||||||
&ValueDef::BlockParam { .. } => {}
|
&ValueDef::BlockParam { .. } => {}
|
||||||
&ValueDef::Operator(_, ref args) => {
|
&ValueDef::Operator(_, ref args, _) => {
|
||||||
for &arg in args {
|
for &arg in args {
|
||||||
f(arg);
|
f(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&ValueDef::PickOutput(from, ..) => f(from),
|
&ValueDef::PickOutput(from, ..) => f(from),
|
||||||
&ValueDef::Alias(value) => f(value),
|
&ValueDef::Alias(value) => f(value),
|
||||||
&ValueDef::Placeholder => {}
|
&ValueDef::Placeholder(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,14 +320,14 @@ impl ValueDef {
|
||||||
match self {
|
match self {
|
||||||
&mut ValueDef::Arg { .. } => {}
|
&mut ValueDef::Arg { .. } => {}
|
||||||
&mut ValueDef::BlockParam { .. } => {}
|
&mut ValueDef::BlockParam { .. } => {}
|
||||||
&mut ValueDef::Operator(_, ref mut args) => {
|
&mut ValueDef::Operator(_, ref mut args, _) => {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
f(arg);
|
f(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&mut ValueDef::PickOutput(ref mut from, ..) => f(from),
|
&mut ValueDef::PickOutput(ref mut from, ..) => f(from),
|
||||||
&mut ValueDef::Alias(ref mut value) => f(value),
|
&mut ValueDef::Alias(ref mut value) => f(value),
|
||||||
&mut ValueDef::Placeholder => {}
|
&mut ValueDef::Placeholder(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ impl UseCountAnalysis {
|
||||||
workqueue_set.remove(&value);
|
workqueue_set.remove(&value);
|
||||||
match &f.values[value.index()] {
|
match &f.values[value.index()] {
|
||||||
&ValueDef::Alias(..) | &ValueDef::Arg(..) | &ValueDef::BlockParam(..) => {}
|
&ValueDef::Alias(..) | &ValueDef::Arg(..) | &ValueDef::BlockParam(..) => {}
|
||||||
&ValueDef::Operator(_op, ref args) => {
|
&ValueDef::Operator(_op, ref args, _) => {
|
||||||
for &arg in args {
|
for &arg in args {
|
||||||
let arg = f.resolve_alias(arg);
|
let arg = f.resolve_alias(arg);
|
||||||
counts.add(arg);
|
counts.add(arg);
|
||||||
|
@ -52,7 +52,7 @@ impl UseCountAnalysis {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&ValueDef::PickOutput(value, _) => {
|
&ValueDef::PickOutput(value, _, _) => {
|
||||||
let value = f.resolve_alias(value);
|
let value = f.resolve_alias(value);
|
||||||
counts.add(value);
|
counts.add(value);
|
||||||
if counts.use_count[value.index()] == 1 {
|
if counts.use_count[value.index()] == 1 {
|
||||||
|
@ -61,7 +61,7 @@ impl UseCountAnalysis {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&ValueDef::Placeholder => {
|
&ValueDef::Placeholder(_) => {
|
||||||
panic!("Unresolved placeholder for value {}", value);
|
panic!("Unresolved placeholder for value {}", value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue