Fix all dead-code warnings in cranelift-codegen
This commit is contained in:
@@ -3,11 +3,10 @@
|
||||
//! This module contains types and functions for working with the encoding tables generated by
|
||||
//! `cranelift-codegen/meta/src/gen_encodings.rs`.
|
||||
|
||||
use crate::constant_hash::{probe, Table};
|
||||
use crate::constant_hash::Table;
|
||||
use crate::ir::{Function, InstructionData, Opcode, Type};
|
||||
use crate::isa::{Encoding, Legalize};
|
||||
use crate::settings::PredicateView;
|
||||
use core::ops::Range;
|
||||
|
||||
/// A recipe predicate.
|
||||
///
|
||||
@@ -49,14 +48,6 @@ pub struct Level1Entry<OffT: Into<u32> + Copy> {
|
||||
pub offset: OffT,
|
||||
}
|
||||
|
||||
impl<OffT: Into<u32> + Copy> Level1Entry<OffT> {
|
||||
/// Get the level 2 table range indicated by this entry.
|
||||
fn range(&self) -> Range<usize> {
|
||||
let b = self.offset.into() as usize;
|
||||
b..b + (1 << self.log2len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<OffT: Into<u32> + Copy> Table<Type> for [Level1Entry<OffT>] {
|
||||
fn len(&self) -> usize {
|
||||
self.len()
|
||||
@@ -97,68 +88,6 @@ impl<OffT: Into<u32> + Copy> Table<Opcode> for [Level2Entry<OffT>] {
|
||||
}
|
||||
}
|
||||
|
||||
/// Two-level hash table lookup and iterator construction.
|
||||
///
|
||||
/// Given the controlling type variable and instruction opcode, find the corresponding encoding
|
||||
/// list.
|
||||
///
|
||||
/// Returns an iterator that produces legal encodings for `inst`.
|
||||
pub fn lookup_enclist<'a, OffT1, OffT2>(
|
||||
ctrl_typevar: Type,
|
||||
inst: &'a InstructionData,
|
||||
func: &'a Function,
|
||||
level1_table: &'static [Level1Entry<OffT1>],
|
||||
level2_table: &'static [Level2Entry<OffT2>],
|
||||
enclist: &'static [EncListEntry],
|
||||
legalize_actions: &'static [Legalize],
|
||||
recipe_preds: &'static [RecipePredicate],
|
||||
inst_preds: &'static [InstPredicate],
|
||||
isa_preds: PredicateView<'a>,
|
||||
) -> Encodings<'a>
|
||||
where
|
||||
OffT1: Into<u32> + Copy,
|
||||
OffT2: Into<u32> + Copy,
|
||||
{
|
||||
let (offset, legalize) = match probe(level1_table, ctrl_typevar, ctrl_typevar.index()) {
|
||||
Err(l1idx) => {
|
||||
// No level 1 entry found for the type.
|
||||
// We have a sentinel entry with the default legalization code.
|
||||
(!0, level1_table[l1idx].legalize)
|
||||
}
|
||||
Ok(l1idx) => {
|
||||
// We have a valid level 1 entry for this type.
|
||||
let l1ent = &level1_table[l1idx];
|
||||
let offset = match level2_table.get(l1ent.range()) {
|
||||
Some(l2tab) => {
|
||||
let opcode = inst.opcode();
|
||||
match probe(l2tab, opcode, opcode as usize) {
|
||||
Ok(l2idx) => l2tab[l2idx].offset.into() as usize,
|
||||
Err(_) => !0,
|
||||
}
|
||||
}
|
||||
// The l1ent range is invalid. This means that we just have a customized
|
||||
// legalization code for this type. The level 2 table is empty.
|
||||
None => !0,
|
||||
};
|
||||
(offset, l1ent.legalize)
|
||||
}
|
||||
};
|
||||
|
||||
// Now we have an offset into `enclist` that is `!0` when no encoding list could be found.
|
||||
// The default legalization code is always valid.
|
||||
Encodings::new(
|
||||
offset,
|
||||
legalize,
|
||||
inst,
|
||||
func,
|
||||
enclist,
|
||||
legalize_actions,
|
||||
recipe_preds,
|
||||
inst_preds,
|
||||
isa_preds,
|
||||
)
|
||||
}
|
||||
|
||||
/// Encoding list entry.
|
||||
///
|
||||
/// Encoding lists are represented as sequences of u16 words.
|
||||
|
||||
@@ -24,77 +24,6 @@ pub enum UnwindInfo {
|
||||
SystemV(systemv::UnwindInfo),
|
||||
}
|
||||
|
||||
/// Intermediate representation for the unwind information
|
||||
/// generated by a backend.
|
||||
pub mod input {
|
||||
use crate::binemit::CodeOffset;
|
||||
use alloc::vec::Vec;
|
||||
#[cfg(feature = "enable-serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Elementary operation in the unwind operations.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub enum UnwindCode<Reg> {
|
||||
/// Defines that a register is saved at the specified offset.
|
||||
SaveRegister {
|
||||
/// The saved register.
|
||||
reg: Reg,
|
||||
/// The specified offset relative to the stack pointer.
|
||||
stack_offset: u32,
|
||||
},
|
||||
/// Defines that a register is as defined before call.
|
||||
RestoreRegister {
|
||||
/// The restored register.
|
||||
reg: Reg,
|
||||
},
|
||||
/// The stack pointer was adjusted to allocate the stack.
|
||||
StackAlloc {
|
||||
/// Size to allocate.
|
||||
size: u32,
|
||||
},
|
||||
/// The stack pointer was adjusted to free the stack.
|
||||
StackDealloc {
|
||||
/// Size to deallocate.
|
||||
size: u32,
|
||||
},
|
||||
/// The alternative register was assigned as frame pointer base.
|
||||
SetFramePointer {
|
||||
/// The specified register.
|
||||
reg: Reg,
|
||||
},
|
||||
/// Restores a frame pointer base to default register.
|
||||
RestoreFramePointer,
|
||||
/// Saves the state.
|
||||
RememberState,
|
||||
/// Restores the state.
|
||||
RestoreState,
|
||||
/// On aarch64 ARMv8.3+ devices, enables or disables pointer authentication.
|
||||
Aarch64SetPointerAuth {
|
||||
/// Whether return addresses (hold in LR) contain a pointer-authentication code.
|
||||
return_addresses: bool,
|
||||
},
|
||||
}
|
||||
|
||||
/// Unwind information as generated by a backend.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub struct UnwindInfo<Reg> {
|
||||
/// Size of the prologue.
|
||||
pub prologue_size: CodeOffset,
|
||||
/// Unwind codes for prologue.
|
||||
pub prologue_unwind_codes: Vec<(CodeOffset, UnwindCode<Reg>)>,
|
||||
/// Unwind codes for epilogues.
|
||||
pub epilogues_unwind_codes: Vec<Vec<(CodeOffset, UnwindCode<Reg>)>>,
|
||||
/// Entire function size.
|
||||
pub function_size: CodeOffset,
|
||||
/// Platform word size in bytes.
|
||||
pub word_size: u8,
|
||||
/// Initial stack pointer offset.
|
||||
pub initial_sp_offset: u8,
|
||||
}
|
||||
}
|
||||
|
||||
/// Unwind pseudoinstruction used in VCode backends: represents that
|
||||
/// at the present location, an action has just been taken.
|
||||
///
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//! System V ABI unwind information.
|
||||
|
||||
use crate::binemit::CodeOffset;
|
||||
use crate::isa::unwind::input;
|
||||
use crate::isa::unwind::UnwindInst;
|
||||
use crate::result::{CodegenError, CodegenResult};
|
||||
use alloc::vec::Vec;
|
||||
@@ -259,66 +258,6 @@ pub(crate) fn create_unwind_info_from_insts<MR: RegisterMapper<regalloc::Reg>>(
|
||||
}
|
||||
|
||||
impl UnwindInfo {
|
||||
// TODO: remove `build()` below when old backend is removed. The new backend uses a simpler
|
||||
// approach in `create_unwind_info_from_insts()` above.
|
||||
|
||||
pub(crate) fn build<'b, Reg: PartialEq + Copy>(
|
||||
unwind: input::UnwindInfo<Reg>,
|
||||
map_reg: &'b dyn RegisterMapper<Reg>,
|
||||
) -> CodegenResult<Self> {
|
||||
use input::UnwindCode;
|
||||
let mut builder = InstructionBuilder::new(unwind.initial_sp_offset, map_reg);
|
||||
|
||||
for (offset, c) in unwind.prologue_unwind_codes.iter().chain(
|
||||
unwind
|
||||
.epilogues_unwind_codes
|
||||
.iter()
|
||||
.map(|c| c.iter())
|
||||
.flatten(),
|
||||
) {
|
||||
match c {
|
||||
UnwindCode::SaveRegister { reg, stack_offset } => {
|
||||
builder
|
||||
.save_reg(*offset, *reg, *stack_offset)
|
||||
.map_err(CodegenError::RegisterMappingError)?;
|
||||
}
|
||||
UnwindCode::StackAlloc { size } => {
|
||||
builder.adjust_sp_down_imm(*offset, *size as i64);
|
||||
}
|
||||
UnwindCode::StackDealloc { size } => {
|
||||
builder.adjust_sp_up_imm(*offset, *size as i64);
|
||||
}
|
||||
UnwindCode::RestoreRegister { reg } => {
|
||||
builder
|
||||
.restore_reg(*offset, *reg)
|
||||
.map_err(CodegenError::RegisterMappingError)?;
|
||||
}
|
||||
UnwindCode::SetFramePointer { reg } => {
|
||||
builder
|
||||
.set_cfa_reg(*offset, *reg)
|
||||
.map_err(CodegenError::RegisterMappingError)?;
|
||||
}
|
||||
UnwindCode::RestoreFramePointer => {
|
||||
builder.restore_cfa(*offset);
|
||||
}
|
||||
UnwindCode::RememberState => {
|
||||
builder.remember_state(*offset);
|
||||
}
|
||||
UnwindCode::RestoreState => {
|
||||
builder.restore_state(*offset);
|
||||
}
|
||||
UnwindCode::Aarch64SetPointerAuth { return_addresses } => {
|
||||
builder.set_aarch64_pauth(*offset, *return_addresses);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let instructions = builder.instructions;
|
||||
let len = unwind.function_size;
|
||||
|
||||
Ok(Self { instructions, len })
|
||||
}
|
||||
|
||||
/// Converts the unwind information into a `FrameDescriptionEntry`.
|
||||
pub fn to_fde(&self, address: Address) -> gimli::write::FrameDescriptionEntry {
|
||||
let mut fde = FrameDescriptionEntry::new(address, self.len);
|
||||
@@ -330,145 +269,3 @@ impl UnwindInfo {
|
||||
fde
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: delete the builder below when the old backend is removed.
|
||||
|
||||
struct InstructionBuilder<'a, Reg: PartialEq + Copy> {
|
||||
sp_offset: i32,
|
||||
frame_register: Option<Reg>,
|
||||
saved_state: Option<(i32, Option<Reg>)>,
|
||||
map_reg: &'a dyn RegisterMapper<Reg>,
|
||||
instructions: Vec<(u32, CallFrameInstruction)>,
|
||||
}
|
||||
|
||||
impl<'a, Reg: PartialEq + Copy> InstructionBuilder<'a, Reg> {
|
||||
fn new(sp_offset: u8, map_reg: &'a (dyn RegisterMapper<Reg> + 'a)) -> Self {
|
||||
Self {
|
||||
sp_offset: sp_offset as i32, // CFA offset starts at the specified offset to account for the return address on stack
|
||||
saved_state: None,
|
||||
frame_register: None,
|
||||
map_reg,
|
||||
instructions: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn save_reg(
|
||||
&mut self,
|
||||
offset: u32,
|
||||
reg: Reg,
|
||||
stack_offset: u32,
|
||||
) -> Result<(), RegisterMappingError> {
|
||||
// Pushes in the prologue are register saves, so record an offset of the save
|
||||
self.instructions.push((
|
||||
offset,
|
||||
CallFrameInstruction::Offset(
|
||||
self.map_reg.map(reg)?,
|
||||
stack_offset as i32 - self.sp_offset,
|
||||
),
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn adjust_sp_down_imm(&mut self, offset: u32, imm: i64) {
|
||||
assert!(imm <= core::u32::MAX as i64);
|
||||
|
||||
self.sp_offset += imm as i32;
|
||||
|
||||
// Don't adjust the CFA if we're using a frame pointer
|
||||
if self.frame_register.is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.instructions
|
||||
.push((offset, CallFrameInstruction::CfaOffset(self.sp_offset)));
|
||||
}
|
||||
|
||||
fn adjust_sp_up_imm(&mut self, offset: u32, imm: i64) {
|
||||
assert!(imm <= core::u32::MAX as i64);
|
||||
|
||||
self.sp_offset -= imm as i32;
|
||||
|
||||
// Don't adjust the CFA if we're using a frame pointer
|
||||
if self.frame_register.is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
let cfa_inst_ofs = {
|
||||
// Scan to find and merge with CFA instruction with the same offset.
|
||||
let mut it = self.instructions.iter_mut();
|
||||
loop {
|
||||
match it.next_back() {
|
||||
Some((i_offset, i)) if *i_offset == offset => {
|
||||
if let CallFrameInstruction::Cfa(_, o) = i {
|
||||
break Some(o);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
break None;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(o) = cfa_inst_ofs {
|
||||
// Update previous CFA instruction.
|
||||
*o = self.sp_offset;
|
||||
} else {
|
||||
// Add just CFA offset instruction.
|
||||
self.instructions
|
||||
.push((offset, CallFrameInstruction::CfaOffset(self.sp_offset)));
|
||||
}
|
||||
}
|
||||
|
||||
fn set_cfa_reg(&mut self, offset: u32, reg: Reg) -> Result<(), RegisterMappingError> {
|
||||
self.instructions.push((
|
||||
offset,
|
||||
CallFrameInstruction::CfaRegister(self.map_reg.map(reg)?),
|
||||
));
|
||||
self.frame_register = Some(reg);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn restore_cfa(&mut self, offset: u32) {
|
||||
// Restore SP and its offset.
|
||||
self.instructions.push((
|
||||
offset,
|
||||
CallFrameInstruction::Cfa(self.map_reg.sp(), self.sp_offset),
|
||||
));
|
||||
self.frame_register = None;
|
||||
}
|
||||
|
||||
fn restore_reg(&mut self, offset: u32, reg: Reg) -> Result<(), RegisterMappingError> {
|
||||
// Pops in the epilogue are register restores, so record a "same value" for the register
|
||||
self.instructions.push((
|
||||
offset,
|
||||
CallFrameInstruction::SameValue(self.map_reg.map(reg)?),
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remember_state(&mut self, offset: u32) {
|
||||
self.saved_state = Some((self.sp_offset, self.frame_register));
|
||||
|
||||
self.instructions
|
||||
.push((offset, CallFrameInstruction::RememberState));
|
||||
}
|
||||
|
||||
fn restore_state(&mut self, offset: u32) {
|
||||
let (sp_offset, frame_register) = self.saved_state.take().unwrap();
|
||||
self.sp_offset = sp_offset;
|
||||
self.frame_register = frame_register;
|
||||
|
||||
self.instructions
|
||||
.push((offset, CallFrameInstruction::RestoreState));
|
||||
}
|
||||
|
||||
fn set_aarch64_pauth(&mut self, offset: u32, return_addresses: bool) {
|
||||
self.instructions.push((
|
||||
offset,
|
||||
CallFrameInstruction::Aarch64SetPointerAuth { return_addresses },
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
//! Windows x64 ABI unwind information.
|
||||
|
||||
use crate::isa::unwind::input;
|
||||
use crate::result::{CodegenError, CodegenResult};
|
||||
use alloc::vec::Vec;
|
||||
use log::warn;
|
||||
@@ -259,76 +258,6 @@ impl UnwindInfo {
|
||||
.iter()
|
||||
.fold(0, |nodes, c| nodes + c.node_count())
|
||||
}
|
||||
|
||||
// TODO: remove `build()` below when old backend is removed. The new backend uses
|
||||
// a simpler approach in `create_unwind_info_from_insts()` below.
|
||||
|
||||
pub(crate) fn build<Reg: PartialEq + Copy + std::fmt::Debug, MR: RegisterMapper<Reg>>(
|
||||
unwind: input::UnwindInfo<Reg>,
|
||||
) -> CodegenResult<Self> {
|
||||
use crate::isa::unwind::input::UnwindCode as InputUnwindCode;
|
||||
|
||||
let word_size: u32 = unwind.word_size.into();
|
||||
let mut unwind_codes = Vec::new();
|
||||
for (offset, c) in unwind.prologue_unwind_codes.iter() {
|
||||
match c {
|
||||
InputUnwindCode::SaveRegister { reg, stack_offset } => {
|
||||
let reg = MR::map(*reg);
|
||||
let offset = ensure_unwind_offset(*offset)?;
|
||||
match reg {
|
||||
MappedRegister::Int(reg) => {
|
||||
// Attempt to convert sequence of the `InputUnwindCode`:
|
||||
// `StackAlloc { size = word_size }`, `SaveRegister { stack_offset: 0 }`
|
||||
// to the shorter `UnwindCode::PushRegister`.
|
||||
let push_reg_sequence = if let Some(UnwindCode::StackAlloc {
|
||||
instruction_offset: alloc_offset,
|
||||
size,
|
||||
}) = unwind_codes.last()
|
||||
{
|
||||
*size == word_size && offset == *alloc_offset && *stack_offset == 0
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if push_reg_sequence {
|
||||
*unwind_codes.last_mut().unwrap() = UnwindCode::PushRegister {
|
||||
instruction_offset: offset,
|
||||
reg,
|
||||
};
|
||||
} else {
|
||||
unwind_codes.push(UnwindCode::SaveReg {
|
||||
instruction_offset: offset,
|
||||
reg,
|
||||
stack_offset: *stack_offset,
|
||||
});
|
||||
}
|
||||
}
|
||||
MappedRegister::Xmm(reg) => {
|
||||
unwind_codes.push(UnwindCode::SaveXmm {
|
||||
instruction_offset: offset,
|
||||
reg,
|
||||
stack_offset: *stack_offset,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
InputUnwindCode::StackAlloc { size } => {
|
||||
unwind_codes.push(UnwindCode::StackAlloc {
|
||||
instruction_offset: ensure_unwind_offset(*offset)?,
|
||||
size: *size,
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
flags: 0, // this assumes cranelift functions have no SEH handlers
|
||||
prologue_size: ensure_unwind_offset(unwind.prologue_size)?,
|
||||
frame_register: None,
|
||||
frame_register_offset: 0,
|
||||
unwind_codes,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const UNWIND_RBP_REG: u8 = 5;
|
||||
|
||||
Reference in New Issue
Block a user