1use crate::cfg::CFGInfo;
17use crate::ssa::validate_ssa;
18use crate::{Function, MachineEnv, Output, PReg, ProgPoint, RegAllocError, RegClass};
19use std::collections::HashMap;
20
21pub(crate) mod data_structures;
22pub use data_structures::Stats;
23use data_structures::*;
24pub(crate) mod reg_traversal;
25use reg_traversal::*;
26pub(crate) mod requirement;
27use requirement::*;
28pub(crate) mod redundant_moves;
29use redundant_moves::*;
30pub(crate) mod liveranges;
31use liveranges::*;
32pub(crate) mod merge;
33pub(crate) mod process;
34use process::*;
35use smallvec::smallvec;
36pub(crate) mod dump;
37pub(crate) mod moves;
38pub(crate) mod spill;
39pub(crate) mod stackmap;
40
41impl<'a, F: Function> Env<'a, F> {
42 pub(crate) fn new(
43 func: &'a F,
44 env: &'a MachineEnv,
45 cfginfo: CFGInfo,
46 annotations_enabled: bool,
47 ) -> Self {
48 let n = func.num_insts();
49 Self {
50 func,
51 env,
52 cfginfo,
53
54 liveins: Vec::with_capacity(func.num_blocks()),
55 liveouts: Vec::with_capacity(func.num_blocks()),
56 blockparam_outs: vec![],
57 blockparam_ins: vec![],
58 bundles: Vec::with_capacity(n),
59 ranges: Vec::with_capacity(4 * n),
60 spillsets: Vec::with_capacity(n),
61 vregs: Vec::with_capacity(n),
62 pregs: vec![],
63 allocation_queue: PrioQueue::new(),
64 safepoints: vec![],
65 safepoints_per_vreg: HashMap::new(),
66 spilled_bundles: vec![],
67 spillslots: vec![],
68 slots_by_size: vec![],
69 allocated_bundle_count: 0,
70
71 extra_spillslots_by_class: [smallvec![], smallvec![]],
72 preferred_victim_by_class: [PReg::invalid(), PReg::invalid()],
73
74 prog_move_srcs: Vec::with_capacity(n / 2),
75 prog_move_dsts: Vec::with_capacity(n / 2),
76 prog_move_merges: Vec::with_capacity(n / 2),
77
78 multi_fixed_reg_fixups: vec![],
79 inserted_moves: vec![],
80 edits: Vec::with_capacity(n),
81 allocs: Vec::with_capacity(4 * n),
82 inst_alloc_offsets: vec![],
83 num_spillslots: 0,
84 safepoint_slots: vec![],
85 debug_locations: vec![],
86
87 stats: Stats::default(),
88
89 debug_annotations: std::collections::HashMap::new(),
90 annotations_enabled,
91
92 conflict_set: Default::default(),
93 }
94 }
95
96 pub(crate) fn init(&mut self) -> Result<(), RegAllocError> {
97 self.create_pregs_and_vregs();
98 self.compute_liveness()?;
99 self.build_liveranges();
100 self.fixup_multi_fixed_vregs();
101 self.merge_vreg_bundles();
102 self.queue_bundles();
103 if trace_enabled!() {
104 self.dump_state();
105 }
106 Ok(())
107 }
108
109 pub(crate) fn run(&mut self) -> Result<(), RegAllocError> {
110 self.process_bundles()?;
111 self.try_allocating_regs_for_spilled_bundles();
112 self.allocate_spillslots();
113 self.apply_allocations_and_insert_moves();
114 self.resolve_inserted_moves();
115 self.compute_stackmaps();
116 Ok(())
117 }
118}
119
120pub fn run<F: Function>(
121 func: &F,
122 mach_env: &MachineEnv,
123 enable_annotations: bool,
124 enable_ssa_checker: bool,
125) -> Result<Output, RegAllocError> {
126 let cfginfo = CFGInfo::new(func)?;
127
128 if enable_ssa_checker {
129 validate_ssa(func, &cfginfo)?;
130 }
131
132 let mut env = Env::new(func, mach_env, cfginfo, enable_annotations);
133 env.init()?;
134
135 env.run()?;
136
137 if enable_annotations {
138 env.dump_results();
139 }
140
141 Ok(Output {
142 edits: env
143 .edits
144 .into_iter()
145 .map(|(pos_prio, edit)| (pos_prio.pos, edit))
146 .collect(),
147 allocs: env.allocs,
148 inst_alloc_offsets: env.inst_alloc_offsets,
149 num_spillslots: env.num_spillslots as usize,
150 debug_locations: env.debug_locations,
151 safepoint_slots: env.safepoint_slots,
152 stats: env.stats,
153 })
154}