1 //! Unwind information for System V ABI (Aarch64).
2
3 use crate::isa::aarch64::inst::regs;
4 use crate::isa::unwind::systemv::RegisterMappingError;
5 use gimli::{write::CommonInformationEntry, Encoding, Format, Register};
6 use regalloc::{Reg, RegClass};
7
8 /// Creates a new aarch64 common information entry (CIE).
create_cie() -> CommonInformationEntry9 pub fn create_cie() -> CommonInformationEntry {
10 use gimli::write::CallFrameInstruction;
11
12 let mut entry = CommonInformationEntry::new(
13 Encoding {
14 address_size: 8,
15 format: Format::Dwarf32,
16 version: 1,
17 },
18 4, // Code alignment factor
19 -8, // Data alignment factor
20 Register(regs::link_reg().get_hw_encoding().into()),
21 );
22
23 // Every frame will start with the call frame address (CFA) at SP
24 let sp = Register(regs::stack_reg().get_hw_encoding().into());
25 entry.add_instruction(CallFrameInstruction::Cfa(sp, 0));
26
27 entry
28 }
29
30 /// Map Cranelift registers to their corresponding Gimli registers.
map_reg(reg: Reg) -> Result<Register, RegisterMappingError>31 pub fn map_reg(reg: Reg) -> Result<Register, RegisterMappingError> {
32 // For AArch64 DWARF register mappings, see:
33 //
34 // https://developer.arm.com/documentation/ihi0057/e/?lang=en#dwarf-register-names
35 //
36 // X0--X31 is 0--31; V0--V31 is 64--95.
37 match reg.get_class() {
38 RegClass::I64 => {
39 let reg = reg.get_hw_encoding() as u16;
40 Ok(Register(reg))
41 }
42 RegClass::V128 => {
43 let reg = reg.get_hw_encoding() as u16;
44 Ok(Register(64 + reg))
45 }
46 _ => Err(RegisterMappingError::UnsupportedRegisterBank("class?")),
47 }
48 }
49
50 pub(crate) struct RegisterMapper;
51
52 impl crate::isa::unwind::systemv::RegisterMapper<Reg> for RegisterMapper {
map(&self, reg: Reg) -> Result<u16, RegisterMappingError>53 fn map(&self, reg: Reg) -> Result<u16, RegisterMappingError> {
54 Ok(map_reg(reg)?.0)
55 }
sp(&self) -> u1656 fn sp(&self) -> u16 {
57 regs::stack_reg().get_hw_encoding().into()
58 }
fp(&self) -> Option<u16>59 fn fp(&self) -> Option<u16> {
60 Some(regs::fp_reg().get_hw_encoding().into())
61 }
lr(&self) -> Option<u16>62 fn lr(&self) -> Option<u16> {
63 Some(regs::link_reg().get_hw_encoding().into())
64 }
lr_offset(&self) -> Option<u32>65 fn lr_offset(&self) -> Option<u32> {
66 Some(8)
67 }
68 }
69