cranelift_codegen/isa/x64/inst/
external.rs1use super::{
4 regs, Amode, Gpr, Inst, LabelUse, MachBuffer, MachLabel, OperandVisitor, OperandVisitorImpl,
5 SyntheticAmode, VCodeConstant, WritableGpr,
6};
7use crate::ir::TrapCode;
8use cranelift_assembler_x64 as asm;
9
10#[derive(Clone, Debug)]
12pub struct CraneliftRegisters;
13impl asm::Registers for CraneliftRegisters {
14 type ReadGpr = Gpr;
15 type ReadWriteGpr = PairedGpr;
16}
17
18#[derive(Clone, Copy, Debug)]
25pub struct PairedGpr {
26 pub(crate) read: Gpr,
27 pub(crate) write: WritableGpr,
28}
29
30impl asm::AsReg for PairedGpr {
31 fn enc(&self) -> u8 {
32 let PairedGpr { read, write } = self;
33 let read = enc(read);
34 let write = enc(&write.to_reg());
35 assert_eq!(read, write);
36 write
37 }
38
39 fn new(_: u8) -> Self {
40 panic!("disallow creation of new assembler registers")
41 }
42}
43
44impl asm::AsReg for Gpr {
46 fn enc(&self) -> u8 {
47 enc(self)
48 }
49
50 fn new(_: u8) -> Self {
51 panic!("disallow creation of new assembler registers")
52 }
53}
54
55#[inline]
57fn enc(gpr: &Gpr) -> u8 {
58 if let Some(real) = gpr.to_reg().to_real_reg() {
59 real.hw_enc()
60 } else {
61 unreachable!()
62 }
63}
64
65pub(crate) struct RegallocVisitor<'a, T>
69where
70 T: OperandVisitorImpl,
71{
72 pub collector: &'a mut T,
73}
74
75impl<'a, T: OperandVisitor> asm::RegisterVisitor<CraneliftRegisters> for RegallocVisitor<'a, T> {
76 fn read(&mut self, reg: &mut Gpr) {
77 self.collector.reg_use(reg);
78 }
79
80 fn read_write(&mut self, reg: &mut PairedGpr) {
81 let PairedGpr { read, write } = reg;
82 self.collector.reg_use(read);
83 self.collector.reg_reuse_def(write, 0);
84 }
85
86 fn fixed_read(&mut self, _reg: &Gpr) {
87 todo!()
88 }
89
90 fn fixed_read_write(&mut self, _reg: &PairedGpr) {
91 todo!()
92 }
93}
94
95impl Into<asm::Amode<Gpr>> for SyntheticAmode {
96 fn into(self) -> asm::Amode<Gpr> {
97 match self {
98 SyntheticAmode::Real(amode) => match amode {
99 Amode::ImmReg {
100 simm32,
101 base,
102 flags,
103 } => asm::Amode::ImmReg {
104 simm32: asm::Simm32PlusKnownOffset {
105 simm32: simm32.into(),
106 offset: None,
107 },
108 base: Gpr::unwrap_new(base),
109 trap: flags.trap_code().map(Into::into),
110 },
111 Amode::ImmRegRegShift {
112 simm32,
113 base,
114 index,
115 shift,
116 flags,
117 } => asm::Amode::ImmRegRegShift {
118 base,
119 index: asm::NonRspGpr::new(index),
120 scale: asm::Scale::new(shift),
121 simm32: simm32.into(),
122 trap: flags.trap_code().map(Into::into),
123 },
124 Amode::RipRelative { target } => asm::Amode::RipRelative {
125 target: asm::DeferredTarget::Label(asm::Label(target.as_u32())),
126 },
127 },
128 SyntheticAmode::IncomingArg { offset } => asm::Amode::ImmReg {
129 base: Gpr::unwrap_new(regs::rbp()),
130 simm32: asm::Simm32PlusKnownOffset {
131 simm32: (-i32::try_from(offset).unwrap()).into(),
132 offset: Some(offsets::KEY_INCOMING_ARG),
133 },
134 trap: None,
135 },
136 SyntheticAmode::SlotOffset { simm32 } => asm::Amode::ImmReg {
137 base: Gpr::unwrap_new(regs::rbp()),
138 simm32: asm::Simm32PlusKnownOffset {
139 simm32: simm32.into(),
140 offset: Some(offsets::KEY_SLOT_OFFSET),
141 },
142 trap: None,
143 },
144 SyntheticAmode::ConstantOffset(vcode_constant) => asm::Amode::RipRelative {
145 target: asm::DeferredTarget::Constant(asm::Constant(vcode_constant.as_u32())),
146 },
147 }
148 }
149}
150
151pub mod offsets {
154 pub const KEY_INCOMING_ARG: usize = 0;
155 pub const KEY_SLOT_OFFSET: usize = 1;
156}
157
158impl asm::CodeSink for MachBuffer<Inst> {
159 fn put1(&mut self, value: u8) {
160 self.put1(value)
161 }
162
163 fn put2(&mut self, value: u16) {
164 self.put2(value)
165 }
166
167 fn put4(&mut self, value: u32) {
168 self.put4(value)
169 }
170
171 fn put8(&mut self, value: u64) {
172 self.put8(value)
173 }
174
175 fn current_offset(&self) -> u32 {
176 self.cur_offset()
177 }
178
179 fn use_label_at_offset(&mut self, offset: u32, label: asm::Label) {
180 self.use_label_at_offset(offset, label.into(), LabelUse::JmpRel32);
181 }
182
183 fn add_trap(&mut self, code: asm::TrapCode) {
184 self.add_trap(code.into());
185 }
186
187 fn get_label_for_constant(&mut self, c: asm::Constant) -> asm::Label {
188 self.get_label_for_constant(c.into()).into()
189 }
190}
191
192impl From<asm::TrapCode> for TrapCode {
193 fn from(value: asm::TrapCode) -> Self {
194 Self::from_raw(value.0)
195 }
196}
197
198impl From<TrapCode> for asm::TrapCode {
199 fn from(value: TrapCode) -> Self {
200 Self(value.as_raw())
201 }
202}
203
204impl From<asm::Label> for MachLabel {
205 fn from(value: asm::Label) -> Self {
206 Self::from_u32(value.0)
207 }
208}
209
210impl From<MachLabel> for asm::Label {
211 fn from(value: MachLabel) -> Self {
212 Self(value.as_u32())
213 }
214}
215
216impl From<asm::Constant> for VCodeConstant {
217 fn from(value: asm::Constant) -> Self {
218 Self::from_u32(value.0)
219 }
220}