charon_lib/transform/
merge_goto_chains.rsuse itertools::Itertools;
use crate::ids::Vector;
use crate::transform::TransformCtx;
use crate::ullbc_ast::*;
use super::ctx::UllbcPass;
pub struct Transform;
impl UllbcPass for Transform {
fn transform_body(&self, ctx: &mut TransformCtx<'_>, body: &mut ExprBody) {
if ctx.options.no_merge_goto_chains {
return;
}
let mut antecedents: Vector<BlockId, usize> = body.body.map_ref(|_| 0);
for block in body.body.iter() {
for target in block.targets() {
*antecedents.get_mut(target).unwrap() += 1;
}
}
let mut to_process = body.body.iter_indices().collect_vec();
while let Some(id) = to_process.pop() {
let Some(block) = body.body.get(id) else {
continue;
};
let RawTerminator::Goto { target } = block.terminator.content else {
continue;
};
if antecedents[target] != 1 {
continue;
};
let target = body.body.remove(target).unwrap();
let source = &mut body.body[id];
source.statements.extend(target.statements);
source.terminator = target.terminator;
to_process.push(id);
}
}
}