squid/frontend/symbolization_passes/
regcache.rs

1use crate::frontend::ao::{
2    Function,
3    Op,
4    Register,
5    Var,
6};
7
8const REGISTER_COUNT: usize = 32 + 32 + 1;
9fn register_index(reg: &Register) -> usize {
10    match reg {
11        Register::Gp(reg) => *reg as usize,
12        Register::Fp(reg) => 32 + *reg as usize,
13        Register::Csr(_) => 64,
14    }
15}
16
17pub(crate) struct RegisterCachingPass {
18    registers: [Option<Var>; REGISTER_COUNT],
19}
20
21impl RegisterCachingPass {
22    #[allow(clippy::new_without_default)]
23    pub(crate) fn new() -> Self {
24        Self {
25            registers: [None; REGISTER_COUNT],
26        }
27    }
28
29    pub(crate) fn run(&mut self, func: &mut Function) -> Result<(), String> {
30        for bb in func.cfg_mut().iter_basic_blocks_mut() {
31            for reg in &mut self.registers {
32                *reg = None;
33            }
34
35            bb.set_cursor(0);
36
37            while let Some(op) = bb.cursor_op() {
38                match op {
39                    Op::StoreRegister {
40                        reg,
41                        var,
42                    } => {
43                        self.registers[register_index(reg)] = Some(*var);
44                    },
45                    Op::LoadRegister {
46                        var,
47                        reg,
48                    } => {
49                        if let Some(orig_var) = &self.registers[register_index(reg)] {
50                            bb.replace_op(Op::Copy {
51                                dst: *var,
52                                src: *orig_var,
53                            });
54                        }
55                    },
56                    _ => {},
57                }
58
59                if !bb.move_cursor_forward() {
60                    break;
61                }
62            }
63        }
64
65        Ok(())
66    }
67}