use qcode::value::{
BlockId, FunctionBody, QCodeView, ValueId,
insn::{Branch, Mnemonic},
util::base_ref::BaseRef,
};
use crate::PassCtx;
pub fn replace_terminator_with_branch<'a, 'str>(
body: &'a mut FunctionBody<'str>,
cx: PassCtx<'a, 'str>,
block: BlockId,
target: BlockId,
args: Vec<ValueId>,
) {
let mut old_successors = cx
.body_view(body)
.block_ref(block)
.successors()
.map(|(edge, _)| edge)
.collect::<Vec<_>>();
old_successors.sort_unstable();
old_successors.dedup();
for edge in old_successors {
body.remove_cfg_edge(edge);
}
let term_id = cx
.body_view(body)
.block_ref(block)
.instruction_ids()
.last()
.copied()
.filter(|&id| cx.body_view(body).insn_ref(id).mnemonic().is_terminator());
let local_target = target.localize(block.func);
let args: Vec<_> = args
.into_iter()
.map(|arg| arg.localize(block.func))
.collect();
if let Some(term_id) = term_id {
body.replace_instruction_mnemonic(
term_id,
Mnemonic::Branch(Branch {
target: local_target,
args,
}),
);
} else {
let branch = body.push_mnemonic(
cx.shr(),
Mnemonic::Branch(Branch {
target: local_target,
args,
}),
0,
);
let end = cx.body_view(body).block_ref(block).instruction_ids().len();
{
let mut host = cx.host(body);
BaseRef::new(host.reborrow(), block).insert_insn_at_index(end, branch);
}
}
body.add_cfg_edge(block, target);
}