Skip to content

Commit def6c41

Browse files
authored
Merge pull request #1545 from ltratt/varlocation_generic
Break some unfortunate dependencies in jitc_yk
2 parents a25c7a4 + a7050e7 commit def6c41

File tree

11 files changed

+314
-300
lines changed

11 files changed

+314
-300
lines changed

ykrt/src/compile/jitc_yk/codegen/reg_alloc.rs

Lines changed: 2 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,9 @@
44
//! - describes the generic interface to register allocators.
55
//! - contains concrete implementations of register allocators.
66
7-
use crate::compile::jitc_yk::jit_ir::{InstIdx, Module};
8-
use dynasmrt::x64::{Rq, Rx};
9-
107
/// Where is an SSA variable stored?
11-
///
12-
/// FIXME: Too much of this is hard-coded to the x64 backend.
138
#[derive(Debug, Clone, Copy, PartialEq)]
14-
pub(crate) enum VarLocation {
9+
pub(crate) enum VarLocation<R> {
1510
/// The SSA variable is on the stack of the of the executed trace or the main interpreter loop.
1611
/// Since we execute the trace on the main interpreter frame we can't distinguish the two.
1712
///
@@ -34,7 +29,7 @@ pub(crate) enum VarLocation {
3429
/// The SSA variable is in a register.
3530
///
3631
/// Note: two SSA variables can alias to the same `Register` location.
37-
Register(Register),
32+
Register(R),
3833
/// A constant integer `bits` wide (see [jit_ir::Const::ConstInt] for the constraints on the
3934
/// bit width) and with value `v`.
4035
ConstInt { bits: u32, v: u64 },
@@ -43,131 +38,3 @@ pub(crate) enum VarLocation {
4338
/// A constant pointer.
4439
ConstPtr(usize),
4540
}
46-
47-
#[derive(Debug, Clone, Copy, PartialEq)]
48-
pub(crate) enum Register {
49-
GP(Rq), // general purpose
50-
FP(Rx), // floating point
51-
}
52-
53-
#[cfg(target_arch = "x86_64")]
54-
impl VarLocation {
55-
pub(crate) fn from_yksmp_location(m: &Module, iidx: InstIdx, x: &yksmp::Location) -> Self {
56-
match x {
57-
yksmp::Location::Register(0, ..) => VarLocation::Register(Register::GP(Rq::RAX)),
58-
yksmp::Location::Register(1, ..) => {
59-
// Since the control point passes the stackmap ID via RDX this case only happens in
60-
// side-traces.
61-
VarLocation::Register(Register::GP(Rq::RDX))
62-
}
63-
yksmp::Location::Register(2, ..) => VarLocation::Register(Register::GP(Rq::RCX)),
64-
yksmp::Location::Register(3, ..) => VarLocation::Register(Register::GP(Rq::RBX)),
65-
yksmp::Location::Register(4, ..) => VarLocation::Register(Register::GP(Rq::RSI)),
66-
yksmp::Location::Register(5, ..) => VarLocation::Register(Register::GP(Rq::RDI)),
67-
yksmp::Location::Register(8, ..) => VarLocation::Register(Register::GP(Rq::R8)),
68-
yksmp::Location::Register(9, ..) => VarLocation::Register(Register::GP(Rq::R9)),
69-
yksmp::Location::Register(10, ..) => VarLocation::Register(Register::GP(Rq::R10)),
70-
yksmp::Location::Register(11, ..) => VarLocation::Register(Register::GP(Rq::R11)),
71-
yksmp::Location::Register(12, ..) => VarLocation::Register(Register::GP(Rq::R12)),
72-
yksmp::Location::Register(13, ..) => VarLocation::Register(Register::GP(Rq::R13)),
73-
yksmp::Location::Register(14, ..) => VarLocation::Register(Register::GP(Rq::R14)),
74-
yksmp::Location::Register(15, ..) => VarLocation::Register(Register::GP(Rq::R15)),
75-
yksmp::Location::Register(x, ..) if *x >= 17 && *x <= 32 => VarLocation::Register(
76-
Register::FP(super::x64::lsregalloc::FP_REGS[usize::from(x - 17)]),
77-
),
78-
yksmp::Location::Direct(6, off, size) => VarLocation::Direct {
79-
frame_off: *off,
80-
size: usize::from(*size),
81-
},
82-
// Since the trace shares the same stack frame as the main interpreter loop, we can
83-
// translate indirect locations into normal stack locations. Note that while stackmaps
84-
// use negative offsets, we use positive offsets for stack locations.
85-
yksmp::Location::Indirect(6, off, size) => VarLocation::Stack {
86-
frame_off: u32::try_from(*off * -1).unwrap(),
87-
size: usize::from(*size),
88-
},
89-
yksmp::Location::Constant(v) => {
90-
// FIXME: This isn't fine-grained enough, as there may be constants of any
91-
// bit-size.
92-
let byte_size = m.inst(iidx).def_byte_size(m);
93-
debug_assert!(byte_size <= 8);
94-
VarLocation::ConstInt {
95-
bits: u32::try_from(byte_size).unwrap() * 8,
96-
v: u64::from(*v),
97-
}
98-
}
99-
e => {
100-
todo!("{:?}", e);
101-
}
102-
}
103-
}
104-
}
105-
106-
impl From<&VarLocation> for yksmp::Location {
107-
fn from(val: &VarLocation) -> Self {
108-
match val {
109-
VarLocation::Stack { frame_off, size } => {
110-
// A stack location translates is an offset in relation to RBP which has the DWARF
111-
// number 6.
112-
yksmp::Location::Indirect(
113-
6,
114-
-i32::try_from(*frame_off).unwrap(),
115-
u16::try_from(*size).unwrap(),
116-
)
117-
}
118-
VarLocation::Direct { frame_off, size } => {
119-
yksmp::Location::Direct(6, *frame_off, u16::try_from(*size).unwrap())
120-
}
121-
VarLocation::Register(reg) => {
122-
let dwarf = match reg {
123-
Register::GP(reg) => match reg {
124-
Rq::RAX => 0,
125-
Rq::RDX => 1,
126-
Rq::RCX => 2,
127-
Rq::RBX => 3,
128-
Rq::RSI => 4,
129-
Rq::RDI => 5,
130-
Rq::R8 => 8,
131-
Rq::R9 => 9,
132-
Rq::R10 => 10,
133-
Rq::R11 => 11,
134-
Rq::R12 => 12,
135-
Rq::R13 => 13,
136-
Rq::R14 => 14,
137-
Rq::R15 => 15,
138-
e => todo!("{:?}", e),
139-
},
140-
Register::FP(reg) => match reg {
141-
Rx::XMM0 => 17,
142-
Rx::XMM1 => 18,
143-
Rx::XMM2 => 19,
144-
Rx::XMM3 => 20,
145-
Rx::XMM4 => 21,
146-
Rx::XMM5 => 22,
147-
Rx::XMM6 => 23,
148-
Rx::XMM7 => 24,
149-
Rx::XMM8 => 25,
150-
Rx::XMM9 => 26,
151-
Rx::XMM10 => 27,
152-
Rx::XMM11 => 28,
153-
Rx::XMM12 => 29,
154-
Rx::XMM13 => 30,
155-
Rx::XMM14 => 31,
156-
Rx::XMM15 => 32,
157-
},
158-
};
159-
// We currently only use 8 byte registers, so the size is constant. Since these are
160-
// JIT values there are no extra locations we need to worry about.
161-
yksmp::Location::Register(dwarf, 8, Vec::new())
162-
}
163-
VarLocation::ConstInt { bits, v } => {
164-
if *bits <= 32 {
165-
yksmp::Location::Constant(u32::try_from(*v).unwrap())
166-
} else {
167-
todo!(">32 bit constant")
168-
}
169-
}
170-
e => todo!("{:?}", e),
171-
}
172-
}
173-
}

ykrt/src/compile/jitc_yk/codegen/x64/deopt.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
1-
use crate::{
2-
aotsmp::AOT_STACKMAPS,
3-
compile::{
4-
jitc_yk::codegen::reg_alloc::{Register, VarLocation},
5-
GuardIdx,
6-
},
7-
log::Verbosity,
8-
mt::MTThread,
9-
};
1+
use super::{Register, VarLocation};
2+
use crate::{aotsmp::AOT_STACKMAPS, compile::GuardIdx, log::Verbosity, mt::MTThread};
103
use dynasmrt::Register as _;
114
use libc::c_void;
125
#[cfg(debug_assertions)]

ykrt/src/compile/jitc_yk/codegen/x64/lsregalloc.rs

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,17 @@
2727
//! where it has spilled an instruction's value: it guarantees to spill an instruction to at most
2828
//! one place on the stack.
2929
30-
use super::rev_analyse::RevAnalyse;
30+
use super::{rev_analyse::RevAnalyse, Register, VarLocation};
3131
use crate::compile::jitc_yk::{
32-
codegen::{
33-
abs_stack::AbstractStack,
34-
reg_alloc::{self, VarLocation},
35-
x64::REG64_BYTESIZE,
36-
},
32+
codegen::{abs_stack::AbstractStack, x64::REG64_BYTESIZE},
3733
jit_ir::{Const, ConstIdx, FloatTy, Inst, InstIdx, Module, Operand, PtrAddInst, Ty},
3834
};
3935
use dynasmrt::{
4036
dynasm,
4137
x64::{
4238
Assembler, {Rq, Rx},
4339
},
44-
DynasmApi, Register,
40+
DynasmApi, Register as dynasmrtRegister,
4541
};
4642
use std::{marker::PhantomData, mem};
4743

@@ -445,8 +441,7 @@ impl LSRegAlloc<'_> {
445441
// Deal with `OutputCanBeSameAsInput`.
446442
for i in 0..constraints.len() {
447443
if let RegConstraint::OutputCanBeSameAsInput(search_op) = constraints[i].clone() {
448-
if let Some(reg_alloc::Register::GP(reg)) = self.rev_an.reg_hints[usize::from(iidx)]
449-
{
444+
if let Some(Register::GP(reg)) = self.rev_an.reg_hints[usize::from(iidx)] {
450445
if avoid.is_set(reg) {
451446
continue;
452447
}
@@ -475,9 +470,7 @@ impl LSRegAlloc<'_> {
475470
RegConstraint::Output
476471
| RegConstraint::OutputCanBeSameAsInput(_)
477472
| RegConstraint::InputOutput(_) => {
478-
if let Some(reg_alloc::Register::GP(reg)) =
479-
self.rev_an.reg_hints[usize::from(iidx)]
480-
{
473+
if let Some(Register::GP(reg)) = self.rev_an.reg_hints[usize::from(iidx)] {
481474
if !avoid.is_set(reg) {
482475
*cnstr = match cnstr {
483476
RegConstraint::Output => RegConstraint::OutputFromReg(reg),
@@ -762,8 +755,7 @@ impl LSRegAlloc<'_> {
762755
if self.is_inst_var_still_used_after(cur_iidx, query_iidx) {
763756
let mut new_reg = None;
764757
// Try to use `query_iidx`s hint, if there is one, and it's not in use...
765-
if let Some(reg_alloc::Register::GP(reg)) =
766-
self.rev_an.reg_hints[usize::from(query_iidx)]
758+
if let Some(Register::GP(reg)) = self.rev_an.reg_hints[usize::from(query_iidx)]
767759
{
768760
if !self.gp_regset.is_set(reg) && !avoid.is_set(reg) {
769761
new_reg = Some(reg);
@@ -913,15 +905,15 @@ impl LSRegAlloc<'_> {
913905
false
914906
}
915907
}) {
916-
VarLocation::Register(reg_alloc::Register::GP(GP_REGS[reg_i]))
908+
VarLocation::Register(Register::GP(GP_REGS[reg_i]))
917909
} else if let Some(reg_i) = self.fp_reg_states.iter().position(|x| {
918910
if let RegState::FromInst(y) = x {
919911
*y == iidx
920912
} else {
921913
false
922914
}
923915
}) {
924-
VarLocation::Register(reg_alloc::Register::FP(FP_REGS[reg_i]))
916+
VarLocation::Register(Register::FP(FP_REGS[reg_i]))
925917
} else {
926918
let inst = self.m.inst(iidx);
927919
let size = inst.def_byte_size(self.m);
@@ -1037,9 +1029,7 @@ impl LSRegAlloc<'_> {
10371029
RegConstraint::Output
10381030
| RegConstraint::OutputCanBeSameAsInput(_)
10391031
| RegConstraint::InputOutput(_) => {
1040-
if let Some(reg_alloc::Register::FP(reg)) =
1041-
self.rev_an.reg_hints[usize::from(iidx)]
1042-
{
1032+
if let Some(Register::FP(reg)) = self.rev_an.reg_hints[usize::from(iidx)] {
10431033
if !avoid.is_set(reg) {
10441034
*cnstr = match cnstr {
10451035
RegConstraint::Output => RegConstraint::OutputFromReg(reg),
@@ -1446,7 +1436,7 @@ impl LSRegAlloc<'_> {
14461436
/// In the following `R` is a fixed register specified inside the variant, whereas *x* is an
14471437
/// unspecified register determined by the allocator.
14481438
#[derive(Clone, Debug)]
1449-
pub(crate) enum RegConstraint<R: Register> {
1439+
pub(crate) enum RegConstraint<R: dynasmrt::Register> {
14501440
/// Make sure `Operand` is loaded into a register *x* on entry; its value must be unchanged
14511441
/// after the instruction is executed.
14521442
Input(Operand),
@@ -1515,7 +1505,7 @@ enum RegState {
15151505
#[derive(Clone, Copy, Debug)]
15161506
struct RegSet<R>(u16, PhantomData<R>);
15171507

1518-
impl<R: Register> RegSet<R> {
1508+
impl<R: dynasmrt::Register> RegSet<R> {
15191509
/// Create a [RegSet] with all registers unused.
15201510
fn blank() -> Self {
15211511
Self(0, PhantomData)

0 commit comments

Comments
 (0)