[meta] Build registers with their own builder and immutably construct the TargetIsa;
This commit is contained in:
committed by
Dan Gohman
parent
f78a61b998
commit
049f067168
@@ -1,192 +1,18 @@
|
||||
use cranelift_entity::PrimaryMap;
|
||||
|
||||
use super::regs::{
|
||||
RegBank, RegBankBuilder, RegBankIndex, RegClass, RegClassBuilder, RegClassIndex, RegClassProto,
|
||||
};
|
||||
use super::regs::IsaRegs;
|
||||
use super::settings::SettingGroup;
|
||||
|
||||
pub struct TargetIsa {
|
||||
pub name: &'static str,
|
||||
pub reg_banks: PrimaryMap<RegBankIndex, RegBank>,
|
||||
pub reg_classes: PrimaryMap<RegClassIndex, RegClass>,
|
||||
pub settings: SettingGroup,
|
||||
pub regs: IsaRegs,
|
||||
}
|
||||
|
||||
impl TargetIsa {
|
||||
pub fn new(name: &'static str, settings: SettingGroup) -> Self {
|
||||
pub fn new(name: &'static str, settings: SettingGroup, regs: IsaRegs) -> Self {
|
||||
Self {
|
||||
name,
|
||||
reg_banks: PrimaryMap::new(),
|
||||
reg_classes: PrimaryMap::new(),
|
||||
settings,
|
||||
regs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TargetIsaBuilder {
|
||||
isa: TargetIsa,
|
||||
}
|
||||
|
||||
impl TargetIsaBuilder {
|
||||
pub fn new(name: &'static str, settings: SettingGroup) -> Self {
|
||||
Self {
|
||||
isa: TargetIsa::new(name, settings),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_reg_bank(&mut self, builder: RegBankBuilder) -> RegBankIndex {
|
||||
let first_unit = if self.isa.reg_banks.len() == 0 {
|
||||
0
|
||||
} else {
|
||||
let last = &self.isa.reg_banks.last().unwrap();
|
||||
let first_available_unit = (last.first_unit + last.units) as i8;
|
||||
let units = builder.units;
|
||||
let align = if units.is_power_of_two() {
|
||||
units
|
||||
} else {
|
||||
units.next_power_of_two()
|
||||
} as i8;
|
||||
(first_available_unit + align - 1) & -align
|
||||
} as u8;
|
||||
|
||||
self.isa.reg_banks.push(RegBank::new(
|
||||
builder.name,
|
||||
first_unit,
|
||||
builder.units,
|
||||
builder.names,
|
||||
builder.prefix,
|
||||
builder
|
||||
.pressure_tracking
|
||||
.expect("Pressure tracking must be explicitly set"),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn add_reg_class(&mut self, builder: RegClassBuilder) -> RegClassIndex {
|
||||
let class_index = self.isa.reg_classes.next_key();
|
||||
|
||||
// Finish delayed construction of RegClass.
|
||||
let (bank, toprc, start, width) = match builder.proto {
|
||||
RegClassProto::TopLevel(bank_index) => {
|
||||
self.isa
|
||||
.reg_banks
|
||||
.get_mut(bank_index)
|
||||
.unwrap()
|
||||
.toprcs
|
||||
.push(class_index);
|
||||
(bank_index, class_index, builder.start, builder.width)
|
||||
}
|
||||
RegClassProto::SubClass(parent_class_index) => {
|
||||
assert!(builder.width == 0);
|
||||
let (bank, toprc, start, width) = {
|
||||
let parent = self.isa.reg_classes.get(parent_class_index).unwrap();
|
||||
(parent.bank, parent.toprc, parent.start, parent.width)
|
||||
};
|
||||
for reg_class in self.isa.reg_classes.values_mut() {
|
||||
if reg_class.toprc == toprc {
|
||||
reg_class.subclasses.push(class_index);
|
||||
}
|
||||
}
|
||||
let subclass_start = start + builder.start * width;
|
||||
(bank, toprc, subclass_start, width)
|
||||
}
|
||||
};
|
||||
|
||||
let reg_bank_units = self.isa.reg_banks.get(bank).unwrap().units;
|
||||
assert!(start < reg_bank_units);
|
||||
|
||||
let count = if builder.count != 0 {
|
||||
builder.count
|
||||
} else {
|
||||
reg_bank_units / width
|
||||
};
|
||||
|
||||
let reg_class = RegClass::new(builder.name, class_index, width, bank, toprc, count, start);
|
||||
self.isa.reg_classes.push(reg_class);
|
||||
|
||||
let reg_bank = self.isa.reg_banks.get_mut(bank).unwrap();
|
||||
reg_bank.classes.push(class_index);
|
||||
|
||||
class_index
|
||||
}
|
||||
|
||||
/// Checks that the set of register classes satisfies:
|
||||
///
|
||||
/// 1. Closed under intersection: The intersection of any two register
|
||||
/// classes in the set is either empty or identical to a member of the
|
||||
/// set.
|
||||
/// 2. There are no identical classes under different names.
|
||||
/// 3. Classes are sorted topologically such that all subclasses have a
|
||||
/// higher index that the superclass.
|
||||
pub fn finish(self) -> TargetIsa {
|
||||
for reg_bank in self.isa.reg_banks.values() {
|
||||
for i1 in reg_bank.classes.iter() {
|
||||
for i2 in reg_bank.classes.iter() {
|
||||
if i1 >= i2 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let rc1 = self.isa.reg_classes.get(*i1).unwrap();
|
||||
let rc2 = self.isa.reg_classes.get(*i2).unwrap();
|
||||
|
||||
let rc1_mask = rc1.mask(0);
|
||||
let rc2_mask = rc2.mask(0);
|
||||
|
||||
assert!(
|
||||
rc1.width != rc2.width || rc1_mask != rc2_mask,
|
||||
"no duplicates"
|
||||
);
|
||||
if rc1.width != rc2.width {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut intersect = Vec::new();
|
||||
for (a, b) in rc1_mask.iter().zip(rc2_mask.iter()) {
|
||||
intersect.push(a & b);
|
||||
}
|
||||
if intersect == vec![0; intersect.len()] {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Classes must be topologically ordered, so the intersection can't be the
|
||||
// superclass.
|
||||
assert!(intersect != rc1_mask);
|
||||
|
||||
// If the intersection is the second one, then it must be a subclass.
|
||||
if intersect == rc2_mask {
|
||||
assert!(self
|
||||
.isa
|
||||
.reg_classes
|
||||
.get(*i1)
|
||||
.unwrap()
|
||||
.subclasses
|
||||
.iter()
|
||||
.find(|x| **x == *i2)
|
||||
.is_some());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This limit should be coordinated with the `RegClassMask` and `RegClassIndex` types in
|
||||
// isa/registers.rs of the non-meta code.
|
||||
assert!(
|
||||
self.isa.reg_classes.len() <= 32,
|
||||
"Too many register classes"
|
||||
);
|
||||
|
||||
// The maximum number of top-level register classes which have pressure tracking should be
|
||||
// kept in sync with the MAX_TRACKED_TOPRCS constant in isa/registers.rs of the non-meta
|
||||
// code.
|
||||
let num_toplevel = self
|
||||
.isa
|
||||
.reg_classes
|
||||
.values()
|
||||
.filter(|x| {
|
||||
x.toprc == x.index && self.isa.reg_banks.get(x.bank).unwrap().pressure_tracking
|
||||
})
|
||||
.count();
|
||||
assert!(num_toplevel <= 4, "Too many top-level register classes");
|
||||
|
||||
self.isa
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use cranelift_entity::entity_impl;
|
||||
use cranelift_entity::EntityRef;
|
||||
use cranelift_entity::{entity_impl, EntityRef, PrimaryMap};
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct RegBankIndex(u32);
|
||||
@@ -178,3 +177,179 @@ impl RegBankBuilder {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IsaRegsBuilder {
|
||||
pub banks: PrimaryMap<RegBankIndex, RegBank>,
|
||||
pub classes: PrimaryMap<RegClassIndex, RegClass>,
|
||||
}
|
||||
|
||||
impl IsaRegsBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
banks: PrimaryMap::new(),
|
||||
classes: PrimaryMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_bank(&mut self, builder: RegBankBuilder) -> RegBankIndex {
|
||||
let first_unit = if self.banks.len() == 0 {
|
||||
0
|
||||
} else {
|
||||
let last = &self.banks.last().unwrap();
|
||||
let first_available_unit = (last.first_unit + last.units) as i8;
|
||||
let units = builder.units;
|
||||
let align = if units.is_power_of_two() {
|
||||
units
|
||||
} else {
|
||||
units.next_power_of_two()
|
||||
} as i8;
|
||||
(first_available_unit + align - 1) & -align
|
||||
} as u8;
|
||||
|
||||
self.banks.push(RegBank::new(
|
||||
builder.name,
|
||||
first_unit,
|
||||
builder.units,
|
||||
builder.names,
|
||||
builder.prefix,
|
||||
builder
|
||||
.pressure_tracking
|
||||
.expect("Pressure tracking must be explicitly set"),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn add_class(&mut self, builder: RegClassBuilder) -> RegClassIndex {
|
||||
let class_index = self.classes.next_key();
|
||||
|
||||
// Finish delayed construction of RegClass.
|
||||
let (bank, toprc, start, width) = match builder.proto {
|
||||
RegClassProto::TopLevel(bank_index) => {
|
||||
self.banks
|
||||
.get_mut(bank_index)
|
||||
.unwrap()
|
||||
.toprcs
|
||||
.push(class_index);
|
||||
(bank_index, class_index, builder.start, builder.width)
|
||||
}
|
||||
RegClassProto::SubClass(parent_class_index) => {
|
||||
assert!(builder.width == 0);
|
||||
let (bank, toprc, start, width) = {
|
||||
let parent = self.classes.get(parent_class_index).unwrap();
|
||||
(parent.bank, parent.toprc, parent.start, parent.width)
|
||||
};
|
||||
for reg_class in self.classes.values_mut() {
|
||||
if reg_class.toprc == toprc {
|
||||
reg_class.subclasses.push(class_index);
|
||||
}
|
||||
}
|
||||
let subclass_start = start + builder.start * width;
|
||||
(bank, toprc, subclass_start, width)
|
||||
}
|
||||
};
|
||||
|
||||
let reg_bank_units = self.banks.get(bank).unwrap().units;
|
||||
assert!(start < reg_bank_units);
|
||||
|
||||
let count = if builder.count != 0 {
|
||||
builder.count
|
||||
} else {
|
||||
reg_bank_units / width
|
||||
};
|
||||
|
||||
let reg_class = RegClass::new(builder.name, class_index, width, bank, toprc, count, start);
|
||||
self.classes.push(reg_class);
|
||||
|
||||
let reg_bank = self.banks.get_mut(bank).unwrap();
|
||||
reg_bank.classes.push(class_index);
|
||||
|
||||
class_index
|
||||
}
|
||||
|
||||
/// Checks that the set of register classes satisfies:
|
||||
///
|
||||
/// 1. Closed under intersection: The intersection of any two register
|
||||
/// classes in the set is either empty or identical to a member of the
|
||||
/// set.
|
||||
/// 2. There are no identical classes under different names.
|
||||
/// 3. Classes are sorted topologically such that all subclasses have a
|
||||
/// higher index that the superclass.
|
||||
pub fn finish(self) -> IsaRegs {
|
||||
for reg_bank in self.banks.values() {
|
||||
for i1 in reg_bank.classes.iter() {
|
||||
for i2 in reg_bank.classes.iter() {
|
||||
if i1 >= i2 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let rc1 = self.classes.get(*i1).unwrap();
|
||||
let rc2 = self.classes.get(*i2).unwrap();
|
||||
|
||||
let rc1_mask = rc1.mask(0);
|
||||
let rc2_mask = rc2.mask(0);
|
||||
|
||||
assert!(
|
||||
rc1.width != rc2.width || rc1_mask != rc2_mask,
|
||||
"no duplicates"
|
||||
);
|
||||
if rc1.width != rc2.width {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut intersect = Vec::new();
|
||||
for (a, b) in rc1_mask.iter().zip(rc2_mask.iter()) {
|
||||
intersect.push(a & b);
|
||||
}
|
||||
if intersect == vec![0; intersect.len()] {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Classes must be topologically ordered, so the intersection can't be the
|
||||
// superclass.
|
||||
assert!(intersect != rc1_mask);
|
||||
|
||||
// If the intersection is the second one, then it must be a subclass.
|
||||
if intersect == rc2_mask {
|
||||
assert!(self
|
||||
.classes
|
||||
.get(*i1)
|
||||
.unwrap()
|
||||
.subclasses
|
||||
.iter()
|
||||
.find(|x| **x == *i2)
|
||||
.is_some());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This limit should be coordinated with the `RegClassMask` and `RegClassIndex` types in
|
||||
// isa/registers.rs of the non-meta code.
|
||||
assert!(self.classes.len() <= 32, "Too many register classes");
|
||||
|
||||
// The maximum number of top-level register classes which have pressure tracking should be
|
||||
// kept in sync with the MAX_TRACKED_TOPRCS constant in isa/registers.rs of the non-meta
|
||||
// code.
|
||||
let num_toplevel = self
|
||||
.classes
|
||||
.values()
|
||||
.filter(|x| x.toprc == x.index && self.banks.get(x.bank).unwrap().pressure_tracking)
|
||||
.count();
|
||||
assert!(num_toplevel <= 4, "Too many top-level register classes");
|
||||
|
||||
IsaRegs::new(self.banks, self.classes)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IsaRegs {
|
||||
pub banks: PrimaryMap<RegBankIndex, RegBank>,
|
||||
pub classes: PrimaryMap<RegClassIndex, RegClass>,
|
||||
}
|
||||
|
||||
impl IsaRegs {
|
||||
fn new(
|
||||
banks: PrimaryMap<RegBankIndex, RegBank>,
|
||||
classes: PrimaryMap<RegClassIndex, RegClass>,
|
||||
) -> Self {
|
||||
Self { banks, classes }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ fn gen_regbank(fmt: &mut Formatter, reg_bank: &RegBank) {
|
||||
}
|
||||
|
||||
fn gen_regclass(isa: &TargetIsa, reg_class: &RegClass, fmt: &mut Formatter) {
|
||||
let reg_bank = isa.reg_banks.get(reg_class.bank).unwrap();
|
||||
let reg_bank = isa.regs.banks.get(reg_class.bank).unwrap();
|
||||
|
||||
let mask: Vec<String> = reg_class
|
||||
.mask(reg_bank.first_unit)
|
||||
@@ -86,7 +86,7 @@ fn gen_isa(isa: &TargetIsa, fmt: &mut Formatter) {
|
||||
fmt.line("banks: &[");
|
||||
// Bank descriptors.
|
||||
fmt.indent(|fmt| {
|
||||
for reg_bank in isa.reg_banks.values() {
|
||||
for reg_bank in isa.regs.banks.values() {
|
||||
gen_regbank(fmt, ®_bank);
|
||||
}
|
||||
});
|
||||
@@ -94,7 +94,7 @@ fn gen_isa(isa: &TargetIsa, fmt: &mut Formatter) {
|
||||
// References to register classes.
|
||||
fmt.line("classes: &[");
|
||||
fmt.indent(|fmt| {
|
||||
for reg_class in isa.reg_classes.values() {
|
||||
for reg_class in isa.regs.classes.values() {
|
||||
fmt.line(&format!("&{}_DATA,", reg_class.name));
|
||||
}
|
||||
});
|
||||
@@ -103,7 +103,7 @@ fn gen_isa(isa: &TargetIsa, fmt: &mut Formatter) {
|
||||
fmt.line("};");
|
||||
|
||||
// Register class descriptors.
|
||||
for rc in isa.reg_classes.values() {
|
||||
for rc in isa.regs.classes.values() {
|
||||
gen_regclass(&isa, rc, fmt);
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ fn gen_isa(isa: &TargetIsa, fmt: &mut Formatter) {
|
||||
fmt.line("#[derive(Clone, Copy)]");
|
||||
fmt.line("pub enum RU {");
|
||||
fmt.indent(|fmt| {
|
||||
for reg_bank in isa.reg_banks.values() {
|
||||
for reg_bank in isa.regs.banks.values() {
|
||||
gen_regbank_units(reg_bank, fmt);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::cdsl::isa::{TargetIsa, TargetIsaBuilder};
|
||||
use crate::cdsl::regs::{RegBankBuilder, RegClassBuilder};
|
||||
use crate::cdsl::isa::TargetIsa;
|
||||
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
|
||||
use crate::cdsl::settings::{SettingGroup, SettingGroupBuilder};
|
||||
|
||||
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
||||
@@ -7,39 +7,45 @@ fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
||||
setting.finish()
|
||||
}
|
||||
|
||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
||||
let mut isa = TargetIsaBuilder::new("arm32", define_settings(shared_settings));
|
||||
fn define_regs() -> IsaRegs {
|
||||
let mut regs = IsaRegsBuilder::new();
|
||||
|
||||
let builder = RegBankBuilder::new("FloatRegs", "s")
|
||||
.units(64)
|
||||
.track_pressure(true);
|
||||
let float_regs = isa.add_reg_bank(builder);
|
||||
let float_regs = regs.add_bank(builder);
|
||||
|
||||
let builder = RegBankBuilder::new("IntRegs", "r")
|
||||
.units(16)
|
||||
.track_pressure(true);
|
||||
let int_regs = isa.add_reg_bank(builder);
|
||||
let int_regs = regs.add_bank(builder);
|
||||
|
||||
let builder = RegBankBuilder::new("FlagRegs", "")
|
||||
.units(1)
|
||||
.names(vec!["nzcv"])
|
||||
.track_pressure(false);
|
||||
let flag_reg = isa.add_reg_bank(builder);
|
||||
let flag_reg = regs.add_bank(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("S", float_regs).count(32);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("D", float_regs).width(2);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("Q", float_regs).width(4);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("FLAG", flag_reg);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
isa.finish()
|
||||
regs.finish()
|
||||
}
|
||||
|
||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
||||
let settings = define_settings(shared_settings);
|
||||
let regs = define_regs();
|
||||
TargetIsa::new("arm32", settings, regs)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::cdsl::isa::{TargetIsa, TargetIsaBuilder};
|
||||
use crate::cdsl::regs::{RegBankBuilder, RegClassBuilder};
|
||||
use crate::cdsl::isa::TargetIsa;
|
||||
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
|
||||
use crate::cdsl::settings::{SettingGroup, SettingGroupBuilder};
|
||||
|
||||
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
||||
@@ -7,35 +7,41 @@ fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
||||
setting.finish()
|
||||
}
|
||||
|
||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
||||
let mut isa = TargetIsaBuilder::new("arm64", define_settings(shared_settings));
|
||||
fn define_registers() -> IsaRegs {
|
||||
let mut regs = IsaRegsBuilder::new();
|
||||
|
||||
// The `x31` regunit serves as the stack pointer / zero register depending on context. We
|
||||
// reserve it and don't model the difference.
|
||||
let builder = RegBankBuilder::new("IntRegs", "x")
|
||||
.units(32)
|
||||
.track_pressure(true);
|
||||
let int_regs = isa.add_reg_bank(builder);
|
||||
let int_regs = regs.add_bank(builder);
|
||||
|
||||
let builder = RegBankBuilder::new("FloatRegs", "v")
|
||||
.units(32)
|
||||
.track_pressure(true);
|
||||
let float_regs = isa.add_reg_bank(builder);
|
||||
let float_regs = regs.add_bank(builder);
|
||||
|
||||
let builder = RegBankBuilder::new("FlagRegs", "")
|
||||
.units(1)
|
||||
.names(vec!["nzcv"])
|
||||
.track_pressure(false);
|
||||
let flag_reg = isa.add_reg_bank(builder);
|
||||
let flag_reg = regs.add_bank(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("FPR", float_regs);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("FLAG", flag_reg);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
isa.finish()
|
||||
regs.finish()
|
||||
}
|
||||
|
||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
||||
let settings = define_settings(shared_settings);
|
||||
let regs = define_registers();
|
||||
TargetIsa::new("arm64", settings, regs)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::cdsl::isa::{TargetIsa, TargetIsaBuilder};
|
||||
use crate::cdsl::regs::{RegBankBuilder, RegClassBuilder};
|
||||
use crate::cdsl::isa::TargetIsa;
|
||||
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
|
||||
use crate::cdsl::settings::{PredicateNode, SettingGroup, SettingGroupBuilder};
|
||||
|
||||
fn define_settings(shared: &SettingGroup) -> SettingGroup {
|
||||
@@ -54,24 +54,30 @@ fn define_settings(shared: &SettingGroup) -> SettingGroup {
|
||||
setting.finish()
|
||||
}
|
||||
|
||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
||||
let mut isa = TargetIsaBuilder::new("riscv", define_settings(shared_settings));
|
||||
fn define_registers() -> IsaRegs {
|
||||
let mut regs = IsaRegsBuilder::new();
|
||||
|
||||
let builder = RegBankBuilder::new("IntRegs", "x")
|
||||
.units(32)
|
||||
.track_pressure(true);
|
||||
let int_regs = isa.add_reg_bank(builder);
|
||||
let int_regs = regs.add_bank(builder);
|
||||
|
||||
let builder = RegBankBuilder::new("FloatRegs", "f")
|
||||
.units(32)
|
||||
.track_pressure(true);
|
||||
let float_regs = isa.add_reg_bank(builder);
|
||||
let float_regs = regs.add_bank(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("FPR", float_regs);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
isa.finish()
|
||||
regs.finish()
|
||||
}
|
||||
|
||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
||||
let settings = define_settings(shared_settings);
|
||||
let regs = define_registers();
|
||||
TargetIsa::new("riscv", settings, regs)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::cdsl::isa::{TargetIsa, TargetIsaBuilder};
|
||||
use crate::cdsl::regs::{RegBankBuilder, RegClassBuilder};
|
||||
use crate::cdsl::isa::TargetIsa;
|
||||
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
|
||||
use crate::cdsl::settings::{PredicateNode, SettingGroup, SettingGroupBuilder};
|
||||
|
||||
pub fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
||||
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
||||
let mut settings = SettingGroupBuilder::new("x86");
|
||||
|
||||
// CPUID.01H:ECX
|
||||
@@ -68,49 +68,49 @@ pub fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
||||
settings.finish()
|
||||
}
|
||||
|
||||
fn define_registers(isa: &mut TargetIsaBuilder) {
|
||||
fn define_registers() -> IsaRegs {
|
||||
let mut regs = IsaRegsBuilder::new();
|
||||
|
||||
let builder = RegBankBuilder::new("IntRegs", "r")
|
||||
.units(16)
|
||||
.names(vec!["rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"])
|
||||
.track_pressure(true);
|
||||
let int_regs = isa.add_reg_bank(builder);
|
||||
let int_regs = regs.add_bank(builder);
|
||||
|
||||
let builder = RegBankBuilder::new("FloatRegs", "xmm")
|
||||
.units(16)
|
||||
.track_pressure(true);
|
||||
let float_regs = isa.add_reg_bank(builder);
|
||||
let float_regs = regs.add_bank(builder);
|
||||
|
||||
let builder = RegBankBuilder::new("FlagRegs", "")
|
||||
.units(1)
|
||||
.names(vec!["rflags"])
|
||||
.track_pressure(false);
|
||||
let flag_reg = isa.add_reg_bank(builder);
|
||||
let flag_reg = regs.add_bank(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
|
||||
let gpr = isa.add_reg_class(builder);
|
||||
let gpr = regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("FPR", float_regs);
|
||||
let fpr = isa.add_reg_class(builder);
|
||||
let fpr = regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::new_toplevel("FLAG", flag_reg);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::subclass_of("GPR8", gpr, 0, 8);
|
||||
let gpr8 = isa.add_reg_class(builder);
|
||||
let gpr8 = regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::subclass_of("ABCD", gpr8, 0, 4);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
let builder = RegClassBuilder::subclass_of("FPR8", fpr, 0, 8);
|
||||
isa.add_reg_class(builder);
|
||||
regs.add_class(builder);
|
||||
|
||||
regs.finish()
|
||||
}
|
||||
|
||||
pub fn define(shared_settings: &SettingGroup) -> TargetIsa {
|
||||
let settings = define_settings(shared_settings);
|
||||
|
||||
let mut isa = TargetIsaBuilder::new("x86", settings);
|
||||
|
||||
define_registers(&mut isa);
|
||||
|
||||
isa.finish()
|
||||
let regs = define_registers();
|
||||
TargetIsa::new("x86", settings, regs)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user