1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//! Compilation backend pipeline: optimized IR to VCode / binemit.

use crate::ir::Function;
use crate::machinst::*;
use crate::settings;
use crate::timing;

use log::debug;
use regalloc::{allocate_registers_with_opts, Algorithm, Options};

/// Compile the given function down to VCode with allocated registers, ready
/// for binary emission.
pub fn compile<B: LowerBackend + MachBackend>(
    f: &Function,
    b: &B,
    abi: Box<dyn ABIBody<I = B::MInst>>,
) -> CodegenResult<VCode<B::MInst>>
where
    B::MInst: ShowWithRRU,
{
    // Compute lowered block order.
    let block_order = BlockLoweringOrder::new(f);
    // Build the lowering context.
    let lower = Lower::new(f, abi, block_order)?;
    // Lower the IR.
    let mut vcode = lower.lower(b)?;

    debug!(
        "vcode from lowering: \n{}",
        vcode.show_rru(Some(b.reg_universe()))
    );

    // Perform register allocation.
    let (run_checker, algorithm) = match vcode.flags().regalloc() {
        settings::Regalloc::Backtracking => (false, Algorithm::Backtracking(Default::default())),
        settings::Regalloc::BacktrackingChecked => {
            (true, Algorithm::Backtracking(Default::default()))
        }
        settings::Regalloc::ExperimentalLinearScan => {
            (false, Algorithm::LinearScan(Default::default()))
        }
        settings::Regalloc::ExperimentalLinearScanChecked => {
            (true, Algorithm::LinearScan(Default::default()))
        }
    };

    let result = {
        let _tt = timing::regalloc();
        allocate_registers_with_opts(
            &mut vcode,
            b.reg_universe(),
            Options {
                run_checker,
                algorithm,
            },
        )
        .map_err(|err| {
            debug!(
                "Register allocation error for vcode\n{}\nError: {:?}",
                vcode.show_rru(Some(b.reg_universe())),
                err
            );
            err
        })
        .expect("register allocation")
    };

    // Reorder vcode into final order and copy out final instruction sequence
    // all at once. This also inserts prologues/epilogues.
    vcode.replace_insns_from_regalloc(result);

    debug!(
        "vcode after regalloc: final version:\n{}",
        vcode.show_rru(Some(b.reg_universe()))
    );

    Ok(vcode)
}