#[cfg(feature = "fuzzing")]
pub mod analysis_main;
#[cfg(not(feature = "fuzzing"))]
mod analysis_main;
mod analysis_control_flow;
mod analysis_data_flow;
mod avl_tree;
mod bt_coalescing_analysis;
mod bt_commitment_map;
mod bt_main;
mod bt_spillslot_allocator;
mod bt_vlr_priority_queue;
mod checker;
mod data_structures;
mod inst_stream;
mod linear_scan;
mod sparse_set;
mod union_find;
use log::{info, log_enabled, Level};
use std::fmt;
pub use crate::data_structures::Map;
pub use crate::data_structures::Set;
pub use crate::data_structures::RegClass;
pub use crate::data_structures::Reg;
pub use crate::data_structures::RealReg;
pub use crate::data_structures::VirtualReg;
pub use crate::data_structures::Writable;
pub use crate::data_structures::NUM_REG_CLASSES;
pub use crate::data_structures::SpillSlot;
pub use crate::data_structures::RealRegUniverse;
pub use crate::data_structures::RegClassInfo;
pub use crate::data_structures::RegUsageCollector;
pub use crate::data_structures::TypedIxVec;
pub use crate::data_structures::{BlockIx, InstIx, Range};
pub trait Function {
type Inst: Clone + fmt::Debug;
fn insns(&self) -> &[Self::Inst];
fn insn_indices(&self) -> Range<InstIx> {
Range::new(InstIx::new(0), self.insns().len())
}
fn insns_mut(&mut self) -> &mut [Self::Inst];
fn get_insn(&self, insn: InstIx) -> &Self::Inst;
fn get_insn_mut(&mut self, insn: InstIx) -> &mut Self::Inst;
fn blocks(&self) -> Range<BlockIx>;
fn entry_block(&self) -> BlockIx;
fn block_insns(&self, block: BlockIx) -> Range<InstIx>;
fn block_succs(&self, block: BlockIx) -> Vec<BlockIx>;
fn is_ret(&self, insn: InstIx) -> bool;
fn get_regs(insn: &Self::Inst, collector: &mut RegUsageCollector);
fn map_regs(
insn: &mut Self::Inst,
pre_map: &Map<VirtualReg, RealReg>,
post_map: &Map<VirtualReg, RealReg>,
);
fn is_move(&self, insn: &Self::Inst) -> Option<(Writable<Reg>, Reg)>;
fn get_spillslot_size(&self, regclass: RegClass, for_vreg: VirtualReg) -> u32;
fn gen_spill(&self, to_slot: SpillSlot, from_reg: RealReg, for_vreg: VirtualReg) -> Self::Inst;
fn gen_reload(
&self,
to_reg: Writable<RealReg>,
from_slot: SpillSlot,
for_vreg: VirtualReg,
) -> Self::Inst;
fn gen_move(
&self,
to_reg: Writable<RealReg>,
from_reg: RealReg,
for_vreg: VirtualReg,
) -> Self::Inst;
fn gen_zero_len_nop(&self) -> Self::Inst;
fn maybe_direct_reload(
&self,
insn: &Self::Inst,
reg: VirtualReg,
slot: SpillSlot,
) -> Option<Self::Inst>;
fn func_liveins(&self) -> Set<RealReg>;
fn func_liveouts(&self) -> Set<RealReg>;
}
pub struct RegAllocResult<F: Function> {
pub insns: Vec<F::Inst>,
pub target_map: TypedIxVec<BlockIx, InstIx>,
pub orig_insn_map: TypedIxVec< InstIx, InstIx>,
pub clobbered_registers: Set<RealReg>,
pub num_spill_slots: u32,
pub block_annotations: Option<TypedIxVec<BlockIx, Vec<String>>>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RegAllocAlgorithm {
Backtracking,
BacktrackingChecked,
LinearScan,
LinearScanChecked,
}
pub use crate::analysis_main::AnalysisError;
pub use crate::checker::{CheckerError, CheckerErrors};
#[derive(Clone, Debug)]
pub enum RegAllocError {
OutOfRegisters(RegClass),
MissingSuggestedScratchReg(RegClass),
Analysis(AnalysisError),
RegChecker(CheckerErrors),
Other(String),
}
impl fmt::Display for RegAllocError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}
#[inline(never)]
pub fn allocate_registers<F: Function>(
func: &mut F,
algorithm: RegAllocAlgorithm,
rreg_universe: &RealRegUniverse,
request_block_annotations: bool,
) -> Result<RegAllocResult<F>, RegAllocError> {
info!("");
info!("================ regalloc.rs: BEGIN function ================");
if log_enabled!(Level::Info) {
let strs = rreg_universe.show();
info!("using RealRegUniverse:");
for s in strs {
info!(" {}", s);
}
}
let res = match algorithm {
RegAllocAlgorithm::Backtracking | RegAllocAlgorithm::BacktrackingChecked => {
let use_checker = algorithm == RegAllocAlgorithm::BacktrackingChecked;
bt_main::alloc_main(func, rreg_universe, use_checker, request_block_annotations)
}
RegAllocAlgorithm::LinearScan | RegAllocAlgorithm::LinearScanChecked => {
let use_checker = algorithm == RegAllocAlgorithm::LinearScanChecked;
linear_scan::run(func, rreg_universe, use_checker)
}
};
info!("================ regalloc.rs: END function ================");
res
}