[meta] Introduce the fmtln! macro to ease writing formatted strings;
This commit is contained in:
@@ -10,25 +10,26 @@ fn gen_regbank(fmt: &mut Formatter, reg_bank: &RegBank) {
|
|||||||
} else {
|
} else {
|
||||||
"".to_string()
|
"".to_string()
|
||||||
};
|
};
|
||||||
fmt.line("RegBank {");
|
fmtln!(fmt, "RegBank {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line(format!(r#"name: "{}","#, reg_bank.name));
|
fmtln!(fmt, r#"name: "{}","#, reg_bank.name);
|
||||||
fmt.line(format!("first_unit: {},", reg_bank.first_unit));
|
fmtln!(fmt, "first_unit: {},", reg_bank.first_unit);
|
||||||
fmt.line(format!("units: {},", reg_bank.units));
|
fmtln!(fmt, "units: {},", reg_bank.units);
|
||||||
fmt.line(format!("names: &[{}],", names));
|
fmtln!(fmt, "names: &[{}],", names);
|
||||||
fmt.line(format!(r#"prefix: "{}","#, reg_bank.prefix));
|
fmtln!(fmt, r#"prefix: "{}","#, reg_bank.prefix);
|
||||||
fmt.line(format!("first_toprc: {},", reg_bank.toprcs[0].index()));
|
fmtln!(fmt, "first_toprc: {},", reg_bank.toprcs[0].index());
|
||||||
fmt.line(format!("num_toprcs: {},", reg_bank.toprcs.len()));
|
fmtln!(fmt, "num_toprcs: {},", reg_bank.toprcs.len());
|
||||||
fmt.line(format!(
|
fmtln!(
|
||||||
|
fmt,
|
||||||
"pressure_tracking: {},",
|
"pressure_tracking: {},",
|
||||||
if reg_bank.pressure_tracking {
|
if reg_bank.pressure_tracking {
|
||||||
"true"
|
"true"
|
||||||
} else {
|
} else {
|
||||||
"false"
|
"false"
|
||||||
}
|
}
|
||||||
));
|
);
|
||||||
});
|
});
|
||||||
fmt.line("},");
|
fmtln!(fmt, "},");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_regclass(isa: &TargetIsa, reg_class: &RegClass, fmt: &mut Formatter) {
|
fn gen_regclass(isa: &TargetIsa, reg_class: &RegClass, fmt: &mut Formatter) {
|
||||||
@@ -41,63 +42,67 @@ fn gen_regclass(isa: &TargetIsa, reg_class: &RegClass, fmt: &mut Formatter) {
|
|||||||
.collect();
|
.collect();
|
||||||
let mask = mask.join(", ");
|
let mask = mask.join(", ");
|
||||||
|
|
||||||
fmt.line(format!(
|
fmtln!(
|
||||||
|
fmt,
|
||||||
"pub static {}_DATA: RegClassData = RegClassData {{",
|
"pub static {}_DATA: RegClassData = RegClassData {{",
|
||||||
reg_class.name
|
reg_class.name
|
||||||
));
|
);
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line(format!(r#"name: "{}","#, reg_class.name));
|
fmtln!(fmt, r#"name: "{}","#, reg_class.name);
|
||||||
fmt.line(format!("index: {},", reg_class.index.index()));
|
fmtln!(fmt, "index: {},", reg_class.index.index());
|
||||||
fmt.line(format!("width: {},", reg_class.width));
|
fmtln!(fmt, "width: {},", reg_class.width);
|
||||||
fmt.line(format!("bank: {},", reg_class.bank.index()));
|
fmtln!(fmt, "bank: {},", reg_class.bank.index());
|
||||||
fmt.line(format!("toprc: {},", reg_class.toprc.index()));
|
fmtln!(fmt, "toprc: {},", reg_class.toprc.index());
|
||||||
fmt.line(format!("first: {},", reg_bank.first_unit + reg_class.start));
|
fmtln!(fmt, "first: {},", reg_bank.first_unit + reg_class.start);
|
||||||
fmt.line(format!("subclasses: {:#x},", reg_class.subclass_mask()));
|
fmtln!(fmt, "subclasses: {:#x},", reg_class.subclass_mask());
|
||||||
fmt.line(format!("mask: [{}],", mask));
|
fmtln!(fmt, "mask: [{}],", mask);
|
||||||
fmt.line("info: &INFO,");
|
fmtln!(fmt, "info: &INFO,");
|
||||||
});
|
});
|
||||||
fmt.line("};");
|
fmtln!(fmt, "};");
|
||||||
fmt.line("#[allow(dead_code)]");
|
|
||||||
fmt.line(format!(
|
fmtln!(fmt, "#[allow(dead_code)]");
|
||||||
|
fmtln!(
|
||||||
|
fmt,
|
||||||
"pub static {}: RegClass = &{}_DATA;",
|
"pub static {}: RegClass = &{}_DATA;",
|
||||||
reg_class.name, reg_class.name
|
reg_class.name,
|
||||||
));
|
reg_class.name
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_regbank_units(reg_bank: &RegBank, fmt: &mut Formatter) {
|
fn gen_regbank_units(reg_bank: &RegBank, fmt: &mut Formatter) {
|
||||||
for unit in 0..reg_bank.units {
|
for unit in 0..reg_bank.units {
|
||||||
let v = unit + reg_bank.first_unit;
|
let v = unit + reg_bank.first_unit;
|
||||||
if (unit as usize) < reg_bank.names.len() {
|
if (unit as usize) < reg_bank.names.len() {
|
||||||
fmt.line(format!("{} = {},", reg_bank.names[unit as usize], v));
|
fmtln!(fmt, "{} = {},", reg_bank.names[unit as usize], v);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
fmt.line(format!("{}{} = {},", reg_bank.prefix, unit, v));
|
fmtln!(fmt, "{}{} = {},", reg_bank.prefix, unit, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_isa(isa: &TargetIsa, fmt: &mut Formatter) {
|
fn gen_isa(isa: &TargetIsa, fmt: &mut Formatter) {
|
||||||
// Emit RegInfo.
|
// Emit RegInfo.
|
||||||
fmt.line("pub static INFO: RegInfo = RegInfo {");
|
fmtln!(fmt, "pub static INFO: RegInfo = RegInfo {");
|
||||||
|
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line("banks: &[");
|
fmtln!(fmt, "banks: &[");
|
||||||
// Bank descriptors.
|
// Bank descriptors.
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
for reg_bank in isa.regs.banks.values() {
|
for reg_bank in isa.regs.banks.values() {
|
||||||
gen_regbank(fmt, ®_bank);
|
gen_regbank(fmt, ®_bank);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fmt.line("],");
|
fmtln!(fmt, "],");
|
||||||
// References to register classes.
|
// References to register classes.
|
||||||
fmt.line("classes: &[");
|
fmtln!(fmt, "classes: &[");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
for reg_class in isa.regs.classes.values() {
|
for reg_class in isa.regs.classes.values() {
|
||||||
fmt.line(format!("&{}_DATA,", reg_class.name));
|
fmtln!(fmt, "&{}_DATA,", reg_class.name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fmt.line("],");
|
fmtln!(fmt, "],");
|
||||||
});
|
});
|
||||||
fmt.line("};");
|
fmtln!(fmt, "};");
|
||||||
|
|
||||||
// Register class descriptors.
|
// Register class descriptors.
|
||||||
for rc in isa.regs.classes.values() {
|
for rc in isa.regs.classes.values() {
|
||||||
@@ -105,26 +110,26 @@ fn gen_isa(isa: &TargetIsa, fmt: &mut Formatter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Emit constants for all the register units.
|
// Emit constants for all the register units.
|
||||||
fmt.line("#[allow(dead_code, non_camel_case_types)]");
|
fmtln!(fmt, "#[allow(dead_code, non_camel_case_types)]");
|
||||||
fmt.line("#[derive(Clone, Copy)]");
|
fmtln!(fmt, "#[derive(Clone, Copy)]");
|
||||||
fmt.line("pub enum RU {");
|
fmtln!(fmt, "pub enum RU {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
for reg_bank in isa.regs.banks.values() {
|
for reg_bank in isa.regs.banks.values() {
|
||||||
gen_regbank_units(reg_bank, fmt);
|
gen_regbank_units(reg_bank, fmt);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
|
|
||||||
// Emit Into conversion for the RU class.
|
// Emit Into conversion for the RU class.
|
||||||
fmt.line("impl Into<RegUnit> for RU {");
|
fmtln!(fmt, "impl Into<RegUnit> for RU {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line("fn into(self) -> RegUnit {");
|
fmtln!(fmt, "fn into(self) -> RegUnit {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line("self as RegUnit");
|
fmtln!(fmt, "self as RegUnit");
|
||||||
});
|
});
|
||||||
fmt.line("}")
|
fmtln!(fmt, "}");
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate(isa: &TargetIsa, base_filename: &str, out_dir: &str) -> Result<(), error::Error> {
|
pub fn generate(isa: &TargetIsa, base_filename: &str, out_dir: &str) -> Result<(), error::Error> {
|
||||||
|
|||||||
@@ -21,84 +21,92 @@ fn gen_constructor(group: &SettingGroup, parent: ParentGroup, fmt: &mut Formatte
|
|||||||
ParentGroup::None => "builder: Builder",
|
ParentGroup::None => "builder: Builder",
|
||||||
ParentGroup::Shared => "shared: &settings::Flags, builder: Builder",
|
ParentGroup::Shared => "shared: &settings::Flags, builder: Builder",
|
||||||
};
|
};
|
||||||
fmt.line("impl Flags {");
|
fmtln!(fmt, "impl Flags {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.doc_comment(format!("Create flags {} settings group.", group.name));
|
fmt.doc_comment(format!("Create flags {} settings group.", group.name));
|
||||||
fmt.line("#[allow(unused_variables)]");
|
fmtln!(fmt, "#[allow(unused_variables)]");
|
||||||
fmt.line(format!("pub fn new({}) -> Self {{", args));
|
fmtln!(fmt, "pub fn new({}) -> Self {{", args);
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line(format!("let bvec = builder.state_for(\"{}\");", group.name));
|
fmtln!(fmt, "let bvec = builder.state_for(\"{}\");", group.name);
|
||||||
fmt.line(format!(
|
fmtln!(
|
||||||
|
fmt,
|
||||||
"let mut {} = Self {{ bytes: [0; {}] }};",
|
"let mut {} = Self {{ bytes: [0; {}] }};",
|
||||||
group.name,
|
group.name,
|
||||||
group.byte_size()
|
group.byte_size()
|
||||||
));
|
);
|
||||||
fmt.line(format!(
|
fmtln!(
|
||||||
|
fmt,
|
||||||
"debug_assert_eq!(bvec.len(), {});",
|
"debug_assert_eq!(bvec.len(), {});",
|
||||||
group.settings_size
|
group.settings_size
|
||||||
));
|
);
|
||||||
fmt.line(format!(
|
fmtln!(
|
||||||
|
fmt,
|
||||||
"{}.bytes[0..{}].copy_from_slice(&bvec);",
|
"{}.bytes[0..{}].copy_from_slice(&bvec);",
|
||||||
group.name, group.settings_size
|
group.name,
|
||||||
));
|
group.settings_size
|
||||||
|
);
|
||||||
|
|
||||||
// Now compute the predicates.
|
// Now compute the predicates.
|
||||||
for p in &group.predicates {
|
for p in &group.predicates {
|
||||||
fmt.comment(format!("Precompute #{}.", p.number));
|
fmt.comment(format!("Precompute #{}.", p.number));
|
||||||
fmt.line(format!("if {} {{", p.render(group)));
|
fmtln!(fmt, "if {} {{", p.render(group));
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line(format!(
|
fmtln!(
|
||||||
|
fmt,
|
||||||
"{}.bytes[{}] |= 1 << {};",
|
"{}.bytes[{}] |= 1 << {};",
|
||||||
group.name,
|
group.name,
|
||||||
group.bool_start_byte_offset + p.number / 8,
|
group.bool_start_byte_offset + p.number / 8,
|
||||||
p.number % 8
|
p.number % 8
|
||||||
));
|
);
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.line(group.name);
|
fmtln!(fmt, group.name);
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emit Display and FromStr implementations for enum settings.
|
/// Emit Display and FromStr implementations for enum settings.
|
||||||
fn gen_to_and_from_str(name: &str, values: &[&'static str], fmt: &mut Formatter) {
|
fn gen_to_and_from_str(name: &str, values: &[&'static str], fmt: &mut Formatter) {
|
||||||
fmt.line(format!("impl fmt::Display for {} {{", name));
|
fmtln!(fmt, "impl fmt::Display for {} {{", name);
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line("fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {");
|
fmtln!(
|
||||||
|
fmt,
|
||||||
|
"fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {"
|
||||||
|
);
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line("f.write_str(match *self {");
|
fmtln!(fmt, "f.write_str(match *self {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
for v in values.iter() {
|
for v in values.iter() {
|
||||||
fmt.line(format!("{}::{} => \"{}\",", name, camel_case(v), v));
|
fmtln!(fmt, "{}::{} => \"{}\",", name, camel_case(v), v);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fmt.line("})");
|
fmtln!(fmt, "})");
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
|
|
||||||
fmt.line(format!("impl str::FromStr for {} {{", name));
|
fmtln!(fmt, "impl str::FromStr for {} {{", name);
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line("type Err = ();");
|
fmtln!(fmt, "type Err = ();");
|
||||||
fmt.line("fn from_str(s: &str) -> Result<Self, Self::Err> {");
|
fmtln!(fmt, "fn from_str(s: &str) -> Result<Self, Self::Err> {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line("match s {");
|
fmtln!(fmt, "match s {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
for v in values.iter() {
|
for v in values.iter() {
|
||||||
fmt.line(format!("\"{}\" => Ok({}::{}),", v, name, camel_case(v)));
|
fmtln!(fmt, "\"{}\" => Ok({}::{}),", v, name, camel_case(v));
|
||||||
}
|
}
|
||||||
fmt.line("_ => Err(()),");
|
fmtln!(fmt, "_ => Err(()),");
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emit real enum for the Enum settings.
|
/// Emit real enum for the Enum settings.
|
||||||
@@ -111,15 +119,15 @@ fn gen_enum_types(group: &SettingGroup, fmt: &mut Formatter) {
|
|||||||
let name = camel_case(setting.name);
|
let name = camel_case(setting.name);
|
||||||
|
|
||||||
fmt.doc_comment(format!("Values for `{}.{}`.", group.name, setting.name));
|
fmt.doc_comment(format!("Values for `{}.{}`.", group.name, setting.name));
|
||||||
fmt.line("#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]");
|
fmtln!(fmt, "#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]");
|
||||||
fmt.line(format!("pub enum {} {{", name));
|
fmtln!(fmt, "pub enum {} {{", name);
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
for v in values.iter() {
|
for v in values.iter() {
|
||||||
fmt.doc_comment(format!("`{}`.", v));
|
fmt.doc_comment(format!("`{}`.", v));
|
||||||
fmt.line(format!("{},", camel_case(v)));
|
fmtln!(fmt, "{},", camel_case(v));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
|
|
||||||
gen_to_and_from_str(&name, values, fmt);
|
gen_to_and_from_str(&name, values, fmt);
|
||||||
}
|
}
|
||||||
@@ -132,15 +140,15 @@ fn gen_getter(setting: &Setting, fmt: &mut Formatter) {
|
|||||||
SpecificSetting::Bool(BoolSetting {
|
SpecificSetting::Bool(BoolSetting {
|
||||||
predicate_number, ..
|
predicate_number, ..
|
||||||
}) => {
|
}) => {
|
||||||
fmt.line(format!("pub fn {}(&self) -> bool {{", setting.name));
|
fmtln!(fmt, "pub fn {}(&self) -> bool {{", setting.name);
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line(format!("self.numbered_predicate({})", predicate_number));
|
fmtln!(fmt, "self.numbered_predicate({})", predicate_number);
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
}
|
}
|
||||||
SpecificSetting::Enum(ref values) => {
|
SpecificSetting::Enum(ref values) => {
|
||||||
let ty = camel_case(setting.name);
|
let ty = camel_case(setting.name);
|
||||||
fmt.line(format!("pub fn {}(&self) -> {} {{", setting.name, ty));
|
fmtln!(fmt, "pub fn {}(&self) -> {} {{", setting.name, ty);
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
let mut m = Match::new(format!("self.bytes[{}]", setting.byte_offset));
|
let mut m = Match::new(format!("self.bytes[{}]", setting.byte_offset));
|
||||||
for (i, v) in values.iter().enumerate() {
|
for (i, v) in values.iter().enumerate() {
|
||||||
@@ -153,53 +161,58 @@ fn gen_getter(setting: &Setting, fmt: &mut Formatter) {
|
|||||||
m.arm("_", vec![], "panic!(\"Invalid enum value\")");
|
m.arm("_", vec![], "panic!(\"Invalid enum value\")");
|
||||||
fmt.add_match(m);
|
fmt.add_match(m);
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
}
|
}
|
||||||
SpecificSetting::Num(_) => {
|
SpecificSetting::Num(_) => {
|
||||||
fmt.line(format!("pub fn {}(&self) -> u8 {{", setting.name));
|
fmtln!(fmt, "pub fn {}(&self) -> u8 {{", setting.name);
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line(format!("self.bytes[{}]", setting.byte_offset));
|
fmtln!(fmt, "self.bytes[{}]", setting.byte_offset);
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_pred_getter(predicate: &Predicate, group: &SettingGroup, fmt: &mut Formatter) {
|
fn gen_pred_getter(predicate: &Predicate, group: &SettingGroup, fmt: &mut Formatter) {
|
||||||
fmt.doc_comment(format!("Computed predicate `{}`.", predicate.render(group)));
|
fmt.doc_comment(format!("Computed predicate `{}`.", predicate.render(group)));
|
||||||
fmt.line(format!("pub fn {}(&self) -> bool {{", predicate.name));
|
fmtln!(fmt, "pub fn {}(&self) -> bool {{", predicate.name);
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line(format!("self.numbered_predicate({})", predicate.number));
|
fmtln!(fmt, "self.numbered_predicate({})", predicate.number);
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emits getters for each setting value.
|
/// Emits getters for each setting value.
|
||||||
fn gen_getters(group: &SettingGroup, fmt: &mut Formatter) {
|
fn gen_getters(group: &SettingGroup, fmt: &mut Formatter) {
|
||||||
fmt.doc_comment("User-defined settings.");
|
fmt.doc_comment("User-defined settings.");
|
||||||
fmt.line("#[allow(dead_code)]");
|
fmtln!(fmt, "#[allow(dead_code)]");
|
||||||
fmt.line("impl Flags {");
|
fmtln!(fmt, "impl Flags {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.doc_comment("Get a view of the boolean predicates.");
|
fmt.doc_comment("Get a view of the boolean predicates.");
|
||||||
fmt.line("pub fn predicate_view(&self) -> ::settings::PredicateView {");
|
fmtln!(
|
||||||
|
fmt,
|
||||||
|
"pub fn predicate_view(&self) -> ::settings::PredicateView {"
|
||||||
|
);
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line(format!(
|
fmtln!(
|
||||||
|
fmt,
|
||||||
"::settings::PredicateView::new(&self.bytes[{}..])",
|
"::settings::PredicateView::new(&self.bytes[{}..])",
|
||||||
group.bool_start_byte_offset
|
group.bool_start_byte_offset
|
||||||
));
|
);
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
|
|
||||||
if group.settings.len() > 0 {
|
if group.settings.len() > 0 {
|
||||||
fmt.doc_comment("Dynamic numbered predicate getter.");
|
fmt.doc_comment("Dynamic numbered predicate getter.");
|
||||||
fmt.line("fn numbered_predicate(&self, p: usize) -> bool {");
|
fmtln!(fmt, "fn numbered_predicate(&self, p: usize) -> bool {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line(format!(
|
fmtln!(
|
||||||
|
fmt,
|
||||||
"self.bytes[{} + p / 8] & (1 << (p % 8)) != 0",
|
"self.bytes[{} + p / 8] & (1 << (p % 8)) != 0",
|
||||||
group.bool_start_byte_offset
|
group.bool_start_byte_offset
|
||||||
));
|
);
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
for setting in &group.settings {
|
for setting in &group.settings {
|
||||||
@@ -209,7 +222,7 @@ fn gen_getters(group: &SettingGroup, fmt: &mut Formatter) {
|
|||||||
gen_pred_getter(&predicate, &group, fmt);
|
gen_pred_getter(&predicate, &group, fmt);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Hash, PartialEq, Eq)]
|
#[derive(Hash, PartialEq, Eq)]
|
||||||
@@ -234,66 +247,66 @@ fn gen_descriptors(group: &SettingGroup, fmt: &mut Formatter) {
|
|||||||
let mut descriptor_index_map: HashMap<SettingOrPreset, usize> = HashMap::new();
|
let mut descriptor_index_map: HashMap<SettingOrPreset, usize> = HashMap::new();
|
||||||
|
|
||||||
// Generate descriptors.
|
// Generate descriptors.
|
||||||
fmt.line(format!(
|
fmtln!(
|
||||||
|
fmt,
|
||||||
"static DESCRIPTORS: [detail::Descriptor; {}] = [",
|
"static DESCRIPTORS: [detail::Descriptor; {}] = [",
|
||||||
group.settings.len() + group.presets.len()
|
group.settings.len() + group.presets.len()
|
||||||
));
|
);
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
for (idx, setting) in group.settings.iter().enumerate() {
|
for (idx, setting) in group.settings.iter().enumerate() {
|
||||||
fmt.line("detail::Descriptor {");
|
fmtln!(fmt, "detail::Descriptor {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line(format!("name: \"{}\",", setting.name));
|
fmtln!(fmt, "name: \"{}\",", setting.name);
|
||||||
fmt.line(format!("offset: {},", setting.byte_offset));
|
fmtln!(fmt, "offset: {},", setting.byte_offset);
|
||||||
match setting.specific {
|
match setting.specific {
|
||||||
SpecificSetting::Bool(BoolSetting { bit_offset, .. }) => {
|
SpecificSetting::Bool(BoolSetting { bit_offset, .. }) => {
|
||||||
fmt.line(format!(
|
fmtln!(
|
||||||
|
fmt,
|
||||||
"detail: detail::Detail::Bool {{ bit: {} }},",
|
"detail: detail::Detail::Bool {{ bit: {} }},",
|
||||||
bit_offset
|
bit_offset
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
SpecificSetting::Enum(ref values) => {
|
SpecificSetting::Enum(ref values) => {
|
||||||
let offset = enum_table.add(values);
|
let offset = enum_table.add(values);
|
||||||
fmt.line(format!(
|
fmtln!(
|
||||||
|
fmt,
|
||||||
"detail: detail::Detail::Enum {{ last: {}, enumerators: {} }},",
|
"detail: detail::Detail::Enum {{ last: {}, enumerators: {} }},",
|
||||||
values.len() - 1,
|
values.len() - 1,
|
||||||
offset
|
offset
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
SpecificSetting::Num(_) => {
|
SpecificSetting::Num(_) => {
|
||||||
fmt.line("detail: detail::Detail::Num,");
|
fmtln!(fmt, "detail: detail::Detail::Num,");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptor_index_map.insert(SettingOrPreset::Setting(setting), idx);
|
descriptor_index_map.insert(SettingOrPreset::Setting(setting), idx);
|
||||||
});
|
});
|
||||||
fmt.line("},");
|
fmtln!(fmt, "},");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (idx, preset) in group.presets.iter().enumerate() {
|
for (idx, preset) in group.presets.iter().enumerate() {
|
||||||
fmt.line("detail::Descriptor {");
|
fmtln!(fmt, "detail::Descriptor {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line(format!("name: \"{}\",", preset.name));
|
fmtln!(fmt, "name: \"{}\",", preset.name);
|
||||||
fmt.line(format!("offset: {},", (idx as u8) * group.settings_size));
|
fmtln!(fmt, "offset: {},", (idx as u8) * group.settings_size);
|
||||||
fmt.line("detail: detail::Detail::Preset,");
|
fmtln!(fmt, "detail: detail::Detail::Preset,");
|
||||||
});
|
});
|
||||||
fmt.line("},");
|
fmtln!(fmt, "},");
|
||||||
|
|
||||||
descriptor_index_map.insert(SettingOrPreset::Preset(preset), idx);
|
descriptor_index_map.insert(SettingOrPreset::Preset(preset), idx);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fmt.line("];");
|
fmtln!(fmt, "];");
|
||||||
|
|
||||||
// Generate enumerators.
|
// Generate enumerators.
|
||||||
fmt.line(format!(
|
fmtln!(fmt, "static ENUMERATORS: [&str; {}] = [", enum_table.len());
|
||||||
"static ENUMERATORS: [&str; {}] = [",
|
|
||||||
enum_table.len()
|
|
||||||
));
|
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
for enum_val in enum_table.iter() {
|
for enum_val in enum_table.iter() {
|
||||||
fmt.line(format!("\"{}\",", enum_val));
|
fmtln!(fmt, "\"{}\",", enum_val);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fmt.line("];");
|
fmtln!(fmt, "];");
|
||||||
|
|
||||||
// Generate hash table.
|
// Generate hash table.
|
||||||
let mut hash_entries: Vec<SettingOrPreset> = Vec::new();
|
let mut hash_entries: Vec<SettingOrPreset> = Vec::new();
|
||||||
@@ -312,40 +325,39 @@ fn gen_descriptors(group: &SettingGroup, fmt: &mut Formatter) {
|
|||||||
.collect::<Vec<SettingOrPreset>>(),
|
.collect::<Vec<SettingOrPreset>>(),
|
||||||
);
|
);
|
||||||
let hash_table = generate_table(&hash_entries, |entry| simple_hash(entry.name()));
|
let hash_table = generate_table(&hash_entries, |entry| simple_hash(entry.name()));
|
||||||
fmt.line(format!(
|
fmtln!(fmt, "static HASH_TABLE: [u16; {}] = [", hash_table.len());
|
||||||
"static HASH_TABLE: [u16; {}] = [",
|
|
||||||
hash_table.len()
|
|
||||||
));
|
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
for h in &hash_table {
|
for h in &hash_table {
|
||||||
match *h {
|
match *h {
|
||||||
Some(setting_or_preset) => fmt.line(format!(
|
Some(setting_or_preset) => fmtln!(
|
||||||
|
fmt,
|
||||||
"{},",
|
"{},",
|
||||||
&descriptor_index_map
|
&descriptor_index_map
|
||||||
.get(setting_or_preset)
|
.get(setting_or_preset)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_string()
|
.to_string()
|
||||||
)),
|
),
|
||||||
None => fmt.line("0xffff,"),
|
None => fmtln!(fmt, "0xffff,"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fmt.line("];");
|
fmtln!(fmt, "];");
|
||||||
|
|
||||||
// Generate presets.
|
// Generate presets.
|
||||||
fmt.line(format!(
|
fmtln!(
|
||||||
|
fmt,
|
||||||
"static PRESETS: [(u8, u8); {}] = [",
|
"static PRESETS: [(u8, u8); {}] = [",
|
||||||
group.presets.len()
|
group.presets.len()
|
||||||
));
|
);
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
for preset in &group.presets {
|
for preset in &group.presets {
|
||||||
fmt.comment(preset.name);
|
fmt.comment(preset.name);
|
||||||
for (mask, value) in preset.layout(&group) {
|
for (mask, value) in preset.layout(&group) {
|
||||||
fmt.line(format!("(0b{:08b}, 0b{:08b}),", mask, value));
|
fmtln!(fmt, "(0b{:08b}, 0b{:08b}),", mask, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fmt.line("];");
|
fmtln!(fmt, "];");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_template(group: &SettingGroup, fmt: &mut Formatter) {
|
fn gen_template(group: &SettingGroup, fmt: &mut Formatter) {
|
||||||
@@ -360,63 +372,70 @@ fn gen_template(group: &SettingGroup, fmt: &mut Formatter) {
|
|||||||
.collect();
|
.collect();
|
||||||
let default_bytes_str = default_bytes.join(", ");
|
let default_bytes_str = default_bytes.join(", ");
|
||||||
|
|
||||||
fmt.line("static TEMPLATE: detail::Template = detail::Template {");
|
fmtln!(
|
||||||
|
fmt,
|
||||||
|
"static TEMPLATE: detail::Template = detail::Template {"
|
||||||
|
);
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line(format!("name: \"{}\",", group.name));
|
fmtln!(fmt, "name: \"{}\",", group.name);
|
||||||
fmt.line("descriptors: &DESCRIPTORS,");
|
fmtln!(fmt, "descriptors: &DESCRIPTORS,");
|
||||||
fmt.line("enumerators: &ENUMERATORS,");
|
fmtln!(fmt, "enumerators: &ENUMERATORS,");
|
||||||
fmt.line("hash_table: &HASH_TABLE,");
|
fmtln!(fmt, "hash_table: &HASH_TABLE,");
|
||||||
fmt.line(format!("defaults: &[{}],", default_bytes_str));
|
fmtln!(fmt, "defaults: &[{}],", default_bytes_str);
|
||||||
fmt.line("presets: &PRESETS,");
|
fmtln!(fmt, "presets: &PRESETS,");
|
||||||
});
|
});
|
||||||
fmt.line("};");
|
fmtln!(fmt, "};");
|
||||||
|
|
||||||
fmt.doc_comment(format!(
|
fmt.doc_comment(format!(
|
||||||
"Create a `settings::Builder` for the {} settings group.",
|
"Create a `settings::Builder` for the {} settings group.",
|
||||||
group.name
|
group.name
|
||||||
));
|
));
|
||||||
fmt.line("pub fn builder() -> Builder {");
|
fmtln!(fmt, "pub fn builder() -> Builder {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line("Builder::new(&TEMPLATE)");
|
fmtln!(fmt, "Builder::new(&TEMPLATE)");
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_display(group: &SettingGroup, fmt: &mut Formatter) {
|
fn gen_display(group: &SettingGroup, fmt: &mut Formatter) {
|
||||||
fmt.line("impl fmt::Display for Flags {");
|
fmtln!(fmt, "impl fmt::Display for Flags {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line("fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {");
|
fmtln!(
|
||||||
|
fmt,
|
||||||
|
"fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {"
|
||||||
|
);
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line(format!("writeln!(f, \"[{}]\")?;", group.name));
|
fmtln!(fmt, "writeln!(f, \"[{}]\")?;", group.name);
|
||||||
fmt.line("for d in &DESCRIPTORS {");
|
fmtln!(fmt, "for d in &DESCRIPTORS {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line("if !d.detail.is_preset() {");
|
fmtln!(fmt, "if !d.detail.is_preset() {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line("write!(f, \"{} = \", d.name)?;");
|
fmtln!(fmt, "write!(f, \"{} = \", d.name)?;");
|
||||||
fmt.line(
|
fmtln!(
|
||||||
|
fmt,
|
||||||
"TEMPLATE.format_toml_value(d.detail, self.bytes[d.offset as usize], f)?;",
|
"TEMPLATE.format_toml_value(d.detail, self.bytes[d.offset as usize], f)?;",
|
||||||
);
|
);
|
||||||
fmt.line("writeln!(f)?;");
|
fmtln!(fmt, "writeln!(f)?;");
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
fmt.line("Ok(())");
|
fmtln!(fmt, "Ok(())");
|
||||||
});
|
});
|
||||||
fmt.line("}")
|
fmtln!(fmt, "}")
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_group(group: &SettingGroup, parent: ParentGroup, fmt: &mut Formatter) {
|
fn gen_group(group: &SettingGroup, parent: ParentGroup, fmt: &mut Formatter) {
|
||||||
// Generate struct.
|
// Generate struct.
|
||||||
fmt.line("#[derive(Clone)]");
|
fmtln!(fmt, "#[derive(Clone)]");
|
||||||
fmt.doc_comment(format!("Flags group `{}`.", group.name));
|
fmt.doc_comment(format!("Flags group `{}`.", group.name));
|
||||||
fmt.line("pub struct Flags {");
|
fmtln!(fmt, "pub struct Flags {");
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line(format!("bytes: [u8; {}],", group.byte_size()));
|
fmtln!(fmt, "bytes: [u8; {}],", group.byte_size());
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmtln!(fmt, "}");
|
||||||
|
|
||||||
gen_constructor(group, parent, fmt);
|
gen_constructor(group, parent, fmt);
|
||||||
gen_enum_types(group, fmt);
|
gen_enum_types(group, fmt);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ fn emit_type(ty: &cdsl_types::ValueType, fmt: &mut srcgen::Formatter) -> Result<
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
fmt.doc_comment(&ty.doc());
|
fmt.doc_comment(&ty.doc());
|
||||||
fmt.line(format!("pub const {}: Type = Type({:#x});\n", name, number));
|
fmtln!(fmt, "pub const {}: Type = Type({:#x});\n", name, number);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod cdsl;
|
mod cdsl;
|
||||||
|
mod srcgen;
|
||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod isa;
|
pub mod isa;
|
||||||
@@ -10,7 +11,6 @@ mod gen_types;
|
|||||||
|
|
||||||
mod constant_hash;
|
mod constant_hash;
|
||||||
mod shared;
|
mod shared;
|
||||||
mod srcgen;
|
|
||||||
mod unique_table;
|
mod unique_table;
|
||||||
|
|
||||||
pub fn isa_from_arch(arch: &str) -> Result<isa::Isa, String> {
|
pub fn isa_from_arch(arch: &str) -> Result<isa::Isa, String> {
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
//! The `srcgen` module contains generic helper routines and classes for
|
//! The `srcgen` module contains generic helper routines and classes for
|
||||||
//! generating source code.
|
//! generating source code.
|
||||||
|
|
||||||
|
#![macro_use]
|
||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::collections::{BTreeMap, BTreeSet};
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@@ -13,6 +15,18 @@ use crate::error;
|
|||||||
|
|
||||||
static SHIFTWIDTH: usize = 4;
|
static SHIFTWIDTH: usize = 4;
|
||||||
|
|
||||||
|
/// A macro that simplifies the usage of the Formatter by allowing format
|
||||||
|
/// strings.
|
||||||
|
macro_rules! fmtln {
|
||||||
|
($fmt:ident, $fmtstring:expr, $($fmtargs:expr),*) => {
|
||||||
|
$fmt.line(format!($fmtstring, $($fmtargs),*));
|
||||||
|
};
|
||||||
|
|
||||||
|
($fmt:ident, $arg:expr) => {
|
||||||
|
$fmt.line($arg);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Formatter {
|
pub struct Formatter {
|
||||||
indent: usize,
|
indent: usize,
|
||||||
lines: Vec<String>,
|
lines: Vec<String>,
|
||||||
@@ -104,7 +118,7 @@ impl Formatter {
|
|||||||
|
|
||||||
/// Add a comment line.
|
/// Add a comment line.
|
||||||
pub fn comment(&mut self, s: impl AsRef<str>) {
|
pub fn comment(&mut self, s: impl AsRef<str>) {
|
||||||
self.line(format!("// {}", s.as_ref()));
|
fmtln!(self, "// {}", s.as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a (multi-line) documentation comment.
|
/// Add a (multi-line) documentation comment.
|
||||||
@@ -123,7 +137,7 @@ impl Formatter {
|
|||||||
|
|
||||||
/// Add a match expression.
|
/// Add a match expression.
|
||||||
pub fn add_match(&mut self, m: Match) {
|
pub fn add_match(&mut self, m: Match) {
|
||||||
self.line(format!("match {} {{", m.expr));
|
fmtln!(self, "match {} {{", m.expr);
|
||||||
self.indent(|fmt| {
|
self.indent(|fmt| {
|
||||||
for (&(ref fields, ref body), ref names) in m.arms.iter() {
|
for (&(ref fields, ref body), ref names) in m.arms.iter() {
|
||||||
// name { fields } | name { fields } => { body }
|
// name { fields } | name { fields } => { body }
|
||||||
@@ -138,7 +152,7 @@ impl Formatter {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let lhs = conditions.join(" | ");
|
let lhs = conditions.join(" | ");
|
||||||
fmt.line(format!("{} => {{", lhs));
|
fmtln!(fmt, "{} => {{", lhs);
|
||||||
fmt.indent(|fmt| {
|
fmt.indent(|fmt| {
|
||||||
fmt.line(body);
|
fmt.line(body);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user