Return error for register mapping failure.

This commit removes a panic when a register mapping fails and instead returns
an error from creating the unwind information.
This commit is contained in:
Peter Huene
2020-04-15 14:02:26 -07:00
parent 5dba941180
commit 2fb7e9f3c2
3 changed files with 34 additions and 27 deletions

View File

@@ -12,7 +12,7 @@ type Expression = Vec<u8>;
/// Enumerate the errors possible in mapping Cranelift registers to their DWARF equivalent. /// Enumerate the errors possible in mapping Cranelift registers to their DWARF equivalent.
#[allow(missing_docs)] #[allow(missing_docs)]
#[derive(Error, Debug)] #[derive(Error, Debug, PartialEq, Eq)]
pub enum RegisterMappingError { pub enum RegisterMappingError {
#[error("unable to find bank for register info")] #[error("unable to find bank for register info")]
MissingBank, MissingBank,

View File

@@ -6,7 +6,7 @@ use crate::isa::{
x86::registers::RU, x86::registers::RU,
CallConv, RegUnit, TargetIsa, CallConv, RegUnit, TargetIsa,
}; };
use crate::result::CodegenResult; use crate::result::{CodegenError, CodegenResult};
use alloc::vec::Vec; use alloc::vec::Vec;
use gimli::{write::CommonInformationEntry, Encoding, Format, Register, X86_64}; use gimli::{write::CommonInformationEntry, Encoding, Format, Register, X86_64};
@@ -117,7 +117,7 @@ impl<'a> InstructionBuilder<'a> {
} }
} }
fn push_reg(&mut self, offset: u32, arg: Value) { fn push_reg(&mut self, offset: u32, arg: Value) -> Result<(), RegisterMappingError> {
self.cfa_offset += 8; self.cfa_offset += 8;
let reg = self.func.locations[arg].unwrap_reg(); let reg = self.func.locations[arg].unwrap_reg();
@@ -135,13 +135,10 @@ impl<'a> InstructionBuilder<'a> {
// Pushes in the prologue are register saves, so record an offset of the save // Pushes in the prologue are register saves, so record an offset of the save
self.instructions.push(( self.instructions.push((
offset, offset,
CallFrameInstruction::Offset( CallFrameInstruction::Offset(map_reg(self.isa, reg)?.0, -self.cfa_offset),
map_reg(self.isa, reg)
.expect("a register mapping from cranelift to gimli")
.0,
-self.cfa_offset,
),
)); ));
Ok(())
} }
fn adjust_sp_down(&mut self, offset: u32) { fn adjust_sp_down(&mut self, offset: u32) {
@@ -183,20 +180,23 @@ impl<'a> InstructionBuilder<'a> {
.push((offset, CallFrameInstruction::CfaOffset(self.cfa_offset))); .push((offset, CallFrameInstruction::CfaOffset(self.cfa_offset)));
} }
fn move_reg(&mut self, offset: u32, src: RegUnit, dst: RegUnit) { fn move_reg(
&mut self,
offset: u32,
src: RegUnit,
dst: RegUnit,
) -> Result<(), RegisterMappingError> {
if let Some(fp) = self.frame_register { if let Some(fp) = self.frame_register {
// Check for change in CFA register (RSP is always the starting CFA) // Check for change in CFA register (RSP is always the starting CFA)
if src == (RU::rsp as RegUnit) && dst == fp { if src == (RU::rsp as RegUnit) && dst == fp {
self.instructions.push(( self.instructions.push((
offset, offset,
CallFrameInstruction::CfaRegister( CallFrameInstruction::CfaRegister(map_reg(self.isa, dst)?.0),
map_reg(self.isa, dst)
.expect("a register mapping from cranelift to gimli")
.0,
),
)); ));
} }
} }
Ok(())
} }
fn prologue_imm_const(&mut self, imm: i64) { fn prologue_imm_const(&mut self, imm: i64) {
@@ -210,7 +210,7 @@ impl<'a> InstructionBuilder<'a> {
self.stack_size = Some(imm as i32); self.stack_size = Some(imm as i32);
} }
fn ret(&mut self, inst: Inst) { fn ret(&mut self, inst: Inst) -> Result<(), RegisterMappingError> {
let args = self.func.dfg.inst_args(inst); let args = self.func.dfg.inst_args(inst);
for (i, arg) in args.iter().rev().enumerate() { for (i, arg) in args.iter().rev().enumerate() {
@@ -229,9 +229,7 @@ impl<'a> InstructionBuilder<'a> {
self.instructions.push(( self.instructions.push((
self.epilogue_pop_offsets[i], self.epilogue_pop_offsets[i],
CallFrameInstruction::Cfa( CallFrameInstruction::Cfa(
map_reg(self.isa, RU::rsp as RegUnit) map_reg(self.isa, RU::rsp as RegUnit)?.0,
.expect("a register mapping from cranelift to gimli")
.0,
self.cfa_offset, self.cfa_offset,
), ),
)); ));
@@ -247,17 +245,15 @@ impl<'a> InstructionBuilder<'a> {
// This isn't necessary when using a frame pointer as the CFA doesn't change for CSR restores // This isn't necessary when using a frame pointer as the CFA doesn't change for CSR restores
self.instructions.push(( self.instructions.push((
self.epilogue_pop_offsets[i], self.epilogue_pop_offsets[i],
CallFrameInstruction::SameValue( CallFrameInstruction::SameValue(map_reg(self.isa, reg)?.0),
map_reg(self.isa, reg)
.expect("a register mapping from cranelift to gimli")
.0,
),
)); ));
} }
}; };
} }
self.epilogue_pop_offsets.clear(); self.epilogue_pop_offsets.clear();
Ok(())
} }
fn insert_pop_offset(&mut self, offset: u32) { fn insert_pop_offset(&mut self, offset: u32) {
@@ -332,7 +328,9 @@ pub(crate) fn create_unwind_info(
match builder.func.dfg[inst] { match builder.func.dfg[inst] {
InstructionData::Unary { opcode, arg } => match opcode { InstructionData::Unary { opcode, arg } => match opcode {
Opcode::X86Push => { Opcode::X86Push => {
builder.push_reg(offset, arg); builder
.push_reg(offset, arg)
.map_err(CodegenError::RegisterMappingError)?;
} }
Opcode::AdjustSpDown => { Opcode::AdjustSpDown => {
builder.adjust_sp_down(offset); builder.adjust_sp_down(offset);
@@ -340,7 +338,9 @@ pub(crate) fn create_unwind_info(
_ => {} _ => {}
}, },
InstructionData::CopySpecial { src, dst, .. } => { InstructionData::CopySpecial { src, dst, .. } => {
builder.move_reg(offset, src, dst); builder
.move_reg(offset, src, dst)
.map_err(CodegenError::RegisterMappingError)?;
} }
InstructionData::NullAry { opcode } => match opcode { InstructionData::NullAry { opcode } => match opcode {
Opcode::X86Pop => { Opcode::X86Pop => {
@@ -362,7 +362,9 @@ pub(crate) fn create_unwind_info(
}, },
InstructionData::MultiAry { opcode, .. } => match opcode { InstructionData::MultiAry { opcode, .. } => match opcode {
Opcode::Return => { Opcode::Return => {
builder.ret(inst); builder
.ret(inst)
.map_err(CodegenError::RegisterMappingError)?;
if !is_last_block { if !is_last_block {
builder.restore_state(offset); builder.restore_state(offset);

View File

@@ -30,6 +30,11 @@ pub enum CodegenError {
/// is exceeded, compilation fails. /// is exceeded, compilation fails.
#[error("Code for function is too large")] #[error("Code for function is too large")]
CodeTooLarge, CodeTooLarge,
/// A failure to map Cranelift register representation to a DWARF register representation.
#[cfg(feature = "unwind")]
#[error("Register mapping error")]
RegisterMappingError(crate::isa::unwind::systemv::RegisterMappingError),
} }
/// A convenient alias for a `Result` that uses `CodegenError` as the error type. /// A convenient alias for a `Result` that uses `CodegenError` as the error type.