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 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 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#[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}