#[cfg(feature = "unwind")]
use gimli::write::{Address, CallFrameInstruction, CommonInformationEntry, FrameDescriptionEntry};
#[cfg(feature = "unwind")]
use gimli::{AArch64, Encoding, Format, X86_64};
use std::fmt::Debug;
#[cfg(feature = "unwind")]
use wasmer_types::target::Architecture;
use crate::location;
#[derive(Clone, Debug, Copy)]
#[allow(clippy::upper_case_acronyms)]
pub enum UnwindRegister<R: location::Reg, S: location::Reg> {
GPR(R),
FPR(S),
}
#[cfg(feature = "unwind")]
impl<R: location::Reg, S: location::Reg> UnwindRegister<R, S> {
pub(crate) fn dwarf_index(&self) -> gimli::Register {
match self {
Self::GPR(reg) => reg.to_dwarf(),
Self::FPR(reg) => reg.to_dwarf(),
}
}
}
#[derive(Clone, Debug)]
#[cfg_attr(not(feature = "unwind"), allow(dead_code))]
pub enum UnwindOps<R: location::Reg, S: location::Reg> {
PushFP {
up_to_sp: u32,
},
SubtractFP {
up_to_sp: u32,
},
Push2Regs {
reg1: UnwindRegister<R, S>,
reg2: UnwindRegister<R, S>,
up_to_sp: u32,
},
DefineNewFrame,
SaveRegister {
reg: UnwindRegister<R, S>,
bp_neg_offset: i32,
},
}
#[cfg(not(feature = "unwind"))]
pub type CallFrameInstruction = u32;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct UnwindInstructions {
pub instructions: Vec<(u32, CallFrameInstruction)>,
pub len: u32,
}
#[cfg(feature = "unwind")]
pub enum UnwindFrame {
SystemV(gimli::write::FrameDescriptionEntry),
}
#[cfg(not(feature = "unwind"))]
pub type UnwindFrame = u32;
#[cfg(feature = "unwind")]
impl UnwindInstructions {
pub fn to_fde(&self, address: Address) -> UnwindFrame {
let mut fde = FrameDescriptionEntry::new(address, self.len);
for (offset, inst) in &self.instructions {
fde.add_instruction(*offset, inst.clone());
}
UnwindFrame::SystemV(fde)
}
}
#[cfg(feature = "unwind")]
pub fn create_systemv_cie(arch: Architecture) -> Option<gimli::write::CommonInformationEntry> {
match arch {
Architecture::X86_64 => {
let mut entry = CommonInformationEntry::new(
Encoding {
address_size: 8,
format: Format::Dwarf32,
version: 1,
},
1,
-8,
X86_64::RA,
);
entry.add_instruction(CallFrameInstruction::Cfa(X86_64::RSP, 8));
entry.add_instruction(CallFrameInstruction::Offset(X86_64::RA, -8));
Some(entry)
}
Architecture::Aarch64(_) => {
let mut entry = CommonInformationEntry::new(
Encoding {
address_size: 8,
format: Format::Dwarf32,
version: 1,
},
1,
-8,
AArch64::X30,
);
entry.add_instruction(CallFrameInstruction::Cfa(AArch64::SP, 0));
Some(entry)
}
Architecture::Riscv64(_) => {
use gimli::RiscV;
let mut entry = CommonInformationEntry::new(
Encoding {
address_size: 8,
format: Format::Dwarf32,
version: 1,
},
1,
-8,
RiscV::RA,
);
entry.add_instruction(CallFrameInstruction::Cfa(RiscV::SP, 0));
Some(entry)
}
_ => None,
}
}