1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
"""Classes for describing instruction formats."""
# noqa
# The typing module is only required by mypy, and we don't use these imports
# outside type comments.
# noqa
pass
"""
Most instruction predicates refer to immediate fields of a specific
instruction format, so their `predicate_context()` method returns the
specific instruction format.
Predicates that only care about the types of SSA values are independent of
the instruction format. They can be evaluated in the context of any
instruction.
The singleton `InstructionContext` class serves as the predicate context
for these predicates.
"""
# type: () -> None
=
# Singleton instance.
=
"""
Every instruction opcode has a corresponding instruction format which
determines the number of operands and their kinds. Instruction formats are
identified structurally, i.e., the format of an instruction is derived from
the kinds of operands used in its declaration.
The instruction format stores two separate lists of operands: Immediates
and values. Immediate operands (including entity references) are
represented as explicit members in the `InstructionData` variants. The
value operands are stored differently, depending on how many there are.
Beyond a certain point, instruction formats switch to an external value
list for storing value arguments. Value lists can hold an arbitrary number
of values.
All instruction formats must be predefined in the
:py:mod:`cranelift.formats` module.
:param kinds: List of `OperandKind` objects describing the operands.
:param name: Instruction format name in CamelCase. This is used as a Rust
variant name in both the `InstructionData` and `InstructionFormat`
enums.
:param typevar_operand: Index of the value input operand that is used to
infer the controlling type variable. By default, this is `0`, the first
`value` operand. The index is relative to the values only, ignoring
immediate operands.
"""
# Map (imm_kinds, num_value_operands) -> format
= # type: Dict[Tuple[Tuple[OperandKind, ...], int, bool], InstructionFormat] # noqa
# All existing formats.
= # type: List[InstructionFormat]
# type: (*Union[OperandKind, Tuple[str, OperandKind]], **Any) -> None # noqa
= # type: str
=
# The number of value operands stored in the format, or `None` when
# `has_value_list` is set.
= 0
# Does this format use a value list for storing value operands?
= False
# Operand fields for the immediate operands. All other instruction
# operands are values or variable argument lists. They are all handled
# specially.
=
# The typevar_operand argument must point to a 'value' operand.
= # type: int
assert < , \
# Default to the first 'value' operand, if there is one.
= 0
# Compute a signature for the global registry.
=
=
=
# type: () -> FormatField
"""
Provides a ValueListField, which is derived from FormatField,
corresponding to the full ValueList of the instruction format. This
is useful for creating predicates for instructions which use variadic
arguments.
"""
return
return None
# type: (Sequence[Union[OperandKind, Tuple[str, OperandKind]]]) -> Iterable[FormatField] # noqa
"""
Extract names of all the immediate operands in the kinds tuple.
Each entry is either an `OperandKind` instance, or a `(member, kind)`
pair. The member names correspond to members in the Rust
`InstructionData` data structure.
Updates the fields `self.num_value_operands` and `self.has_value_list`.
Yields the immediate operand fields.
"""
= 0
=
=
, =
# We define 'immediate' as not a value or variable arguments.
+= 1
= True
yield
+= 1
# type: () -> str
=
return
# type: (str) -> FormatField
"""
Make immediate instruction format members available as attributes.
Each non-value format member becomes a corresponding `FormatField`
attribute.
"""
# Cache this field attribute so we won't have to search again.
return
# type: (Sequence[Operand], Sequence[Operand]) -> InstructionFormat
"""
Find an existing instruction format that matches the given lists of
instruction inputs and outputs.
The `ins` and `outs` arguments correspond to the
:py:class:`Instruction` arguments of the same name, except they must be
tuples of :py:`Operand` objects.
"""
# Construct a signature.
=
=
=
=
return
# Try another value list format as an alternative.
=
return
# type: (Dict[str, Any]) -> None
"""
Given a dict mapping name -> object as returned by `globals()`, find
all the InstructionFormat objects and set their name from the dict key.
This is used to name a bunch of global values in a module.
"""
assert is None
=
"""
An immediate field in an instruction format.
This corresponds to a single member of a variant of the `InstructionData`
data type.
:param iform: Parent `InstructionFormat`.
:param immnum: Immediate operand number in parent.
:param kind: Immediate Operand kind.
:param member: Member name in `InstructionData` variant.
"""
# type: (InstructionFormat, int, OperandKind, str) -> None
=
=
=
=
# type: () -> str
return
# type: () -> str
return
# type: () -> str
return
"""
The full value list field of an instruction format.
This corresponds to all Value-type members of a variant of the
`InstructionData` format, which contains a ValueList.
:param iform: Parent `InstructionFormat`.
"""
# type: (InstructionFormat) -> None
=
=
# type: () -> str
return