cranelift_codegen_meta/
gen_registers.rs

1//! Generate the ISA-specific registers.
2use crate::cdsl::isa::TargetIsa;
3use crate::cdsl::regs::{RegBank, RegClass};
4use crate::error;
5use crate::srcgen::Formatter;
6use cranelift_entity::EntityRef;
7
8fn gen_regbank(fmt: &mut Formatter, reg_bank: &RegBank) {
9    let names = if !reg_bank.names.is_empty() {
10        format!(r#""{}""#, reg_bank.names.join(r#"", ""#))
11    } else {
12        "".to_string()
13    };
14    fmtln!(fmt, "RegBank {");
15    fmt.indent(|fmt| {
16        fmtln!(fmt, r#"name: "{}","#, reg_bank.name);
17        fmtln!(fmt, "first_unit: {},", reg_bank.first_unit);
18        fmtln!(fmt, "units: {},", reg_bank.units);
19        fmtln!(fmt, "names: &[{}],", names);
20        fmtln!(fmt, r#"prefix: "{}","#, reg_bank.prefix);
21        fmtln!(fmt, "first_toprc: {},", reg_bank.toprcs[0].index());
22        fmtln!(fmt, "num_toprcs: {},", reg_bank.toprcs.len());
23        fmtln!(
24            fmt,
25            "pressure_tracking: {},",
26            if reg_bank.pressure_tracking {
27                "true"
28            } else {
29                "false"
30            }
31        );
32    });
33    fmtln!(fmt, "},");
34}
35
36fn gen_regclass(isa: &TargetIsa, reg_class: &RegClass, fmt: &mut Formatter) {
37    let reg_bank = isa.regs.banks.get(reg_class.bank).unwrap();
38
39    let mask: Vec<String> = reg_class
40        .mask(reg_bank.first_unit)
41        .iter()
42        .map(|x| format!("0x{:08x}", x))
43        .collect();
44    let mask = mask.join(", ");
45
46    fmtln!(
47        fmt,
48        "pub static {}_DATA: RegClassData = RegClassData {{",
49        reg_class.name
50    );
51    fmt.indent(|fmt| {
52        fmtln!(fmt, r#"name: "{}","#, reg_class.name);
53        fmtln!(fmt, "index: {},", reg_class.index.index());
54        fmtln!(fmt, "width: {},", reg_class.width);
55        fmtln!(fmt, "bank: {},", reg_class.bank.index());
56        fmtln!(fmt, "toprc: {},", reg_class.toprc.index());
57        fmtln!(fmt, "first: {},", reg_bank.first_unit + reg_class.start);
58        fmtln!(fmt, "subclasses: {:#x},", reg_class.subclass_mask());
59        fmtln!(fmt, "mask: [{}],", mask);
60        fmtln!(fmt, "pinned_reg: {:?},", reg_bank.pinned_reg);
61        fmtln!(fmt, "info: &INFO,");
62    });
63    fmtln!(fmt, "};");
64
65    fmtln!(fmt, "#[allow(dead_code)]");
66    fmtln!(
67        fmt,
68        "pub static {}: RegClass = &{}_DATA;",
69        reg_class.name,
70        reg_class.name
71    );
72}
73
74fn gen_regbank_units(reg_bank: &RegBank, fmt: &mut Formatter) {
75    for unit in 0..reg_bank.units {
76        let v = unit + reg_bank.first_unit;
77        if (unit as usize) < reg_bank.names.len() {
78            fmtln!(fmt, "{} = {},", reg_bank.names[unit as usize], v);
79            continue;
80        }
81        fmtln!(fmt, "{}{} = {},", reg_bank.prefix, unit, v);
82    }
83}
84
85fn gen_isa(isa: &TargetIsa, fmt: &mut Formatter) {
86    // Emit RegInfo.
87    fmtln!(fmt, "pub static INFO: RegInfo = RegInfo {");
88
89    fmt.indent(|fmt| {
90        fmtln!(fmt, "banks: &[");
91        // Bank descriptors.
92        fmt.indent(|fmt| {
93            for reg_bank in isa.regs.banks.values() {
94                gen_regbank(fmt, &reg_bank);
95            }
96        });
97        fmtln!(fmt, "],");
98        // References to register classes.
99        fmtln!(fmt, "classes: &[");
100        fmt.indent(|fmt| {
101            for reg_class in isa.regs.classes.values() {
102                fmtln!(fmt, "&{}_DATA,", reg_class.name);
103            }
104        });
105        fmtln!(fmt, "],");
106    });
107    fmtln!(fmt, "};");
108
109    // Register class descriptors.
110    for rc in isa.regs.classes.values() {
111        gen_regclass(&isa, rc, fmt);
112    }
113
114    // Emit constants for all the register units.
115    fmtln!(fmt, "#[allow(dead_code, non_camel_case_types)]");
116    fmtln!(fmt, "#[derive(Clone, Copy)]");
117    fmtln!(fmt, "pub enum RU {");
118    fmt.indent(|fmt| {
119        for reg_bank in isa.regs.banks.values() {
120            gen_regbank_units(reg_bank, fmt);
121        }
122    });
123    fmtln!(fmt, "}");
124
125    // Emit Into conversion for the RU class.
126    fmtln!(fmt, "impl Into<RegUnit> for RU {");
127    fmt.indent(|fmt| {
128        fmtln!(fmt, "fn into(self) -> RegUnit {");
129        fmt.indent(|fmt| {
130            fmtln!(fmt, "self as RegUnit");
131        });
132        fmtln!(fmt, "}");
133    });
134    fmtln!(fmt, "}");
135}
136
137pub(crate) fn generate(isa: &TargetIsa, filename: &str, out_dir: &str) -> Result<(), error::Error> {
138    let mut fmt = Formatter::new();
139    gen_isa(&isa, &mut fmt);
140    fmt.update_file(filename, out_dir)?;
141    Ok(())
142}