Path: blob/main/cranelift/codegen/src/isa/pulley_shared/mod.rs
3068 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::string::String;20use alloc::vec::Vec;21use core::fmt::Debug;22use core::marker::PhantomData;23use cranelift_control::ControlPlane;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 value_labels_ranges = emit_result.value_labels_ranges;183let buffer = emit_result.buffer;184185if let Some(disasm) = emit_result.disasm.as_ref() {186log::debug!("disassembly:\n{disasm}");187}188189Ok(CompiledCodeStencil {190buffer,191vcode: emit_result.disasm,192value_labels_ranges,193bb_starts: emit_result.bb_offsets,194bb_edges: emit_result.bb_edges,195})196}197198fn emit_unwind_info(199&self,200_result: &crate::CompiledCode,201_kind: super::unwind::UnwindInfoKind,202) -> CodegenResult<Option<isa::unwind::UnwindInfo>> {203// TODO: actually support unwind info?204Ok(None)205}206207fn text_section_builder(208&self,209num_labeled_funcs: usize,210) -> alloc::boxed::Box<dyn TextSectionBuilder> {211Box::new(MachTextSectionBuilder::<inst::InstAndKind<P>>::new(212num_labeled_funcs,213))214}215216fn function_alignment(&self) -> FunctionAlignment {217inst::InstAndKind::<P>::function_alignment()218}219220fn pretty_print_reg(&self, reg: crate::Reg, _size: u8) -> String {221format!("{reg:?}")222}223224fn has_native_fma(&self) -> bool {225// The pulley interpreter does have fma opcodes.226true227}228229fn has_round(&self) -> bool {230// The pulley interpreter does have rounding opcodes.231true232}233234fn has_blendv_lowering(&self, _ty: ir::Type) -> bool {235false236}237238fn has_x86_pshufb_lowering(&self) -> bool {239false240}241242fn has_x86_pmulhrsw_lowering(&self) -> bool {243false244}245246fn has_x86_pmaddubsw_lowering(&self) -> bool {247false248}249250fn default_argument_extension(&self) -> ir::ArgumentExtension {251ir::ArgumentExtension::None252}253}254255/// Create a new Pulley ISA builder.256pub fn isa_builder(triple: Triple) -> IsaBuilder {257let constructor = match triple.architecture {258Architecture::Pulley32 | Architecture::Pulley32be => isa_constructor_32,259Architecture::Pulley64 | Architecture::Pulley64be => isa_constructor_64,260other => panic!("unexpected architecture {other:?}"),261};262IsaBuilder {263triple,264setup: self::settings::builder(),265constructor,266}267}268269fn isa_constructor_32(270triple: Triple,271shared_flags: Flags,272builder: &shared_settings::Builder,273) -> CodegenResult<OwnedTargetIsa> {274use crate::settings::Configurable;275let mut builder = builder.clone();276builder.set("pointer_width", "pointer32").unwrap();277if triple.endianness().unwrap() == target_lexicon::Endianness::Big {278builder.enable("big_endian").unwrap();279}280let isa_flags = PulleyFlags::new(&shared_flags, &builder);281282let backend =283PulleyBackend::<super::pulley32::Pulley32>::new_with_flags(triple, shared_flags, isa_flags);284Ok(backend.wrapped())285}286287fn isa_constructor_64(288triple: Triple,289shared_flags: Flags,290builder: &shared_settings::Builder,291) -> CodegenResult<OwnedTargetIsa> {292use crate::settings::Configurable;293let mut builder = builder.clone();294builder.set("pointer_width", "pointer64").unwrap();295if triple.endianness().unwrap() == target_lexicon::Endianness::Big {296builder.enable("big_endian").unwrap();297}298let isa_flags = PulleyFlags::new(&shared_flags, &builder);299300let backend =301PulleyBackend::<super::pulley64::Pulley64>::new_with_flags(triple, shared_flags, isa_flags);302Ok(backend.wrapped())303}304305impl PulleyFlags {306fn endianness(&self) -> ir::Endianness {307if self.big_endian() {308ir::Endianness::Big309} else {310ir::Endianness::Little311}312}313}314315316