diff --git a/cranelift/codegen/meta/src/cdsl/instructions.rs b/cranelift/codegen/meta/src/cdsl/instructions.rs index d57bcc254a..4bcd6ea402 100644 --- a/cranelift/codegen/meta/src/cdsl/instructions.rs +++ b/cranelift/codegen/meta/src/cdsl/instructions.rs @@ -1,3 +1,10 @@ +use std::fmt; +use std::ops; +use std::rc::Rc; +use std::slice; + +use cranelift_entity::{entity_impl, PrimaryMap}; + use crate::cdsl::camel_case; use crate::cdsl::formats::{ FormatField, FormatRegistry, InstructionFormat, InstructionFormatIndex, @@ -7,41 +14,49 @@ use crate::cdsl::type_inference::Constraint; use crate::cdsl::types::{LaneType, ValueType}; use crate::cdsl::typevar::TypeVar; -use std::fmt; -use std::ops; -use std::rc::Rc; -use std::slice; +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct OpcodeNumber(u32); +entity_impl!(OpcodeNumber); -pub struct InstructionGroupBuilder<'format_reg> { +pub type AllInstructions = PrimaryMap; + +pub struct InstructionGroupBuilder<'format_reg, 'all_inst> { _name: &'static str, _doc: &'static str, format_registry: &'format_reg FormatRegistry, - instructions: Vec, + all_instructions: &'all_inst mut AllInstructions, + own_instructions: Vec, } -impl<'format_reg> InstructionGroupBuilder<'format_reg> { +impl<'format_reg, 'all_inst> InstructionGroupBuilder<'format_reg, 'all_inst> { pub fn new( name: &'static str, doc: &'static str, + all_instructions: &'all_inst mut AllInstructions, format_registry: &'format_reg FormatRegistry, ) -> Self { Self { _name: name, _doc: doc, format_registry, - instructions: Vec::new(), + all_instructions, + own_instructions: Vec::new(), } } pub fn push(&mut self, builder: InstructionBuilder) { - self.instructions.push(builder.build(self.format_registry)); + let opcode_number = OpcodeNumber(self.all_instructions.next_key().as_u32()); + let inst = builder.build(self.format_registry, opcode_number); + // Note this clone is cheap, since Instruction is a Rc<> wrapper for InstructionContent. + self.own_instructions.push(inst.clone()); + self.all_instructions.push(inst); } pub fn build(self) -> InstructionGroup { InstructionGroup { _name: self._name, _doc: self._doc, - instructions: self.instructions, + instructions: self.own_instructions, } } } @@ -78,6 +93,7 @@ pub struct InstructionContent { /// Instruction mnemonic, also becomes opcode name. pub name: String, pub camel_name: String, + pub opcode_number: OpcodeNumber, /// Documentation string. doc: String, @@ -300,7 +316,7 @@ impl InstructionBuilder { self } - fn build(self, format_registry: &FormatRegistry) -> Instruction { + fn build(self, format_registry: &FormatRegistry, opcode_number: OpcodeNumber) -> Instruction { let operands_in = self.operands_in.unwrap_or_else(Vec::new); let operands_out = self.operands_out.unwrap_or_else(Vec::new); @@ -333,10 +349,12 @@ impl InstructionBuilder { let writes_cpu_flags = operands_out.iter().any(|op| op.is_cpu_flags()); let camel_name = camel_case(&self.name); + Instruction { content: Rc::new(InstructionContent { name: self.name, camel_name, + opcode_number, doc: self.doc, operands_in, operands_out, diff --git a/cranelift/codegen/meta/src/cdsl/xform.rs b/cranelift/codegen/meta/src/cdsl/xform.rs index 0cc0c6a03c..e988bf12ac 100644 --- a/cranelift/codegen/meta/src/cdsl/xform.rs +++ b/cranelift/codegen/meta/src/cdsl/xform.rs @@ -404,11 +404,12 @@ impl TransformGroups { #[should_panic] fn test_double_custom_legalization() { use crate::cdsl::formats::{FormatRegistry, InstructionFormatBuilder}; - use crate::cdsl::instructions::{InstructionBuilder, InstructionGroupBuilder}; + use crate::cdsl::instructions::{AllInstructions, InstructionBuilder, InstructionGroupBuilder}; + let mut dummy_all = AllInstructions::new(); let mut format = FormatRegistry::new(); format.insert(InstructionFormatBuilder::new("nullary")); - let mut inst_group = InstructionGroupBuilder::new("test", "", &format); + let mut inst_group = InstructionGroupBuilder::new("test", "", &mut dummy_all, &format); inst_group.push(InstructionBuilder::new("dummy", "doc")); let inst_group = inst_group.build(); let dummy_inst = inst_group.by_name("dummy"); diff --git a/cranelift/codegen/meta/src/constant_hash.rs b/cranelift/codegen/meta/src/constant_hash.rs index 7f629d0d8b..4090e4d77d 100644 --- a/cranelift/codegen/meta/src/constant_hash.rs +++ b/cranelift/codegen/meta/src/constant_hash.rs @@ -1,3 +1,5 @@ +use std::iter; + pub fn simple_hash(s: &str) -> usize { let mut h: u32 = 5381; for c in s.chars() { @@ -9,8 +11,12 @@ pub fn simple_hash(s: &str) -> usize { /// Compute an open addressed, quadratically probed hash table containing /// `items`. The returned table is a list containing the elements of the /// iterable `items` and `None` in unused slots. -pub fn generate_table usize>(items: &Vec, hash_function: H) -> Vec> { - let size = (1.20 * items.len() as f64) as usize; +pub fn generate_table<'cont, T, I: iter::Iterator, H: Fn(&T) -> usize>( + items: I, + num_items: usize, + hash_function: H, +) -> Vec> { + let size = (1.20 * num_items as f64) as usize; // TODO do we really need the multiply by two here? let size = if size.is_power_of_two() { size * 2 @@ -18,10 +24,10 @@ pub fn generate_table usize>(items: &Vec, hash_function: H) - size.next_power_of_two() }; - let mut table: Vec> = vec![None; size]; + let mut table = vec![None; size]; for i in items { - let mut h = hash_function(i) % size; + let mut h = hash_function(&i) % size; let mut s = 0; while table[h].is_some() { s += 1; @@ -36,7 +42,7 @@ pub fn generate_table usize>(items: &Vec, hash_function: H) - #[test] fn test_generate_table() { let v = vec!["Hello".to_string(), "world".to_string()]; - let table = generate_table(&v, |s| simple_hash(&s)); + let table = generate_table(v.iter(), v.len(), |s| simple_hash(&s)); assert_eq!( table, vec![ diff --git a/cranelift/codegen/meta/src/gen_inst.rs b/cranelift/codegen/meta/src/gen_inst.rs index 613987421b..8e499cb866 100644 --- a/cranelift/codegen/meta/src/gen_inst.rs +++ b/cranelift/codegen/meta/src/gen_inst.rs @@ -1,15 +1,20 @@ +use std::fmt; + +use cranelift_entity::EntityRef; + use crate::cdsl::camel_case; use crate::cdsl::formats::{FormatRegistry, InstructionFormat}; -use crate::cdsl::instructions::{Instruction, InstructionGroup}; +use crate::cdsl::instructions::{AllInstructions, Instruction}; use crate::cdsl::operands::Operand; use crate::cdsl::typevar::{TypeSet, TypeVar}; + +use crate::shared::Definitions as SharedDefinitions; + use crate::constant_hash; use crate::error; use crate::srcgen::{Formatter, Match}; use crate::unique_table::{UniqueSeqTable, UniqueTable}; -use std::fmt; - // TypeSet indexes are encoded in 8 bits, with `0xff` reserved. const TYPESET_LIMIT: usize = 0xff; @@ -368,7 +373,7 @@ fn gen_instruction_data_impl(registry: &FormatRegistry, fmt: &mut Formatter) { } fn gen_bool_accessor bool>( - instruction_groups: &Vec<&InstructionGroup>, + all_inst: &AllInstructions, get_attr: T, name: &'static str, doc: &'static str, @@ -378,11 +383,9 @@ fn gen_bool_accessor bool>( fmtln!(fmt, "pub fn {}(self) -> bool {{", name); fmt.indent(|fmt| { let mut m = Match::new("self"); - for group in instruction_groups.iter() { - for inst in group.iter() { - if get_attr(inst) { - m.arm_no_fields(format!("Opcode::{}", inst.camel_name), "true"); - } + for inst in all_inst.values() { + if get_attr(inst) { + m.arm_no_fields(format!("Opcode::{}", inst.camel_name), "true"); } } m.arm_no_fields("_", "false"); @@ -392,18 +395,7 @@ fn gen_bool_accessor bool>( fmt.empty_line(); } -fn gen_opcodes<'a>( - formats: &FormatRegistry, - igroups: &Vec<&'a InstructionGroup>, - fmt: &mut Formatter, -) -> Vec<&'a Instruction> { - let mut all_inst = Vec::new(); - for group in igroups { - for inst in group.iter() { - all_inst.push(inst); - } - } - +fn gen_opcodes<'a>(all_inst: &AllInstructions, formats: &FormatRegistry, fmt: &mut Formatter) { fmt.doc_comment( r#" An instruction opcode. @@ -420,10 +412,7 @@ fn gen_opcodes<'a>( fmt.line("pub enum Opcode {"); fmt.indent(|fmt| { let mut is_first_opcode = true; - for inst in &all_inst { - // TODO we might need to set an instruction number here. Probably can do in the - // InstructionGroup itself when adding instruction (would need to remember last - // instruction number in the SharedDefinitions or somewhere else). + for inst in all_inst.values() { let format = formats.get(inst.format); fmt.doc_comment(format!("`{}`. ({})", inst, format.name)); @@ -440,6 +429,8 @@ fn gen_opcodes<'a>( // Enum variant itself. if is_first_opcode { + assert!(inst.opcode_number.index() == 0); + // TODO the python crate requires opcode numbers to start from one. fmtln!(fmt, "{} = 1,", inst.camel_name); is_first_opcode = false; } else { @@ -453,77 +444,77 @@ fn gen_opcodes<'a>( fmt.line("impl Opcode {"); fmt.indent(|fmt| { gen_bool_accessor( - igroups, + all_inst, |inst| inst.is_terminator, "is_terminator", "True for instructions that terminate the EBB", fmt, ); gen_bool_accessor( - igroups, + all_inst, |inst| inst.is_branch, "is_branch", "True for all branch or jump instructions.", fmt, ); gen_bool_accessor( - igroups, + all_inst, |inst| inst.is_indirect_branch, "is_indirect_branch", "True for all indirect branch or jump instructions.", fmt, ); gen_bool_accessor( - igroups, + all_inst, |inst| inst.is_call, "is_call", "Is this a call instruction?", fmt, ); gen_bool_accessor( - igroups, + all_inst, |inst| inst.is_return, "is_return", "Is this a return instruction?", fmt, ); gen_bool_accessor( - igroups, + all_inst, |inst| inst.is_ghost, "is_ghost", "Is this a ghost instruction?", fmt, ); gen_bool_accessor( - igroups, + all_inst, |inst| inst.can_load, "can_load", "Can this instruction read from memory?", fmt, ); gen_bool_accessor( - igroups, + all_inst, |inst| inst.can_store, "can_store", "Can this instruction write to memory?", fmt, ); gen_bool_accessor( - igroups, + all_inst, |inst| inst.can_trap, "can_trap", "Can this instruction cause a trap?", fmt, ); gen_bool_accessor( - igroups, + all_inst, |inst| inst.other_side_effects, "other_side_effects", "Does this instruction have other side effects besides can_* flags?", fmt, ); gen_bool_accessor( - igroups, + all_inst, |inst| inst.writes_cpu_flags, "writes_cpu_flags", "Does this instruction write to CPU flags?", @@ -540,7 +531,7 @@ fn gen_opcodes<'a>( all_inst.len() ); fmt.indent(|fmt| { - for inst in &all_inst { + for inst in all_inst.values() { let format = formats.get(inst.format); fmtln!(fmt, "InstructionFormat::{}, // {}", format.name, inst.name); } @@ -552,7 +543,7 @@ fn gen_opcodes<'a>( fmt.line("fn opcode_name(opc: Opcode) -> &\'static str {"); fmt.indent(|fmt| { let mut m = Match::new("opc"); - for inst in &all_inst { + for inst in all_inst.values() { m.arm_no_fields( format!("Opcode::{}", inst.camel_name), format!("\"{}\"", inst.name), @@ -564,8 +555,9 @@ fn gen_opcodes<'a>( fmt.empty_line(); // Generate an opcode hash table for looking up opcodes by name. - let hash_table = - constant_hash::generate_table(&all_inst, |inst| constant_hash::simple_hash(&inst.name)); + let hash_table = constant_hash::generate_table(all_inst.values(), all_inst.len(), |inst| { + constant_hash::simple_hash(&inst.name) + }); fmtln!( fmt, "const OPCODE_HASH_TABLE: [Option; {}] = [", @@ -581,8 +573,6 @@ fn gen_opcodes<'a>( }); fmtln!(fmt, "];"); fmt.empty_line(); - - all_inst } /// Get the value type constraint for an SSA value operand, where @@ -698,7 +688,7 @@ pub fn gen_typesets_table(type_sets: &UniqueTable, fmt: &mut Formatter) /// - Emit a compact constant table of ValueTypeSet objects. /// - Emit a compact constant table of OperandConstraint objects. /// - Emit an opcode-indexed table of instruction constraints. -fn gen_type_constraints(all_inst: &Vec<&Instruction>, fmt: &mut Formatter) { +fn gen_type_constraints(all_inst: &AllInstructions, fmt: &mut Formatter) { // Table of TypeSet instances. let mut type_sets = UniqueTable::new(); @@ -719,7 +709,7 @@ fn gen_type_constraints(all_inst: &Vec<&Instruction>, fmt: &mut Formatter) { all_inst.len() ); fmt.indent(|fmt| { - for inst in all_inst { + for inst in all_inst.values() { let (ctrl_typevar, ctrl_typeset) = if let Some(poly) = &inst.polymorphic_info { let index = type_sets.add(&*poly.ctrl_typevar.get_raw_typeset()); (Some(&poly.ctrl_typevar), index) @@ -1035,7 +1025,7 @@ fn gen_inst_builder(inst: &Instruction, format: &InstructionFormat, fmt: &mut Fo } /// Generate a Builder trait with methods for all instructions. -fn gen_builder(instructions: &Vec<&Instruction>, formats: &FormatRegistry, fmt: &mut Formatter) { +fn gen_builder(instructions: &AllInstructions, formats: &FormatRegistry, fmt: &mut Formatter) { fmt.doc_comment( r#" Convenience methods for building instructions. @@ -1055,7 +1045,7 @@ fn gen_builder(instructions: &Vec<&Instruction>, formats: &FormatRegistry, fmt: ); fmt.line("pub trait InstBuilder<'f>: InstBuilderBase<'f> {"); fmt.indent(|fmt| { - for inst in instructions { + for inst in instructions.values() { gen_inst_builder(inst, formats.get(inst.format), fmt); } for format in formats.iter() { @@ -1066,12 +1056,14 @@ fn gen_builder(instructions: &Vec<&Instruction>, formats: &FormatRegistry, fmt: } pub fn generate( - all_inst_groups: Vec<&InstructionGroup>, - format_registry: &FormatRegistry, + shared_defs: &SharedDefinitions, opcode_filename: &str, inst_builder_filename: &str, out_dir: &str, ) -> Result<(), error::Error> { + let format_registry = &shared_defs.format_registry; + let all_inst = &shared_defs.all_instructions; + // Opcodes. let mut fmt = Formatter::new(); gen_formats(format_registry, &mut fmt); @@ -1079,13 +1071,13 @@ pub fn generate( fmt.empty_line(); gen_instruction_data_impl(format_registry, &mut fmt); fmt.empty_line(); - let all_inst = gen_opcodes(format_registry, &all_inst_groups, &mut fmt); - gen_type_constraints(&all_inst, &mut fmt); + gen_opcodes(all_inst, format_registry, &mut fmt); + gen_type_constraints(all_inst, &mut fmt); fmt.update_file(opcode_filename, out_dir)?; // Instruction builder. let mut fmt = Formatter::new(); - gen_builder(&all_inst, format_registry, &mut fmt); + gen_builder(all_inst, format_registry, &mut fmt); fmt.update_file(inst_builder_filename, out_dir)?; Ok(()) diff --git a/cranelift/codegen/meta/src/gen_settings.rs b/cranelift/codegen/meta/src/gen_settings.rs index 0238ef1ec6..cdd07d78bd 100644 --- a/cranelift/codegen/meta/src/gen_settings.rs +++ b/cranelift/codegen/meta/src/gen_settings.rs @@ -308,7 +308,9 @@ fn gen_descriptors(group: &SettingGroup, fmt: &mut Formatter) { hash_entries.extend(group.settings.iter().map(|x| SettingOrPreset::Setting(x))); hash_entries.extend(group.presets.iter().map(|x| SettingOrPreset::Preset(x))); - let hash_table = generate_table(&hash_entries, |entry| simple_hash(entry.name())); + let hash_table = generate_table(hash_entries.iter(), hash_entries.len(), |entry| { + simple_hash(entry.name()) + }); fmtln!(fmt, "static HASH_TABLE: [u16; {}] = [", hash_table.len()); fmt.indent(|fmt| { for h in &hash_table { diff --git a/cranelift/codegen/meta/src/isa/arm32/mod.rs b/cranelift/codegen/meta/src/isa/arm32/mod.rs index ee238866f7..c1b6e05fda 100644 --- a/cranelift/codegen/meta/src/isa/arm32/mod.rs +++ b/cranelift/codegen/meta/src/isa/arm32/mod.rs @@ -55,6 +55,7 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { let inst_group = InstructionGroupBuilder::new( "arm32", "arm32 specific instruction set", + &mut shared_defs.all_instructions, &shared_defs.format_registry, ) .build(); diff --git a/cranelift/codegen/meta/src/isa/arm64/mod.rs b/cranelift/codegen/meta/src/isa/arm64/mod.rs index 5a11e69848..c1276f5924 100644 --- a/cranelift/codegen/meta/src/isa/arm64/mod.rs +++ b/cranelift/codegen/meta/src/isa/arm64/mod.rs @@ -51,6 +51,7 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { let inst_group = InstructionGroupBuilder::new( "arm64", "arm64 specific instruction set", + &mut shared_defs.all_instructions, &shared_defs.format_registry, ) .build(); diff --git a/cranelift/codegen/meta/src/isa/riscv/mod.rs b/cranelift/codegen/meta/src/isa/riscv/mod.rs index 776224d74f..6c00b98f52 100644 --- a/cranelift/codegen/meta/src/isa/riscv/mod.rs +++ b/cranelift/codegen/meta/src/isa/riscv/mod.rs @@ -89,6 +89,7 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { let inst_group = InstructionGroupBuilder::new( "riscv", "riscv specific instruction set", + &mut shared_defs.all_instructions, &shared_defs.format_registry, ) .build(); diff --git a/cranelift/codegen/meta/src/isa/x86/instructions.rs b/cranelift/codegen/meta/src/isa/x86/instructions.rs index 1fcf37a68f..2f365165b8 100644 --- a/cranelift/codegen/meta/src/isa/x86/instructions.rs +++ b/cranelift/codegen/meta/src/isa/x86/instructions.rs @@ -2,16 +2,23 @@ use crate::cdsl::formats::FormatRegistry; use crate::cdsl::instructions::{ - InstructionBuilder as Inst, InstructionGroup, InstructionGroupBuilder, + AllInstructions, InstructionBuilder as Inst, InstructionGroup, InstructionGroupBuilder, }; use crate::cdsl::operands::{create_operand as operand, create_operand_doc as operand_doc}; use crate::cdsl::types::ValueType; use crate::cdsl::typevar::{Interval, TypeSetBuilder, TypeVar}; use crate::shared::types; -pub fn define(format_registry: &FormatRegistry) -> InstructionGroup { - let mut ig = - InstructionGroupBuilder::new("x86", "x86 specific instruction set", format_registry); +pub fn define( + mut all_instructions: &mut AllInstructions, + format_registry: &FormatRegistry, +) -> InstructionGroup { + let mut ig = InstructionGroupBuilder::new( + "x86", + "x86 specific instruction set", + &mut all_instructions, + format_registry, + ); let iflags: &TypeVar = &ValueType::Special(types::Flag::IFlags.into()).into(); diff --git a/cranelift/codegen/meta/src/isa/x86/mod.rs b/cranelift/codegen/meta/src/isa/x86/mod.rs index dba5737062..993a4d9a3b 100644 --- a/cranelift/codegen/meta/src/isa/x86/mod.rs +++ b/cranelift/codegen/meta/src/isa/x86/mod.rs @@ -15,7 +15,10 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { let settings = settings::define(&shared_defs.settings); let regs = registers::define(); - let inst_group = instructions::define(&shared_defs.format_registry); + let inst_group = instructions::define( + &mut shared_defs.all_instructions, + &shared_defs.format_registry, + ); legalize::define(shared_defs, &inst_group); // CPU modes for 32-bit and 64-bit operations. diff --git a/cranelift/codegen/meta/src/lib.rs b/cranelift/codegen/meta/src/lib.rs index 9ac2a54306..af8e51bb9d 100644 --- a/cranelift/codegen/meta/src/lib.rs +++ b/cranelift/codegen/meta/src/lib.rs @@ -35,16 +35,7 @@ pub fn generate(isas: &Vec, out_dir: &str) -> Result<(), error::Error> // Per ISA definitions. let isas = isa::define(isas, &mut shared_defs); - let mut all_inst_groups = vec![&shared_defs.instructions]; - all_inst_groups.extend(isas.iter().map(|isa| &isa.instructions)); - - gen_inst::generate( - all_inst_groups, - &shared_defs.format_registry, - "opcodes.rs", - "inst_builder.rs", - &out_dir, - )?; + gen_inst::generate(&shared_defs, "opcodes.rs", "inst_builder.rs", &out_dir)?; gen_legalizer::generate( &isas, diff --git a/cranelift/codegen/meta/src/shared/instructions.rs b/cranelift/codegen/meta/src/shared/instructions.rs index d9a45f0a3b..b89fa019b9 100644 --- a/cranelift/codegen/meta/src/shared/instructions.rs +++ b/cranelift/codegen/meta/src/shared/instructions.rs @@ -2,7 +2,7 @@ use crate::cdsl::formats::FormatRegistry; use crate::cdsl::instructions::{ - InstructionBuilder as Inst, InstructionGroup, InstructionGroupBuilder, + AllInstructions, InstructionBuilder as Inst, InstructionGroup, InstructionGroupBuilder, }; use crate::cdsl::operands::{create_operand as operand, create_operand_doc as operand_doc}; use crate::cdsl::type_inference::Constraint::WiderOrEq; @@ -11,12 +11,17 @@ use crate::cdsl::typevar::{Interval, TypeSetBuilder, TypeVar}; use crate::shared::{types, OperandKinds}; pub fn define( + all_instructions: &mut AllInstructions, format_registry: &FormatRegistry, immediates: &OperandKinds, entities: &OperandKinds, ) -> InstructionGroup { - let mut ig = - InstructionGroupBuilder::new("base", "Shared base instruction set", format_registry); + let mut ig = InstructionGroupBuilder::new( + "base", + "Shared base instruction set", + all_instructions, + format_registry, + ); // Operand kind shorthands. let intcc = immediates.by_name("intcc"); diff --git a/cranelift/codegen/meta/src/shared/mod.rs b/cranelift/codegen/meta/src/shared/mod.rs index f16fb7bb8b..817f67c340 100644 --- a/cranelift/codegen/meta/src/shared/mod.rs +++ b/cranelift/codegen/meta/src/shared/mod.rs @@ -9,13 +9,14 @@ pub mod settings; pub mod types; use crate::cdsl::formats::FormatRegistry; -use crate::cdsl::instructions::InstructionGroup; +use crate::cdsl::instructions::{AllInstructions, InstructionGroup}; use crate::cdsl::operands::OperandKind; use crate::cdsl::settings::SettingGroup; use crate::cdsl::xform::TransformGroups; pub struct Definitions { pub settings: SettingGroup, + pub all_instructions: AllInstructions, pub instructions: InstructionGroup, pub operand_kinds: OperandKinds, pub format_registry: FormatRegistry, @@ -50,14 +51,22 @@ impl OperandKinds { } pub fn define() -> Definitions { + let mut all_instructions = AllInstructions::new(); + let immediates = OperandKinds(immediates::define()); let entities = OperandKinds(entities::define()); let format_registry = formats::define(&immediates, &entities); - let instructions = instructions::define(&format_registry, &immediates, &entities); + let instructions = instructions::define( + &mut all_instructions, + &format_registry, + &immediates, + &entities, + ); let transform_groups = legalize::define(&instructions, &immediates); Definitions { settings: settings::define(), + all_instructions, instructions, operand_kinds: immediates, format_registry,