use crate::dominator_tree::DominatorTree;
use crate::flowgraph::ControlFlowGraph;
use crate::ir::Function;
use crate::isa::TargetIsa;
use crate::regalloc::branch_splitting;
use crate::regalloc::coalescing::Coalescing;
use crate::regalloc::coloring::Coloring;
use crate::regalloc::live_value_tracker::LiveValueTracker;
use crate::regalloc::liveness::Liveness;
use crate::regalloc::reload::Reload;
use crate::regalloc::safepoint::emit_stack_maps;
use crate::regalloc::spilling::Spilling;
use crate::regalloc::virtregs::VirtRegs;
use crate::result::CodegenResult;
use crate::timing;
use crate::topo_order::TopoOrder;
use crate::verifier::{
verify_context, verify_cssa, verify_liveness, verify_locations, VerifierErrors,
};
pub struct Context {
liveness: Liveness,
virtregs: VirtRegs,
coalescing: Coalescing,
topo: TopoOrder,
tracker: LiveValueTracker,
spilling: Spilling,
reload: Reload,
coloring: Coloring,
}
impl Context {
pub fn new() -> Self {
Self {
liveness: Liveness::new(),
virtregs: VirtRegs::new(),
coalescing: Coalescing::new(),
topo: TopoOrder::new(),
tracker: LiveValueTracker::new(),
spilling: Spilling::new(),
reload: Reload::new(),
coloring: Coloring::new(),
}
}
pub fn clear(&mut self) {
self.liveness.clear();
self.virtregs.clear();
self.coalescing.clear();
self.topo.clear();
self.tracker.clear();
self.spilling.clear();
self.reload.clear();
self.coloring.clear();
}
pub fn liveness(&self) -> &Liveness {
&self.liveness
}
pub fn run(
&mut self,
isa: &dyn TargetIsa,
func: &mut Function,
cfg: &mut ControlFlowGraph,
domtree: &mut DominatorTree,
) -> CodegenResult<()> {
let _tt = timing::regalloc();
debug_assert!(domtree.is_valid());
let mut errors = VerifierErrors::default();
self.virtregs.clear();
self.tracker.clear();
branch_splitting::run(isa, func, cfg, domtree, &mut self.topo);
self.liveness.compute(isa, func, cfg);
if isa.flags().enable_verifier() {
let ok = verify_liveness(isa, func, cfg, &self.liveness, &mut errors).is_ok();
if !ok {
return Err(errors.into());
}
}
self.coalescing.conventional_ssa(
isa,
func,
cfg,
domtree,
&mut self.liveness,
&mut self.virtregs,
);
if isa.flags().enable_verifier() {
let ok = verify_context(func, cfg, domtree, isa, &mut errors).is_ok()
&& verify_liveness(isa, func, cfg, &self.liveness, &mut errors).is_ok()
&& verify_cssa(
func,
cfg,
domtree,
&self.liveness,
&self.virtregs,
&mut errors,
)
.is_ok();
if !ok {
return Err(errors.into());
}
}
self.spilling.run(
isa,
func,
domtree,
&mut self.liveness,
&self.virtregs,
&mut self.topo,
&mut self.tracker,
);
if isa.flags().enable_verifier() {
let ok = verify_context(func, cfg, domtree, isa, &mut errors).is_ok()
&& verify_liveness(isa, func, cfg, &self.liveness, &mut errors).is_ok()
&& verify_cssa(
func,
cfg,
domtree,
&self.liveness,
&self.virtregs,
&mut errors,
)
.is_ok();
if !ok {
return Err(errors.into());
}
}
self.reload.run(
isa,
func,
domtree,
&mut self.liveness,
&mut self.topo,
&mut self.tracker,
);
if isa.flags().enable_verifier() {
let ok = verify_context(func, cfg, domtree, isa, &mut errors).is_ok()
&& verify_liveness(isa, func, cfg, &self.liveness, &mut errors).is_ok()
&& verify_cssa(
func,
cfg,
domtree,
&self.liveness,
&self.virtregs,
&mut errors,
)
.is_ok();
if !ok {
return Err(errors.into());
}
}
self.coloring.run(
isa,
func,
cfg,
domtree,
&mut self.liveness,
&mut self.tracker,
);
let safepoints_enabled = isa.flags().enable_safepoints();
for val in func.dfg.values() {
let ty = func.dfg.value_type(val);
if ty.lane_type().is_ref() {
assert!(
safepoints_enabled,
"reference types were found but safepoints were not enabled"
);
emit_stack_maps(func, domtree, &self.liveness, &mut self.tracker, isa);
break;
}
}
if isa.flags().enable_verifier() {
let ok = verify_context(func, cfg, domtree, isa, &mut errors).is_ok()
&& verify_liveness(isa, func, cfg, &self.liveness, &mut errors).is_ok()
&& verify_locations(isa, func, cfg, Some(&self.liveness), &mut errors).is_ok()
&& verify_cssa(
func,
cfg,
domtree,
&self.liveness,
&self.virtregs,
&mut errors,
)
.is_ok();
if !ok {
return Err(errors.into());
}
}
if errors.is_empty() {
Ok(())
} else {
Err(errors.into())
}
}
}