1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//! Frame layout item changes.

use crate::ir::entities::Inst;
use crate::isa::RegUnit;
use std::boxed::Box;

use crate::HashMap;

/// Change in the frame layout information.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum FrameLayoutChange {
    /// Base CallFrameAddress (CFA) pointer moved to different register/offset.
    CallFrameAddressAt {
        /// CFA register.
        reg: RegUnit,
        /// CFA offset.
        offset: isize,
    },
    /// Register saved at.
    RegAt {
        /// Saved register.
        reg: RegUnit,
        /// Offset in the frame (offset from CFA).
        cfa_offset: isize,
    },
    /// Return address saved at.
    ReturnAddressAt {
        /// Offset in the frame (offset from CFA).
        cfa_offset: isize,
    },
    /// The entire frame layout must be preserved somewhere to be restored at a corresponding
    /// `Restore` change.
    ///
    /// This likely maps to the DWARF call frame instruction `.cfa_remember_state`.
    Preserve,
    /// Restore the entire frame layout from a corresponding prior `Preserve` frame change.
    ///
    /// This likely maps to the DWARF call frame instruction `.cfa_restore_state`.
    Restore,
}

/// Set of frame layout changes.
pub type FrameLayoutChanges = Box<[FrameLayoutChange]>;

/// Frame items layout for (prologue/epilogue) instructions.
#[derive(Debug, Clone)]
pub struct FrameLayout {
    /// Initial frame layout.
    pub initial: FrameLayoutChanges,

    /// Instruction frame layout (changes). Because the map will not be dense,
    /// a HashMap is used instead of a SecondaryMap.
    pub instructions: HashMap<Inst, FrameLayoutChanges>,
}

impl FrameLayout {
    /// Create instance of FrameLayout.
    pub fn new() -> Self {
        Self {
            initial: vec![].into_boxed_slice(),
            instructions: HashMap::new(),
        }
    }

    /// Clear the structure.
    pub fn clear(&mut self) {
        self.initial = vec![].into_boxed_slice();
        self.instructions.clear();
    }
}