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