charon_lib/transform/
remove_unused_locals.rs

1//! Remove the locals (which are not used for the input arguments) which are
2//! never used in the function bodies.  This is useful to remove the locals with
3//! type `Never`. We actually check that there are no such local variables
4//! remaining afterwards.
5use std::collections::{HashMap, HashSet};
6use std::mem;
7
8use crate::ast::*;
9use crate::transform::TransformCtx;
10
11use super::ctx::TransformPass;
12
13fn remove_unused_locals<Body: BodyVisitable>(body: &mut GExprBody<Body>) {
14    // Compute the set of used locals.
15    // We always register the return variable and the input arguments.
16    let mut used_locals: HashSet<LocalId> = (0..(body.locals.arg_count + 1))
17        .map(|i| LocalId::new(i))
18        .collect();
19    body.body.dyn_visit_in_body(|lid: &LocalId| {
20        used_locals.insert(*lid);
21    });
22    trace!("used_locals: {:?}", used_locals);
23
24    // Keep only the variables that are used and update their indices to be contiguous.
25    let mut ids_map: HashMap<LocalId, LocalId> = HashMap::new();
26    for local in mem::take(&mut body.locals.locals) {
27        if used_locals.contains(&local.index) {
28            let old_id = local.index;
29            let new_id = body
30                .locals
31                .locals
32                .push_with(|index| Local { index, ..local });
33            ids_map.insert(old_id, new_id);
34        }
35    }
36    trace!("ids_maps: {:?}", ids_map);
37
38    // Update all `LocalId`s.
39    body.body.dyn_visit_in_body_mut(|lid: &mut LocalId| {
40        *lid = *ids_map.get(lid).unwrap();
41    });
42}
43
44pub struct Transform;
45impl TransformPass for Transform {
46    fn transform_ctx(&self, ctx: &mut TransformCtx) {
47        ctx.for_each_fun_decl(|_ctx, fun| {
48            if let Ok(body) = &mut fun.body {
49                match body {
50                    Body::Unstructured(body) => remove_unused_locals(body),
51                    Body::Structured(body) => remove_unused_locals(body),
52                }
53            }
54        });
55    }
56}