Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/codegen/meta/src/cdsl/operands.rs
1693 views
1
use std::collections::HashMap;
2
3
use crate::cdsl::typevar::TypeVar;
4
5
/// An instruction operand can be an *immediate*, an *SSA value*, or an *entity reference*. The
6
/// type of the operand is one of:
7
///
8
/// 1. A `ValueType` instance indicates an SSA value operand with a concrete type.
9
///
10
/// 2. A `TypeVar` instance indicates an SSA value operand, and the instruction is polymorphic over
11
/// the possible concrete types that the type variable can assume.
12
///
13
/// 3. An `ImmediateKind` instance indicates an immediate operand whose value is encoded in the
14
/// instruction itself rather than being passed as an SSA value.
15
///
16
/// 4. An `EntityRefKind` instance indicates an operand that references another entity in the
17
/// function, typically something declared in the function preamble.
18
#[derive(Clone, Debug)]
19
pub(crate) struct Operand {
20
/// Name of the operand variable, as it appears in function parameters, legalizations, etc.
21
pub name: &'static str,
22
23
/// Type of the operand.
24
pub kind: OperandKind,
25
26
doc: Option<&'static str>,
27
}
28
29
impl Operand {
30
pub fn new(name: &'static str, kind: impl Into<OperandKind>) -> Self {
31
Self {
32
name,
33
doc: None,
34
kind: kind.into(),
35
}
36
}
37
pub fn with_doc(mut self, doc: &'static str) -> Self {
38
self.doc = Some(doc);
39
self
40
}
41
42
pub fn doc(&self) -> &str {
43
if let Some(doc) = &self.doc {
44
return doc;
45
}
46
match &self.kind.fields {
47
OperandKindFields::TypeVar(tvar) => &tvar.doc,
48
_ => self.kind.doc(),
49
}
50
}
51
52
pub fn is_value(&self) -> bool {
53
matches!(self.kind.fields, OperandKindFields::TypeVar(_))
54
}
55
56
pub fn type_var(&self) -> Option<&TypeVar> {
57
match &self.kind.fields {
58
OperandKindFields::TypeVar(typevar) => Some(typevar),
59
_ => None,
60
}
61
}
62
63
pub fn is_varargs(&self) -> bool {
64
matches!(self.kind.fields, OperandKindFields::VariableArgs)
65
}
66
67
/// Returns true if the operand has an immediate kind or is an EntityRef.
68
pub fn is_immediate_or_entityref(&self) -> bool {
69
matches!(
70
self.kind.fields,
71
OperandKindFields::ImmEnum(_)
72
| OperandKindFields::ImmValue
73
| OperandKindFields::EntityRef
74
)
75
}
76
77
/// Returns true if the operand has an immediate kind.
78
pub fn is_immediate(&self) -> bool {
79
matches!(
80
self.kind.fields,
81
OperandKindFields::ImmEnum(_) | OperandKindFields::ImmValue
82
)
83
}
84
}
85
86
pub type EnumValues = HashMap<&'static str, &'static str>;
87
88
#[derive(Clone, Debug)]
89
pub(crate) enum OperandKindFields {
90
EntityRef,
91
VariableArgs,
92
ImmValue,
93
ImmEnum(EnumValues),
94
TypeVar(TypeVar),
95
}
96
97
impl OperandKindFields {
98
/// Return the [EnumValues] for this field if it is an `enum`.
99
pub(crate) fn enum_values(&self) -> Option<&EnumValues> {
100
match self {
101
OperandKindFields::ImmEnum(map) => Some(map),
102
_ => None,
103
}
104
}
105
}
106
107
#[derive(Clone, Debug)]
108
pub(crate) struct OperandKind {
109
/// String representation of the Rust type mapping to this OperandKind.
110
pub rust_type: &'static str,
111
112
/// Name of this OperandKind in the format's member field.
113
pub rust_field_name: &'static str,
114
115
/// Type-specific fields for this OperandKind.
116
pub fields: OperandKindFields,
117
118
doc: Option<&'static str>,
119
}
120
121
impl OperandKind {
122
pub fn new(
123
rust_field_name: &'static str,
124
rust_type: &'static str,
125
fields: OperandKindFields,
126
doc: &'static str,
127
) -> Self {
128
Self {
129
rust_field_name,
130
rust_type,
131
fields,
132
doc: Some(doc),
133
}
134
}
135
fn doc(&self) -> &str {
136
if let Some(doc) = &self.doc {
137
return doc;
138
}
139
match &self.fields {
140
OperandKindFields::TypeVar(type_var) => &type_var.doc,
141
// The only method to create an OperandKind with `doc` set to None is using a TypeVar,
142
// so all other options are unreachable here.
143
OperandKindFields::ImmEnum(_)
144
| OperandKindFields::ImmValue
145
| OperandKindFields::EntityRef
146
| OperandKindFields::VariableArgs => unreachable!(),
147
}
148
}
149
150
pub(crate) fn is_block(&self) -> bool {
151
self.rust_type == "ir::BlockCall"
152
}
153
154
pub(crate) fn is_raw_block(&self) -> bool {
155
self.rust_type == "ir::Block"
156
}
157
}
158
159
impl From<&TypeVar> for OperandKind {
160
fn from(type_var: &TypeVar) -> Self {
161
OperandKind {
162
rust_field_name: "value",
163
rust_type: "ir::Value",
164
fields: OperandKindFields::TypeVar(type_var.into()),
165
doc: None,
166
}
167
}
168
}
169
impl From<&OperandKind> for OperandKind {
170
fn from(kind: &OperandKind) -> Self {
171
kind.clone()
172
}
173
}
174
175