Path: blob/main/cranelift/codegen/meta/src/cdsl/operands.rs
1693 views
use std::collections::HashMap;12use crate::cdsl::typevar::TypeVar;34/// An instruction operand can be an *immediate*, an *SSA value*, or an *entity reference*. The5/// type of the operand is one of:6///7/// 1. A `ValueType` instance indicates an SSA value operand with a concrete type.8///9/// 2. A `TypeVar` instance indicates an SSA value operand, and the instruction is polymorphic over10/// the possible concrete types that the type variable can assume.11///12/// 3. An `ImmediateKind` instance indicates an immediate operand whose value is encoded in the13/// instruction itself rather than being passed as an SSA value.14///15/// 4. An `EntityRefKind` instance indicates an operand that references another entity in the16/// function, typically something declared in the function preamble.17#[derive(Clone, Debug)]18pub(crate) struct Operand {19/// Name of the operand variable, as it appears in function parameters, legalizations, etc.20pub name: &'static str,2122/// Type of the operand.23pub kind: OperandKind,2425doc: Option<&'static str>,26}2728impl Operand {29pub fn new(name: &'static str, kind: impl Into<OperandKind>) -> Self {30Self {31name,32doc: None,33kind: kind.into(),34}35}36pub fn with_doc(mut self, doc: &'static str) -> Self {37self.doc = Some(doc);38self39}4041pub fn doc(&self) -> &str {42if let Some(doc) = &self.doc {43return doc;44}45match &self.kind.fields {46OperandKindFields::TypeVar(tvar) => &tvar.doc,47_ => self.kind.doc(),48}49}5051pub fn is_value(&self) -> bool {52matches!(self.kind.fields, OperandKindFields::TypeVar(_))53}5455pub fn type_var(&self) -> Option<&TypeVar> {56match &self.kind.fields {57OperandKindFields::TypeVar(typevar) => Some(typevar),58_ => None,59}60}6162pub fn is_varargs(&self) -> bool {63matches!(self.kind.fields, OperandKindFields::VariableArgs)64}6566/// Returns true if the operand has an immediate kind or is an EntityRef.67pub fn is_immediate_or_entityref(&self) -> bool {68matches!(69self.kind.fields,70OperandKindFields::ImmEnum(_)71| OperandKindFields::ImmValue72| OperandKindFields::EntityRef73)74}7576/// Returns true if the operand has an immediate kind.77pub fn is_immediate(&self) -> bool {78matches!(79self.kind.fields,80OperandKindFields::ImmEnum(_) | OperandKindFields::ImmValue81)82}83}8485pub type EnumValues = HashMap<&'static str, &'static str>;8687#[derive(Clone, Debug)]88pub(crate) enum OperandKindFields {89EntityRef,90VariableArgs,91ImmValue,92ImmEnum(EnumValues),93TypeVar(TypeVar),94}9596impl OperandKindFields {97/// Return the [EnumValues] for this field if it is an `enum`.98pub(crate) fn enum_values(&self) -> Option<&EnumValues> {99match self {100OperandKindFields::ImmEnum(map) => Some(map),101_ => None,102}103}104}105106#[derive(Clone, Debug)]107pub(crate) struct OperandKind {108/// String representation of the Rust type mapping to this OperandKind.109pub rust_type: &'static str,110111/// Name of this OperandKind in the format's member field.112pub rust_field_name: &'static str,113114/// Type-specific fields for this OperandKind.115pub fields: OperandKindFields,116117doc: Option<&'static str>,118}119120impl OperandKind {121pub fn new(122rust_field_name: &'static str,123rust_type: &'static str,124fields: OperandKindFields,125doc: &'static str,126) -> Self {127Self {128rust_field_name,129rust_type,130fields,131doc: Some(doc),132}133}134fn doc(&self) -> &str {135if let Some(doc) = &self.doc {136return doc;137}138match &self.fields {139OperandKindFields::TypeVar(type_var) => &type_var.doc,140// The only method to create an OperandKind with `doc` set to None is using a TypeVar,141// so all other options are unreachable here.142OperandKindFields::ImmEnum(_)143| OperandKindFields::ImmValue144| OperandKindFields::EntityRef145| OperandKindFields::VariableArgs => unreachable!(),146}147}148149pub(crate) fn is_block(&self) -> bool {150self.rust_type == "ir::BlockCall"151}152153pub(crate) fn is_raw_block(&self) -> bool {154self.rust_type == "ir::Block"155}156}157158impl From<&TypeVar> for OperandKind {159fn from(type_var: &TypeVar) -> Self {160OperandKind {161rust_field_name: "value",162rust_type: "ir::Value",163fields: OperandKindFields::TypeVar(type_var.into()),164doc: None,165}166}167}168impl From<&OperandKind> for OperandKind {169fn from(kind: &OperandKind) -> Self {170kind.clone()171}172}173174175