isle: expand enums in ISLE (#3586)
* x64: expand FloatCC enum in ISLE * isle: regenerate manifests * isle: generate all enum fields in `clif.isle` This expands the `gen_isle` function to write all of the immediate `enum`s out explicitly in `clif.isle`. Non-`enum` immediates are still `extern primitive`. * Only compile `enum_values` with `rebuild-isle` feature * Only compile `gen_enum_isle` with `rebuild-isle` feature
This commit is contained in:
@@ -1087,9 +1087,11 @@ fn gen_inst_builder(inst: &Instruction, format: &InstructionFormat, fmt: &mut Fo
|
||||
|
||||
#[cfg(feature = "rebuild-isle")]
|
||||
fn gen_isle(formats: &[&InstructionFormat], instructions: &AllInstructions, fmt: &mut Formatter) {
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::fmt::Write;
|
||||
|
||||
use crate::cdsl::formats::FormatField;
|
||||
|
||||
fmt.multi_line(
|
||||
r#"
|
||||
;; GENERATED BY `gen_isle`. DO NOT EDIT!!!
|
||||
@@ -1101,23 +1103,42 @@ fn gen_isle(formats: &[&InstructionFormat], instructions: &AllInstructions, fmt:
|
||||
);
|
||||
fmt.empty_line();
|
||||
|
||||
// Generate all the extern type declarations we need for various immediates.
|
||||
fmt.line(";;;; Extern type declarations for immediates ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;");
|
||||
fmt.empty_line();
|
||||
let imm_tys: BTreeSet<_> = formats
|
||||
// Collect and deduplicate the immediate types from the instruction fields.
|
||||
let rust_name = |f: &FormatField| f.kind.rust_type.rsplit("::").next().unwrap();
|
||||
let fields = |f: &FormatField| f.kind.fields.clone();
|
||||
let immediate_types: BTreeMap<_, _> = formats
|
||||
.iter()
|
||||
.flat_map(|f| {
|
||||
f.imm_fields
|
||||
.iter()
|
||||
.map(|i| i.kind.rust_type.rsplit("::").next().unwrap())
|
||||
.map(|i| (rust_name(i), fields(i)))
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.collect();
|
||||
for ty in imm_tys {
|
||||
|
||||
// Separate the `enum` immediates (e.g., `FloatCC`) from other kinds of
|
||||
// immediates.
|
||||
let (enums, others): (BTreeMap<_, _>, BTreeMap<_, _>) = immediate_types
|
||||
.iter()
|
||||
.partition(|(_, field)| field.enum_values().is_some());
|
||||
|
||||
// Generate all the extern type declarations we need for the non-`enum`
|
||||
// immediates.
|
||||
fmt.line(";;;; Extern type declarations for immediates ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;");
|
||||
fmt.empty_line();
|
||||
for ty in others.keys() {
|
||||
fmtln!(fmt, "(type {} (primitive {}))", ty, ty);
|
||||
}
|
||||
fmt.empty_line();
|
||||
|
||||
// Generate the `enum` immediates, expanding all of the available variants
|
||||
// into ISLE.
|
||||
for (name, field) in enums {
|
||||
let field = field.enum_values().expect("only enums considered here");
|
||||
let variants = field.values().cloned().collect();
|
||||
gen_isle_enum(name, variants, fmt)
|
||||
}
|
||||
|
||||
// Generate all of the value arrays we need for `InstructionData` as well as
|
||||
// the constructors and extractors for them.
|
||||
fmt.line(";;;; Value Arrays ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;");
|
||||
@@ -1323,6 +1344,27 @@ fn gen_isle(formats: &[&InstructionFormat], instructions: &AllInstructions, fmt:
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate an `enum` immediate in ISLE.
|
||||
#[cfg(feature = "rebuild-isle")]
|
||||
fn gen_isle_enum(name: &str, mut variants: Vec<&str>, fmt: &mut Formatter) {
|
||||
variants.sort();
|
||||
let prefix = format!(";;;; Enumerated Immediate: {} ", name);
|
||||
fmtln!(fmt, "{:;<80}", prefix);
|
||||
fmt.empty_line();
|
||||
fmtln!(fmt, "(type {} extern", name);
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line("(enum");
|
||||
fmt.indent(|fmt| {
|
||||
for variant in variants {
|
||||
fmtln!(fmt, "{}", variant);
|
||||
}
|
||||
});
|
||||
fmt.line(")");
|
||||
});
|
||||
fmt.line(")");
|
||||
fmt.empty_line();
|
||||
}
|
||||
|
||||
/// Generate a Builder trait with methods for all instructions.
|
||||
fn gen_builder(
|
||||
instructions: &AllInstructions,
|
||||
|
||||
Reference in New Issue
Block a user