cranelift_codegen/machinst/
compile.rs

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