wasmer_compiler_singlepass/
unwind.rs1#[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 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#[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}