wasmer_compiler_singlepass/
unwind.rs

1#[cfg(feature = "unwind")]
2use gimli::write::{Address, CallFrameInstruction, CommonInformationEntry, FrameDescriptionEntry};
3#[cfg(feature = "unwind")]
4use gimli::{AArch64, Encoding, Format, X86_64};
5use std::fmt::Debug;
6#[cfg(feature = "unwind")]
7use wasmer_types::target::Architecture;
8
9use crate::location;
10
11#[derive(Clone, Debug, Copy)]
12#[allow(clippy::upper_case_acronyms)]
13pub enum UnwindRegister<R: location::Reg, S: location::Reg> {
14    GPR(R),
15    FPR(S),
16}
17
18#[cfg(feature = "unwind")]
19impl<R: location::Reg, S: location::Reg> UnwindRegister<R, S> {
20    pub(crate) fn dwarf_index(&self) -> gimli::Register {
21        match self {
22            Self::GPR(reg) => reg.to_dwarf(),
23            Self::FPR(reg) => reg.to_dwarf(),
24        }
25    }
26}
27
28#[derive(Clone, Debug)]
29#[cfg_attr(not(feature = "unwind"), allow(dead_code))]
30pub enum UnwindOps<R: location::Reg, S: location::Reg> {
31    PushFP {
32        up_to_sp: u32,
33    },
34    SubtractFP {
35        up_to_sp: u32,
36    },
37    Push2Regs {
38        reg1: UnwindRegister<R, S>,
39        reg2: UnwindRegister<R, S>,
40        up_to_sp: u32,
41    },
42    DefineNewFrame,
43    SaveRegister {
44        reg: UnwindRegister<R, S>,
45        bp_neg_offset: i32,
46    },
47}
48
49#[cfg(not(feature = "unwind"))]
50pub type CallFrameInstruction = u32;
51
52#[derive(Clone, Debug, PartialEq, Eq)]
53pub struct UnwindInstructions {
54    pub instructions: Vec<(u32, CallFrameInstruction)>,
55    pub len: u32,
56}
57
58#[cfg(feature = "unwind")]
59pub enum UnwindFrame {
60    SystemV(gimli::write::FrameDescriptionEntry),
61}
62
63#[cfg(not(feature = "unwind"))]
64pub type UnwindFrame = u32;
65
66#[cfg(feature = "unwind")]
67impl UnwindInstructions {
68    /// Converts the unwind information into a `FrameDescriptionEntry`.
69    pub fn to_fde(&self, address: Address) -> UnwindFrame {
70        let mut fde = FrameDescriptionEntry::new(address, self.len);
71        for (offset, inst) in &self.instructions {
72            fde.add_instruction(*offset, inst.clone());
73        }
74        UnwindFrame::SystemV(fde)
75    }
76}
77
78/// generate a default systemv  cie
79#[cfg(feature = "unwind")]
80pub fn create_systemv_cie(arch: Architecture) -> Option<gimli::write::CommonInformationEntry> {
81    match arch {
82        Architecture::X86_64 => {
83            let mut entry = CommonInformationEntry::new(
84                Encoding {
85                    address_size: 8,
86                    format: Format::Dwarf32,
87                    version: 1,
88                },
89                1,
90                -8,
91                X86_64::RA,
92            );
93            entry.add_instruction(CallFrameInstruction::Cfa(X86_64::RSP, 8));
94            entry.add_instruction(CallFrameInstruction::Offset(X86_64::RA, -8));
95            Some(entry)
96        }
97        Architecture::Aarch64(_) => {
98            let mut entry = CommonInformationEntry::new(
99                Encoding {
100                    address_size: 8,
101                    format: Format::Dwarf32,
102                    version: 1,
103                },
104                1,
105                -8,
106                AArch64::X30,
107            );
108            entry.add_instruction(CallFrameInstruction::Cfa(AArch64::SP, 0));
109            Some(entry)
110        }
111        Architecture::Riscv64(_) => {
112            use gimli::RiscV;
113
114            let mut entry = CommonInformationEntry::new(
115                Encoding {
116                    address_size: 8,
117                    format: Format::Dwarf32,
118                    version: 1,
119                },
120                1,
121                -8,
122                RiscV::RA,
123            );
124            entry.add_instruction(CallFrameInstruction::Cfa(RiscV::SP, 0));
125            Some(entry)
126        }
127        _ => None,
128    }
129}