cranelift: Rework block instructions to use BlockCall (#5464)
Add a new type BlockCall that represents the pair of a block name with arguments to be passed to it. (The mnemonic here is that it looks a bit like a function call.) Rework the implementation of jump, brz, and brnz to use BlockCall instead of storing the block arguments as varargs in the instruction's ValueList. To ensure that we're processing block arguments from BlockCall values in instructions, three new functions have been introduced on DataFlowGraph that both sets of arguments: inst_values - returns an iterator that traverses values in the instruction and block arguments map_inst_values - applies a function to each value in the instruction and block arguments overwrite_inst_values - overwrite all values in an instruction and block arguments with values from the iterator Co-authored-by: Jamey Sharp <jamey@minilop.net>
This commit is contained in:
@@ -111,7 +111,10 @@ impl<'short, 'long> InstBuilderBase<'short> for FuncInstBuilder<'short, 'long> {
|
||||
Some(dest_block) => {
|
||||
// If the user has supplied jump arguments we must adapt the arguments of
|
||||
// the destination block
|
||||
self.builder.declare_successor(dest_block, inst);
|
||||
self.builder.declare_successor(
|
||||
dest_block.block(&self.builder.func.dfg.value_lists),
|
||||
inst,
|
||||
);
|
||||
}
|
||||
None => {
|
||||
// branch_destination() doesn't detect jump_tables
|
||||
@@ -676,11 +679,14 @@ impl<'a> FunctionBuilder<'a> {
|
||||
/// **Note:** You are responsible for maintaining the coherence with the arguments of
|
||||
/// other jump instructions.
|
||||
pub fn change_jump_destination(&mut self, inst: Inst, new_dest: Block) {
|
||||
let old_dest = self.func.dfg.insts[inst]
|
||||
let dfg = &mut self.func.dfg;
|
||||
let old_dest = dfg.insts[inst]
|
||||
.branch_destination_mut()
|
||||
.expect("you want to change the jump destination of a non-jump instruction");
|
||||
self.func_ctx.ssa.remove_block_predecessor(*old_dest, inst);
|
||||
*old_dest = new_dest;
|
||||
self.func_ctx
|
||||
.ssa
|
||||
.remove_block_predecessor(old_dest.block(&dfg.value_lists), inst);
|
||||
old_dest.set_block(new_dest, &mut dfg.value_lists);
|
||||
self.func_ctx.ssa.declare_block_predecessor(new_dest, inst);
|
||||
}
|
||||
|
||||
|
||||
@@ -584,8 +584,12 @@ impl SSABuilder {
|
||||
}
|
||||
// For a single destination appending a jump argument to the instruction
|
||||
// is sufficient.
|
||||
BranchInfo::SingleDest(_, _) => {
|
||||
func.dfg.append_inst_arg(branch, val);
|
||||
BranchInfo::SingleDest(_) => {
|
||||
let dfg = &mut func.dfg;
|
||||
dfg.insts[branch]
|
||||
.branch_destination_mut()
|
||||
.unwrap()
|
||||
.append_argument(val, &mut dfg.value_lists);
|
||||
None
|
||||
}
|
||||
BranchInfo::Table(mut jt, _default_block) => {
|
||||
@@ -832,23 +836,23 @@ mod tests {
|
||||
assert_eq!(x_ssa, x_use3);
|
||||
assert_eq!(y_ssa, y_use3);
|
||||
match func.dfg.analyze_branch(brnz_block0_block2) {
|
||||
BranchInfo::SingleDest(dest, jump_args) => {
|
||||
assert_eq!(dest, block2);
|
||||
assert_eq!(jump_args.len(), 0);
|
||||
BranchInfo::SingleDest(dest) => {
|
||||
assert_eq!(dest.block(&func.dfg.value_lists), block2);
|
||||
assert_eq!(dest.args_slice(&func.dfg.value_lists).len(), 0);
|
||||
}
|
||||
_ => assert!(false),
|
||||
};
|
||||
match func.dfg.analyze_branch(jump_block0_block1) {
|
||||
BranchInfo::SingleDest(dest, jump_args) => {
|
||||
assert_eq!(dest, block1);
|
||||
assert_eq!(jump_args.len(), 0);
|
||||
BranchInfo::SingleDest(dest) => {
|
||||
assert_eq!(dest.block(&func.dfg.value_lists), block1);
|
||||
assert_eq!(dest.args_slice(&func.dfg.value_lists).len(), 0);
|
||||
}
|
||||
_ => assert!(false),
|
||||
};
|
||||
match func.dfg.analyze_branch(jump_block1_block2) {
|
||||
BranchInfo::SingleDest(dest, jump_args) => {
|
||||
assert_eq!(dest, block2);
|
||||
assert_eq!(jump_args.len(), 0);
|
||||
BranchInfo::SingleDest(dest) => {
|
||||
assert_eq!(dest.block(&func.dfg.value_lists), block2);
|
||||
assert_eq!(dest.args_slice(&func.dfg.value_lists).len(), 0);
|
||||
}
|
||||
_ => assert!(false),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user