diff --git a/cranelift/codegen/meta/src/cdsl/encodings.rs b/cranelift/codegen/meta/src/cdsl/encodings.rs index f79d3b9430..af6dd296bc 100644 --- a/cranelift/codegen/meta/src/cdsl/encodings.rs +++ b/cranelift/codegen/meta/src/cdsl/encodings.rs @@ -95,7 +95,7 @@ impl EncodingBuilder { &inst.inst.format, immediate_operand .kind - .default_member + .default_member() .expect("Immediates must always have a default member name set."), immediate_value.to_string(), ); diff --git a/cranelift/codegen/meta/src/cdsl/formats.rs b/cranelift/codegen/meta/src/cdsl/formats.rs index bcfc6f5650..40b1d63958 100644 --- a/cranelift/codegen/meta/src/cdsl/formats.rs +++ b/cranelift/codegen/meta/src/cdsl/formats.rs @@ -127,7 +127,7 @@ impl InstructionFormatBuilder { pub fn imm(mut self, operand_kind: &OperandKind) -> Self { let field = FormatField { kind: operand_kind.clone(), - member: operand_kind.default_member.unwrap(), + member: operand_kind.default_member().unwrap(), }; self.imm_fields.push(field); self diff --git a/cranelift/codegen/meta/src/cdsl/operands.rs b/cranelift/codegen/meta/src/cdsl/operands.rs index f8403bf910..414a381c03 100644 --- a/cranelift/codegen/meta/src/cdsl/operands.rs +++ b/cranelift/codegen/meta/src/cdsl/operands.rs @@ -111,18 +111,55 @@ pub(crate) enum OperandKindFields { #[derive(Clone, Debug)] pub(crate) struct OperandKind { pub name: &'static str, - - doc: Option, - - pub default_member: Option<&'static str>, - + doc: Option<&'static str>, + default_member: Option<&'static str>, /// The camel-cased name of an operand kind is also the Rust type used to represent it. pub rust_type: String, - pub fields: OperandKindFields, } impl OperandKind { + fn new( + name: &'static str, + doc: Option<&'static str>, + default_member: Option<&'static str>, + rust_type: Option<&'static str>, + fields: OperandKindFields, + ) -> Self { + // Compute the default rust_type value, if it wasn't provided. + let rust_type = match rust_type { + Some(rust_type) => rust_type.to_string(), + None => match &fields { + OperandKindFields::ImmEnum(_) | OperandKindFields::ImmValue => { + format!("ir::immediates::{}", camel_case(name)) + } + OperandKindFields::VariableArgs => "&[Value]".to_string(), + OperandKindFields::TypeVar(_) | OperandKindFields::EntityRef => { + format!("ir::{}", camel_case(name)) + } + }, + }; + Self { + name, + doc, + default_member, + rust_type, + fields, + } + } + + /// Name of this OperandKind in the format's member field. + pub fn default_member(&self) -> Option<&'static str> { + if let Some(member) = &self.default_member { + return Some(member); + } + match &self.fields { + OperandKindFields::ImmEnum(_) | OperandKindFields::ImmValue => Some("imm"), + OperandKindFields::TypeVar(_) | OperandKindFields::EntityRef => Some(self.name), + OperandKindFields::VariableArgs => None, + } + } + fn doc(&self) -> Option<&str> { if let Some(doc) = &self.doc { return Some(doc); @@ -146,16 +183,22 @@ impl OperandKind { } } +impl Into for &TypeVar { + fn into(self) -> OperandKind { + OperandKindBuilder::new("value", OperandKindFields::TypeVar(self.into())).build() + } +} +impl Into for &OperandKind { + fn into(self) -> OperandKind { + self.clone() + } +} + pub(crate) struct OperandKindBuilder { name: &'static str, - - doc: Option, - + doc: Option<&'static str>, default_member: Option<&'static str>, - - /// The camel-cased name of an operand kind is also the Rust type used to represent it. - rust_type: Option, - + rust_type: Option<&'static str>, fields: OperandKindFields, } @@ -169,7 +212,6 @@ impl OperandKindBuilder { fields, } } - pub fn new_imm(name: &'static str) -> Self { Self { name, @@ -179,7 +221,6 @@ impl OperandKindBuilder { fields: OperandKindFields::ImmValue, } } - pub fn new_enum(name: &'static str, values: EnumValues) -> Self { Self { name, @@ -189,10 +230,9 @@ impl OperandKindBuilder { fields: OperandKindFields::ImmEnum(values), } } - pub fn doc(mut self, doc: &'static str) -> Self { assert!(self.doc.is_none()); - self.doc = Some(doc.to_string()); + self.doc = Some(doc); self } pub fn default_member(mut self, default_member: &'static str) -> Self { @@ -202,50 +242,16 @@ impl OperandKindBuilder { } pub fn rust_type(mut self, rust_type: &'static str) -> Self { assert!(self.rust_type.is_none()); - self.rust_type = Some(rust_type.to_string()); + self.rust_type = Some(rust_type); self } - pub fn build(self) -> OperandKind { - let default_member = match self.default_member { - Some(default_member) => Some(default_member), - None => match &self.fields { - OperandKindFields::ImmEnum(_) | OperandKindFields::ImmValue => Some("imm"), - OperandKindFields::TypeVar(_) | OperandKindFields::EntityRef => Some(self.name), - OperandKindFields::VariableArgs => None, - }, - }; - - let rust_type = match self.rust_type { - Some(rust_type) => rust_type.to_string(), - None => match &self.fields { - OperandKindFields::ImmEnum(_) | OperandKindFields::ImmValue => { - format!("ir::immediates::{}", camel_case(self.name)) - } - OperandKindFields::VariableArgs => "&[Value]".to_string(), - OperandKindFields::TypeVar(_) | OperandKindFields::EntityRef => { - format!("ir::{}", camel_case(self.name)) - } - }, - }; - - OperandKind { - name: self.name, - doc: self.doc, - default_member, - rust_type, - fields: self.fields, - } - } -} - -impl Into for &TypeVar { - fn into(self) -> OperandKind { - OperandKindBuilder::new("value", OperandKindFields::TypeVar(self.into())).build() - } -} -impl Into for &OperandKind { - fn into(self) -> OperandKind { - self.clone() + OperandKind::new( + self.name, + self.doc, + self.default_member, + self.rust_type, + self.fields, + ) } }