WIP.
This commit is contained in:
parent
498f5008d6
commit
6eb6297a2c
122
src/frontend.rs
122
src/frontend.rs
|
@ -153,6 +153,11 @@ fn parse_body<'a>(
|
||||||
builder.handle_op(wasmparser::Operator::Return)?;
|
builder.handle_op(wasmparser::Operator::Return)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for block in 0..builder.body.blocks.len() {
|
||||||
|
log::trace!("checking if block is sealed: {}", block);
|
||||||
|
assert!(builder.locals.is_sealed(block));
|
||||||
|
}
|
||||||
|
|
||||||
trace!("Final function body:{:?}", ret);
|
trace!("Final function body:{:?}", ret);
|
||||||
|
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
|
@ -184,6 +189,7 @@ impl LocalTracker {
|
||||||
|
|
||||||
pub fn add_pred(&mut self, block: BlockId, pred: BlockId) {
|
pub fn add_pred(&mut self, block: BlockId, pred: BlockId) {
|
||||||
assert!(!self.block_sealed.contains(&block));
|
assert!(!self.block_sealed.contains(&block));
|
||||||
|
log::trace!("add_pred: block {} pred {}", block, pred);
|
||||||
self.block_preds
|
self.block_preds
|
||||||
.entry(block)
|
.entry(block)
|
||||||
.or_insert_with(|| vec![])
|
.or_insert_with(|| vec![])
|
||||||
|
@ -192,10 +198,12 @@ impl LocalTracker {
|
||||||
|
|
||||||
pub fn start_block(&mut self, block: BlockId) {
|
pub fn start_block(&mut self, block: BlockId) {
|
||||||
self.finish_block();
|
self.finish_block();
|
||||||
|
log::trace!("start_block: block {}", block);
|
||||||
self.cur_block = Some(block);
|
self.cur_block = Some(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finish_block(&mut self) {
|
pub fn finish_block(&mut self) {
|
||||||
|
log::trace!("finish_block: block {:?}", self.cur_block);
|
||||||
if let Some(block) = self.cur_block {
|
if let Some(block) = self.cur_block {
|
||||||
let mapping = std::mem::take(&mut self.in_cur_block);
|
let mapping = std::mem::take(&mut self.in_cur_block);
|
||||||
self.block_end.insert(block, mapping);
|
self.block_end.insert(block, mapping);
|
||||||
|
@ -204,6 +212,7 @@ impl LocalTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seal_block_preds(&mut self, block: BlockId, body: &mut FunctionBody) {
|
pub fn seal_block_preds(&mut self, block: BlockId, body: &mut FunctionBody) {
|
||||||
|
log::trace!("seal_block_preds: block {}", block);
|
||||||
let not_sealed = self.block_sealed.insert(block);
|
let not_sealed = self.block_sealed.insert(block);
|
||||||
assert!(not_sealed);
|
assert!(not_sealed);
|
||||||
for (local, phi_value) in self
|
for (local, phi_value) in self
|
||||||
|
@ -220,8 +229,12 @@ impl LocalTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(&mut self, local: LocalId, value: Value) {
|
pub fn set(&mut self, local: LocalId, value: Value) {
|
||||||
assert!(self.cur_block.is_some());
|
if self.cur_block.is_none() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
debug_assert!(self.is_sealed(self.cur_block.unwrap()));
|
debug_assert!(self.is_sealed(self.cur_block.unwrap()));
|
||||||
|
log::trace!("set: local {} value {:?}", local, value);
|
||||||
self.in_cur_block.insert(local, value);
|
self.in_cur_block.insert(local, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,10 +244,12 @@ impl LocalTracker {
|
||||||
at_block: BlockId,
|
at_block: BlockId,
|
||||||
local: LocalId,
|
local: LocalId,
|
||||||
) -> Value {
|
) -> Value {
|
||||||
|
log::trace!("get_in_block: at_block {} local {}", at_block, local);
|
||||||
let ty = body.locals[local as usize];
|
let ty = body.locals[local as usize];
|
||||||
|
|
||||||
if self.cur_block.unwrap() == at_block {
|
if self.cur_block == Some(at_block) {
|
||||||
if let Some(&value) = self.in_cur_block.get(&local) {
|
if let Some(&value) = self.in_cur_block.get(&local) {
|
||||||
|
log::trace!(" -> {:?}", value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,6 +257,7 @@ impl LocalTracker {
|
||||||
if self.is_sealed(at_block) {
|
if self.is_sealed(at_block) {
|
||||||
if let Some(end_mapping) = self.block_end.get(&at_block) {
|
if let Some(end_mapping) = self.block_end.get(&at_block) {
|
||||||
if let Some(&value) = end_mapping.get(&local) {
|
if let Some(&value) = end_mapping.get(&local) {
|
||||||
|
log::trace!(" -> {:?}", value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,7 +268,9 @@ impl LocalTracker {
|
||||||
.map(|preds| preds.is_empty())
|
.map(|preds| preds.is_empty())
|
||||||
.unwrap_or(true)
|
.unwrap_or(true)
|
||||||
{
|
{
|
||||||
return self.create_default_value(body, ty);
|
let value = self.create_default_value(body, ty);
|
||||||
|
log::trace!(" -> created default: {:?}", value);
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
let placeholder = body.add_placeholder(ty);
|
let placeholder = body.add_placeholder(ty);
|
||||||
|
@ -260,6 +278,7 @@ impl LocalTracker {
|
||||||
.entry(at_block)
|
.entry(at_block)
|
||||||
.or_insert_with(|| FxHashMap::default())
|
.or_insert_with(|| FxHashMap::default())
|
||||||
.insert(local, placeholder);
|
.insert(local, placeholder);
|
||||||
|
log::trace!(" -> created placeholder: {:?}", placeholder);
|
||||||
self.compute_blockparam(body, at_block, local, placeholder);
|
self.compute_blockparam(body, at_block, local, placeholder);
|
||||||
placeholder
|
placeholder
|
||||||
} else {
|
} else {
|
||||||
|
@ -268,6 +287,10 @@ impl LocalTracker {
|
||||||
.entry(at_block)
|
.entry(at_block)
|
||||||
.or_insert_with(|| FxHashMap::default())
|
.or_insert_with(|| FxHashMap::default())
|
||||||
.insert(local, placeholder);
|
.insert(local, placeholder);
|
||||||
|
log::trace!(
|
||||||
|
" -> created placeholder and added as incomplete phi: {:?}",
|
||||||
|
placeholder
|
||||||
|
);
|
||||||
self.incomplete_phis
|
self.incomplete_phis
|
||||||
.entry(at_block)
|
.entry(at_block)
|
||||||
.or_insert_with(|| vec![])
|
.or_insert_with(|| vec![])
|
||||||
|
@ -278,8 +301,10 @@ impl LocalTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&mut self, body: &mut FunctionBody, local: LocalId) -> Value {
|
pub fn get(&mut self, body: &mut FunctionBody, local: LocalId) -> Value {
|
||||||
assert!(self.cur_block.is_some());
|
if self.cur_block.is_none() {
|
||||||
debug_assert!(self.is_sealed(self.cur_block.unwrap()));
|
return Value::undef();
|
||||||
|
}
|
||||||
|
|
||||||
let block = self.cur_block.unwrap();
|
let block = self.cur_block.unwrap();
|
||||||
assert!((local as usize) < body.locals.len());
|
assert!((local as usize) < body.locals.len());
|
||||||
self.get_in_block(body, block, local)
|
self.get_in_block(body, block, local)
|
||||||
|
@ -324,6 +349,12 @@ impl LocalTracker {
|
||||||
local: LocalId,
|
local: LocalId,
|
||||||
value: Value,
|
value: Value,
|
||||||
) {
|
) {
|
||||||
|
log::trace!(
|
||||||
|
"compute_blockparam: block {} local {} value {:?}",
|
||||||
|
block,
|
||||||
|
local,
|
||||||
|
value
|
||||||
|
);
|
||||||
let mut results: Vec<Value> = vec![];
|
let mut results: Vec<Value> = vec![];
|
||||||
let preds = self
|
let preds = self
|
||||||
.block_preds
|
.block_preds
|
||||||
|
@ -332,6 +363,14 @@ impl LocalTracker {
|
||||||
.unwrap_or_else(|| vec![]);
|
.unwrap_or_else(|| vec![]);
|
||||||
for pred in preds {
|
for pred in preds {
|
||||||
let pred_value = self.get_in_block(body, pred, local);
|
let pred_value = self.get_in_block(body, pred, local);
|
||||||
|
log::trace!(
|
||||||
|
"compute_blockparam: block {} local {} value {:?}: pred {} -> {:?}",
|
||||||
|
block,
|
||||||
|
local,
|
||||||
|
value,
|
||||||
|
pred,
|
||||||
|
pred_value
|
||||||
|
);
|
||||||
results.push(pred_value);
|
results.push(pred_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,8 +382,21 @@ impl LocalTracker {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(v) = trivial_alias {
|
if let Some(v) = trivial_alias {
|
||||||
|
log::trace!(
|
||||||
|
"compute_blockparam: block {} local {} value {:?}: alias to {:?}",
|
||||||
|
block,
|
||||||
|
local,
|
||||||
|
value,
|
||||||
|
v
|
||||||
|
);
|
||||||
body.set_alias(value, v);
|
body.set_alias(value, v);
|
||||||
} else {
|
} else {
|
||||||
|
log::trace!(
|
||||||
|
"compute_blockparam: block {} local {} value {:?}: making blockparam",
|
||||||
|
block,
|
||||||
|
local,
|
||||||
|
value,
|
||||||
|
);
|
||||||
body.replace_placeholder_with_blockparam(block, value);
|
body.replace_placeholder_with_blockparam(block, value);
|
||||||
for (i, (pred, result)) in self
|
for (i, (pred, result)) in self
|
||||||
.block_preds
|
.block_preds
|
||||||
|
@ -357,6 +409,14 @@ impl LocalTracker {
|
||||||
{
|
{
|
||||||
let index = body.blocks[block].pos_in_pred_succ[i];
|
let index = body.blocks[block].pos_in_pred_succ[i];
|
||||||
body.blocks[pred].terminator.update_target(index, |target| {
|
body.blocks[pred].terminator.update_target(index, |target| {
|
||||||
|
log::trace!(
|
||||||
|
"compute_blockparam: block {} local {} value {:?}: in pred {}, adding branch arg {:?}",
|
||||||
|
block,
|
||||||
|
local,
|
||||||
|
value,
|
||||||
|
pred,
|
||||||
|
result,
|
||||||
|
);
|
||||||
target.args.push(result);
|
target.args.push(result);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -477,6 +537,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
// Push initial implicit Block.
|
// Push initial implicit Block.
|
||||||
let results = module.signatures[my_sig].returns.to_vec();
|
let results = module.signatures[my_sig].returns.to_vec();
|
||||||
let out = ret.body.add_block();
|
let out = ret.body.add_block();
|
||||||
|
ret.add_block_params(out, &results[..]);
|
||||||
ret.ctrl_stack.push(Frame::Block {
|
ret.ctrl_stack.push(Frame::Block {
|
||||||
start_depth: 0,
|
start_depth: 0,
|
||||||
out,
|
out,
|
||||||
|
@ -717,6 +778,15 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
wasmparser::Operator::End if self.cur_block.is_none() => {
|
wasmparser::Operator::End if self.cur_block.is_none() => {
|
||||||
let frame = self.ctrl_stack.pop().unwrap();
|
let frame = self.ctrl_stack.pop().unwrap();
|
||||||
self.op_stack.truncate(frame.start_depth());
|
self.op_stack.truncate(frame.start_depth());
|
||||||
|
match frame {
|
||||||
|
Frame::Block { out, .. } | Frame::If { out, .. } | Frame::Else { out, .. } => {
|
||||||
|
self.locals.seal_block_preds(out, &mut self.body);
|
||||||
|
}
|
||||||
|
Frame::Loop { out, header, .. } => {
|
||||||
|
self.locals.seal_block_preds(out, &mut self.body);
|
||||||
|
self.locals.seal_block_preds(header, &mut self.body);
|
||||||
|
}
|
||||||
|
}
|
||||||
self.cur_block = Some(frame.out());
|
self.cur_block = Some(frame.out());
|
||||||
self.push_block_params(frame.results().len());
|
self.push_block_params(frame.results().len());
|
||||||
self.locals.start_block(frame.out());
|
self.locals.start_block(frame.out());
|
||||||
|
@ -785,7 +855,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
self.locals.start_block(*el);
|
self.locals.start_block(*el);
|
||||||
self.locals.finish_block();
|
self.locals.finish_block();
|
||||||
self.emit_branch(*el, &else_result_values[..]);
|
self.emit_branch(*out, &else_result_values[..]);
|
||||||
assert_eq!(self.op_stack.len(), *start_depth);
|
assert_eq!(self.op_stack.len(), *start_depth);
|
||||||
self.cur_block = Some(*out);
|
self.cur_block = Some(*out);
|
||||||
self.locals.seal_block_preds(*out, &mut self.body);
|
self.locals.seal_block_preds(*out, &mut self.body);
|
||||||
|
@ -970,6 +1040,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_block_params(&mut self, block: BlockId, tys: &[Type]) {
|
fn add_block_params(&mut self, block: BlockId, tys: &[Type]) {
|
||||||
|
log::trace!("add_block_params: block {} tys {:?}", block, tys);
|
||||||
for &ty in tys {
|
for &ty in tys {
|
||||||
self.body.add_blockparam(block, ty);
|
self.body.add_blockparam(block, ty);
|
||||||
}
|
}
|
||||||
|
@ -994,6 +1065,12 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_branch(&mut self, target: BlockId, args: &[Value]) {
|
fn emit_branch(&mut self, target: BlockId, args: &[Value]) {
|
||||||
|
log::trace!(
|
||||||
|
"emit_branch: cur_block {:?} target {} args {:?}",
|
||||||
|
self.cur_block,
|
||||||
|
target,
|
||||||
|
args
|
||||||
|
);
|
||||||
if let Some(block) = self.cur_block {
|
if let Some(block) = self.cur_block {
|
||||||
let args = args.to_vec();
|
let args = args.to_vec();
|
||||||
self.locals.add_pred(target, block);
|
self.locals.add_pred(target, block);
|
||||||
|
@ -1013,6 +1090,14 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
if_false: BlockId,
|
if_false: BlockId,
|
||||||
if_false_args: &[Value],
|
if_false_args: &[Value],
|
||||||
) {
|
) {
|
||||||
|
log::trace!(
|
||||||
|
"emit_cond_branch: cur_block {:?} if_true {} args {:?} if_false {} args {:?}",
|
||||||
|
self.cur_block,
|
||||||
|
if_true,
|
||||||
|
if_true_args,
|
||||||
|
if_false,
|
||||||
|
if_false_args
|
||||||
|
);
|
||||||
if let Some(block) = self.cur_block {
|
if let Some(block) = self.cur_block {
|
||||||
let if_true_args = if_true_args.to_vec();
|
let if_true_args = if_true_args.to_vec();
|
||||||
let if_false_args = if_false_args.to_vec();
|
let if_false_args = if_false_args.to_vec();
|
||||||
|
@ -1039,6 +1124,14 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
indexed_targets: &[BlockId],
|
indexed_targets: &[BlockId],
|
||||||
args: &[Value],
|
args: &[Value],
|
||||||
) {
|
) {
|
||||||
|
log::trace!(
|
||||||
|
"emit_br_table: cur_block {:?} index {:?} default {} indexed {:?} args {:?}",
|
||||||
|
self.cur_block,
|
||||||
|
index,
|
||||||
|
default_target,
|
||||||
|
indexed_targets,
|
||||||
|
args,
|
||||||
|
);
|
||||||
if let Some(block) = self.cur_block {
|
if let Some(block) = self.cur_block {
|
||||||
let args = args.to_vec();
|
let args = args.to_vec();
|
||||||
let targets = indexed_targets
|
let targets = indexed_targets
|
||||||
|
@ -1076,12 +1169,18 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_block_params(&mut self, num_params: usize) {
|
fn push_block_params(&mut self, num_params: usize) {
|
||||||
|
log::trace!(
|
||||||
|
"push_block_params: cur_block {:?}, {} params",
|
||||||
|
self.cur_block,
|
||||||
|
num_params
|
||||||
|
);
|
||||||
let block = self.cur_block.unwrap();
|
let block = self.cur_block.unwrap();
|
||||||
for i in 0..num_params {
|
for i in 0..num_params {
|
||||||
let ty = self.body.blocks[block].params[i];
|
let ty = self.body.blocks[block].params[i];
|
||||||
let value = self
|
let value = self
|
||||||
.body
|
.body
|
||||||
.add_value(ValueDef::BlockParam(block, i), Some(ty));
|
.add_value(ValueDef::BlockParam(block, i), Some(ty));
|
||||||
|
log::trace!(" -> push {:?} ty {:?}", value, ty);
|
||||||
self.op_stack.push((ty, value));
|
self.op_stack.push((ty, value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1096,6 +1195,13 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
)?;
|
)?;
|
||||||
let outputs = op_outputs(self.module, &self.body.locals[..], &self.op_stack[..], &op)?;
|
let outputs = op_outputs(self.module, &self.body.locals[..], &self.op_stack[..], &op)?;
|
||||||
|
|
||||||
|
log::trace!(
|
||||||
|
"emit into block {:?}: op {:?} inputs {:?}",
|
||||||
|
self.cur_block,
|
||||||
|
op,
|
||||||
|
inputs
|
||||||
|
);
|
||||||
|
|
||||||
if let Some(block) = self.cur_block {
|
if let Some(block) = self.cur_block {
|
||||||
let n_outputs = outputs.len();
|
let n_outputs = outputs.len();
|
||||||
|
|
||||||
|
@ -1106,6 +1212,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
input_operands.push(stack_top);
|
input_operands.push(stack_top);
|
||||||
}
|
}
|
||||||
input_operands.reverse();
|
input_operands.reverse();
|
||||||
|
log::trace!(" -> operands: {:?}", input_operands);
|
||||||
|
|
||||||
let ty = if n_outputs == 1 {
|
let ty = if n_outputs == 1 {
|
||||||
Some(outputs[0])
|
Some(outputs[0])
|
||||||
|
@ -1115,6 +1222,8 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
let value = self
|
let value = self
|
||||||
.body
|
.body
|
||||||
.add_value(ValueDef::Operator(op, input_operands), ty);
|
.add_value(ValueDef::Operator(op, input_operands), ty);
|
||||||
|
log::trace!(" -> value: {:?} ty {:?}", value, ty);
|
||||||
|
|
||||||
if !op_effects(&op).unwrap().is_empty() {
|
if !op_effects(&op).unwrap().is_empty() {
|
||||||
self.body.blocks[block].insts.push(value);
|
self.body.blocks[block].insts.push(value);
|
||||||
}
|
}
|
||||||
|
@ -1128,6 +1237,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
.body
|
.body
|
||||||
.add_value(ValueDef::PickOutput(value, i), Some(output_ty));
|
.add_value(ValueDef::PickOutput(value, i), Some(output_ty));
|
||||||
self.op_stack.push((output_ty, pick));
|
self.op_stack.push((output_ty, pick));
|
||||||
|
log::trace!(" -> pick {}: {:?} ty {:?}", i, pick, output_ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
11
src/ir.rs
11
src/ir.rs
|
@ -57,6 +57,7 @@ impl FunctionBody {
|
||||||
let id = self.blocks.len();
|
let id = self.blocks.len();
|
||||||
self.blocks.push(Block::default());
|
self.blocks.push(Block::default());
|
||||||
self.blocks[id].id = id;
|
self.blocks[id].id = id;
|
||||||
|
log::trace!("add_block: block {}", id);
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,22 +68,26 @@ impl FunctionBody {
|
||||||
self.blocks[to].preds.push(from);
|
self.blocks[to].preds.push(from);
|
||||||
self.blocks[from].pos_in_succ_pred.push(pred_pos);
|
self.blocks[from].pos_in_succ_pred.push(pred_pos);
|
||||||
self.blocks[to].pos_in_pred_succ.push(succ_pos);
|
self.blocks[to].pos_in_pred_succ.push(succ_pos);
|
||||||
|
log::trace!("add_edge: from {} to {}", from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_value(&mut self, value: ValueDef, ty: Option<Type>) -> Value {
|
pub fn add_value(&mut self, value: ValueDef, ty: Option<Type>) -> Value {
|
||||||
match self.value_dedup.entry(value.clone()) {
|
let id = match self.value_dedup.entry(value.clone()) {
|
||||||
Entry::Occupied(o) => *o.get(),
|
Entry::Occupied(o) => *o.get(),
|
||||||
Entry::Vacant(v) => {
|
Entry::Vacant(v) => {
|
||||||
let id = Value(self.values.len() as u32);
|
let id = Value(self.values.len() as u32);
|
||||||
self.values.push(value);
|
self.values.push(value.clone());
|
||||||
self.types.push(ty);
|
self.types.push(ty);
|
||||||
v.insert(id);
|
v.insert(id);
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
log::trace!("add_value: def {:?} ty {:?} -> {:?}", value, ty, id);
|
||||||
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_alias(&mut self, value: Value, to: Value) {
|
pub fn set_alias(&mut self, value: Value, to: Value) {
|
||||||
|
log::trace!("set_alias: value {:?} to {:?}", value, to);
|
||||||
// Resolve the `to` value through all existing aliases.
|
// Resolve the `to` value through all existing aliases.
|
||||||
let to = self.resolve_alias(to);
|
let to = self.resolve_alias(to);
|
||||||
// Disallow cycles.
|
// Disallow cycles.
|
||||||
|
|
Loading…
Reference in a new issue