Path: blob/main/cranelift/codegen/src/isa/riscv64/inst/unwind/systemv.rs
1693 views
//! Unwind information for System V ABI (Riscv64).12use crate::isa::riscv64::inst::regs;3use crate::isa::unwind::systemv::RegisterMappingError;4use crate::machinst::Reg;5use gimli::{Encoding, Format, Register, write::CommonInformationEntry};6use regalloc2::RegClass;78/// Creates a new riscv64 common information entry (CIE).9pub fn create_cie() -> CommonInformationEntry {10use gimli::write::CallFrameInstruction;1112let mut entry = CommonInformationEntry::new(13Encoding {14address_size: 8,15format: Format::Dwarf32,16version: 1,17},182, // Code alignment factor19-8, // Data alignment factor20Register(regs::link_reg().to_real_reg().unwrap().hw_enc() as u16),21);2223// Every frame will start with the call frame address (CFA) at SP24let sp = Register(regs::stack_reg().to_real_reg().unwrap().hw_enc().into());25entry.add_instruction(CallFrameInstruction::Cfa(sp, 0));2627entry28}2930/// Map Cranelift registers to their corresponding Gimli registers.31pub fn map_reg(reg: Reg) -> Result<Register, RegisterMappingError> {32let reg_offset = match reg.class() {33RegClass::Int => 0,34RegClass::Float => 32,35RegClass::Vector => 64,36};3738let reg = reg.to_real_reg().unwrap().hw_enc() as u16;39Ok(Register(reg_offset + reg))40}4142pub(crate) struct RegisterMapper;4344impl crate::isa::unwind::systemv::RegisterMapper<Reg> for RegisterMapper {45fn map(&self, reg: Reg) -> Result<u16, RegisterMappingError> {46Ok(map_reg(reg)?.0)47}48fn fp(&self) -> Option<u16> {49Some(regs::fp_reg().to_real_reg().unwrap().hw_enc() as u16)50}51fn lr(&self) -> Option<u16> {52Some(regs::link_reg().to_real_reg().unwrap().hw_enc() as u16)53}54fn lr_offset(&self) -> Option<u32> {55Some(8)56}57}5859#[cfg(test)]60mod tests {61use crate::cursor::{Cursor, FuncCursor};6263use crate::Context;64use crate::ir::{65AbiParam, Function, InstBuilder, Signature, StackSlotData, StackSlotKind, UserFuncName,66types,67};68use crate::isa::{CallConv, lookup};69use crate::settings::{Flags, builder};70use gimli::write::Address;71use target_lexicon::triple;7273#[test]74fn test_simple_func() {75let isa = lookup(triple!("riscv64"))76.expect("expect riscv64 ISA")77.finish(Flags::new(builder()))78.expect("Creating compiler backend");7980let mut context = Context::for_function(create_function(81CallConv::SystemV,82Some(StackSlotData::new(StackSlotKind::ExplicitSlot, 64, 0)),83));8485let code = context86.compile(&*isa, &mut Default::default())87.expect("expected compilation");8889let fde = match code90.create_unwind_info(isa.as_ref())91.expect("can create unwind info")92{93Some(crate::isa::unwind::UnwindInfo::SystemV(info)) => {94info.to_fde(Address::Constant(1234))95}96_ => panic!("expected unwind information"),97};9899assert_eq!(100format!("{fde:?}"),101"FrameDescriptionEntry { address: Constant(1234), length: 40, lsda: None, instructions: [(12, CfaOffset(16)), (12, Offset(Register(8), -16)), (12, Offset(Register(1), -8)), (16, CfaRegister(Register(8)))] }"102);103}104105fn create_function(call_conv: CallConv, stack_slot: Option<StackSlotData>) -> Function {106let mut func =107Function::with_name_signature(UserFuncName::user(0, 0), Signature::new(call_conv));108109let block0 = func.dfg.make_block();110let mut pos = FuncCursor::new(&mut func);111pos.insert_block(block0);112pos.ins().return_(&[]);113114if let Some(stack_slot) = stack_slot {115func.sized_stack_slots.push(stack_slot);116}117118func119}120121#[test]122fn test_multi_return_func() {123let isa = lookup(triple!("riscv64"))124.expect("expect riscv64 ISA")125.finish(Flags::new(builder()))126.expect("Creating compiler backend");127128let mut context = Context::for_function(create_multi_return_function(CallConv::SystemV));129130let code = context131.compile(&*isa, &mut Default::default())132.expect("expected compilation");133134let fde = match code135.create_unwind_info(isa.as_ref())136.expect("can create unwind info")137{138Some(crate::isa::unwind::UnwindInfo::SystemV(info)) => {139info.to_fde(Address::Constant(4321))140}141_ => panic!("expected unwind information"),142};143144assert_eq!(145format!("{fde:?}"),146"FrameDescriptionEntry { address: Constant(4321), length: 16, lsda: None, instructions: [] }"147);148}149150fn create_multi_return_function(call_conv: CallConv) -> Function {151let mut sig = Signature::new(call_conv);152sig.params.push(AbiParam::new(types::I32));153let mut func = Function::with_name_signature(UserFuncName::user(0, 0), sig);154155let block0 = func.dfg.make_block();156let v0 = func.dfg.append_block_param(block0, types::I32);157let block1 = func.dfg.make_block();158let block2 = func.dfg.make_block();159160let mut pos = FuncCursor::new(&mut func);161pos.insert_block(block0);162pos.ins().brif(v0, block2, &[], block1, &[]);163164pos.insert_block(block1);165pos.ins().return_(&[]);166167pos.insert_block(block2);168pos.ins().return_(&[]);169170func171}172}173174175