lamina_codegen/aarch64/
frame.rs1use lamina_mir::{Function, Instruction, Register};
6use std::collections::{HashMap, HashSet};
7
8pub struct FrameMap {
10 pub slots: HashMap<Register, i32>,
11 pub frame_size: i32,
12}
13
14impl FrameMap {
15 pub fn from_function(f: &Function) -> Self {
17 let mut regs: HashSet<Register> = HashSet::new();
18 for p in &f.sig.params {
19 regs.insert(p.reg.clone());
20 }
21 for b in &f.blocks {
22 for ins in &b.instructions {
23 if let Some(d) = ins.def_reg() {
24 regs.insert(d.clone());
25 }
26 if let Instruction::StackAddr { slot, .. } = &ins.instr {
27 regs.insert(Register::Virtual(*slot));
28 }
29 for u in ins.use_regs() {
30 regs.insert(u.clone());
31 }
32 }
33 }
34
35 let mut reg_vec: Vec<Register> = regs.into_iter().collect();
36 reg_vec.sort_by(|a, b| format!("{a:?}").cmp(&format!("{b:?}")));
37
38 let mut slots = HashMap::new();
39 let mut offset: i32 = -8;
40 for r in reg_vec {
41 if let Register::Virtual(v) = &r {
42 let extra = f.stack_reservations.get(v).copied().unwrap_or(0) as i32;
45 offset -= 8 * extra;
46 if let Some(align) = f.stack_alignments.get(v) {
47 let align = *align as i32;
48 let limit = offset - 8 * align;
49 while offset % align != 0 {
50 offset -= 8;
51 assert!(
52 offset > limit,
53 "no slot within {align} steps lands on a {align}-byte boundary"
54 );
55 }
56 }
57 slots.insert(r.clone(), offset);
58 offset -= 8;
59 }
60 }
61 let mut frame_size = -offset - 8;
62 if frame_size < 0 {
63 frame_size = 0;
64 }
65 frame_size = (frame_size + 15) & !15;
66 Self { slots, frame_size }
67 }
68
69 pub fn recompute_frame_size_from_slots(&mut self) {
70 let mut min_off = 0i32;
71 for &o in self.slots.values() {
72 if o < min_off {
73 min_off = o;
74 }
75 }
76 let mut frame_size = (-min_off).max(0);
79 frame_size = (frame_size + 15) & !15;
80 self.frame_size = frame_size;
81 }
82
83 pub fn slot_of(&self, r: &Register) -> Option<i32> {
85 self.slots.get(r).copied()
86 }
87}