cranelift_codegen/isa/x64/inst/
external.rs1use super::{
4 regs, Amode, Gpr, Inst, LabelUse, MachBuffer, MachLabel, OperandVisitor, OperandVisitorImpl,
5 SyntheticAmode, VCodeConstant, WritableGpr, WritableXmm, Xmm,
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 type ReadXmm = Xmm;
17 type ReadWriteXmm = PairedXmm;
18}
19
20#[derive(Clone, Copy, Debug)]
27pub struct PairedGpr {
28 pub(crate) read: Gpr,
29 pub(crate) write: WritableGpr,
30}
31
32impl asm::AsReg for PairedGpr {
33 fn enc(&self) -> u8 {
34 let PairedGpr { read, write } = self;
35 let read = enc_gpr(read);
36 let write = enc_gpr(&write.to_reg());
37 assert_eq!(read, write);
38 write
39 }
40
41 fn new(_: u8) -> Self {
42 panic!("disallow creation of new assembler registers")
43 }
44}
45
46#[derive(Clone, Copy, Debug)]
48pub struct PairedXmm {
49 pub(crate) read: Xmm,
50 pub(crate) write: WritableXmm,
51}
52
53impl asm::AsReg for PairedXmm {
54 fn enc(&self) -> u8 {
55 let PairedXmm { read, write } = self;
56 let read = enc_xmm(read);
57 let write = enc_xmm(&write.to_reg());
58 assert_eq!(read, write);
59 write
60 }
61
62 fn new(_: u8) -> Self {
63 panic!("disallow creation of new assembler registers")
64 }
65}
66
67impl asm::AsReg for Gpr {
69 fn enc(&self) -> u8 {
70 enc_gpr(self)
71 }
72
73 fn new(_: u8) -> Self {
74 panic!("disallow creation of new assembler registers")
75 }
76}
77
78impl asm::AsReg for Xmm {
80 fn enc(&self) -> u8 {
81 enc_xmm(self)
82 }
83
84 fn new(_: u8) -> Self {
85 panic!("disallow creation of new assembler registers")
86 }
87}
88
89#[inline]
91fn enc_gpr(gpr: &Gpr) -> u8 {
92 if let Some(real) = gpr.to_reg().to_real_reg() {
93 real.hw_enc()
94 } else {
95 unreachable!()
96 }
97}
98
99#[inline]
101fn enc_xmm(xmm: &Xmm) -> u8 {
102 if let Some(real) = xmm.to_reg().to_real_reg() {
103 real.hw_enc()
104 } else {
105 unreachable!()
106 }
107}
108
109pub(crate) struct RegallocVisitor<'a, T>
113where
114 T: OperandVisitorImpl,
115{
116 pub collector: &'a mut T,
117}
118
119impl<'a, T: OperandVisitor> asm::RegisterVisitor<CraneliftRegisters> for RegallocVisitor<'a, T> {
120 fn read(&mut self, reg: &mut Gpr) {
121 self.collector.reg_use(reg);
122 }
123
124 fn read_write(&mut self, reg: &mut PairedGpr) {
125 let PairedGpr { read, write } = reg;
126 self.collector.reg_use(read);
127 self.collector.reg_reuse_def(write, 0);
128 }
129
130 fn fixed_read(&mut self, _reg: &Gpr) {
131 todo!()
132 }
133
134 fn fixed_read_write(&mut self, _reg: &PairedGpr) {
135 todo!()
136 }
137
138 fn read_xmm(&mut self, reg: &mut Xmm) {
139 self.collector.reg_use(reg);
140 }
141
142 fn read_write_xmm(&mut self, reg: &mut PairedXmm) {
143 let PairedXmm { read, write } = reg;
144 self.collector.reg_use(read);
145 self.collector.reg_reuse_def(write, 0);
146 }
147
148 fn fixed_read_xmm(&mut self, _reg: &Xmm) {
149 todo!()
150 }
151
152 fn fixed_read_write_xmm(&mut self, _reg: &PairedXmm) {
153 todo!()
154 }
155}
156
157impl Into<asm::Amode<Gpr>> for SyntheticAmode {
158 fn into(self) -> asm::Amode<Gpr> {
159 match self {
160 SyntheticAmode::Real(amode) => match amode {
161 Amode::ImmReg {
162 simm32,
163 base,
164 flags,
165 } => asm::Amode::ImmReg {
166 simm32: asm::AmodeOffsetPlusKnownOffset {
167 simm32: simm32.into(),
168 offset: None,
169 },
170 base: Gpr::unwrap_new(base),
171 trap: flags.trap_code().map(Into::into),
172 },
173 Amode::ImmRegRegShift {
174 simm32,
175 base,
176 index,
177 shift,
178 flags,
179 } => asm::Amode::ImmRegRegShift {
180 base,
181 index: asm::NonRspGpr::new(index),
182 scale: asm::Scale::new(shift),
183 simm32: simm32.into(),
184 trap: flags.trap_code().map(Into::into),
185 },
186 Amode::RipRelative { target } => asm::Amode::RipRelative {
187 target: asm::DeferredTarget::Label(asm::Label(target.as_u32())),
188 },
189 },
190 SyntheticAmode::IncomingArg { offset } => asm::Amode::ImmReg {
191 base: Gpr::unwrap_new(regs::rbp()),
192 simm32: asm::AmodeOffsetPlusKnownOffset {
193 simm32: (-i32::try_from(offset).unwrap()).into(),
194 offset: Some(offsets::KEY_INCOMING_ARG),
195 },
196 trap: None,
197 },
198 SyntheticAmode::SlotOffset { simm32 } => asm::Amode::ImmReg {
199 base: Gpr::unwrap_new(regs::rbp()),
200 simm32: asm::AmodeOffsetPlusKnownOffset {
201 simm32: simm32.into(),
202 offset: Some(offsets::KEY_SLOT_OFFSET),
203 },
204 trap: None,
205 },
206 SyntheticAmode::ConstantOffset(vcode_constant) => asm::Amode::RipRelative {
207 target: asm::DeferredTarget::Constant(asm::Constant(vcode_constant.as_u32())),
208 },
209 }
210 }
211}
212
213pub mod offsets {
216 pub const KEY_INCOMING_ARG: usize = 0;
217 pub const KEY_SLOT_OFFSET: usize = 1;
218}
219
220impl asm::CodeSink for MachBuffer<Inst> {
221 fn put1(&mut self, value: u8) {
222 self.put1(value)
223 }
224
225 fn put2(&mut self, value: u16) {
226 self.put2(value)
227 }
228
229 fn put4(&mut self, value: u32) {
230 self.put4(value)
231 }
232
233 fn put8(&mut self, value: u64) {
234 self.put8(value)
235 }
236
237 fn current_offset(&self) -> u32 {
238 self.cur_offset()
239 }
240
241 fn use_label_at_offset(&mut self, offset: u32, label: asm::Label) {
242 self.use_label_at_offset(offset, label.into(), LabelUse::JmpRel32);
243 }
244
245 fn add_trap(&mut self, code: asm::TrapCode) {
246 self.add_trap(code.into());
247 }
248
249 fn get_label_for_constant(&mut self, c: asm::Constant) -> asm::Label {
250 self.get_label_for_constant(c.into()).into()
251 }
252}
253
254impl From<asm::TrapCode> for TrapCode {
255 fn from(value: asm::TrapCode) -> Self {
256 Self::from_raw(value.0)
257 }
258}
259
260impl From<TrapCode> for asm::TrapCode {
261 fn from(value: TrapCode) -> Self {
262 Self(value.as_raw())
263 }
264}
265
266impl From<asm::Label> for MachLabel {
267 fn from(value: asm::Label) -> Self {
268 Self::from_u32(value.0)
269 }
270}
271
272impl From<MachLabel> for asm::Label {
273 fn from(value: MachLabel) -> Self {
274 Self(value.as_u32())
275 }
276}
277
278impl From<asm::Constant> for VCodeConstant {
279 fn from(value: asm::Constant) -> Self {
280 Self::from_u32(value.0)
281 }
282}
283
284include!(concat!(env!("OUT_DIR"), "/assembler-isle-macro.rs"));
288pub(crate) use isle_assembler_methods;