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