Remove more old backend ISA concepts (#3402)
This also paves the way for unifying TargetIsa and MachBackend, since now they map one to one. In theory the two traits could be merged, which would be nice to limit the number of total concepts. Also they have quite different responsibilities, so it might be fine to keep them separate. Interestingly, this PR started as removing RegInfo from the TargetIsa trait since the adapter returned a dummy value there. From the fallout, noticed that all Display implementations didn't needed an ISA anymore (since these were only used to render ISA specific registers). Also the whole family of RegInfo / ValueLoc / RegUnit was exclusively used for the old backend, and these could be removed. Notably, some IR instructions needed to be removed, because they were using RegUnit too: this was the oddball of regfill / regmove / regspill / copy_special, which were IR instructions inserted by the old regalloc. Fare thee well!
This commit is contained in:
@@ -15,9 +15,7 @@
|
||||
//! `CodeSink::put*` methods, so the performance impact of the virtual callbacks is less severe.
|
||||
use super::{Addend, CodeInfo, CodeOffset, CodeSink, Reloc};
|
||||
use crate::binemit::stack_map::StackMap;
|
||||
use crate::ir::entities::Value;
|
||||
use crate::ir::{ConstantOffset, ExternalName, Function, JumpTable, Opcode, SourceLoc, TrapCode};
|
||||
use crate::isa::TargetIsa;
|
||||
use crate::ir::{ConstantOffset, ExternalName, JumpTable, Opcode, SourceLoc, TrapCode};
|
||||
use core::ptr::write_unaligned;
|
||||
|
||||
/// A `CodeSink` that writes binary machine code directly into memory.
|
||||
@@ -38,7 +36,6 @@ pub struct MemoryCodeSink<'a> {
|
||||
offset: isize,
|
||||
relocs: &'a mut dyn RelocSink,
|
||||
traps: &'a mut dyn TrapSink,
|
||||
stack_maps: &'a mut dyn StackMapSink,
|
||||
/// Information about the generated code and read-only data.
|
||||
pub info: CodeInfo,
|
||||
}
|
||||
@@ -54,7 +51,6 @@ impl<'a> MemoryCodeSink<'a> {
|
||||
data: *mut u8,
|
||||
relocs: &'a mut dyn RelocSink,
|
||||
traps: &'a mut dyn TrapSink,
|
||||
stack_maps: &'a mut dyn StackMapSink,
|
||||
) -> Self {
|
||||
Self {
|
||||
data,
|
||||
@@ -67,7 +63,6 @@ impl<'a> MemoryCodeSink<'a> {
|
||||
},
|
||||
relocs,
|
||||
traps,
|
||||
stack_maps,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -174,12 +169,6 @@ impl<'a> CodeSink for MemoryCodeSink<'a> {
|
||||
self.info.total_size = self.offset();
|
||||
}
|
||||
|
||||
fn add_stack_map(&mut self, val_list: &[Value], func: &Function, isa: &dyn TargetIsa) {
|
||||
let ofs = self.offset();
|
||||
let stack_map = StackMap::from_values(&val_list, func, isa);
|
||||
self.stack_maps.add_stack_map(ofs, stack_map);
|
||||
}
|
||||
|
||||
fn add_call_site(&mut self, opcode: Opcode, loc: SourceLoc) {
|
||||
debug_assert!(
|
||||
opcode.is_call(),
|
||||
|
||||
@@ -11,7 +11,6 @@ pub use self::memorysink::{
|
||||
TrapSink,
|
||||
};
|
||||
pub use self::stack_map::StackMap;
|
||||
use crate::ir::entities::Value;
|
||||
use crate::ir::{
|
||||
ConstantOffset, ExternalName, Function, Inst, JumpTable, Opcode, SourceLoc, TrapCode,
|
||||
};
|
||||
@@ -169,9 +168,6 @@ pub trait CodeSink {
|
||||
/// Read-only data output is complete, we're done.
|
||||
fn end_codegen(&mut self);
|
||||
|
||||
/// Add a stack map at the current code offset.
|
||||
fn add_stack_map(&mut self, _: &[Value], _: &Function, _: &dyn TargetIsa);
|
||||
|
||||
/// Add a call site for a call with the given opcode, returning at the current offset.
|
||||
fn add_call_site(&mut self, _: Opcode, _: SourceLoc) {
|
||||
// Default implementation doesn't need to do anything.
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use crate::bitset::BitSet;
|
||||
use crate::ir;
|
||||
use crate::isa::TargetIsa;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
type Num = u32;
|
||||
@@ -76,57 +74,6 @@ pub struct StackMap {
|
||||
}
|
||||
|
||||
impl StackMap {
|
||||
/// Create a `StackMap` based on where references are located on a
|
||||
/// function's stack.
|
||||
pub fn from_values(
|
||||
args: &[ir::entities::Value],
|
||||
func: &ir::Function,
|
||||
isa: &dyn TargetIsa,
|
||||
) -> Self {
|
||||
let loc = &func.locations;
|
||||
let mut live_ref_in_stack_slot = crate::HashSet::new();
|
||||
// References can be in registers, and live registers values are pushed onto the stack before calls and traps.
|
||||
// TODO: Implement register maps. If a register containing a reference is spilled and reused after a safepoint,
|
||||
// it could contain a stale reference value if the garbage collector relocated the value.
|
||||
for val in args {
|
||||
if let Some(value_loc) = loc.get(*val) {
|
||||
match *value_loc {
|
||||
ir::ValueLoc::Stack(stack_slot) => {
|
||||
live_ref_in_stack_slot.insert(stack_slot);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let stack = &func.stack_slots;
|
||||
let info = func.stack_slots.layout_info.unwrap();
|
||||
|
||||
// Refer to the doc comment for `StackMap` above to understand the
|
||||
// bitmap representation used here.
|
||||
let map_size = (info.frame_size + info.inbound_args_size) as usize;
|
||||
let word_size = isa.pointer_bytes() as usize;
|
||||
let num_words = map_size / word_size;
|
||||
|
||||
let mut vec = alloc::vec::Vec::with_capacity(num_words);
|
||||
vec.resize(num_words, false);
|
||||
|
||||
for (ss, ssd) in stack.iter() {
|
||||
if !live_ref_in_stack_slot.contains(&ss)
|
||||
|| ssd.kind == ir::stackslot::StackSlotKind::OutgoingArg
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
debug_assert!(ssd.size as usize == word_size);
|
||||
let bytes_from_bottom = info.frame_size as i32 + ssd.offset.unwrap();
|
||||
let words_from_bottom = (bytes_from_bottom as usize) / word_size;
|
||||
vec[words_from_bottom] = true;
|
||||
}
|
||||
|
||||
Self::from_slice(&vec)
|
||||
}
|
||||
|
||||
/// Create a vec of Bitsets from a slice of bools.
|
||||
pub fn from_slice(vec: &[bool]) -> Self {
|
||||
let len = vec.len();
|
||||
|
||||
Reference in New Issue
Block a user