diff --git a/cranelift/codegen/meta/src/cdsl/cpu_modes.rs b/cranelift/codegen/meta/src/cdsl/cpu_modes.rs index 30a7028cf9..4b4406d2d3 100644 --- a/cranelift/codegen/meta/src/cdsl/cpu_modes.rs +++ b/cranelift/codegen/meta/src/cdsl/cpu_modes.rs @@ -1,25 +1,34 @@ -use crate::cdsl::types::LaneType; -use crate::cdsl::xform::{TransformGroup, TransformGroupIndex, TransformGroups}; - -use std::collections::{HashMap, HashSet}; +use std::collections::{hash_map, HashMap, HashSet}; use std::iter::FromIterator; +use crate::cdsl::encodings::Encoding; +use crate::cdsl::types::{LaneType, ValueType}; +use crate::cdsl::xform::{TransformGroup, TransformGroupIndex}; + pub struct CpuMode { - _name: &'static str, + pub name: &'static str, default_legalize: Option, monomorphic_legalize: Option, - typed_legalize: HashMap, + typed_legalize: HashMap, + pub encodings: Vec, } impl CpuMode { pub fn new(name: &'static str) -> Self { Self { - _name: name, + name, default_legalize: None, monomorphic_legalize: None, typed_legalize: HashMap::new(), + encodings: Vec::new(), } } + + pub fn set_encodings(&mut self, encodings: Vec) { + assert!(self.encodings.is_empty(), "clobbering encodings"); + self.encodings = encodings; + } + pub fn legalize_monomorphic(&mut self, group: &TransformGroup) { assert!(self.monomorphic_legalize.is_none()); self.monomorphic_legalize = Some(group.id); @@ -31,10 +40,30 @@ impl CpuMode { pub fn legalize_type(&mut self, lane_type: impl Into, group: &TransformGroup) { assert!(self .typed_legalize - .insert(lane_type.into().to_string(), group.id) + .insert(lane_type.into().into(), group.id) .is_none()); } + pub fn get_default_legalize_code(&self) -> TransformGroupIndex { + self.default_legalize + .expect("a finished CpuMode must have a default legalize code") + } + pub fn get_legalize_code_for(&self, typ: &Option) -> TransformGroupIndex { + match typ { + Some(typ) => self + .typed_legalize + .get(typ) + .map(|x| *x) + .unwrap_or_else(|| self.get_default_legalize_code()), + None => self + .monomorphic_legalize + .unwrap_or_else(|| self.get_default_legalize_code()), + } + } + pub fn get_legalized_types(&self) -> hash_map::Keys { + self.typed_legalize.keys() + } + /// Returns a deterministically ordered, deduplicated list of TransformGroupIndex for the directly /// reachable set of TransformGroup this TargetIsa uses. pub fn direct_transform_groups(&self) -> Vec { diff --git a/cranelift/codegen/meta/src/cdsl/encodings.rs b/cranelift/codegen/meta/src/cdsl/encodings.rs new file mode 100644 index 0000000000..cd05eb9b38 --- /dev/null +++ b/cranelift/codegen/meta/src/cdsl/encodings.rs @@ -0,0 +1,160 @@ +use std::rc::Rc; + +use crate::cdsl::instructions::{ + InstSpec, Instruction, InstructionPredicate, InstructionPredicateNode, + InstructionPredicateNumber, InstructionPredicateRegistry, ValueTypeOrAny, +}; +use crate::cdsl::recipes::{EncodingRecipeNumber, Recipes}; +use crate::cdsl::settings::SettingPredicateNumber; +use crate::cdsl::types::ValueType; + +/// Encoding for a concrete instruction. +/// +/// An `Encoding` object ties an instruction opcode with concrete type variables together with an +/// encoding recipe and encoding encbits. +/// +/// The concrete instruction can be in three different forms: +/// +/// 1. A naked opcode: `trap` for non-polymorphic instructions. +/// 2. With bound type variables: `iadd.i32` for polymorphic instructions. +/// 3. With operands providing constraints: `icmp.i32(intcc.eq, x, y)`. +/// +/// If the instruction is polymorphic, all type variables must be provided. +pub struct EncodingContent { + /// The `Instruction` or `BoundInstruction` being encoded. + inst: InstSpec, + + /// The `EncodingRecipe` to use. + pub recipe: EncodingRecipeNumber, + + /// Additional encoding bits to be interpreted by `recipe`. + pub encbits: u16, + + /// An instruction predicate that must be true to allow selecting this encoding. + pub inst_predicate: Option, + + /// An ISA predicate that must be true to allow selecting this encoding. + pub isa_predicate: Option, + + /// The value type this encoding has been bound to, for encodings of polymorphic instructions. + pub bound_type: Option, +} + +impl EncodingContent { + pub fn inst(&self) -> &Instruction { + self.inst.inst() + } + pub fn to_rust_comment(&self, recipes: &Recipes) -> String { + format!("[{}#{:02x}]", recipes[self.recipe].name, self.encbits) + } +} + +pub type Encoding = Rc; + +pub struct EncodingBuilder { + inst: InstSpec, + recipe: EncodingRecipeNumber, + encbits: u16, + inst_predicate: Option, + isa_predicate: Option, + bound_type: Option, +} + +impl EncodingBuilder { + 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; + + assert!( + inst.value_types.len() == other_typevars.len() + 1, + "partially bound polymorphic instruction" + ); + + // Add secondary type variables to the instruction predicate. + let value_types = &inst.value_types; + let mut inst_predicate = None; + for (typevar, value_type) in other_typevars.iter().zip(value_types.iter().skip(1)) { + let value_type = match value_type { + ValueTypeOrAny::Any => continue, + ValueTypeOrAny::ValueType(vt) => vt, + }; + let type_predicate = + InstructionPredicate::new_typevar_check(&inst.inst, typevar, value_type); + inst_predicate = Some(type_predicate.into()); + } + + let ctrl_type = value_types[0] + .clone() + .expect("Controlling type shouldn't be Any"); + (inst_predicate, Some(ctrl_type)) + } + + InstSpec::Inst(inst) => { + assert!( + inst.polymorphic_info.is_none(), + "unbound polymorphic instruction" + ); + (None, None) + } + }; + + Self { + inst, + recipe, + encbits, + inst_predicate, + isa_predicate: None, + bound_type, + } + } + + pub fn inst_predicate(mut self, inst_predicate: InstructionPredicateNode) -> Self { + let inst_predicate = Some(match self.inst_predicate { + Some(node) => node.and(inst_predicate), + None => inst_predicate.into(), + }); + self.inst_predicate = inst_predicate; + self + } + + pub fn isa_predicate(mut self, isa_predicate: SettingPredicateNumber) -> Self { + assert!(self.isa_predicate.is_none()); + self.isa_predicate = Some(isa_predicate); + self + } + + pub fn build( + self, + recipes: &Recipes, + inst_pred_reg: &mut InstructionPredicateRegistry, + ) -> Encoding { + let inst_predicate = self.inst_predicate.map(|pred| inst_pred_reg.insert(pred)); + + let inst = self.inst.inst(); + assert!( + inst.format == recipes[self.recipe].format, + format!( + "Inst {} and recipe {} must have the same format!", + inst.name, recipes[self.recipe].name + ) + ); + + assert_eq!( + inst.is_branch && !inst.is_indirect_branch, + recipes[self.recipe].branch_range.is_some(), + "Inst {}'s is_branch contradicts recipe {} branch_range!", + inst.name, + recipes[self.recipe].name + ); + + Rc::new(EncodingContent { + inst: self.inst, + recipe: self.recipe, + encbits: self.encbits, + inst_predicate, + isa_predicate: self.isa_predicate, + bound_type: self.bound_type, + }) + } +} diff --git a/cranelift/codegen/meta/src/cdsl/isa.rs b/cranelift/codegen/meta/src/cdsl/isa.rs index 07467229c7..e561ce2e9c 100644 --- a/cranelift/codegen/meta/src/cdsl/isa.rs +++ b/cranelift/codegen/meta/src/cdsl/isa.rs @@ -1,18 +1,21 @@ +use std::collections::HashSet; +use std::iter::FromIterator; + use crate::cdsl::cpu_modes::CpuMode; -use crate::cdsl::instructions::InstructionGroup; +use crate::cdsl::instructions::{InstructionGroup, InstructionPredicateMap}; +use crate::cdsl::recipes::Recipes; use crate::cdsl::regs::IsaRegs; use crate::cdsl::settings::SettingGroup; use crate::cdsl::xform::{TransformGroupIndex, TransformGroups}; -use std::collections::HashSet; -use std::iter::FromIterator; - pub struct TargetIsa { pub name: &'static str, pub instructions: InstructionGroup, pub settings: SettingGroup, pub regs: IsaRegs, + pub recipes: Recipes, pub cpu_modes: Vec, + pub encodings_predicates: InstructionPredicateMap, /// TransformGroupIndex are global to all the ISAs, while we want to have indices into the /// local array of transform groups that are directly used. We use this map to get this @@ -26,7 +29,9 @@ impl TargetIsa { instructions: InstructionGroup, settings: SettingGroup, regs: IsaRegs, + recipes: Recipes, cpu_modes: Vec, + encodings_predicates: InstructionPredicateMap, ) -> Self { // Compute the local TransformGroup index. let mut local_transform_groups = Vec::new(); @@ -49,7 +54,9 @@ impl TargetIsa { instructions, settings, regs, + recipes, cpu_modes, + encodings_predicates, local_transform_groups, } } diff --git a/cranelift/codegen/meta/src/cdsl/mod.rs b/cranelift/codegen/meta/src/cdsl/mod.rs index d3227e2dd8..370b442ae4 100644 --- a/cranelift/codegen/meta/src/cdsl/mod.rs +++ b/cranelift/codegen/meta/src/cdsl/mod.rs @@ -6,10 +6,12 @@ #[macro_use] pub mod ast; pub mod cpu_modes; +pub mod encodings; pub mod formats; pub mod instructions; pub mod isa; pub mod operands; +pub mod recipes; pub mod regs; pub mod settings; pub mod type_inference; diff --git a/cranelift/codegen/meta/src/cdsl/recipes.rs b/cranelift/codegen/meta/src/cdsl/recipes.rs new file mode 100644 index 0000000000..84510cf0d1 --- /dev/null +++ b/cranelift/codegen/meta/src/cdsl/recipes.rs @@ -0,0 +1,297 @@ +use cranelift_entity::{entity_impl, PrimaryMap}; + +use crate::cdsl::formats::{FormatRegistry, InstructionFormatIndex}; +use crate::cdsl::instructions::InstructionPredicate; +use crate::cdsl::regs::RegClassIndex; +use crate::cdsl::settings::SettingPredicateNumber; + +/// A specific register in a register class. +/// +/// A register is identified by the top-level register class it belongs to and +/// its first register unit. +/// +/// Specific registers are used to describe constraints on instructions where +/// some operands must use a fixed register. +/// +/// Register instances can be created with the constructor, or accessed as +/// attributes on the register class: `GPR.rcx`. +#[derive(Copy, Clone, Hash, PartialEq, Eq)] +pub struct Register { + pub regclass: RegClassIndex, + pub unit: u8, +} + +impl Register { + pub fn new(regclass: RegClassIndex, unit: u8) -> Self { + Self { regclass, unit } + } +} + +/// An operand that must be in a stack slot. +/// +/// A `Stack` object can be used to indicate an operand constraint for a value +/// operand that must live in a stack slot. +#[derive(Copy, Clone, Hash, PartialEq)] +pub struct Stack { + pub regclass: RegClassIndex, +} + +impl Stack { + pub fn new(regclass: RegClassIndex) -> Self { + Self { regclass } + } + pub fn stack_base_mask(&self) -> &'static str { + // TODO: Make this configurable instead of just using the SP. + "StackBaseMask(1)" + } +} + +#[derive(Clone, Hash, PartialEq)] +pub struct BranchRange { + pub inst_size: u64, + pub range: u64, +} + +#[derive(Copy, Clone, Hash, PartialEq)] +pub enum OperandConstraint { + RegClass(RegClassIndex), + FixedReg(Register), + TiedInput(usize), + Stack(Stack), +} + +impl Into for RegClassIndex { + fn into(self) -> OperandConstraint { + OperandConstraint::RegClass(self) + } +} + +impl Into for Register { + fn into(self) -> OperandConstraint { + OperandConstraint::FixedReg(self) + } +} + +impl Into for usize { + fn into(self) -> OperandConstraint { + OperandConstraint::TiedInput(self) + } +} + +impl Into for Stack { + fn into(self) -> OperandConstraint { + OperandConstraint::Stack(self) + } +} + +/// A recipe for encoding instructions with a given format. +/// +/// Many different instructions can be encoded by the same recipe, but they +/// must all have the same instruction format. +/// +/// The `operands_in` and `operands_out` arguments are tuples specifying the register +/// allocation constraints for the value operands and results respectively. The +/// possible constraints for an operand are: +/// +/// - A `RegClass` specifying the set of allowed registers. +/// - A `Register` specifying a fixed-register operand. +/// - An integer indicating that this result is tied to a value operand, so +/// they must use the same register. +/// - A `Stack` specifying a value in a stack slot. +/// +/// The `branch_range` argument must be provided for recipes that can encode +/// branch instructions. It is an `(origin, bits)` tuple describing the exact +/// range that can be encoded in a branch instruction. +#[derive(Clone, Hash)] +pub struct EncodingRecipe { + /// Short mnemonic name for this recipe. + pub name: String, + + /// Associated instruction format. + pub format: InstructionFormatIndex, + + /// Base number of bytes in the binary encoded instruction. + pub base_size: u64, + + /// Tuple of register constraints for value operands. + pub operands_in: Vec, + + /// Tuple of register constraints for results. + pub operands_out: Vec, + + /// Function name to use when computing actual size. + pub compute_size: &'static str, + + /// `(origin, bits)` range for branches. + pub branch_range: Option, + + /// This instruction clobbers `iflags` and `fflags`; true by default. + pub clobbers_flags: bool, + + /// Instruction predicate. + pub inst_predicate: Option, + + /// ISA predicate. + pub isa_predicate: Option, + + /// Rust code for binary emission. + pub emit: Option, +} + +// 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 + && self.base_size == other.base_size + && self.operands_in == other.operands_in + && self.operands_out == other.operands_out + && self.compute_size == other.compute_size + && self.branch_range == other.branch_range + && self.clobbers_flags == other.clobbers_flags + && self.inst_predicate == other.inst_predicate + && self.isa_predicate == other.isa_predicate + && self.emit == other.emit + } +} + +// To allow using it in a hashmap. +impl Eq for EncodingRecipe {} + +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct EncodingRecipeNumber(u32); +entity_impl!(EncodingRecipeNumber); + +pub type Recipes = PrimaryMap; + +#[derive(Clone)] +pub struct EncodingRecipeBuilder { + pub name: String, + format: InstructionFormatIndex, + pub base_size: u64, + pub operands_in: Option>, + pub operands_out: Option>, + compute_size: Option<&'static str>, + pub branch_range: Option, + pub emit: Option, + clobbers_flags: Option, + inst_predicate: Option, + isa_predicate: Option, +} + +impl EncodingRecipeBuilder { + pub fn new(name: impl Into, format: InstructionFormatIndex, base_size: u64) -> Self { + Self { + name: name.into(), + format, + base_size, + operands_in: None, + operands_out: None, + compute_size: None, + branch_range: None, + emit: None, + clobbers_flags: None, + inst_predicate: None, + isa_predicate: None, + } + } + + // Setters. + pub fn operands_in(mut self, constraints: Vec>) -> Self { + assert!(self.operands_in.is_none()); + self.operands_in = Some( + constraints + .into_iter() + .map(|constr| constr.into()) + .collect(), + ); + self + } + pub fn operands_out(mut self, constraints: Vec>) -> Self { + assert!(self.operands_out.is_none()); + self.operands_out = Some( + constraints + .into_iter() + .map(|constr| constr.into()) + .collect(), + ); + self + } + pub fn clobbers_flags(mut self, flag: bool) -> Self { + assert!(self.clobbers_flags.is_none()); + self.clobbers_flags = Some(flag); + self + } + pub fn emit(mut self, code: impl Into) -> Self { + assert!(self.emit.is_none()); + self.emit = Some(code.into()); + self + } + pub fn branch_range(mut self, range: (u64, u64)) -> Self { + assert!(self.branch_range.is_none()); + self.branch_range = Some(BranchRange { + inst_size: range.0, + range: range.1, + }); + self + } + pub fn isa_predicate(mut self, pred: SettingPredicateNumber) -> Self { + assert!(self.isa_predicate.is_none()); + self.isa_predicate = Some(pred); + self + } + pub fn inst_predicate(mut self, inst_predicate: impl Into) -> Self { + assert!(self.inst_predicate.is_none()); + self.inst_predicate = Some(inst_predicate.into()); + self + } + pub fn compute_size(mut self, compute_size: &'static str) -> Self { + assert!(self.compute_size.is_none()); + self.compute_size = Some(compute_size); + self + } + + pub fn build(self, formats: &FormatRegistry) -> 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); + assert!( + operands_in.len() == format.num_value_operands, + format!( + "missing operand constraints for recipe {} (format {})", + self.name, format.name + ) + ); + } + + // Ensure tied inputs actually refer to existing inputs. + for constraint in operands_in.iter().chain(operands_out.iter()) { + if let OperandConstraint::TiedInput(n) = *constraint { + assert!(n < operands_in.len()); + } + } + + let compute_size = match self.compute_size { + Some(compute_size) => compute_size, + None => "base_size", + }; + + let clobbers_flags = self.clobbers_flags.unwrap_or(true); + + EncodingRecipe { + name: self.name.into(), + format: self.format, + base_size: self.base_size, + operands_in, + operands_out, + compute_size, + branch_range: self.branch_range, + clobbers_flags, + inst_predicate: self.inst_predicate, + isa_predicate: self.isa_predicate, + emit: self.emit, + } + } +} diff --git a/cranelift/codegen/meta/src/cdsl/regs.rs b/cranelift/codegen/meta/src/cdsl/regs.rs index 8a84d03617..60bf8f5818 100644 --- a/cranelift/codegen/meta/src/cdsl/regs.rs +++ b/cranelift/codegen/meta/src/cdsl/regs.rs @@ -35,9 +35,24 @@ impl RegBank { classes: Vec::new(), } } + + fn unit_by_name(&self, name: &'static str) -> u8 { + let unit = if let Some(found) = self.names.iter().position(|®_name| reg_name == name) { + found + } else { + // Try to match without the bank prefix. + assert!(name.starts_with(self.prefix)); + let name_without_prefix = &name[self.prefix.len()..]; + self.names + .iter() + .position(|®_name| reg_name == name_without_prefix) + .expect(&format!("invalid register name {}", name)) + }; + self.first_unit + (unit as u8) + } } -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] pub struct RegClassIndex(u32); entity_impl!(RegClassIndex); @@ -352,4 +367,17 @@ impl IsaRegs { ) -> Self { Self { banks, classes } } + + pub fn class_by_name(&self, name: &str) -> RegClassIndex { + self.classes + .values() + .find(|&class| class.name == name) + .expect(&format!("register class {} not found", name)) + .index + } + + pub fn regunit_by_name(&self, class_index: RegClassIndex, name: &'static str) -> u8 { + let bank_index = self.classes.get(class_index).unwrap().bank; + self.banks.get(bank_index).unwrap().unit_by_name(name) + } } diff --git a/cranelift/codegen/meta/src/cdsl/types.rs b/cranelift/codegen/meta/src/cdsl/types.rs index a8aa4020d8..21bf0161c4 100644 --- a/cranelift/codegen/meta/src/cdsl/types.rs +++ b/cranelift/codegen/meta/src/cdsl/types.rs @@ -27,7 +27,7 @@ static _RUST_NAME_PREFIX: &'static str = "ir::types::"; /// /// All SSA values have a type that is described by an instance of `ValueType` /// or one of its subclasses. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum ValueType { BV(BVType), Lane(LaneType), @@ -147,7 +147,7 @@ impl From for ValueType { } /// A concrete scalar type that can appear as a vector lane too. -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, Copy, PartialEq, Eq, Hash)] pub enum LaneType { BoolType(shared_types::Bool), FloatType(shared_types::Float), @@ -327,7 +327,7 @@ impl Iterator for LaneTypeIterator { /// /// A vector type has a lane type which is an instance of `LaneType`, /// and a positive number of lanes. -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, Eq, Hash)] pub struct VectorType { base: LaneType, lanes: u64, @@ -393,7 +393,7 @@ impl fmt::Debug for VectorType { } /// A flat bitvector type. Used for semantics description only. -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, Eq, Hash)] pub struct BVType { bits: u64, } diff --git a/cranelift/codegen/meta/src/isa/arm32/mod.rs b/cranelift/codegen/meta/src/isa/arm32/mod.rs index c1b6e05fda..d143a15163 100644 --- a/cranelift/codegen/meta/src/isa/arm32/mod.rs +++ b/cranelift/codegen/meta/src/isa/arm32/mod.rs @@ -1,6 +1,7 @@ use crate::cdsl::cpu_modes::CpuMode; -use crate::cdsl::instructions::InstructionGroupBuilder; +use crate::cdsl::instructions::{InstructionGroupBuilder, InstructionPredicateMap}; use crate::cdsl::isa::TargetIsa; +use crate::cdsl::recipes::Recipes; use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder}; use crate::cdsl::settings::{SettingGroup, SettingGroupBuilder}; @@ -71,5 +72,19 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { let cpu_modes = vec![a32, t32]; - TargetIsa::new("arm32", inst_group, settings, regs, cpu_modes) + // TODO implement arm32 recipes. + let recipes = Recipes::new(); + + // TODO implement arm32 encodings and predicates. + let encodings_predicates = InstructionPredicateMap::new(); + + TargetIsa::new( + "arm32", + inst_group, + settings, + regs, + recipes, + cpu_modes, + encodings_predicates, + ) } diff --git a/cranelift/codegen/meta/src/isa/arm64/mod.rs b/cranelift/codegen/meta/src/isa/arm64/mod.rs index c1276f5924..195fc80ae6 100644 --- a/cranelift/codegen/meta/src/isa/arm64/mod.rs +++ b/cranelift/codegen/meta/src/isa/arm64/mod.rs @@ -1,6 +1,7 @@ use crate::cdsl::cpu_modes::CpuMode; -use crate::cdsl::instructions::InstructionGroupBuilder; +use crate::cdsl::instructions::{InstructionGroupBuilder, InstructionPredicateMap}; use crate::cdsl::isa::TargetIsa; +use crate::cdsl::recipes::Recipes; use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder}; use crate::cdsl::settings::{SettingGroup, SettingGroupBuilder}; @@ -64,5 +65,19 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { let cpu_modes = vec![a64]; - TargetIsa::new("arm64", inst_group, settings, regs, cpu_modes) + // TODO implement arm64 recipes. + let recipes = Recipes::new(); + + // TODO implement arm64 encodings and predicates. + let encodings_predicates = InstructionPredicateMap::new(); + + TargetIsa::new( + "arm64", + inst_group, + settings, + regs, + recipes, + cpu_modes, + encodings_predicates, + ) } diff --git a/cranelift/codegen/meta/src/isa/riscv/mod.rs b/cranelift/codegen/meta/src/isa/riscv/mod.rs index 6c00b98f52..5bf9c05390 100644 --- a/cranelift/codegen/meta/src/isa/riscv/mod.rs +++ b/cranelift/codegen/meta/src/isa/riscv/mod.rs @@ -1,6 +1,7 @@ use crate::cdsl::cpu_modes::CpuMode; -use crate::cdsl::instructions::InstructionGroupBuilder; +use crate::cdsl::instructions::{InstructionGroupBuilder, InstructionPredicateMap}; use crate::cdsl::isa::TargetIsa; +use crate::cdsl::recipes::Recipes; use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder}; use crate::cdsl::settings::{PredicateNode, SettingGroup, SettingGroupBuilder}; @@ -115,5 +116,17 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { let cpu_modes = vec![rv_32, rv_64]; - TargetIsa::new("riscv", inst_group, settings, regs, cpu_modes) + let recipes = Recipes::new(); + + let encodings_predicates = InstructionPredicateMap::new(); + + TargetIsa::new( + "riscv", + inst_group, + settings, + regs, + recipes, + cpu_modes, + encodings_predicates, + ) } diff --git a/cranelift/codegen/meta/src/isa/x86/mod.rs b/cranelift/codegen/meta/src/isa/x86/mod.rs index 993a4d9a3b..5407ec2e87 100644 --- a/cranelift/codegen/meta/src/isa/x86/mod.rs +++ b/cranelift/codegen/meta/src/isa/x86/mod.rs @@ -1,5 +1,7 @@ use crate::cdsl::cpu_modes::CpuMode; +use crate::cdsl::instructions::InstructionPredicateMap; use crate::cdsl::isa::TargetIsa; +use crate::cdsl::recipes::Recipes; use crate::shared::types::Bool::B1; use crate::shared::types::Float::{F32, F64}; @@ -51,5 +53,17 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { let cpu_modes = vec![x86_64, x86_32]; - TargetIsa::new("x86", inst_group, settings, regs, cpu_modes) + let recipes = Recipes::new(); + + let encodings_predicates = InstructionPredicateMap::new(); + + TargetIsa::new( + "x86", + inst_group, + settings, + regs, + recipes, + cpu_modes, + encodings_predicates, + ) } diff --git a/cranelift/codegen/meta/src/shared/legalize.rs b/cranelift/codegen/meta/src/shared/legalize.rs index d8ec65e3b7..004bdff95b 100644 --- a/cranelift/codegen/meta/src/shared/legalize.rs +++ b/cranelift/codegen/meta/src/shared/legalize.rs @@ -804,7 +804,7 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG expand_flags.build_and_add_to(&mut groups); - // XXX The order of declarations unfortunately matters to be compatible with the Python code. + // TODO The order of declarations unfortunately matters to be compatible with the Python code. // When it's all migrated, we can put this next to the narrow/expand build_and_add_to calls // above. widen.build_and_add_to(&mut groups); diff --git a/cranelift/codegen/meta/src/shared/types.rs b/cranelift/codegen/meta/src/shared/types.rs index aff837252b..b327da67db 100644 --- a/cranelift/codegen/meta/src/shared/types.rs +++ b/cranelift/codegen/meta/src/shared/types.rs @@ -1,6 +1,6 @@ //! This module predefines all the Cranelift scalar types. -#[derive(Debug, Clone, Copy, Eq, PartialEq)] +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] pub enum Bool { /// 1-bit bool. B1 = 1, @@ -41,7 +41,7 @@ impl Iterator for BoolIterator { } } -#[derive(Debug, Clone, Copy, Eq, PartialEq)] +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] pub enum Int { /// 8-bit int. I8 = 8, @@ -79,7 +79,7 @@ impl Iterator for IntIterator { } } -#[derive(Debug, Clone, Copy, Eq, PartialEq)] +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] pub enum Float { F32 = 32, F64 = 64,