From 86611d3bbc92b781ed136dcda7cdba9ec2c1cbee Mon Sep 17 00:00:00 2001 From: Andrew Brown Date: Sun, 12 Dec 2021 18:31:42 -0800 Subject: [PATCH] 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 --- cranelift/codegen/meta/src/cdsl/operands.rs | 11 +++ cranelift/codegen/meta/src/gen_inst.rs | 56 ++++++++++++-- cranelift/codegen/src/clif.isle | 73 ++++++++++++++++++- .../lower/isle/generated_code.manifest | 2 +- .../x64/lower/isle/generated_code.manifest | 2 +- 5 files changed, 131 insertions(+), 13 deletions(-) diff --git a/cranelift/codegen/meta/src/cdsl/operands.rs b/cranelift/codegen/meta/src/cdsl/operands.rs index 915b8b6380..945f2f6e3a 100644 --- a/cranelift/codegen/meta/src/cdsl/operands.rs +++ b/cranelift/codegen/meta/src/cdsl/operands.rs @@ -111,6 +111,17 @@ pub(crate) enum OperandKindFields { TypeVar(TypeVar), } +impl OperandKindFields { + /// Return the [EnumValues] for this field if it is an `enum`. + #[cfg(feature = "rebuild-isle")] + pub(crate) fn enum_values(&self) -> Option<&EnumValues> { + match self { + OperandKindFields::ImmEnum(map) => Some(map), + _ => None, + } + } +} + #[derive(Clone, Debug)] pub(crate) struct OperandKind { /// String representation of the Rust type mapping to this OperandKind. diff --git a/cranelift/codegen/meta/src/gen_inst.rs b/cranelift/codegen/meta/src/gen_inst.rs index 54d8647ddf..6705170c11 100644 --- a/cranelift/codegen/meta/src/gen_inst.rs +++ b/cranelift/codegen/meta/src/gen_inst.rs @@ -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::>() }) .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, diff --git a/cranelift/codegen/src/clif.isle b/cranelift/codegen/src/clif.isle index fbea08c5ae..d667aeccaf 100644 --- a/cranelift/codegen/src/clif.isle +++ b/cranelift/codegen/src/clif.isle @@ -6,10 +6,8 @@ ;;;; Extern type declarations for immediates ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(type AtomicRmwOp (primitive AtomicRmwOp)) (type Block (primitive Block)) (type Constant (primitive Constant)) -(type FloatCC (primitive FloatCC)) (type FuncRef (primitive FuncRef)) (type GlobalValue (primitive GlobalValue)) (type Heap (primitive Heap)) @@ -17,18 +15,85 @@ (type Ieee64 (primitive Ieee64)) (type Imm64 (primitive Imm64)) (type Immediate (primitive Immediate)) -(type IntCC (primitive IntCC)) (type JumpTable (primitive JumpTable)) (type MemFlags (primitive MemFlags)) (type Offset32 (primitive Offset32)) (type SigRef (primitive SigRef)) (type StackSlot (primitive StackSlot)) (type Table (primitive Table)) -(type TrapCode (primitive TrapCode)) (type Uimm32 (primitive Uimm32)) (type Uimm8 (primitive Uimm8)) (type bool (primitive bool)) +;;;; Enumerated Immediate: AtomicRmwOp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(type AtomicRmwOp extern + (enum + Add + And + Nand + Or + Smax + Smin + Sub + Umax + Umin + Xchg + Xor + ) +) + +;;;; Enumerated Immediate: FloatCC ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(type FloatCC extern + (enum + Equal + GreaterThan + GreaterThanOrEqual + LessThan + LessThanOrEqual + NotEqual + Ordered + OrderedNotEqual + Unordered + UnorderedOrEqual + UnorderedOrGreaterThan + UnorderedOrGreaterThanOrEqual + UnorderedOrLessThan + UnorderedOrLessThanOrEqual + ) +) + +;;;; Enumerated Immediate: IntCC ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(type IntCC extern + (enum + Equal + NotEqual + NotOverflow + Overflow + SignedGreaterThan + SignedGreaterThanOrEqual + SignedLessThan + SignedLessThanOrEqual + UnsignedGreaterThan + UnsignedGreaterThanOrEqual + UnsignedLessThan + UnsignedLessThanOrEqual + ) +) + +;;;; Enumerated Immediate: TrapCode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(type TrapCode extern + (enum + HeapOutOfBounds + IntegerDivisionByZero + IntegerOverflow + StackOverflow + ) +) + ;;;; Value Arrays ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ISLE representation of `[Value; 2]`. diff --git a/cranelift/codegen/src/isa/aarch64/lower/isle/generated_code.manifest b/cranelift/codegen/src/isa/aarch64/lower/isle/generated_code.manifest index a5f3198e22..f832d97efa 100644 --- a/cranelift/codegen/src/isa/aarch64/lower/isle/generated_code.manifest +++ b/cranelift/codegen/src/isa/aarch64/lower/isle/generated_code.manifest @@ -1,4 +1,4 @@ -src/clif.isle 9c0563583e5500de00ec5e226edc0547ac3ea789c8d76f1da0401c80ec619320fdc9a6f17fd76bbcac74a5894f85385c1f51c900c2b83bc9906d03d0f29bf5cb +src/clif.isle be1359b4b6b153f378517c1dd95cd80f4a6bed0c7b86eaba11c088fd71b7bfe80a3c868ace245b2da0bfbbd6ded262ea9576c8e0eeacbf89d03c34a17a709602 src/prelude.isle 9bd1fcb6a3604a24cf2e05e6b7eb04dcb3b9dc8fa9a2f1c8f29c25b6e3bf7f679b3b1b72dff87501497b72bc30fc92fd755b898db7e03f380235fae931b6a74b src/isa/aarch64/inst.isle 6e042ec14166fceae4b7133f681fdf604e20a2997e1d60f797e40acd683ccb34e33376189f6b7ed2f5eb441dc61d592cad2592256dfea51296330752181b9403 src/isa/aarch64/lower.isle 64a725771537f69c445f44c728e04bffd8a715d6a4d87a5a2bf2e89714ee290b7497c5ca8b335bdddd775f6734be03318ff9aa67e2e4068949ebae06b0902b3f diff --git a/cranelift/codegen/src/isa/x64/lower/isle/generated_code.manifest b/cranelift/codegen/src/isa/x64/lower/isle/generated_code.manifest index db3765c102..570c14b1af 100644 --- a/cranelift/codegen/src/isa/x64/lower/isle/generated_code.manifest +++ b/cranelift/codegen/src/isa/x64/lower/isle/generated_code.manifest @@ -1,4 +1,4 @@ -src/clif.isle 9c0563583e5500de00ec5e226edc0547ac3ea789c8d76f1da0401c80ec619320fdc9a6f17fd76bbcac74a5894f85385c1f51c900c2b83bc9906d03d0f29bf5cb +src/clif.isle be1359b4b6b153f378517c1dd95cd80f4a6bed0c7b86eaba11c088fd71b7bfe80a3c868ace245b2da0bfbbd6ded262ea9576c8e0eeacbf89d03c34a17a709602 src/prelude.isle 9bd1fcb6a3604a24cf2e05e6b7eb04dcb3b9dc8fa9a2f1c8f29c25b6e3bf7f679b3b1b72dff87501497b72bc30fc92fd755b898db7e03f380235fae931b6a74b src/isa/x64/inst.isle b151120df3c356ac697122a8557becd8857eb725851506e844edeb85d831d461322a96d280ad84f9a23518e1e4efb607aebc0e249004148675e4cc19e89f0655 src/isa/x64/lower.isle c9b408df0a089fb4f207838973ac775b0f9b56c86f056867c28e6bae317873d3844f74f713f9acd6fed98d3d11a2f9d19d392fe5049169dad33b1fc703b9b766