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(®alloc_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