From 9e9a7626d7f4019dd10b39654ccf6bb2988615d2 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 18 Oct 2019 16:45:51 +0200 Subject: [PATCH] [meta] Use a ref-counted pointer to an InstructionFormat in instructions; This avoids a lot of dereferences, and InstructionFormat are immutable once they're created. It removes a lot of code that was keeping the FormatRegistry around, just in case we needed the format. This is more in line with the way we create Instructions, and make it easy to reference InstructionFormats in general. --- cranelift/codegen/meta/src/cdsl/ast.rs | 29 ++-- cranelift/codegen/meta/src/cdsl/encodings.rs | 12 +- cranelift/codegen/meta/src/cdsl/formats.rs | 46 ++--- .../codegen/meta/src/cdsl/instructions.rs | 15 +- cranelift/codegen/meta/src/cdsl/recipes.rs | 23 +-- cranelift/codegen/meta/src/gen_binemit.rs | 15 +- cranelift/codegen/meta/src/gen_inst.rs | 19 +- cranelift/codegen/meta/src/gen_legalizer.rs | 43 +---- .../codegen/meta/src/isa/riscv/encodings.rs | 13 +- .../codegen/meta/src/isa/riscv/recipes.rs | 46 ++--- .../codegen/meta/src/isa/x86/encodings.rs | 64 +++---- cranelift/codegen/meta/src/isa/x86/recipes.rs | 164 +++++++++--------- cranelift/codegen/meta/src/lib.rs | 9 +- 13 files changed, 222 insertions(+), 276 deletions(-) diff --git a/cranelift/codegen/meta/src/cdsl/ast.rs b/cranelift/codegen/meta/src/cdsl/ast.rs index f047a74e55..3a994f27ed 100644 --- a/cranelift/codegen/meta/src/cdsl/ast.rs +++ b/cranelift/codegen/meta/src/cdsl/ast.rs @@ -1,4 +1,3 @@ -use crate::cdsl::formats::FormatRegistry; use crate::cdsl::instructions::{InstSpec, Instruction, InstructionPredicate}; use crate::cdsl::operands::{OperandKind, OperandKindFields}; use crate::cdsl::types::ValueType; @@ -523,23 +522,23 @@ impl Apply { format!("{}({})", inst_name, args) } - pub fn inst_predicate( - &self, - format_registry: &FormatRegistry, - var_pool: &VarPool, - ) -> InstructionPredicate { - let iform = format_registry.get(self.inst.format); - + pub fn inst_predicate(&self, var_pool: &VarPool) -> InstructionPredicate { let mut pred = InstructionPredicate::new(); - for (format_field, &op_num) in iform.imm_fields.iter().zip(self.inst.imm_opnums.iter()) { + for (format_field, &op_num) in self + .inst + .format + .imm_fields + .iter() + .zip(self.inst.imm_opnums.iter()) + { let arg = &self.args[op_num]; if arg.maybe_var().is_some() { // Ignore free variables for now. continue; } pred = pred.and(InstructionPredicate::new_is_field_equal_ast( - iform, - &format_field, + &*self.inst.format, + format_field, arg.to_rust_code(var_pool), )); } @@ -565,12 +564,8 @@ impl Apply { } /// Same as `inst_predicate()`, but also check the controlling type variable. - pub fn inst_predicate_with_ctrl_typevar( - &self, - format_registry: &FormatRegistry, - var_pool: &VarPool, - ) -> InstructionPredicate { - let mut pred = self.inst_predicate(format_registry, var_pool); + pub fn inst_predicate_with_ctrl_typevar(&self, var_pool: &VarPool) -> InstructionPredicate { + let mut pred = self.inst_predicate(var_pool); if !self.value_types.is_empty() { let bound_type = &self.value_types[0]; diff --git a/cranelift/codegen/meta/src/cdsl/encodings.rs b/cranelift/codegen/meta/src/cdsl/encodings.rs index 540d3402ae..6797672a87 100644 --- a/cranelift/codegen/meta/src/cdsl/encodings.rs +++ b/cranelift/codegen/meta/src/cdsl/encodings.rs @@ -1,4 +1,3 @@ -use crate::cdsl::formats::FormatRegistry; use crate::cdsl::instructions::{ InstSpec, Instruction, InstructionPredicate, InstructionPredicateNode, InstructionPredicateNumber, InstructionPredicateRegistry, ValueTypeOrAny, @@ -62,12 +61,7 @@ pub(crate) struct EncodingBuilder { } impl EncodingBuilder { - pub fn new( - inst: InstSpec, - recipe: EncodingRecipeNumber, - encbits: u16, - formats: &FormatRegistry, - ) -> Self { + pub fn new(inst: InstSpec, recipe: EncodingRecipeNumber, encbits: u16) -> Self { let (inst_predicate, bound_type) = match &inst { InstSpec::Bound(inst) => { let other_typevars = &inst.inst.polymorphic_info.as_ref().unwrap().other_typevars; @@ -98,7 +92,7 @@ impl EncodingBuilder { .zip(inst.inst.operands_in.iter().filter(|o| o.is_immediate())) { let immediate_predicate = InstructionPredicate::new_is_field_equal( - formats.get(inst.inst.format), + &inst.inst.format, immediate_operand.name, immediate_value.to_string(), ); @@ -158,7 +152,7 @@ impl EncodingBuilder { let inst = self.inst.inst(); assert!( - inst.format == recipes[self.recipe].format, + Rc::ptr_eq(&inst.format, &recipes[self.recipe].format), format!( "Inst {} and recipe {} must have the same format!", inst.name, recipes[self.recipe].name diff --git a/cranelift/codegen/meta/src/cdsl/formats.rs b/cranelift/codegen/meta/src/cdsl/formats.rs index cf82da180a..0e71f37a97 100644 --- a/cranelift/codegen/meta/src/cdsl/formats.rs +++ b/cranelift/codegen/meta/src/cdsl/formats.rs @@ -2,10 +2,9 @@ use crate::cdsl::operands::{Operand, OperandKind}; use std::collections::{HashMap, HashSet}; use std::fmt; +use std::rc::Rc; use std::slice; -use cranelift_entity::{entity_impl, PrimaryMap}; - /// An immediate field in an instruction format. /// /// This corresponds to a single member of a variant of the `InstructionData` @@ -152,15 +151,10 @@ impl InstructionFormatBuilder { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct InstructionFormatIndex(u32); -entity_impl!(InstructionFormatIndex); - pub struct FormatRegistry { - /// Map (immediate kinds names, number of values, has varargs) to an instruction format index - /// in the actual map. - sig_to_index: HashMap<(Vec, usize, bool), InstructionFormatIndex>, - map: PrimaryMap, + /// Map (immediate kinds names, number of values, has varargs) to an instruction format. + sig_to_index: HashMap<(Vec, usize, bool), usize>, + formats: Vec>, name_set: HashSet<&'static str>, } @@ -168,14 +162,14 @@ impl FormatRegistry { pub fn new() -> Self { Self { sig_to_index: HashMap::new(), - map: PrimaryMap::new(), + formats: Vec::new(), name_set: HashSet::new(), } } /// Find an existing instruction format that matches the given lists of instruction inputs and /// outputs. - pub fn lookup(&self, operands_in: &Vec) -> InstructionFormatIndex { + pub fn lookup(&self, operands_in: &Vec) -> &Rc { let mut imm_keys = Vec::new(); let mut num_values = 0; let mut has_varargs = false; @@ -193,22 +187,19 @@ impl FormatRegistry { } let sig = (imm_keys, num_values, has_varargs); - *self + let index = *self .sig_to_index .get(&sig) - .expect("unknown InstructionFormat; please define it in shared/formats.rs first") + .expect("unknown InstructionFormat; please define it in shared/formats.rs first"); + &self.formats[index] } - pub fn by_name(&self, name: &str) -> InstructionFormatIndex { - self.map + pub fn by_name(&self, name: &str) -> &Rc { + &self + .formats .iter() - .find(|(_key, value)| value.name == name) + .find(|format| format.name == name) .unwrap_or_else(|| panic!("format with name '{}' doesn't exist", name)) - .0 - } - - pub fn get(&self, index: InstructionFormatIndex) -> &InstructionFormat { - self.map.get(index).unwrap() } pub fn insert(&mut self, inst_format: InstructionFormatBuilder) { @@ -230,17 +221,18 @@ impl FormatRegistry { .collect(); let key = (imm_keys, format.num_value_operands, format.has_value_list); - let index = self.map.push(format); + let index = self.formats.len(); + self.formats.push(Rc::new(format)); if let Some(already_inserted) = self.sig_to_index.insert(key, index) { panic!( "duplicate InstructionFormat: trying to insert '{}' while '{}' already has the same structure.", - self.map.get(index).unwrap().name, - self.map.get(already_inserted).unwrap().name + self.formats[index].name, + self.formats[already_inserted].name ); } } - pub fn iter(&self) -> slice::Iter { - self.map.values() + pub fn iter(&self) -> slice::Iter> { + self.formats.iter() } } diff --git a/cranelift/codegen/meta/src/cdsl/instructions.rs b/cranelift/codegen/meta/src/cdsl/instructions.rs index e642a512a7..fb92b85572 100644 --- a/cranelift/codegen/meta/src/cdsl/instructions.rs +++ b/cranelift/codegen/meta/src/cdsl/instructions.rs @@ -6,9 +6,7 @@ use std::fmt::{Display, Error, Formatter}; use std::rc::Rc; use crate::cdsl::camel_case; -use crate::cdsl::formats::{ - FormatField, FormatRegistry, InstructionFormat, InstructionFormatIndex, -}; +use crate::cdsl::formats::{FormatField, FormatRegistry, InstructionFormat}; use crate::cdsl::operands::Operand; use crate::cdsl::type_inference::Constraint; use crate::cdsl::types::{LaneType, ReferenceType, ValueType, VectorType}; @@ -104,7 +102,7 @@ pub(crate) struct InstructionContent { pub constraints: Vec, /// Instruction format, automatically derived from the input operands. - pub format: InstructionFormatIndex, + pub format: Rc, /// One of the input or output operands is a free type variable. None if the instruction is not /// polymorphic, set otherwise. @@ -321,8 +319,7 @@ impl InstructionBuilder { .filter_map(|(i, op)| if op.is_value() { Some(i) } else { None }) .collect(); - let format_index = format_registry.lookup(&operands_in); - let format = format_registry.get(format_index); + let format = format_registry.lookup(&operands_in).clone(); let polymorphic_info = verify_polymorphic(&operands_in, &operands_out, &format, &value_opnums); @@ -339,7 +336,7 @@ impl InstructionBuilder { operands_in, operands_out, constraints: self.constraints.unwrap_or_else(Vec::new), - format: format_index, + format, polymorphic_info, value_opnums, value_results, @@ -1093,9 +1090,9 @@ impl InstructionPredicate { } pub fn new_is_colocated_data(format_registry: &FormatRegistry) -> InstructionPredicateNode { - let format = format_registry.get(format_registry.by_name("UnaryGlobalValue")); + let format = format_registry.by_name("UnaryGlobalValue"); InstructionPredicateNode::FormatPredicate(FormatPredicateNode::new( - format, + &*format, "global_value", FormatPredicateKind::IsColocatedData, )) diff --git a/cranelift/codegen/meta/src/cdsl/recipes.rs b/cranelift/codegen/meta/src/cdsl/recipes.rs index ed31cbbfd8..20b5c077cb 100644 --- a/cranelift/codegen/meta/src/cdsl/recipes.rs +++ b/cranelift/codegen/meta/src/cdsl/recipes.rs @@ -1,6 +1,8 @@ +use std::rc::Rc; + use cranelift_entity::{entity_impl, PrimaryMap}; -use crate::cdsl::formats::{FormatRegistry, InstructionFormatIndex}; +use crate::cdsl::formats::InstructionFormat; use crate::cdsl::instructions::InstructionPredicate; use crate::cdsl::regs::RegClassIndex; use crate::cdsl::settings::SettingPredicateNumber; @@ -108,7 +110,7 @@ pub(crate) struct EncodingRecipe { pub name: String, /// Associated instruction format. - pub format: InstructionFormatIndex, + pub format: Rc, /// Base number of bytes in the binary encoded instruction. pub base_size: u64, @@ -141,7 +143,7 @@ pub(crate) struct EncodingRecipe { // Implement PartialEq ourselves: take all the fields into account but the name. impl PartialEq for EncodingRecipe { fn eq(&self, other: &Self) -> bool { - self.format == other.format + Rc::ptr_eq(&self.format, &other.format) && self.base_size == other.base_size && self.operands_in == other.operands_in && self.operands_out == other.operands_out @@ -166,7 +168,7 @@ pub(crate) type Recipes = PrimaryMap; #[derive(Clone)] pub(crate) struct EncodingRecipeBuilder { pub name: String, - format: InstructionFormatIndex, + format: Rc, pub base_size: u64, pub operands_in: Option>, pub operands_out: Option>, @@ -179,10 +181,10 @@ pub(crate) struct EncodingRecipeBuilder { } impl EncodingRecipeBuilder { - pub fn new(name: impl Into, format: InstructionFormatIndex, base_size: u64) -> Self { + pub fn new(name: impl Into, format: &Rc, base_size: u64) -> Self { Self { name: name.into(), - format, + format: format.clone(), base_size, operands_in: None, operands_out: None, @@ -250,18 +252,17 @@ impl EncodingRecipeBuilder { self } - pub fn build(self, formats: &FormatRegistry) -> EncodingRecipe { + pub fn build(self) -> EncodingRecipe { let operands_in = self.operands_in.unwrap_or(Vec::new()); let operands_out = self.operands_out.unwrap_or(Vec::new()); // The number of input constraints must match the number of format input operands. - if !formats.get(self.format).has_value_list { - let format = formats.get(self.format); + if !self.format.has_value_list { assert!( - operands_in.len() == format.num_value_operands, + operands_in.len() == self.format.num_value_operands, format!( "missing operand constraints for recipe {} (format {})", - self.name, format.name + self.name, self.format.name ) ); } diff --git a/cranelift/codegen/meta/src/gen_binemit.rs b/cranelift/codegen/meta/src/gen_binemit.rs index fed145cbd4..3d7b08a227 100644 --- a/cranelift/codegen/meta/src/gen_binemit.rs +++ b/cranelift/codegen/meta/src/gen_binemit.rs @@ -5,7 +5,6 @@ use cranelift_entity::EntityRef; use crate::error; use crate::srcgen::Formatter; -use crate::cdsl::formats::FormatRegistry; use crate::cdsl::recipes::{EncodingRecipe, OperandConstraint, Recipes}; /// Generate code to handle a single recipe. @@ -14,11 +13,12 @@ use crate::cdsl::recipes::{EncodingRecipe, OperandConstraint, Recipes}; /// - Determine register locations for operands with register constraints. /// - Determine stack slot locations for operands with stack constraints. /// - Call hand-written code for the actual emission. -fn gen_recipe(formats: &FormatRegistry, recipe: &EncodingRecipe, fmt: &mut Formatter) { - let inst_format = formats.get(recipe.format); +fn gen_recipe(recipe: &EncodingRecipe, fmt: &mut Formatter) { + let inst_format = &recipe.format; let num_value_ops = inst_format.num_value_operands; - // TODO: Set want_args to true for only MultiAry instructions instead of all formats with value list. + // TODO: Set want_args to true for only MultiAry instructions instead of all formats with value + // list. let want_args = inst_format.has_value_list || recipe.operands_in.iter().any(|c| match c { OperandConstraint::RegClass(_) | OperandConstraint::Stack(_) => true, @@ -148,7 +148,7 @@ fn unwrap_values( varlist } -fn gen_isa(formats: &FormatRegistry, isa_name: &str, recipes: &Recipes, fmt: &mut Formatter) { +fn gen_isa(isa_name: &str, recipes: &Recipes, fmt: &mut Formatter) { fmt.doc_comment(format!( "Emit binary machine code for `inst` for the {} ISA.", isa_name @@ -193,7 +193,7 @@ fn gen_isa(formats: &FormatRegistry, isa_name: &str, recipes: &Recipes, fmt: &mu fmt.comment(format!("Recipe {}", recipe.name)); fmtln!(fmt, "{} => {{", i.index()); fmt.indent(|fmt| { - gen_recipe(formats, recipe, fmt); + gen_recipe(recipe, fmt); }); fmt.line("}"); } @@ -212,14 +212,13 @@ fn gen_isa(formats: &FormatRegistry, isa_name: &str, recipes: &Recipes, fmt: &mu } pub(crate) fn generate( - formats: &FormatRegistry, isa_name: &str, recipes: &Recipes, binemit_filename: &str, out_dir: &str, ) -> Result<(), error::Error> { let mut fmt = Formatter::new(); - gen_isa(formats, isa_name, recipes, &mut fmt); + gen_isa(isa_name, recipes, &mut fmt); fmt.update_file(binemit_filename, out_dir)?; Ok(()) } diff --git a/cranelift/codegen/meta/src/gen_inst.rs b/cranelift/codegen/meta/src/gen_inst.rs index 85a853150e..053eba2517 100644 --- a/cranelift/codegen/meta/src/gen_inst.rs +++ b/cranelift/codegen/meta/src/gen_inst.rs @@ -400,7 +400,7 @@ fn gen_bool_accessor bool>( fmt.empty_line(); } -fn gen_opcodes<'a>(all_inst: &AllInstructions, formats: &FormatRegistry, fmt: &mut Formatter) { +fn gen_opcodes<'a>(all_inst: &AllInstructions, fmt: &mut Formatter) { fmt.doc_comment( r#" An instruction opcode. @@ -418,13 +418,12 @@ fn gen_opcodes<'a>(all_inst: &AllInstructions, formats: &FormatRegistry, fmt: &m fmt.indent(|fmt| { let mut is_first_opcode = true; for inst in all_inst.values() { - let format = formats.get(inst.format); - fmt.doc_comment(format!("`{}`. ({})", inst, format.name)); + fmt.doc_comment(format!("`{}`. ({})", inst, inst.format.name)); // Document polymorphism. if let Some(poly) = &inst.polymorphic_info { if poly.use_typevar_operand { - let op_num = inst.value_opnums[format.typevar_operand.unwrap()]; + let op_num = inst.value_opnums[inst.format.typevar_operand.unwrap()]; fmt.doc_comment(format!( "Type inferred from `{}`.", inst.operands_in[op_num].name @@ -537,8 +536,12 @@ fn gen_opcodes<'a>(all_inst: &AllInstructions, formats: &FormatRegistry, fmt: &m ); fmt.indent(|fmt| { for inst in all_inst.values() { - let format = formats.get(inst.format); - fmtln!(fmt, "InstructionFormat::{}, // {}", format.name, inst.name); + fmtln!( + fmt, + "InstructionFormat::{}, // {}", + inst.format.name, + inst.name + ); } }); fmtln!(fmt, "];"); @@ -1055,7 +1058,7 @@ fn gen_builder(instructions: &AllInstructions, formats: &FormatRegistry, fmt: &m fmt.line("pub trait InstBuilder<'f>: InstBuilderBase<'f> {"); fmt.indent(|fmt| { for inst in instructions.values() { - gen_inst_builder(inst, formats.get(inst.format), fmt); + gen_inst_builder(inst, &*inst.format, fmt); } for format in formats.iter() { gen_format_constructor(format, fmt); @@ -1080,7 +1083,7 @@ pub(crate) fn generate( fmt.empty_line(); gen_instruction_data_impl(format_registry, &mut fmt); fmt.empty_line(); - gen_opcodes(all_inst, format_registry, &mut fmt); + gen_opcodes(all_inst, &mut fmt); gen_type_constraints(all_inst, &mut fmt); fmt.update_file(opcode_filename, out_dir)?; diff --git a/cranelift/codegen/meta/src/gen_legalizer.rs b/cranelift/codegen/meta/src/gen_legalizer.rs index f4033c64b5..c93262701d 100644 --- a/cranelift/codegen/meta/src/gen_legalizer.rs +++ b/cranelift/codegen/meta/src/gen_legalizer.rs @@ -1,5 +1,4 @@ use crate::cdsl::ast::{Def, DefPool, Expr, VarPool}; -use crate::cdsl::formats::FormatRegistry; use crate::cdsl::isa::TargetIsa; use crate::cdsl::operands::Operand; use crate::cdsl::type_inference::Constraint; @@ -21,18 +20,14 @@ use std::iter::FromIterator; /// /// Also create a local variable named `predicate` with the value of the evaluated instruction /// predicate, or `true` if the node has no predicate. -fn unwrap_inst( - transform: &Transform, - format_registry: &FormatRegistry, - fmt: &mut Formatter, -) -> bool { +fn unwrap_inst(transform: &Transform, fmt: &mut Formatter) -> bool { let var_pool = &transform.var_pool; let def_pool = &transform.def_pool; let def = def_pool.get(transform.src); let apply = &def.apply; let inst = &apply.inst; - let iform = format_registry.get(inst.format); + let iform = &inst.format; fmt.comment(format!( "Unwrap fields from instruction format {}", @@ -438,7 +433,6 @@ fn emit_dst_inst(def: &Def, def_pool: &DefPool, var_pool: &VarPool, fmt: &mut Fo fn gen_transform<'a>( replace_inst: bool, transform: &'a Transform, - format_registry: &FormatRegistry, type_sets: &mut UniqueTable<'a, TypeSet>, fmt: &mut Formatter, ) { @@ -446,7 +440,7 @@ fn gen_transform<'a>( let apply = &transform.def_pool.get(transform.src).apply; let inst_predicate = apply - .inst_predicate_with_ctrl_typevar(format_registry, &transform.var_pool) + .inst_predicate_with_ctrl_typevar(&transform.var_pool) .rust_predicate("pos.func"); let has_extra_constraints = !transform.type_env.constraints.is_empty(); @@ -560,7 +554,6 @@ fn gen_transform<'a>( fn gen_transform_group<'a>( group: &'a TransformGroup, - format_registry: &FormatRegistry, transform_groups: &TransformGroups, type_sets: &mut UniqueTable<'a, TypeSet>, fmt: &mut Formatter, @@ -610,14 +603,14 @@ fn gen_transform_group<'a>( let transforms = inst_to_transforms.get(camel_name).unwrap(); // Unwrap the source instruction, create local variables for the input variables. - let replace_inst = unwrap_inst(&transforms[0], format_registry, fmt); + let replace_inst = unwrap_inst(&transforms[0], fmt); fmt.empty_line(); for (i, transform) in transforms.into_iter().enumerate() { if i > 0 { fmt.empty_line(); } - gen_transform(replace_inst, transform, format_registry, type_sets, fmt); + gen_transform(replace_inst, transform, type_sets, fmt); } }); fmtln!(fmt, "}"); @@ -665,7 +658,6 @@ fn gen_transform_group<'a>( /// Generate `TYPE_SETS` and `LEGALIZE_ACTIONS` tables. fn gen_isa( isa: &TargetIsa, - format_registry: &FormatRegistry, transform_groups: &TransformGroups, shared_group_names: &mut HashSet<&'static str>, fmt: &mut Formatter, @@ -679,13 +671,7 @@ fn gen_isa( isa_name == isa.name, "ISA-specific legalizations must be used by the same ISA" ); - gen_transform_group( - group, - format_registry, - transform_groups, - &mut type_sets, - fmt, - ); + gen_transform_group(group, transform_groups, &mut type_sets, fmt); } None => { shared_group_names.insert(group.name); @@ -712,7 +698,6 @@ fn gen_isa( /// Generate the legalizer files. pub(crate) fn generate( isas: &Vec, - format_registry: &FormatRegistry, transform_groups: &TransformGroups, filename_prefix: &str, out_dir: &str, @@ -721,13 +706,7 @@ pub(crate) fn generate( for isa in isas { let mut fmt = Formatter::new(); - gen_isa( - isa, - format_registry, - transform_groups, - &mut shared_group_names, - &mut fmt, - ); + gen_isa(isa, transform_groups, &mut shared_group_names, &mut fmt); fmt.update_file(format!("{}-{}.rs", filename_prefix, isa.name), out_dir)?; } @@ -738,13 +717,7 @@ pub(crate) fn generate( sorted_shared_group_names.sort(); for group_name in &sorted_shared_group_names { let group = transform_groups.by_name(group_name); - gen_transform_group( - group, - format_registry, - transform_groups, - &mut type_sets, - &mut fmt, - ); + gen_transform_group(group, transform_groups, &mut type_sets, &mut fmt); } gen_typesets_table(&type_sets, &mut fmt); fmt.update_file(format!("{}r.rs", filename_prefix), out_dir)?; diff --git a/cranelift/codegen/meta/src/isa/riscv/encodings.rs b/cranelift/codegen/meta/src/isa/riscv/encodings.rs index 21ad3c469c..936579b2bc 100644 --- a/cranelift/codegen/meta/src/isa/riscv/encodings.rs +++ b/cranelift/codegen/meta/src/isa/riscv/encodings.rs @@ -13,24 +13,21 @@ use crate::shared::types::Reference::{R32, R64}; use crate::shared::Definitions as SharedDefinitions; use super::recipes::RecipeGroup; -use crate::cdsl::formats::FormatRegistry; pub(crate) struct PerCpuModeEncodings<'defs> { pub inst_pred_reg: InstructionPredicateRegistry, pub enc32: Vec, pub enc64: Vec, recipes: &'defs Recipes, - formats: &'defs FormatRegistry, } impl<'defs> PerCpuModeEncodings<'defs> { - fn new(recipes: &'defs Recipes, formats: &'defs FormatRegistry) -> Self { + fn new(recipes: &'defs Recipes) -> Self { Self { inst_pred_reg: InstructionPredicateRegistry::new(), enc32: Vec::new(), enc64: Vec::new(), recipes, - formats, } } fn enc( @@ -39,7 +36,7 @@ impl<'defs> PerCpuModeEncodings<'defs> { recipe: EncodingRecipeNumber, bits: u16, ) -> EncodingBuilder { - EncodingBuilder::new(inst.into(), recipe, bits, self.formats) + EncodingBuilder::new(inst.into(), recipe, bits) } fn add32(&mut self, encoding: EncodingBuilder) { self.enc32 @@ -176,7 +173,7 @@ pub(crate) fn define<'defs>( let use_m = isa_settings.predicate_by_name("use_m"); // Definitions. - let mut e = PerCpuModeEncodings::new(&recipes.recipes, &shared_defs.format_registry); + let mut e = PerCpuModeEncodings::new(&recipes.recipes); // Basic arithmetic binary instructions are encoded in an R-type instruction. for &(inst, inst_imm, f3, f7) in &[ @@ -242,7 +239,7 @@ pub(crate) fn define<'defs>( bound_inst.clone().into(), vec![Expr::Literal(cc), Expr::Var(x), Expr::Var(y)], ) - .inst_predicate(&shared_defs.format_registry, &var_pool) + .inst_predicate(&var_pool) .unwrap() }; @@ -339,7 +336,7 @@ pub(crate) fn define<'defs>( Expr::Var(args), ], ) - .inst_predicate(&shared_defs.format_registry, &var_pool) + .inst_predicate(&var_pool) .unwrap() }; diff --git a/cranelift/codegen/meta/src/isa/riscv/recipes.rs b/cranelift/codegen/meta/src/isa/riscv/recipes.rs index b1297479ec..ab70595b34 100644 --- a/cranelift/codegen/meta/src/isa/riscv/recipes.rs +++ b/cranelift/codegen/meta/src/isa/riscv/recipes.rs @@ -1,16 +1,12 @@ use std::collections::HashMap; -use crate::cdsl::formats::FormatRegistry; use crate::cdsl::instructions::InstructionPredicate; use crate::cdsl::recipes::{EncodingRecipeBuilder, EncodingRecipeNumber, Recipes, Stack}; use crate::cdsl::regs::IsaRegs; use crate::shared::Definitions as SharedDefinitions; /// An helper to create recipes and use them when defining the RISCV encodings. -pub(crate) struct RecipeGroup<'formats> { - /// Memoized format registry, to pass it to the builders. - formats: &'formats FormatRegistry, - +pub(crate) struct RecipeGroup { /// The actualy list of recipes explicitly created in this file. pub recipes: Recipes, @@ -18,10 +14,9 @@ pub(crate) struct RecipeGroup<'formats> { name_to_recipe: HashMap, } -impl<'formats> RecipeGroup<'formats> { - fn new(formats: &'formats FormatRegistry) -> Self { +impl RecipeGroup { + fn new() -> Self { Self { - formats, recipes: Recipes::new(), name_to_recipe: HashMap::new(), } @@ -33,7 +28,7 @@ impl<'formats> RecipeGroup<'formats> { format!("riscv recipe '{}' created twice", builder.name) ); let name = builder.name.clone(); - let number = self.recipes.push(builder.build(self.formats)); + let number = self.recipes.push(builder.build()); self.name_to_recipe.insert(name, number); } @@ -50,13 +45,10 @@ impl<'formats> RecipeGroup<'formats> { } } -pub(crate) fn define<'formats>( - shared_defs: &'formats SharedDefinitions, - regs: &IsaRegs, -) -> RecipeGroup<'formats> { +pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeGroup { + // Format shorthands. let formats = &shared_defs.format_registry; - // Format shorthands. let f_binary = formats.by_name("Binary"); let f_binary_imm = formats.by_name("BinaryImm"); let f_branch = formats.by_name("Branch"); @@ -76,7 +68,7 @@ pub(crate) fn define<'formats>( let gpr = regs.class_by_name("GPR"); // Definitions. - let mut recipes = RecipeGroup::new(&shared_defs.format_registry); + let mut recipes = RecipeGroup::new(); // R-type 32-bit instructions: These are mostly binary arithmetic instructions. // The encbits are `opcode[6:2] | (funct3 << 5) | (funct7 << 8) @@ -103,36 +95,42 @@ pub(crate) fn define<'formats>( .emit("put_r(bits, in_reg0, in_reg1, out_reg0, sink);"), ); - let format = formats.get(f_binary_imm); recipes.push( EncodingRecipeBuilder::new("Ii", f_binary_imm, 4) .operands_in(vec![gpr]) .operands_out(vec![gpr]) .inst_predicate(InstructionPredicate::new_is_signed_int( - format, "imm", 12, 0, + &*f_binary_imm, + "imm", + 12, + 0, )) .emit("put_i(bits, in_reg0, imm.into(), out_reg0, sink);"), ); // I-type instruction with a hardcoded %x0 rs1. - let format = formats.get(f_unary_imm); recipes.push( EncodingRecipeBuilder::new("Iz", f_unary_imm, 4) .operands_out(vec![gpr]) .inst_predicate(InstructionPredicate::new_is_signed_int( - format, "imm", 12, 0, + &*f_unary_imm, + "imm", + 12, + 0, )) .emit("put_i(bits, 0, imm.into(), out_reg0, sink);"), ); // I-type encoding of an integer comparison. - let format = formats.get(f_int_compare_imm); recipes.push( EncodingRecipeBuilder::new("Iicmp", f_int_compare_imm, 4) .operands_in(vec![gpr]) .operands_out(vec![gpr]) .inst_predicate(InstructionPredicate::new_is_signed_int( - format, "imm", 12, 0, + &*f_int_compare_imm, + "imm", + 12, + 0, )) .emit("put_i(bits, in_reg0, imm.into(), out_reg0, sink);"), ); @@ -195,12 +193,14 @@ pub(crate) fn define<'formats>( ); // U-type instructions have a 20-bit immediate that targets bits 12-31. - let format = formats.get(f_unary_imm); recipes.push( EncodingRecipeBuilder::new("U", f_unary_imm, 4) .operands_out(vec![gpr]) .inst_predicate(InstructionPredicate::new_is_signed_int( - format, "imm", 32, 12, + &*f_unary_imm, + "imm", + 32, + 12, )) .emit("put_u(bits, imm.into(), out_reg0, sink);"), ); diff --git a/cranelift/codegen/meta/src/isa/x86/encodings.rs b/cranelift/codegen/meta/src/isa/x86/encodings.rs index f957dd7791..a9a6f700ac 100644 --- a/cranelift/codegen/meta/src/isa/x86/encodings.rs +++ b/cranelift/codegen/meta/src/isa/x86/encodings.rs @@ -20,27 +20,24 @@ use crate::shared::Definitions as SharedDefinitions; use crate::isa::x86::opcodes::*; use super::recipes::{RecipeGroup, Template}; -use crate::cdsl::formats::FormatRegistry; use crate::cdsl::instructions::BindParameter::Any; -pub(crate) struct PerCpuModeEncodings<'defs> { +pub(crate) struct PerCpuModeEncodings { pub enc32: Vec, pub enc64: Vec, pub recipes: Recipes, recipes_by_name: HashMap, pub inst_pred_reg: InstructionPredicateRegistry, - formats: &'defs FormatRegistry, } -impl<'defs> PerCpuModeEncodings<'defs> { - fn new(formats: &'defs FormatRegistry) -> Self { +impl PerCpuModeEncodings { + fn new() -> Self { Self { enc32: Vec::new(), enc64: Vec::new(), recipes: Recipes::new(), recipes_by_name: HashMap::new(), inst_pred_reg: InstructionPredicateRegistry::new(), - formats, } } @@ -73,7 +70,7 @@ impl<'defs> PerCpuModeEncodings<'defs> { { let (recipe, bits) = template.build(); let recipe_number = self.add_recipe(recipe); - let builder = EncodingBuilder::new(inst.into(), recipe_number, bits, self.formats); + let builder = EncodingBuilder::new(inst.into(), recipe_number, bits); builder_closure(builder).build(&self.recipes, &mut self.inst_pred_reg) } @@ -105,7 +102,7 @@ impl<'defs> PerCpuModeEncodings<'defs> { } fn enc32_rec(&mut self, inst: impl Into, recipe: &EncodingRecipe, bits: u16) { let recipe_number = self.add_recipe(recipe.clone()); - let builder = EncodingBuilder::new(inst.into(), recipe_number, bits, self.formats); + let builder = EncodingBuilder::new(inst.into(), recipe_number, bits); let encoding = builder.build(&self.recipes, &mut self.inst_pred_reg); self.enc32.push(encoding); } @@ -138,7 +135,7 @@ impl<'defs> PerCpuModeEncodings<'defs> { } fn enc64_rec(&mut self, inst: impl Into, recipe: &EncodingRecipe, bits: u16) { let recipe_number = self.add_recipe(recipe.clone()); - let builder = EncodingBuilder::new(inst.into(), recipe_number, bits, self.formats); + let builder = EncodingBuilder::new(inst.into(), recipe_number, bits); let encoding = builder.build(&self.recipes, &mut self.inst_pred_reg); self.enc64.push(encoding); } @@ -370,12 +367,12 @@ impl<'defs> PerCpuModeEncodings<'defs> { // Definitions. -pub(crate) fn define<'defs>( - shared_defs: &'defs SharedDefinitions, +pub(crate) fn define( + shared_defs: &SharedDefinitions, settings: &SettingGroup, x86: &InstructionGroup, r: &RecipeGroup, -) -> PerCpuModeEncodings<'defs> { +) -> PerCpuModeEncodings { let shared = &shared_defs.instructions; let formats = &shared_defs.format_registry; @@ -688,7 +685,7 @@ pub(crate) fn define<'defs>( let use_sse41_simd = settings.predicate_by_name("use_sse41_simd"); // Definitions. - let mut e = PerCpuModeEncodings::new(formats); + let mut e = PerCpuModeEncodings::new(); // The pinned reg is fixed to a certain value entirely user-controlled, so it generates nothing! e.enc64_rec(get_pinned_reg.bind(I64), rec_get_pinned_reg, 0); @@ -777,8 +774,8 @@ pub(crate) fn define<'defs>( e.enc64(iconst.bind(I32), rec_pu_id.opcodes(&MOV_IMM)); // The 32-bit immediate movl also zero-extends to 64 bits. - let f_unary_imm = formats.get(formats.by_name("UnaryImm")); - let is_unsigned_int32 = InstructionPredicate::new_is_unsigned_int(f_unary_imm, "imm", 32, 0); + let f_unary_imm = formats.by_name("UnaryImm"); + let is_unsigned_int32 = InstructionPredicate::new_is_unsigned_int(&*f_unary_imm, "imm", 32, 0); e.enc64_func( iconst.bind(I64), @@ -883,8 +880,8 @@ pub(crate) fn define<'defs>( e.enc64_isap(ctz.bind(I32), rec_urm.opcodes(&TZCNT), use_bmi1); // Loads and stores. - let f_load_complex = formats.get(formats.by_name("LoadComplex")); - let is_load_complex_length_two = InstructionPredicate::new_length_equals(f_load_complex, 2); + let f_load_complex = formats.by_name("LoadComplex"); + let is_load_complex_length_two = InstructionPredicate::new_length_equals(&*f_load_complex, 2); for recipe in &[rec_ldWithIndex, rec_ldWithIndexDisp8, rec_ldWithIndexDisp32] { e.enc_i32_i64_instp( @@ -928,8 +925,9 @@ pub(crate) fn define<'defs>( ); } - let f_store_complex = formats.get(formats.by_name("StoreComplex")); - let is_store_complex_length_three = InstructionPredicate::new_length_equals(f_store_complex, 3); + let f_store_complex = formats.by_name("StoreComplex"); + let is_store_complex_length_three = + InstructionPredicate::new_length_equals(&*f_store_complex, 3); for recipe in &[rec_stWithIndex, rec_stWithIndexDisp8, rec_stWithIndexDisp32] { e.enc_i32_i64_instp( @@ -1235,8 +1233,8 @@ pub(crate) fn define<'defs>( ); // 64-bit, colocated, both PIC and non-PIC. Use the lea instruction's pc-relative field. - let f_func_addr = formats.get(formats.by_name("FuncAddr")); - let is_colocated_func = InstructionPredicate::new_is_colocated_func(f_func_addr, "func_ref"); + let f_func_addr = formats.by_name("FuncAddr"); + let is_colocated_func = InstructionPredicate::new_is_colocated_func(&*f_func_addr, "func_ref"); e.enc64_instp( func_addr.bind(I64), rec_pcrel_fnaddr8.opcodes(&LEA).rex().w(), @@ -1295,8 +1293,8 @@ pub(crate) fn define<'defs>( e.enc32(call, rec_call_id.opcodes(&CALL_RELATIVE)); // 64-bit, colocated, both PIC and non-PIC. Use the call instruction's pc-relative field. - let f_call = formats.get(formats.by_name("Call")); - let is_colocated_func = InstructionPredicate::new_is_colocated_func(f_call, "func_ref"); + let f_call = formats.by_name("Call"); + let is_colocated_func = InstructionPredicate::new_is_colocated_func(&*f_call, "func_ref"); e.enc64_instp(call, rec_call_id.opcodes(&CALL_RELATIVE), is_colocated_func); // 64-bit, non-colocated, PIC. There is no 64-bit non-colocated non-PIC version, since non-PIC @@ -1566,16 +1564,18 @@ pub(crate) fn define<'defs>( // Floating-point constants equal to 0.0 can be encoded using either `xorps` or `xorpd`, for // 32-bit and 64-bit floats respectively. - let f_unary_ieee32 = formats.get(formats.by_name("UnaryIeee32")); - let is_zero_32_bit_float = InstructionPredicate::new_is_zero_32bit_float(f_unary_ieee32, "imm"); + let f_unary_ieee32 = formats.by_name("UnaryIeee32"); + let is_zero_32_bit_float = + InstructionPredicate::new_is_zero_32bit_float(&*f_unary_ieee32, "imm"); e.enc32_instp( f32const, rec_f32imm_z.opcodes(&XORPS), is_zero_32_bit_float.clone(), ); - let f_unary_ieee64 = formats.get(formats.by_name("UnaryIeee64")); - let is_zero_64_bit_float = InstructionPredicate::new_is_zero_64bit_float(f_unary_ieee64, "imm"); + let f_unary_ieee64 = formats.by_name("UnaryIeee64"); + let is_zero_64_bit_float = + InstructionPredicate::new_is_zero_64bit_float(&*f_unary_ieee64, "imm"); e.enc32_instp( f64const, rec_f64imm_z.opcodes(&XORPD), @@ -1847,18 +1847,18 @@ pub(crate) fn define<'defs>( // this must be encoded prior to the MOVUPS implementation (below) so the compiler sees this // encoding first for ty in ValueType::all_lane_types().filter(allowed_simd_type) { - let f_unary_const = formats.get(formats.by_name("UnaryConst")); + let f_unary_const = formats.by_name("UnaryConst"); let instruction = vconst.bind(vector(ty, sse_vector_size)); let is_zero_128bit = - InstructionPredicate::new_is_all_zeroes(f_unary_const, "constant_handle"); + InstructionPredicate::new_is_all_zeroes(&*f_unary_const, "constant_handle"); let template = rec_vconst_optimized.nonrex().opcodes(&PXOR); e.enc_32_64_func(instruction.clone(), template, |builder| { builder.inst_predicate(is_zero_128bit) }); let is_ones_128bit = - InstructionPredicate::new_is_all_ones(f_unary_const, "constant_handle"); + InstructionPredicate::new_is_all_ones(&*f_unary_const, "constant_handle"); let template = rec_vconst_optimized.nonrex().opcodes(&PCMPEQB); e.enc_32_64_func(instruction, template, |builder| { builder.inst_predicate(is_ones_128bit) @@ -2038,9 +2038,9 @@ pub(crate) fn define<'defs>( }; let instruction = icmp.bind(vector(ty, sse_vector_size)); - let f_int_compare = formats.get(formats.by_name("IntCompare")); + let f_int_compare = formats.by_name("IntCompare"); let has_eq_condition_code = - InstructionPredicate::new_has_condition_code(f_int_compare, IntCC::Equal, "cond"); + InstructionPredicate::new_has_condition_code(&*f_int_compare, IntCC::Equal, "cond"); let template = rec_icscc_fpr.nonrex().opcodes(opcodes); e.enc_32_64_func(instruction, template, |builder| { let builder = builder.inst_predicate(has_eq_condition_code); diff --git a/cranelift/codegen/meta/src/isa/x86/recipes.rs b/cranelift/codegen/meta/src/isa/x86/recipes.rs index 8063e9441f..bf91a6326c 100644 --- a/cranelift/codegen/meta/src/isa/x86/recipes.rs +++ b/cranelift/codegen/meta/src/isa/x86/recipes.rs @@ -1,7 +1,7 @@ use std::rc::Rc; use crate::cdsl::ast::Literal; -use crate::cdsl::formats::{FormatRegistry, InstructionFormat}; +use crate::cdsl::formats::InstructionFormat; use crate::cdsl::instructions::InstructionPredicate; use crate::cdsl::recipes::{ EncodingRecipe, EncodingRecipeBuilder, OperandConstraint, Register, Stack, @@ -16,9 +16,6 @@ use crate::isa::x86::opcodes; /// It contains all the recipes and recipe templates that might be used in the encodings crate of /// this same directory. pub(crate) struct RecipeGroup<'builder> { - /// Memoized format pointer, to pass it to builders later. - formats: &'builder FormatRegistry, - /// Memoized registers description, to pass it to builders later. regs: &'builder IsaRegs, @@ -31,19 +28,18 @@ pub(crate) struct RecipeGroup<'builder> { } impl<'builder> RecipeGroup<'builder> { - fn new(formats: &'builder FormatRegistry, regs: &'builder IsaRegs) -> Self { + fn new(regs: &'builder IsaRegs) -> Self { Self { - formats, regs, recipes: Vec::new(), templates: Vec::new(), } } fn add_recipe(&mut self, recipe: EncodingRecipeBuilder) { - self.recipes.push(recipe.build(self.formats)); + self.recipes.push(recipe.build()); } fn add_template_recipe(&mut self, recipe: EncodingRecipeBuilder) -> Rc> { - let template = Rc::new(Template::new(recipe, self.formats, self.regs)); + let template = Rc::new(Template::new(recipe, self.regs)); self.templates.push(template.clone()); template } @@ -165,9 +161,6 @@ fn replace_nonrex_constraints( /// reconsidered later. #[derive(Clone)] pub(crate) struct Template<'builder> { - /// Mapping of format indexes to format data, used in the build() method. - formats: &'builder FormatRegistry, - /// Description of registers, used in the build() method. regs: &'builder IsaRegs, @@ -192,13 +185,8 @@ pub(crate) struct Template<'builder> { } impl<'builder> Template<'builder> { - fn new( - recipe: EncodingRecipeBuilder, - formats: &'builder FormatRegistry, - regs: &'builder IsaRegs, - ) -> Self { + fn new(recipe: EncodingRecipeBuilder, regs: &'builder IsaRegs) -> Self { Self { - formats, regs, recipe, requires_prefix: false, @@ -293,7 +281,7 @@ impl<'builder> Template<'builder> { self.recipe.operands_out = Some(replace_nonrex_constraints(self.regs, operands_out)); } - (self.recipe.build(self.formats), bits) + (self.recipe.build(), bits) } } @@ -340,8 +328,6 @@ pub(crate) fn define<'shared>( .map(|name| Literal::enumerator_for(floatcc, name)) .collect(); - let formats = &shared_defs.format_registry; - // Register classes shorthands. let abcd = regs.class_by_name("ABCD"); let gpr = regs.class_by_name("GPR"); @@ -360,6 +346,8 @@ pub(crate) fn define<'shared>( let stack_fpr32 = Stack::new(fpr); // Format shorthands, prefixed with f_. + let formats = &shared_defs.format_registry; + let f_binary = formats.by_name("Binary"); let f_binary_imm = formats.by_name("BinaryImm"); let f_branch = formats.by_name("Branch"); @@ -408,7 +396,7 @@ pub(crate) fn define<'shared>( let use_sse41 = settings.predicate_by_name("use_sse41"); // Definitions. - let mut recipes = RecipeGroup::new(formats, regs); + let mut recipes = RecipeGroup::new(regs); // A null unary instruction that takes a GPR register. Can be used for identity copies and // no-op conversions. @@ -501,7 +489,7 @@ pub(crate) fn define<'shared>( .clobbers_flags(false) .inst_predicate(supported_floatccs_predicate( &supported_floatccs, - formats.get(f_float_cond_trap), + &*f_float_cond_trap, )) .emit( r#" @@ -570,13 +558,15 @@ pub(crate) fn define<'shared>( // XX /r with FPR ins and outs. A form with a byte immediate. { - let format = formats.get(f_insert_lane); recipes.add_template_recipe( EncodingRecipeBuilder::new("fa_ib", f_insert_lane, 2) .operands_in(vec![fpr, fpr]) .operands_out(vec![0]) .inst_predicate(InstructionPredicate::new_is_unsigned_int( - format, "lane", 8, 0, + &*f_insert_lane, + "lane", + 8, + 0, )) .emit( r#" @@ -686,7 +676,6 @@ pub(crate) fn define<'shared>( modrm_rr(in_reg0, out_reg0, sink); "#, ), - formats, regs, ) .when_prefixed(urm_noflags), @@ -850,12 +839,16 @@ pub(crate) fn define<'shared>( // XX /n ib with 8-bit immediate sign-extended. { - let format = formats.get(f_binary_imm); recipes.add_template_recipe( EncodingRecipeBuilder::new("r_ib", f_binary_imm, 2) .operands_in(vec![gpr]) .operands_out(vec![0]) - .inst_predicate(InstructionPredicate::new_is_signed_int(format, "imm", 8, 0)) + .inst_predicate(InstructionPredicate::new_is_signed_int( + &*f_binary_imm, + "imm", + 8, + 0, + )) .emit( r#" {{PUT_OP}}(bits, rex1(in_reg0), sink); @@ -872,7 +865,10 @@ pub(crate) fn define<'shared>( .operands_in(vec![gpr]) .operands_out(vec![0]) .inst_predicate(InstructionPredicate::new_is_signed_int( - format, "imm", 32, 0, + &*f_binary_imm, + "imm", + 32, + 0, )) .emit( r#" @@ -887,13 +883,15 @@ pub(crate) fn define<'shared>( // XX /r ib with 8-bit unsigned immediate (e.g. for pshufd) { - let format = formats.get(f_extract_lane); recipes.add_template_recipe( EncodingRecipeBuilder::new("r_ib_unsigned_fpr", f_extract_lane, 2) .operands_in(vec![fpr]) .operands_out(vec![fpr]) .inst_predicate(InstructionPredicate::new_is_unsigned_int( - format, "lane", 8, 0, + &*f_extract_lane, + "lane", + 8, + 0, )) // TODO if the format name is changed then "lane" should be renamed to something more appropriate--ordering mask? broadcast immediate? .emit( r#" @@ -908,13 +906,12 @@ pub(crate) fn define<'shared>( // XX /r ib with 8-bit unsigned immediate (e.g. for extractlane) { - let format = formats.get(f_extract_lane); recipes.add_template_recipe( EncodingRecipeBuilder::new("r_ib_unsigned_gpr", f_extract_lane, 2) .operands_in(vec![fpr]) .operands_out(vec![gpr]) .inst_predicate(InstructionPredicate::new_is_unsigned_int( - format, "lane", 8, 0, + &*f_extract_lane, "lane", 8, 0, )) .emit( r#" @@ -929,13 +926,15 @@ pub(crate) fn define<'shared>( // XX /r ib with 8-bit unsigned immediate (e.g. for insertlane) { - let format = formats.get(f_insert_lane); recipes.add_template_recipe( EncodingRecipeBuilder::new("r_ib_unsigned_r", f_insert_lane, 2) .operands_in(vec![fpr, gpr]) .operands_out(vec![0]) .inst_predicate(InstructionPredicate::new_is_unsigned_int( - format, "lane", 8, 0, + &*f_insert_lane, + "lane", + 8, + 0, )) .emit( r#" @@ -950,12 +949,14 @@ pub(crate) fn define<'shared>( { // XX /n id with 32-bit immediate sign-extended. UnaryImm version. - let format = formats.get(f_unary_imm); recipes.add_template_recipe( EncodingRecipeBuilder::new("u_id", f_unary_imm, 5) .operands_out(vec![gpr]) .inst_predicate(InstructionPredicate::new_is_signed_int( - format, "imm", 32, 0, + &*f_unary_imm, + "imm", + 32, + 0, )) .emit( r#" @@ -1039,11 +1040,13 @@ pub(crate) fn define<'shared>( // XX /n Unary with floating point 32-bit immediate equal to zero. { - let format = formats.get(f_unary_ieee32); recipes.add_template_recipe( EncodingRecipeBuilder::new("f32imm_z", f_unary_ieee32, 1) .operands_out(vec![fpr]) - .inst_predicate(InstructionPredicate::new_is_zero_32bit_float(format, "imm")) + .inst_predicate(InstructionPredicate::new_is_zero_32bit_float( + &*f_unary_ieee32, + "imm", + )) .emit( r#" {{PUT_OP}}(bits, rex2(out_reg0, out_reg0), sink); @@ -1055,11 +1058,13 @@ pub(crate) fn define<'shared>( // XX /n Unary with floating point 64-bit immediate equal to zero. { - let format = formats.get(f_unary_ieee64); recipes.add_template_recipe( EncodingRecipeBuilder::new("f64imm_z", f_unary_ieee64, 1) .operands_out(vec![fpr]) - .inst_predicate(InstructionPredicate::new_is_zero_64bit_float(format, "imm")) + .inst_predicate(InstructionPredicate::new_is_zero_64bit_float( + &*f_unary_ieee64, + "imm", + )) .emit( r#" {{PUT_OP}}(bits, rex2(out_reg0, out_reg0), sink); @@ -1114,10 +1119,14 @@ pub(crate) fn define<'shared>( ); { - let format = formats.get(f_unary_imm); recipes.add_template_recipe( EncodingRecipeBuilder::new("adjustsp_ib", f_unary_imm, 2) - .inst_predicate(InstructionPredicate::new_is_signed_int(format, "imm", 8, 0)) + .inst_predicate(InstructionPredicate::new_is_signed_int( + &*f_unary_imm, + "imm", + 8, + 0, + )) .emit( r#" {{PUT_OP}}(bits, rex1(RU::rsp.into()), sink); @@ -1131,7 +1140,10 @@ pub(crate) fn define<'shared>( recipes.add_template_recipe( EncodingRecipeBuilder::new("adjustsp_id", f_unary_imm, 5) .inst_predicate(InstructionPredicate::new_is_signed_int( - format, "imm", 32, 0, + &*f_unary_imm, + "imm", + 32, + 0, )) .emit( r#" @@ -1350,10 +1362,10 @@ pub(crate) fn define<'shared>( { // Simple stores. - let format = formats.get(f_store); // A predicate asking if the offset is zero. - let has_no_offset = InstructionPredicate::new_is_field_equal(format, "offset", "0".into()); + let has_no_offset = + InstructionPredicate::new_is_field_equal(&*f_store, "offset", "0".into()); // XX /r register-indirect store with no offset. let st = recipes.add_template_recipe( @@ -1407,7 +1419,6 @@ pub(crate) fn define<'shared>( } "#, ), - formats, regs, ) .when_prefixed(st), @@ -1439,7 +1450,7 @@ pub(crate) fn define<'shared>( ), ); - let has_small_offset = InstructionPredicate::new_is_signed_int(format, "offset", 8, 0); + let has_small_offset = InstructionPredicate::new_is_signed_int(&*f_store, "offset", 8, 0); // XX /r register-indirect store with 8-bit offset. let st_disp8 = recipes.add_template_recipe( @@ -1491,7 +1502,6 @@ pub(crate) fn define<'shared>( sink.put1(offset as u8); "#, ), - formats, regs, ) .when_prefixed(st_disp8), @@ -1570,7 +1580,6 @@ pub(crate) fn define<'shared>( sink.put4(offset as u32); "#, ), - formats, regs, ) .when_prefixed(st_disp32), @@ -1603,10 +1612,10 @@ pub(crate) fn define<'shared>( { // Complex stores. - let format = formats.get(f_store_complex); // A predicate asking if the offset is zero. - let has_no_offset = InstructionPredicate::new_is_field_equal(format, "offset", "0".into()); + let has_no_offset = + InstructionPredicate::new_is_field_equal(&*f_store_complex, "offset", "0".into()); // XX /r register-indirect store with index and no offset. recipes.add_template_recipe( @@ -1687,7 +1696,8 @@ pub(crate) fn define<'shared>( ), ); - let has_small_offset = InstructionPredicate::new_is_signed_int(format, "offset", 8, 0); + let has_small_offset = + InstructionPredicate::new_is_signed_int(&*f_store_complex, "offset", 8, 0); // XX /r register-indirect store with index and 8-bit offset. recipes.add_template_recipe( @@ -1750,7 +1760,8 @@ pub(crate) fn define<'shared>( ), ); - let has_big_offset = InstructionPredicate::new_is_signed_int(format, "offset", 32, 0); + let has_big_offset = + InstructionPredicate::new_is_signed_int(&*f_store_complex, "offset", 32, 0); // XX /r register-indirect store with index and 32-bit offset. recipes.add_template_recipe( @@ -1890,10 +1901,10 @@ pub(crate) fn define<'shared>( { // Simple loads. - let format = formats.get(f_load); // A predicate asking if the offset is zero. - let has_no_offset = InstructionPredicate::new_is_field_equal(format, "offset", "0".into()); + let has_no_offset = + InstructionPredicate::new_is_field_equal(&*f_load, "offset", "0".into()); // XX /r load with no offset. recipes.add_template_recipe( @@ -1949,7 +1960,7 @@ pub(crate) fn define<'shared>( ), ); - let has_small_offset = InstructionPredicate::new_is_signed_int(format, "offset", 8, 0); + let has_small_offset = InstructionPredicate::new_is_signed_int(&*f_load, "offset", 8, 0); // XX /r load with 8-bit offset. recipes.add_template_recipe( @@ -2003,7 +2014,7 @@ pub(crate) fn define<'shared>( ), ); - let has_big_offset = InstructionPredicate::new_is_signed_int(format, "offset", 32, 0); + let has_big_offset = InstructionPredicate::new_is_signed_int(&*f_load, "offset", 32, 0); // XX /r load with 32-bit offset. recipes.add_template_recipe( @@ -2060,10 +2071,10 @@ pub(crate) fn define<'shared>( { // Complex loads. - let format = formats.get(f_load_complex); // A predicate asking if the offset is zero. - let has_no_offset = InstructionPredicate::new_is_field_equal(format, "offset", "0".into()); + let has_no_offset = + InstructionPredicate::new_is_field_equal(&*f_load_complex, "offset", "0".into()); // XX /r load with index and no offset. recipes.add_template_recipe( @@ -2119,7 +2130,8 @@ pub(crate) fn define<'shared>( ), ); - let has_small_offset = InstructionPredicate::new_is_signed_int(format, "offset", 8, 0); + let has_small_offset = + InstructionPredicate::new_is_signed_int(&*f_load_complex, "offset", 8, 0); // XX /r load with index and 8-bit offset. recipes.add_template_recipe( @@ -2163,7 +2175,8 @@ pub(crate) fn define<'shared>( ), ); - let has_big_offset = InstructionPredicate::new_is_signed_int(format, "offset", 32, 0); + let has_big_offset = + InstructionPredicate::new_is_signed_int(&*f_load_complex, "offset", 32, 0); // XX /r load with index and 32-bit offset. recipes.add_template_recipe( @@ -2377,7 +2390,7 @@ pub(crate) fn define<'shared>( .clobbers_flags(false) .inst_predicate(supported_floatccs_predicate( &supported_floatccs, - formats.get(f_branch_float), + &*f_branch_float, )) .emit( r#" @@ -2394,7 +2407,7 @@ pub(crate) fn define<'shared>( .clobbers_flags(false) .inst_predicate(supported_floatccs_predicate( &supported_floatccs, - formats.get(f_branch_float), + &*f_branch_float, )) .emit( r#" @@ -2421,7 +2434,7 @@ pub(crate) fn define<'shared>( .operands_in(vec![gpr, gpr]) .operands_out(vec![gpr]) .clobbers_flags(false) - .inst_predicate(valid_scale(formats.get(f_branch_table_entry))) + .inst_predicate(valid_scale(&*f_branch_table_entry)) .compute_size("size_plus_maybe_offset_for_in_reg_1") .emit( r#" @@ -2499,7 +2512,6 @@ pub(crate) fn define<'shared>( modrm_r_bits(out_reg0, bits, sink); "#, ), - formats, regs, ) .requires_prefix(true), @@ -2517,7 +2529,6 @@ pub(crate) fn define<'shared>( modrm_r_bits(out_reg0, bits, sink); "#, ), - formats, regs, ) .when_prefixed(seti), @@ -2535,7 +2546,6 @@ pub(crate) fn define<'shared>( modrm_r_bits(out_reg0, bits, sink); "#, ), - formats, regs, ) .requires_prefix(true), @@ -2553,7 +2563,6 @@ pub(crate) fn define<'shared>( modrm_r_bits(out_reg0, bits, sink); "#, ), - formats, regs, ) .when_prefixed(setf), @@ -2695,9 +2704,7 @@ pub(crate) fn define<'shared>( ); { - let format = formats.get(f_binary_imm); - - let has_small_offset = InstructionPredicate::new_is_signed_int(format, "imm", 8, 0); + let has_small_offset = InstructionPredicate::new_is_signed_int(&*f_binary_imm, "imm", 8, 0); // XX /n, MI form with imm8. recipes.add_template_recipe( @@ -2715,7 +2722,7 @@ pub(crate) fn define<'shared>( ), ); - let has_big_offset = InstructionPredicate::new_is_signed_int(format, "imm", 32, 0); + let has_big_offset = InstructionPredicate::new_is_signed_int(&*f_binary_imm, "imm", 32, 0); // XX /n, MI form with imm32. recipes.add_template_recipe( @@ -2798,7 +2805,6 @@ pub(crate) fn define<'shared>( disp1(destination, func, sink); "#, ), - formats, regs, ) .requires_prefix(true), @@ -2819,7 +2825,6 @@ pub(crate) fn define<'shared>( disp1(destination, func, sink); "#, ), - formats, regs, ) .when_prefixed(t8jccb), @@ -2841,7 +2846,6 @@ pub(crate) fn define<'shared>( disp4(destination, func, sink); "#, ), - formats, regs, ) .requires_prefix(true), @@ -2863,7 +2867,6 @@ pub(crate) fn define<'shared>( disp4(destination, func, sink); "#, ), - formats, regs, ) .when_prefixed(t8jccd), @@ -2944,9 +2947,8 @@ pub(crate) fn define<'shared>( ); { - let format = formats.get(f_int_compare_imm); - - let is_small_imm = InstructionPredicate::new_is_signed_int(format, "imm", 8, 0); + let is_small_imm = + InstructionPredicate::new_is_signed_int(&*f_int_compare_imm, "imm", 8, 0); recipes.add_template_recipe( EncodingRecipeBuilder::new("icscc_ib", f_int_compare_imm, 2 + 3) @@ -2969,7 +2971,7 @@ pub(crate) fn define<'shared>( ), ); - let is_big_imm = InstructionPredicate::new_is_signed_int(format, "imm", 32, 0); + let is_big_imm = InstructionPredicate::new_is_signed_int(&*f_int_compare_imm, "imm", 32, 0); recipes.add_template_recipe( EncodingRecipeBuilder::new("icscc_id", f_int_compare_imm, 5 + 3) @@ -3014,7 +3016,7 @@ pub(crate) fn define<'shared>( .operands_out(vec![abcd]) .inst_predicate(supported_floatccs_predicate( &supported_floatccs, - formats.get(f_float_compare), + &*f_float_compare, )) .emit( r#" diff --git a/cranelift/codegen/meta/src/lib.rs b/cranelift/codegen/meta/src/lib.rs index 92d8721334..1513b09e18 100644 --- a/cranelift/codegen/meta/src/lib.rs +++ b/cranelift/codegen/meta/src/lib.rs @@ -39,13 +39,7 @@ pub fn generate(isas: &Vec, out_dir: &str) -> Result<(), error::Error> gen_inst::generate(&shared_defs, "opcodes.rs", "inst_builder.rs", &out_dir)?; - gen_legalizer::generate( - &isas, - &shared_defs.format_registry, - &shared_defs.transform_groups, - "legalize", - &out_dir, - )?; + gen_legalizer::generate(&isas, &shared_defs.transform_groups, "legalize", &out_dir)?; for isa in isas { gen_registers::generate(&isa, &format!("registers-{}.rs", isa.name), &out_dir)?; @@ -65,7 +59,6 @@ pub fn generate(isas: &Vec, out_dir: &str) -> Result<(), error::Error> )?; gen_binemit::generate( - &shared_defs.format_registry, &isa.name, &isa.recipes, &format!("binemit-{}.rs", isa.name),