Path: blob/main/cranelift/codegen/src/isa/aarch64/inst/unwind/systemv.rs
1693 views
//! Unwind information for System V ABI (Aarch64).12use crate::isa::aarch64::inst::regs;3use crate::isa::unwind::systemv::RegisterMappingError;4use crate::machinst::{Reg, RegClass};5use gimli::{Encoding, Format, Register, write::CommonInformationEntry};67/// Creates a new aarch64 common information entry (CIE).8pub fn create_cie() -> CommonInformationEntry {9use gimli::write::CallFrameInstruction;1011let mut entry = CommonInformationEntry::new(12Encoding {13address_size: 8,14format: Format::Dwarf32,15version: 1,16},174, // Code alignment factor18-8, // Data alignment factor19Register(regs::link_reg().to_real_reg().unwrap().hw_enc().into()),20);2122// Every frame will start with the call frame address (CFA) at SP23let sp = Register((regs::stack_reg().to_real_reg().unwrap().hw_enc() & 31).into());24entry.add_instruction(CallFrameInstruction::Cfa(sp, 0));2526entry27}2829/// Map Cranelift registers to their corresponding Gimli registers.30pub fn map_reg(reg: Reg) -> Result<Register, RegisterMappingError> {31// For AArch64 DWARF register mappings, see:32//33// https://developer.arm.com/documentation/ihi0057/e/?lang=en#dwarf-register-names34//35// X0--X31 is 0--31; V0--V31 is 64--95.36match reg.class() {37RegClass::Int => {38let reg = (reg.to_real_reg().unwrap().hw_enc() & 31) as u16;39Ok(Register(reg))40}41RegClass::Float => {42let reg = reg.to_real_reg().unwrap().hw_enc() as u16;43Ok(Register(64 + reg))44}45RegClass::Vector => unreachable!(),46}47}4849pub(crate) struct RegisterMapper;5051impl crate::isa::unwind::systemv::RegisterMapper<Reg> for RegisterMapper {52fn map(&self, reg: Reg) -> Result<u16, RegisterMappingError> {53Ok(map_reg(reg)?.0)54}55fn fp(&self) -> Option<u16> {56Some(regs::fp_reg().to_real_reg().unwrap().hw_enc().into())57}58fn lr(&self) -> Option<u16> {59Some(regs::link_reg().to_real_reg().unwrap().hw_enc().into())60}61fn lr_offset(&self) -> Option<u32> {62Some(8)63}64}6566#[cfg(test)]67mod tests {68use crate::Context;69use crate::cursor::{Cursor, FuncCursor};70use crate::ir::{71AbiParam, Function, InstBuilder, Signature, StackSlotData, StackSlotKind, types,72};73use crate::isa::{CallConv, lookup};74use crate::settings::{Flags, builder};75use gimli::write::Address;76use target_lexicon::triple;7778#[test]79fn test_simple_func() {80let isa = lookup(triple!("aarch64"))81.expect("expect aarch64 ISA")82.finish(Flags::new(builder()))83.expect("Creating compiler backend");8485let mut context = Context::for_function(create_function(86CallConv::SystemV,87Some(StackSlotData::new(StackSlotKind::ExplicitSlot, 64, 0)),88));8990let code = context91.compile(&*isa, &mut Default::default())92.expect("expected compilation");9394let fde = match code95.create_unwind_info(isa.as_ref())96.expect("can create unwind info")97{98Some(crate::isa::unwind::UnwindInfo::SystemV(info)) => {99info.to_fde(Address::Constant(1234))100}101_ => panic!("expected unwind information"),102};103104assert_eq!(105format!("{fde:?}"),106"FrameDescriptionEntry { address: Constant(1234), length: 24, lsda: None, instructions: [(4, CfaOffset(16)), (4, Offset(Register(29), -16)), (4, Offset(Register(30), -8)), (8, CfaRegister(Register(29)))] }"107);108}109110fn create_function(call_conv: CallConv, stack_slot: Option<StackSlotData>) -> Function {111let mut func = Function::with_name_signature(Default::default(), Signature::new(call_conv));112113let block0 = func.dfg.make_block();114let mut pos = FuncCursor::new(&mut func);115pos.insert_block(block0);116pos.ins().return_(&[]);117118if let Some(stack_slot) = stack_slot {119func.sized_stack_slots.push(stack_slot);120}121122func123}124125#[test]126fn test_multi_return_func() {127let isa = lookup(triple!("aarch64"))128.expect("expect aarch64 ISA")129.finish(Flags::new(builder()))130.expect("Creating compiler backend");131132let mut context = Context::for_function(create_multi_return_function(CallConv::SystemV));133134let code = context135.compile(&*isa, &mut Default::default())136.expect("expected compilation");137138let fde = match code139.create_unwind_info(isa.as_ref())140.expect("can create unwind info")141{142Some(crate::isa::unwind::UnwindInfo::SystemV(info)) => {143info.to_fde(Address::Constant(4321))144}145_ => panic!("expected unwind information"),146};147148assert_eq!(149format!("{fde:?}"),150"FrameDescriptionEntry { address: Constant(4321), length: 16, lsda: None, instructions: [] }"151);152}153154fn create_multi_return_function(call_conv: CallConv) -> Function {155let mut sig = Signature::new(call_conv);156sig.params.push(AbiParam::new(types::I32));157let mut func = Function::with_name_signature(Default::default(), sig);158159let block0 = func.dfg.make_block();160let v0 = func.dfg.append_block_param(block0, types::I32);161let block1 = func.dfg.make_block();162let block2 = func.dfg.make_block();163164let mut pos = FuncCursor::new(&mut func);165pos.insert_block(block0);166pos.ins().brif(v0, block2, &[], block1, &[]);167168pos.insert_block(block1);169pos.ins().return_(&[]);170171pos.insert_block(block2);172pos.ins().return_(&[]);173174func175}176}177178179