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 dominator_tree::DominatorTree,
12 ir,
13 isa::{self, OwnedTargetIsa, TargetIsa},
14 machinst::{self, CompiledCodeStencil, MachInst, SigSet, VCode},
15 result::CodegenResult,
16 settings::{self as shared_settings, Flags},
17 MachTextSectionBuilder, TextSectionBuilder,
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 dynamic_vector_bytes(&self, _dynamic_ty: ir::Type) -> u32 {
159 512
160 }
161
162 fn page_size_align_log2(&self) -> u8 {
163 16
165 }
166
167 fn compile_function(
168 &self,
169 func: &ir::Function,
170 domtree: &DominatorTree,
171 want_disasm: bool,
172 ctrl_plane: &mut cranelift_control::ControlPlane,
173 ) -> CodegenResult<CompiledCodeStencil> {
174 let (vcode, regalloc_result) = self.compile_vcode(func, domtree, ctrl_plane)?;
175
176 let want_disasm =
177 want_disasm || (cfg!(feature = "trace-log") && log::log_enabled!(log::Level::Debug));
178 let emit_result = vcode.emit(®alloc_result, want_disasm, &self.flags, ctrl_plane);
179 let frame_size = emit_result.frame_size;
180 let value_labels_ranges = emit_result.value_labels_ranges;
181 let buffer = emit_result.buffer;
182 let sized_stackslot_offsets = emit_result.sized_stackslot_offsets;
183 let dynamic_stackslot_offsets = emit_result.dynamic_stackslot_offsets;
184
185 if let Some(disasm) = emit_result.disasm.as_ref() {
186 log::debug!("disassembly:\n{}", disasm);
187 }
188
189 Ok(CompiledCodeStencil {
190 buffer,
191 frame_size,
192 vcode: emit_result.disasm,
193 value_labels_ranges,
194 sized_stackslot_offsets,
195 dynamic_stackslot_offsets,
196 bb_starts: emit_result.bb_offsets,
197 bb_edges: emit_result.bb_edges,
198 })
199 }
200
201 fn emit_unwind_info(
202 &self,
203 _result: &crate::CompiledCode,
204 _kind: super::unwind::UnwindInfoKind,
205 ) -> CodegenResult<Option<isa::unwind::UnwindInfo>> {
206 Ok(None)
208 }
209
210 fn text_section_builder(
211 &self,
212 num_labeled_funcs: usize,
213 ) -> alloc::boxed::Box<dyn TextSectionBuilder> {
214 Box::new(MachTextSectionBuilder::<inst::InstAndKind<P>>::new(
215 num_labeled_funcs,
216 ))
217 }
218
219 fn function_alignment(&self) -> FunctionAlignment {
220 inst::InstAndKind::<P>::function_alignment()
221 }
222
223 fn pretty_print_reg(&self, reg: crate::Reg, _size: u8) -> String {
224 format!("{reg:?}")
225 }
226
227 fn has_native_fma(&self) -> bool {
228 false
229 }
230
231 fn has_x86_blendv_lowering(&self, _ty: ir::Type) -> bool {
232 false
233 }
234
235 fn has_x86_pshufb_lowering(&self) -> bool {
236 false
237 }
238
239 fn has_x86_pmulhrsw_lowering(&self) -> bool {
240 false
241 }
242
243 fn has_x86_pmaddubsw_lowering(&self) -> bool {
244 false
245 }
246
247 fn default_argument_extension(&self) -> ir::ArgumentExtension {
248 ir::ArgumentExtension::None
249 }
250}
251
252pub fn isa_builder(triple: Triple) -> IsaBuilder {
254 let constructor = match triple.architecture {
255 Architecture::Pulley32 | Architecture::Pulley32be => isa_constructor_32,
256 Architecture::Pulley64 | Architecture::Pulley64be => isa_constructor_64,
257 other => panic!("unexpected architecture {other:?}"),
258 };
259 IsaBuilder {
260 triple,
261 setup: self::settings::builder(),
262 constructor,
263 }
264}
265
266fn isa_constructor_32(
267 triple: Triple,
268 shared_flags: Flags,
269 builder: &shared_settings::Builder,
270) -> CodegenResult<OwnedTargetIsa> {
271 use crate::settings::Configurable;
272 let mut builder = builder.clone();
273 builder.set("pointer_width", "pointer32").unwrap();
274 if triple.endianness().unwrap() == target_lexicon::Endianness::Big {
275 builder.enable("big_endian").unwrap();
276 }
277 let isa_flags = PulleyFlags::new(&shared_flags, &builder);
278
279 let backend =
280 PulleyBackend::<super::pulley32::Pulley32>::new_with_flags(triple, shared_flags, isa_flags);
281 Ok(backend.wrapped())
282}
283
284fn isa_constructor_64(
285 triple: Triple,
286 shared_flags: Flags,
287 builder: &shared_settings::Builder,
288) -> CodegenResult<OwnedTargetIsa> {
289 use crate::settings::Configurable;
290 let mut builder = builder.clone();
291 builder.set("pointer_width", "pointer64").unwrap();
292 if triple.endianness().unwrap() == target_lexicon::Endianness::Big {
293 builder.enable("big_endian").unwrap();
294 }
295 let isa_flags = PulleyFlags::new(&shared_flags, &builder);
296
297 let backend =
298 PulleyBackend::<super::pulley64::Pulley64>::new_with_flags(triple, shared_flags, isa_flags);
299 Ok(backend.wrapped())
300}
301
302impl PulleyFlags {
303 fn endianness(&self) -> ir::Endianness {
304 if self.big_endian() {
305 ir::Endianness::Big
306 } else {
307 ir::Endianness::Little
308 }
309 }
310}