1 //! Compilation backend pipeline: optimized IR to VCode / binemit. 2 3 use crate::dominator_tree::DominatorTree; 4 use crate::ir::pcc; 5 use crate::ir::Function; 6 use crate::isa::TargetIsa; 7 use crate::machinst::*; 8 use crate::timing; 9 use crate::trace; 10 use crate::CodegenError; 11 12 use regalloc2::RegallocOptions; 13 14 /// Compile the given function down to VCode with allocated registers, ready 15 /// for binary emission. 16 pub fn compile<B: LowerBackend + TargetIsa>( 17 f: &Function, 18 domtree: &DominatorTree, 19 b: &B, 20 abi: Callee<<<B as LowerBackend>::MInst as MachInst>::ABIMachineSpec>, 21 emit_info: <B::MInst as MachInstEmit>::Info, 22 sigs: SigSet, 23 ctrl_plane: &mut ControlPlane, 24 ) -> CodegenResult<(VCode<B::MInst>, regalloc2::Output)> { 25 // Compute lowered block order. 26 let block_order = BlockLoweringOrder::new(f, domtree, ctrl_plane); 27 28 // Build the lowering context. 29 let lower = crate::machinst::Lower::new(f, abi, emit_info, block_order, sigs)?; 30 31 // Lower the IR. 32 let vcode = { 33 log::debug!( 34 "Number of CLIF instructions to lower: {}", 35 f.dfg.num_insts() 36 ); 37 log::debug!("Number of CLIF blocks to lower: {}", f.dfg.num_blocks()); 38 39 let _tt = timing::vcode_lower(); 40 lower.lower(b, ctrl_plane)? 41 }; 42 43 log::debug!( 44 "Number of lowered vcode instructions: {}", 45 vcode.num_insts() 46 ); 47 log::debug!("Number of lowered vcode blocks: {}", vcode.num_blocks()); 48 trace!("vcode from lowering: \n{:?}", vcode); 49 50 // Perform validation of proof-carrying-code facts, if requested. 51 if b.flags().enable_pcc() { 52 pcc::check_vcode_facts(f, &vcode, b).map_err(CodegenError::Pcc)?; 53 } 54 55 // Perform register allocation. 56 let regalloc_result = { 57 let _tt = timing::regalloc(); 58 let mut options = RegallocOptions::default(); 59 options.verbose_log = b.flags().regalloc_verbose_logs(); 60 61 if cfg!(debug_assertions) { 62 options.validate_ssa = true; 63 } 64 65 regalloc2::run(&vcode, vcode.machine_env(), &options) 66 .map_err(|err| { 67 log::error!( 68 "Register allocation error for vcode\n{:?}\nError: {:?}\nCLIF for error:\n{:?}", 69 vcode, 70 err, 71 f, 72 ); 73 err 74 }) 75 .expect("register allocation") 76 }; 77 78 // Run the regalloc checker, if requested. Also run the checker if 79 // PCC is enabled (PCC only validates up to pre-regalloc VCode, so 80 // for a full guarantee we need to ensure that regalloc did a 81 // faithful translation to allocated machine code.) 82 if b.flags().regalloc_checker() || b.flags().enable_pcc() { 83 let _tt = timing::regalloc_checker(); 84 let mut checker = regalloc2::checker::Checker::new(&vcode, vcode.machine_env()); 85 checker.prepare(®alloc_result); 86 checker 87 .run() 88 .map_err(|err| { 89 log::error!( 90 "Register allocation checker errors:\n{:?}\nfor vcode:\n{:?}", 91 err, 92 vcode 93 ); 94 err 95 }) 96 .expect("register allocation checker"); 97 } 98 99 Ok((vcode, regalloc_result)) 100 } 101