use crate::binemit::{Addend, CodeInfo, CodeOffset, Reloc, StackMap};
use crate::ir::function::FunctionParameters;
use crate::ir::{DynamicStackSlot, RelSourceLoc, StackSlot, Type};
use crate::result::CodegenResult;
use crate::settings::Flags;
use crate::value_label::ValueLabelsRanges;
use alloc::vec::Vec;
use core::fmt::Debug;
use cranelift_entity::PrimaryMap;
use regalloc2::{Allocation, VReg};
use smallvec::{smallvec, SmallVec};
use std::string::String;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
#[macro_use]
pub mod isle;
pub mod lower;
pub use lower::*;
pub mod vcode;
pub use vcode::*;
pub mod compile;
pub use compile::*;
pub mod blockorder;
pub use blockorder::*;
pub mod abi;
pub use abi::*;
pub mod buffer;
pub use buffer::*;
pub mod helpers;
pub use helpers::*;
pub mod inst_common;
pub use inst_common::*;
pub mod valueregs;
pub use reg::*;
pub use valueregs::*;
pub mod reg;
pub trait MachInst: Clone + Debug {
type ABIMachineSpec: ABIMachineSpec<I = Self>;
fn get_operands<F: Fn(VReg) -> VReg>(&self, collector: &mut OperandCollector<'_, F>);
fn is_move(&self) -> Option<(Writable<Reg>, Reg)>;
fn is_term(&self) -> MachTerminator;
fn is_args(&self) -> bool;
fn is_included_in_clobbers(&self) -> bool {
true
}
fn gen_move(to_reg: Writable<Reg>, from_reg: Reg, ty: Type) -> Self;
fn gen_constant<F: FnMut(Type) -> Writable<Reg>>(
to_regs: ValueRegs<Writable<Reg>>,
value: u128,
ty: Type,
alloc_tmp: F,
) -> SmallVec<[Self; 4]>;
fn gen_dummy_use(reg: Reg) -> Self;
fn rc_for_type(ty: Type) -> CodegenResult<(&'static [RegClass], &'static [Type])>;
fn canonical_type_for_rc(rc: RegClass) -> Type;
fn gen_jump(target: MachLabel) -> Self;
fn gen_nop(preferred_size: usize) -> Self;
fn align_basic_block(offset: CodeOffset) -> CodeOffset {
offset
}
fn worst_case_size() -> CodeOffset;
fn ref_type_regclass(_flags: &Flags) -> RegClass;
fn is_safepoint(&self) -> bool;
fn gen_block_start(
_is_indirect_branch_target: bool,
_is_forward_edge_cfi_enabled: bool,
) -> Option<Self> {
None
}
type LabelUse: MachInstLabelUse;
}
pub trait MachInstLabelUse: Clone + Copy + Debug + Eq {
const ALIGN: CodeOffset;
fn max_pos_range(self) -> CodeOffset;
fn max_neg_range(self) -> CodeOffset;
fn patch_size(self) -> CodeOffset;
fn patch(self, buffer: &mut [u8], use_offset: CodeOffset, label_offset: CodeOffset);
fn supports_veneer(self) -> bool;
fn veneer_size(self) -> CodeOffset;
fn generate_veneer(self, buffer: &mut [u8], veneer_offset: CodeOffset) -> (CodeOffset, Self);
fn from_reloc(reloc: Reloc, addend: Addend) -> Option<Self>;
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum MachTerminator {
None,
Ret,
Uncond,
Cond,
Indirect,
}
pub trait MachInstEmit: MachInst {
type State: MachInstEmitState<Self>;
type Info;
fn emit(
&self,
allocs: &[Allocation],
code: &mut MachBuffer<Self>,
info: &Self::Info,
state: &mut Self::State,
);
fn pretty_print_inst(&self, allocs: &[Allocation], state: &mut Self::State) -> String;
}
pub trait MachInstEmitState<I: VCodeInst>: Default + Clone + Debug {
fn new(abi: &Callee<I::ABIMachineSpec>) -> Self;
fn pre_safepoint(&mut self, _stack_map: StackMap) {}
fn pre_sourceloc(&mut self, _srcloc: RelSourceLoc) {}
}
#[derive(PartialEq, Debug, Clone)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct CompiledCodeBase<T: CompilePhase> {
pub buffer: MachBufferFinalized<T>,
pub frame_size: u32,
pub disasm: Option<String>,
pub value_labels_ranges: ValueLabelsRanges,
pub sized_stackslot_offsets: PrimaryMap<StackSlot, u32>,
pub dynamic_stackslot_offsets: PrimaryMap<DynamicStackSlot, u32>,
pub bb_starts: Vec<CodeOffset>,
pub bb_edges: Vec<(CodeOffset, CodeOffset)>,
pub alignment: u32,
}
impl CompiledCodeStencil {
pub fn apply_params(self, params: &FunctionParameters) -> CompiledCode {
CompiledCode {
buffer: self.buffer.apply_params(params),
frame_size: self.frame_size,
disasm: self.disasm,
value_labels_ranges: self.value_labels_ranges,
sized_stackslot_offsets: self.sized_stackslot_offsets,
dynamic_stackslot_offsets: self.dynamic_stackslot_offsets,
bb_starts: self.bb_starts,
bb_edges: self.bb_edges,
alignment: self.alignment,
}
}
}
impl<T: CompilePhase> CompiledCodeBase<T> {
pub fn code_info(&self) -> CodeInfo {
CodeInfo {
total_size: self.buffer.total_size(),
}
}
pub fn code_buffer(&self) -> &[u8] {
self.buffer.data()
}
}
pub type CompiledCodeStencil = CompiledCodeBase<Stencil>;
pub type CompiledCode = CompiledCodeBase<Final>;
pub trait TextSectionBuilder {
fn append(&mut self, labeled: bool, data: &[u8], align: u32) -> u64;
fn resolve_reloc(&mut self, offset: u64, reloc: Reloc, addend: Addend, target: u32) -> bool;
fn force_veneers(&mut self);
fn finish(&mut self) -> Vec<u8>;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum UnwindInfoKind {
None,
#[cfg(feature = "unwind")]
SystemV,
#[cfg(feature = "unwind")]
Windows,
}