1 //! Compilation backend pipeline: optimized IR to VCode / binemit.
2 
3 use crate::ir::Function;
4 use crate::isa::TargetIsa;
5 use crate::machinst::*;
6 use crate::timing;
7 
8 use regalloc2::RegallocOptions;
9 use regalloc2::{self, MachineEnv};
10 
11 /// Compile the given function down to VCode with allocated registers, ready
12 /// for binary emission.
13 pub fn compile<B: LowerBackend + TargetIsa>(
14     f: &Function,
15     b: &B,
16     abi: Box<dyn ABICallee<I = B::MInst>>,
17     machine_env: &MachineEnv,
18     emit_info: <B::MInst as MachInstEmit>::Info,
19 ) -> CodegenResult<(VCode<B::MInst>, regalloc2::Output)> {
20     // Compute lowered block order.
21     let block_order = BlockLoweringOrder::new(f);
22     // Build the lowering context.
23     let lower = Lower::new(f, abi, emit_info, block_order)?;
24     // Lower the IR.
25     let vcode = {
26         let _tt = timing::vcode_lower();
27         lower.lower(b)?
28     };
29 
30     log::trace!("vcode from lowering: \n{:?}", vcode);
31 
32     // Perform register allocation.
33     let regalloc_result = {
34         let _tt = timing::regalloc();
35         let mut options = RegallocOptions::default();
36         options.verbose_log = log::log_enabled!(log::Level::Trace);
37         regalloc2::run(&vcode, machine_env, &options)
38             .map_err(|err| {
39                 log::error!(
40                     "Register allocation error for vcode\n{:?}\nError: {:?}\nCLIF for error:\n{:?}",
41                     vcode,
42                     err,
43                     f,
44                 );
45                 err
46             })
47             .expect("register allocation")
48     };
49 
50     // Run the regalloc checker, if requested.
51     if b.flags().regalloc_checker() {
52         let _tt = timing::regalloc_checker();
53         let mut checker = regalloc2::checker::Checker::new(&vcode, machine_env);
54         checker.prepare(&regalloc_result);
55         checker
56             .run()
57             .map_err(|err| {
58                 log::error!(
59                     "Register allocation checker errors:\n{:?}\nfor vcode:\n{:?}",
60                     err,
61                     vcode
62                 );
63                 err
64             })
65             .expect("register allocation checker");
66     }
67 
68     Ok((vcode, regalloc_result))
69 }
70