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    Push2Regs {
35        reg1: UnwindRegister<R, S>,
36        reg2: UnwindRegister<R, S>,
37        up_to_sp: u32,
38    },
39    DefineNewFrame,
40    SaveRegister {
41        reg: UnwindRegister<R, S>,
42        bp_neg_offset: i32,
43    },
44}
45
46#[cfg(not(feature = "unwind"))]
47pub type CallFrameInstruction = u32;
48
49#[derive(Clone, Debug, PartialEq, Eq)]
50pub struct UnwindInstructions {
51    pub instructions: Vec<(u32, CallFrameInstruction)>,
52    pub len: u32,
53}
54
55#[cfg(feature = "unwind")]
56pub enum UnwindFrame {
57    SystemV(gimli::write::FrameDescriptionEntry),
58}
59
60#[cfg(not(feature = "unwind"))]
61pub type UnwindFrame = u32;
62
63#[cfg(feature = "unwind")]
64impl UnwindInstructions {
65    /// Converts the unwind information into a `FrameDescriptionEntry`.
66    pub fn to_fde(&self, address: Address) -> UnwindFrame {
67        let mut fde = FrameDescriptionEntry::new(address, self.len);
68        for (offset, inst) in &self.instructions {
69            fde.add_instruction(*offset, inst.clone());
70        }
71        UnwindFrame::SystemV(fde)
72    }
73}
74
75/// generate a default systemv  cie
76#[cfg(feature = "unwind")]
77pub fn create_systemv_cie(arch: Architecture) -> Option<gimli::write::CommonInformationEntry> {
78    match arch {
79        Architecture::X86_64 => {
80            let mut entry = CommonInformationEntry::new(
81                Encoding {
82                    address_size: 8,
83                    format: Format::Dwarf32,
84                    version: 1,
85                },
86                1,
87                -8,
88                X86_64::RA,
89            );
90            entry.add_instruction(CallFrameInstruction::Cfa(X86_64::RSP, 8));
91            entry.add_instruction(CallFrameInstruction::Offset(X86_64::RA, -8));
92            Some(entry)
93        }
94        Architecture::Aarch64(_) => {
95            let mut entry = CommonInformationEntry::new(
96                Encoding {
97                    address_size: 8,
98                    format: Format::Dwarf32,
99                    version: 1,
100                },
101                1,
102                -8,
103                AArch64::X30,
104            );
105            entry.add_instruction(CallFrameInstruction::Cfa(AArch64::SP, 0));
106            Some(entry)
107        }
108        _ => None,
109    }
110}