Path: blob/main/cranelift/codegen/src/isa/s390x/inst/unwind/systemv.rs
1693 views
//! Unwind information for System V ABI (s390x).12use crate::isa::unwind::systemv::RegisterMappingError;3use crate::machinst::{Reg, RegClass};4use gimli::{Encoding, Format, Register, write::CommonInformationEntry};56/// Creates a new s390x common information entry (CIE).7pub fn create_cie() -> CommonInformationEntry {8use gimli::write::CallFrameInstruction;910let mut entry = CommonInformationEntry::new(11Encoding {12address_size: 8,13format: Format::Dwarf32,14version: 1,15},161, // Code alignment factor17-8, // Data alignment factor18Register(14), // Return address column - register %r1419);2021// Every frame will start with the call frame address (CFA) at %r15 + 160.22entry.add_instruction(CallFrameInstruction::Cfa(Register(15), 160));2324entry25}2627/// Map Cranelift registers to their corresponding Gimli registers.28pub fn map_reg(reg: Reg) -> Result<Register, RegisterMappingError> {29const GPR_MAP: [gimli::Register; 16] = [30Register(0),31Register(1),32Register(2),33Register(3),34Register(4),35Register(5),36Register(6),37Register(7),38Register(8),39Register(9),40Register(10),41Register(11),42Register(12),43Register(13),44Register(14),45Register(15),46];47const VR_MAP: [gimli::Register; 32] = [48Register(16),49Register(20),50Register(17),51Register(21),52Register(18),53Register(22),54Register(19),55Register(23),56Register(24),57Register(28),58Register(25),59Register(29),60Register(26),61Register(30),62Register(27),63Register(31),64Register(68),65Register(72),66Register(69),67Register(73),68Register(70),69Register(74),70Register(71),71Register(75),72Register(76),73Register(80),74Register(77),75Register(81),76Register(78),77Register(82),78Register(79),79Register(83),80];8182match reg.class() {83RegClass::Int => Ok(GPR_MAP[reg.to_real_reg().unwrap().hw_enc() as usize]),84RegClass::Float => Ok(VR_MAP[reg.to_real_reg().unwrap().hw_enc() as usize]),85RegClass::Vector => unreachable!(),86}87}8889pub(crate) struct RegisterMapper;9091impl crate::isa::unwind::systemv::RegisterMapper<Reg> for RegisterMapper {92fn map(&self, reg: Reg) -> Result<u16, RegisterMappingError> {93Ok(map_reg(reg)?.0)94}95}9697#[cfg(test)]98mod tests {99use crate::Context;100use crate::cursor::{Cursor, FuncCursor};101use crate::ir::{102AbiParam, Function, InstBuilder, Signature, StackSlotData, StackSlotKind, types,103};104use crate::isa::{CallConv, lookup};105use crate::settings::{Flags, builder};106use gimli::write::Address;107use target_lexicon::triple;108109#[test]110fn test_simple_func() {111let isa = lookup(triple!("s390x"))112.expect("expect s390x ISA")113.finish(Flags::new(builder()))114.expect("Creating compiler backend");115116let mut context = Context::for_function(create_function(117CallConv::SystemV,118Some(StackSlotData::new(StackSlotKind::ExplicitSlot, 64, 0)),119));120121let code = context122.compile(&*isa, &mut Default::default())123.expect("expected compilation");124125let fde = match code126.create_unwind_info(isa.as_ref())127.expect("can create unwind info")128{129Some(crate::isa::unwind::UnwindInfo::SystemV(info)) => {130info.to_fde(Address::Constant(1234))131}132_ => panic!("expected unwind information"),133};134135assert_eq!(136format!("{fde:?}"),137"FrameDescriptionEntry { address: Constant(1234), length: 10, lsda: None, instructions: [(4, CfaOffset(224))] }"138);139}140141fn create_function(call_conv: CallConv, stack_slot: Option<StackSlotData>) -> Function {142let mut func = Function::with_name_signature(Default::default(), Signature::new(call_conv));143144let block0 = func.dfg.make_block();145let mut pos = FuncCursor::new(&mut func);146pos.insert_block(block0);147pos.ins().return_(&[]);148149if let Some(stack_slot) = stack_slot {150func.sized_stack_slots.push(stack_slot);151}152153func154}155156#[test]157fn test_multi_return_func() {158let isa = lookup(triple!("s390x"))159.expect("expect s390x ISA")160.finish(Flags::new(builder()))161.expect("Creating compiler backend");162163let mut context = Context::for_function(create_multi_return_function(164CallConv::SystemV,165Some(StackSlotData::new(StackSlotKind::ExplicitSlot, 64, 0)),166));167168let code = context169.compile(&*isa, &mut Default::default())170.expect("expected compilation");171172let fde = match code173.create_unwind_info(isa.as_ref())174.expect("can create unwind info")175{176Some(crate::isa::unwind::UnwindInfo::SystemV(info)) => {177info.to_fde(Address::Constant(4321))178}179_ => panic!("expected unwind information"),180};181182assert_eq!(183format!("{fde:?}"),184"FrameDescriptionEntry { address: Constant(4321), length: 26, lsda: None, instructions: [(4, CfaOffset(224))] }"185);186}187188fn create_multi_return_function(189call_conv: CallConv,190stack_slot: Option<StackSlotData>,191) -> Function {192let mut sig = Signature::new(call_conv);193sig.params.push(AbiParam::new(types::I32));194let mut func = Function::with_name_signature(Default::default(), sig);195196let block0 = func.dfg.make_block();197let v0 = func.dfg.append_block_param(block0, types::I32);198let block1 = func.dfg.make_block();199let block2 = func.dfg.make_block();200201let mut pos = FuncCursor::new(&mut func);202pos.insert_block(block0);203pos.ins().brif(v0, block2, &[], block1, &[]);204205pos.insert_block(block1);206pos.ins().return_(&[]);207208pos.insert_block(block2);209pos.ins().return_(&[]);210211if let Some(stack_slot) = stack_slot {212func.sized_stack_slots.push(stack_slot);213}214215func216}217}218219220