Path: blob/main/cranelift/codegen/src/isa/pulley_shared/mod.rs
1693 views
//! Common support compiling to either 32- or 64-bit Pulley bytecode.12mod abi;3mod inst;4mod lower;5mod settings;67use self::inst::EmitInfo;8use super::{Builder as IsaBuilder, FunctionAlignment};9use crate::{10MachTextSectionBuilder, TextSectionBuilder,11dominator_tree::DominatorTree,12ir,13isa::{self, IsaFlagsHashKey, OwnedTargetIsa, TargetIsa},14machinst::{self, CompiledCodeStencil, MachInst, SigSet, VCode},15result::CodegenResult,16settings::{self as shared_settings, Flags},17};18use alloc::boxed::Box;19use alloc::vec::Vec;20use core::fmt::Debug;21use core::marker::PhantomData;22use cranelift_control::ControlPlane;23use std::string::String;24use target_lexicon::{Architecture, Triple};2526pub use settings::Flags as PulleyFlags;2728/// A trait to abstract over the different kinds of Pulley targets that exist29/// (32- vs 64-bit).30pub trait PulleyTargetKind: 'static + Clone + Debug + Default + Send + Sync {31// Required types and methods.3233fn pointer_width() -> PointerWidth;3435// Provided methods. Don't overwrite.3637fn name() -> &'static str {38match Self::pointer_width() {39PointerWidth::PointerWidth32 => "pulley32",40PointerWidth::PointerWidth64 => "pulley64",41}42}43}4445pub enum PointerWidth {46PointerWidth32,47PointerWidth64,48}4950impl PointerWidth {51pub fn bits(self) -> u8 {52match self {53PointerWidth::PointerWidth32 => 32,54PointerWidth::PointerWidth64 => 64,55}56}5758pub fn bytes(self) -> u8 {59self.bits() / 860}61}6263/// A Pulley backend.64pub struct PulleyBackend<P>65where66P: PulleyTargetKind,67{68pulley_target: PhantomData<P>,69triple: Triple,70flags: Flags,71isa_flags: PulleyFlags,72}7374impl<P> core::fmt::Debug for PulleyBackend<P>75where76P: PulleyTargetKind,77{78fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {79let PulleyBackend {80pulley_target: _,81triple,82flags: _,83isa_flags: _,84} = self;85f.debug_struct("PulleyBackend")86.field("triple", triple)87.finish_non_exhaustive()88}89}9091impl<P> core::fmt::Display for PulleyBackend<P>92where93P: PulleyTargetKind,94{95fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {96core::fmt::Debug::fmt(self, f)97}98}99100impl<P> PulleyBackend<P>101where102P: PulleyTargetKind,103{104/// Create a new pulley backend with the given (shared) flags.105pub fn new_with_flags(106triple: Triple,107flags: shared_settings::Flags,108isa_flags: PulleyFlags,109) -> Self {110PulleyBackend {111pulley_target: PhantomData,112triple,113flags,114isa_flags,115}116}117118/// This performs lowering to VCode, register-allocates the code, computes block layout and119/// finalizes branches. The result is ready for binary emission.120fn compile_vcode(121&self,122func: &ir::Function,123domtree: &DominatorTree,124ctrl_plane: &mut ControlPlane,125) -> CodegenResult<(VCode<inst::InstAndKind<P>>, regalloc2::Output)> {126let emit_info = EmitInfo::new(127func.signature.call_conv,128self.flags.clone(),129self.isa_flags.clone(),130);131let sigs = SigSet::new::<abi::PulleyMachineDeps<P>>(func, &self.flags)?;132let abi = abi::PulleyCallee::new(func, self, &self.isa_flags, &sigs)?;133machinst::compile::<Self>(func, domtree, self, abi, emit_info, sigs, ctrl_plane)134}135}136137impl<P> TargetIsa for PulleyBackend<P>138where139P: PulleyTargetKind,140{141fn name(&self) -> &'static str {142P::name()143}144145fn triple(&self) -> &Triple {146&self.triple147}148149fn flags(&self) -> &Flags {150&self.flags151}152153fn isa_flags(&self) -> Vec<shared_settings::Value> {154self.isa_flags.iter().collect()155}156157fn isa_flags_hash_key(&self) -> IsaFlagsHashKey<'_> {158IsaFlagsHashKey(self.isa_flags.hash_key())159}160161fn dynamic_vector_bytes(&self, _dynamic_ty: ir::Type) -> u32 {162512163}164165fn page_size_align_log2(&self) -> u8 {166// Claim 64KiB pages to be conservative.16716168}169170fn compile_function(171&self,172func: &ir::Function,173domtree: &DominatorTree,174want_disasm: bool,175ctrl_plane: &mut cranelift_control::ControlPlane,176) -> CodegenResult<CompiledCodeStencil> {177let (vcode, regalloc_result) = self.compile_vcode(func, domtree, ctrl_plane)?;178179let want_disasm =180want_disasm || (cfg!(feature = "trace-log") && log::log_enabled!(log::Level::Debug));181let emit_result = vcode.emit(®alloc_result, want_disasm, &self.flags, ctrl_plane);182let frame_size = emit_result.frame_size;183let value_labels_ranges = emit_result.value_labels_ranges;184let buffer = emit_result.buffer;185let sized_stackslot_offsets = emit_result.sized_stackslot_offsets;186let dynamic_stackslot_offsets = emit_result.dynamic_stackslot_offsets;187188if let Some(disasm) = emit_result.disasm.as_ref() {189log::debug!("disassembly:\n{disasm}");190}191192Ok(CompiledCodeStencil {193buffer,194frame_size,195vcode: emit_result.disasm,196value_labels_ranges,197sized_stackslot_offsets,198dynamic_stackslot_offsets,199bb_starts: emit_result.bb_offsets,200bb_edges: emit_result.bb_edges,201})202}203204fn emit_unwind_info(205&self,206_result: &crate::CompiledCode,207_kind: super::unwind::UnwindInfoKind,208) -> CodegenResult<Option<isa::unwind::UnwindInfo>> {209// TODO: actually support unwind info?210Ok(None)211}212213fn text_section_builder(214&self,215num_labeled_funcs: usize,216) -> alloc::boxed::Box<dyn TextSectionBuilder> {217Box::new(MachTextSectionBuilder::<inst::InstAndKind<P>>::new(218num_labeled_funcs,219))220}221222fn function_alignment(&self) -> FunctionAlignment {223inst::InstAndKind::<P>::function_alignment()224}225226fn pretty_print_reg(&self, reg: crate::Reg, _size: u8) -> String {227format!("{reg:?}")228}229230fn has_native_fma(&self) -> bool {231// The pulley interpreter does have fma opcodes.232true233}234235fn has_round(&self) -> bool {236// The pulley interpreter does have rounding opcodes.237true238}239240fn has_x86_blendv_lowering(&self, _ty: ir::Type) -> bool {241false242}243244fn has_x86_pshufb_lowering(&self) -> bool {245false246}247248fn has_x86_pmulhrsw_lowering(&self) -> bool {249false250}251252fn has_x86_pmaddubsw_lowering(&self) -> bool {253false254}255256fn default_argument_extension(&self) -> ir::ArgumentExtension {257ir::ArgumentExtension::None258}259}260261/// Create a new Pulley ISA builder.262pub fn isa_builder(triple: Triple) -> IsaBuilder {263let constructor = match triple.architecture {264Architecture::Pulley32 | Architecture::Pulley32be => isa_constructor_32,265Architecture::Pulley64 | Architecture::Pulley64be => isa_constructor_64,266other => panic!("unexpected architecture {other:?}"),267};268IsaBuilder {269triple,270setup: self::settings::builder(),271constructor,272}273}274275fn isa_constructor_32(276triple: Triple,277shared_flags: Flags,278builder: &shared_settings::Builder,279) -> CodegenResult<OwnedTargetIsa> {280use crate::settings::Configurable;281let mut builder = builder.clone();282builder.set("pointer_width", "pointer32").unwrap();283if triple.endianness().unwrap() == target_lexicon::Endianness::Big {284builder.enable("big_endian").unwrap();285}286let isa_flags = PulleyFlags::new(&shared_flags, &builder);287288let backend =289PulleyBackend::<super::pulley32::Pulley32>::new_with_flags(triple, shared_flags, isa_flags);290Ok(backend.wrapped())291}292293fn isa_constructor_64(294triple: Triple,295shared_flags: Flags,296builder: &shared_settings::Builder,297) -> CodegenResult<OwnedTargetIsa> {298use crate::settings::Configurable;299let mut builder = builder.clone();300builder.set("pointer_width", "pointer64").unwrap();301if triple.endianness().unwrap() == target_lexicon::Endianness::Big {302builder.enable("big_endian").unwrap();303}304let isa_flags = PulleyFlags::new(&shared_flags, &builder);305306let backend =307PulleyBackend::<super::pulley64::Pulley64>::new_with_flags(triple, shared_flags, isa_flags);308Ok(backend.wrapped())309}310311impl PulleyFlags {312fn endianness(&self) -> ir::Endianness {313if self.big_endian() {314ir::Endianness::Big315} else {316ir::Endianness::Little317}318}319}320321322