cranelift_codegen/isa/pulley_shared/
mod.rs1mod abi;
4mod inst;
5mod lower;
6mod settings;
7
8use self::inst::EmitInfo;
9use super::{Builder as IsaBuilder, FunctionAlignment};
10use crate::{
11 MachTextSectionBuilder, TextSectionBuilder,
12 dominator_tree::DominatorTree,
13 ir,
14 isa::{self, IsaFlagsHashKey, OwnedTargetIsa, TargetIsa},
15 machinst::{self, CompiledCodeStencil, MachInst, SigSet, VCode},
16 result::CodegenResult,
17 settings::{self as shared_settings, Flags},
18};
19use alloc::boxed::Box;
20use alloc::vec::Vec;
21use core::fmt::Debug;
22use core::marker::PhantomData;
23use cranelift_control::ControlPlane;
24use std::string::String;
25use target_lexicon::{Architecture, Triple};
26
27pub use settings::Flags as PulleyFlags;
28
29pub trait PulleyTargetKind: 'static + Clone + Debug + Default + Send + Sync {
32 fn pointer_width() -> PointerWidth;
35
36 fn name() -> &'static str {
39 match Self::pointer_width() {
40 PointerWidth::PointerWidth32 => "pulley32",
41 PointerWidth::PointerWidth64 => "pulley64",
42 }
43 }
44}
45
46pub enum PointerWidth {
47 PointerWidth32,
48 PointerWidth64,
49}
50
51impl PointerWidth {
52 pub fn bits(self) -> u8 {
53 match self {
54 PointerWidth::PointerWidth32 => 32,
55 PointerWidth::PointerWidth64 => 64,
56 }
57 }
58
59 pub fn bytes(self) -> u8 {
60 self.bits() / 8
61 }
62}
63
64pub struct PulleyBackend<P>
66where
67 P: PulleyTargetKind,
68{
69 pulley_target: PhantomData<P>,
70 triple: Triple,
71 flags: Flags,
72 isa_flags: PulleyFlags,
73}
74
75impl<P> core::fmt::Debug for PulleyBackend<P>
76where
77 P: PulleyTargetKind,
78{
79 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
80 let PulleyBackend {
81 pulley_target: _,
82 triple,
83 flags: _,
84 isa_flags: _,
85 } = self;
86 f.debug_struct("PulleyBackend")
87 .field("triple", triple)
88 .finish_non_exhaustive()
89 }
90}
91
92impl<P> core::fmt::Display for PulleyBackend<P>
93where
94 P: PulleyTargetKind,
95{
96 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
97 core::fmt::Debug::fmt(self, f)
98 }
99}
100
101impl<P> PulleyBackend<P>
102where
103 P: PulleyTargetKind,
104{
105 pub fn new_with_flags(
107 triple: Triple,
108 flags: shared_settings::Flags,
109 isa_flags: PulleyFlags,
110 ) -> Self {
111 PulleyBackend {
112 pulley_target: PhantomData,
113 triple,
114 flags,
115 isa_flags,
116 }
117 }
118
119 fn compile_vcode(
122 &self,
123 func: &ir::Function,
124 domtree: &DominatorTree,
125 ctrl_plane: &mut ControlPlane,
126 ) -> CodegenResult<(VCode<inst::InstAndKind<P>>, regalloc2::Output)> {
127 let emit_info = EmitInfo::new(
128 func.signature.call_conv,
129 self.flags.clone(),
130 self.isa_flags.clone(),
131 );
132 let sigs = SigSet::new::<abi::PulleyMachineDeps<P>>(func, &self.flags)?;
133 let abi = abi::PulleyCallee::new(func, self, &self.isa_flags, &sigs)?;
134 machinst::compile::<Self>(func, domtree, self, abi, emit_info, sigs, ctrl_plane)
135 }
136}
137
138impl<P> TargetIsa for PulleyBackend<P>
139where
140 P: PulleyTargetKind,
141{
142 fn name(&self) -> &'static str {
143 P::name()
144 }
145
146 fn triple(&self) -> &Triple {
147 &self.triple
148 }
149
150 fn flags(&self) -> &Flags {
151 &self.flags
152 }
153
154 fn isa_flags(&self) -> Vec<shared_settings::Value> {
155 self.isa_flags.iter().collect()
156 }
157
158 fn isa_flags_hash_key(&self) -> IsaFlagsHashKey<'_> {
159 IsaFlagsHashKey(self.isa_flags.hash_key())
160 }
161
162 fn dynamic_vector_bytes(&self, _dynamic_ty: ir::Type) -> u32 {
163 512
164 }
165
166 fn page_size_align_log2(&self) -> u8 {
167 16
169 }
170
171 fn compile_function(
172 &self,
173 func: &ir::Function,
174 domtree: &DominatorTree,
175 want_disasm: bool,
176 ctrl_plane: &mut cranelift_control::ControlPlane,
177 ) -> CodegenResult<CompiledCodeStencil> {
178 let (vcode, regalloc_result) = self.compile_vcode(func, domtree, ctrl_plane)?;
179
180 let want_disasm =
181 want_disasm || (cfg!(feature = "trace-log") && log::log_enabled!(log::Level::Debug));
182 let emit_result = vcode.emit(®alloc_result, want_disasm, &self.flags, ctrl_plane);
183 let frame_size = emit_result.frame_size;
184 let value_labels_ranges = emit_result.value_labels_ranges;
185 let buffer = emit_result.buffer;
186 let sized_stackslot_offsets = emit_result.sized_stackslot_offsets;
187 let dynamic_stackslot_offsets = emit_result.dynamic_stackslot_offsets;
188
189 if let Some(disasm) = emit_result.disasm.as_ref() {
190 log::debug!("disassembly:\n{disasm}");
191 }
192
193 Ok(CompiledCodeStencil {
194 buffer,
195 frame_size,
196 vcode: emit_result.disasm,
197 value_labels_ranges,
198 sized_stackslot_offsets,
199 dynamic_stackslot_offsets,
200 bb_starts: emit_result.bb_offsets,
201 bb_edges: emit_result.bb_edges,
202 })
203 }
204
205 fn emit_unwind_info(
206 &self,
207 _result: &crate::CompiledCode,
208 _kind: super::unwind::UnwindInfoKind,
209 ) -> CodegenResult<Option<isa::unwind::UnwindInfo>> {
210 Ok(None)
212 }
213
214 fn text_section_builder(
215 &self,
216 num_labeled_funcs: usize,
217 ) -> alloc::boxed::Box<dyn TextSectionBuilder> {
218 Box::new(MachTextSectionBuilder::<inst::InstAndKind<P>>::new(
219 num_labeled_funcs,
220 ))
221 }
222
223 fn function_alignment(&self) -> FunctionAlignment {
224 inst::InstAndKind::<P>::function_alignment()
225 }
226
227 fn pretty_print_reg(&self, reg: crate::Reg, _size: u8) -> String {
228 format!("{reg:?}")
229 }
230
231 fn has_native_fma(&self) -> bool {
232 true
234 }
235
236 fn has_round(&self) -> bool {
237 true
239 }
240
241 fn has_x86_blendv_lowering(&self, _ty: ir::Type) -> bool {
242 false
243 }
244
245 fn has_x86_pshufb_lowering(&self) -> bool {
246 false
247 }
248
249 fn has_x86_pmulhrsw_lowering(&self) -> bool {
250 false
251 }
252
253 fn has_x86_pmaddubsw_lowering(&self) -> bool {
254 false
255 }
256
257 fn default_argument_extension(&self) -> ir::ArgumentExtension {
258 ir::ArgumentExtension::None
259 }
260}
261
262pub fn isa_builder(triple: Triple) -> IsaBuilder {
264 let constructor = match triple.architecture {
265 Architecture::Pulley32 | Architecture::Pulley32be => isa_constructor_32,
266 Architecture::Pulley64 | Architecture::Pulley64be => isa_constructor_64,
267 other => panic!("unexpected architecture {other:?}"),
268 };
269 IsaBuilder {
270 triple,
271 setup: self::settings::builder(),
272 constructor,
273 }
274}
275
276fn isa_constructor_32(
277 triple: Triple,
278 shared_flags: Flags,
279 builder: &shared_settings::Builder,
280) -> CodegenResult<OwnedTargetIsa> {
281 use crate::settings::Configurable;
282 let mut builder = builder.clone();
283 builder.set("pointer_width", "pointer32").unwrap();
284 if triple.endianness().unwrap() == target_lexicon::Endianness::Big {
285 builder.enable("big_endian").unwrap();
286 }
287 let isa_flags = PulleyFlags::new(&shared_flags, &builder);
288
289 let backend =
290 PulleyBackend::<super::pulley32::Pulley32>::new_with_flags(triple, shared_flags, isa_flags);
291 Ok(backend.wrapped())
292}
293
294fn isa_constructor_64(
295 triple: Triple,
296 shared_flags: Flags,
297 builder: &shared_settings::Builder,
298) -> CodegenResult<OwnedTargetIsa> {
299 use crate::settings::Configurable;
300 let mut builder = builder.clone();
301 builder.set("pointer_width", "pointer64").unwrap();
302 if triple.endianness().unwrap() == target_lexicon::Endianness::Big {
303 builder.enable("big_endian").unwrap();
304 }
305 let isa_flags = PulleyFlags::new(&shared_flags, &builder);
306
307 let backend =
308 PulleyBackend::<super::pulley64::Pulley64>::new_with_flags(triple, shared_flags, isa_flags);
309 Ok(backend.wrapped())
310}
311
312impl PulleyFlags {
313 fn endianness(&self) -> ir::Endianness {
314 if self.big_endian() {
315 ir::Endianness::Big
316 } else {
317 ir::Endianness::Little
318 }
319 }
320}