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