Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
instruction_spec.cpp
Go to the documentation of this file.
2
5
6#include <array>
7
8namespace bb::avm2 {
9
10namespace {
11
12// This structure is code-generated (but manually set) by the test:
13// DecompositionSelectors.CodeGen (op_decomposition.test.cpp)
14// Ordered to match WireOpCode enum
16 // Compute
17 { WireOpCode::ADD_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
18 { WireOpCode::ADD_16, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
19 { WireOpCode::SUB_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
20 { WireOpCode::SUB_16, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
21 { WireOpCode::MUL_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
22 { WireOpCode::MUL_16, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
23 { WireOpCode::DIV_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
24 { WireOpCode::DIV_16, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
25 { WireOpCode::FDIV_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
26 { WireOpCode::FDIV_16, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
27 { WireOpCode::EQ_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
28 { WireOpCode::EQ_16, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
29 { WireOpCode::LT_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
30 { WireOpCode::LT_16, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
31 { WireOpCode::LTE_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
32 { WireOpCode::LTE_16, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
33 { WireOpCode::AND_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
34 { WireOpCode::AND_16, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
35 { WireOpCode::OR_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
36 { WireOpCode::OR_16, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
37 { WireOpCode::XOR_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
38 { WireOpCode::XOR_16, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
39 { WireOpCode::NOT_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
40 { WireOpCode::NOT_16, { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
41 { WireOpCode::SHL_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
42 { WireOpCode::SHL_16, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
43 { WireOpCode::SHR_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
44 { WireOpCode::SHR_16, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
45 { WireOpCode::CAST_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
46 { WireOpCode::CAST_16, { 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
47
48 // Execution Environment
49 { WireOpCode::GETENVVAR_16, { 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 } },
50 // Execution Environment - Calldata
51 { WireOpCode::CALLDATACOPY, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
52 { WireOpCode::SUCCESSCOPY, { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
53 { WireOpCode::RETURNDATASIZE, { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
54 { WireOpCode::RETURNDATACOPY, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
55
56 // Machine State
57 // Machine State - Internal Control Flow
58 { WireOpCode::JUMP_32, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 } },
59 { WireOpCode::JUMPI_32, { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } },
60 { WireOpCode::INTERNALCALL, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 } },
61 { WireOpCode::INTERNALRETURN, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
62 // Machine State - Memory
63 { WireOpCode::SET_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
64 { WireOpCode::SET_16, { 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0 } },
65 { WireOpCode::SET_32, { 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 } },
66 { WireOpCode::SET_64, { 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 } },
67 { WireOpCode::SET_128, { 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 } },
68 { WireOpCode::SET_FF, { 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0 } },
69 { WireOpCode::MOV_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
70 { WireOpCode::MOV_16, { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
71
72 // World State
73 { WireOpCode::SLOAD, { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
74 { WireOpCode::SSTORE, { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
75 { WireOpCode::NOTEHASHEXISTS, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
76 { WireOpCode::EMITNOTEHASH, { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
77 { WireOpCode::NULLIFIEREXISTS, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
78 { WireOpCode::EMITNULLIFIER, { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
79 { WireOpCode::L1TOL2MSGEXISTS, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
80 { WireOpCode::GETCONTRACTINSTANCE, { 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
81
82 // Accrued Substate
83 { WireOpCode::EMITUNENCRYPTEDLOG, { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
84 { WireOpCode::SENDL2TOL1MSG, { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
85
86 // Control Flow - Contract Calls
87 { WireOpCode::CALL, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
88 { WireOpCode::STATICCALL, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
89 { WireOpCode::RETURN, { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
90 { WireOpCode::REVERT_8, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
91 { WireOpCode::REVERT_16, { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
92
93 // Misc
94 { WireOpCode::DEBUGLOG, { 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
95
96 // Gadgets
97 { WireOpCode::POSEIDON2PERM, { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
98 { WireOpCode::SHA256COMPRESSION, { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
99 { WireOpCode::KECCAKF1600, { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
100 { WireOpCode::ECADD, { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
101 // Conversions
102 { WireOpCode::TORADIXBE, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
103};
104
105} // namespace
106
107// Ordered to match WireOpCode enum
109 // Compute
111 { .exec_opcode = ExecutionOpCode::ADD,
112 .size_in_bytes = 5,
113 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::ADD_8) } },
115 { .exec_opcode = ExecutionOpCode::ADD,
116 .size_in_bytes = 8,
117 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::ADD_16) } },
119 { .exec_opcode = ExecutionOpCode::SUB,
120 .size_in_bytes = 5,
121 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SUB_8) } },
123 { .exec_opcode = ExecutionOpCode::SUB,
124 .size_in_bytes = 8,
125 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SUB_16) } },
127 { .exec_opcode = ExecutionOpCode::MUL,
128 .size_in_bytes = 5,
129 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::MUL_8) } },
131 { .exec_opcode = ExecutionOpCode::MUL,
132 .size_in_bytes = 8,
133 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::MUL_16) } },
135 { .exec_opcode = ExecutionOpCode::DIV,
136 .size_in_bytes = 5,
137 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::DIV_8) } },
139 { .exec_opcode = ExecutionOpCode::DIV,
140 .size_in_bytes = 8,
141 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::DIV_16) } },
143 { .exec_opcode = ExecutionOpCode::FDIV,
144 .size_in_bytes = 5,
145 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::FDIV_8) } },
147 { .exec_opcode = ExecutionOpCode::FDIV,
148 .size_in_bytes = 8,
149 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::FDIV_16) } },
151 { .exec_opcode = ExecutionOpCode::EQ,
152 .size_in_bytes = 5,
153 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::EQ_8) } },
155 { .exec_opcode = ExecutionOpCode::EQ,
156 .size_in_bytes = 8,
157 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::EQ_16) } },
159 { .exec_opcode = ExecutionOpCode::LT,
160 .size_in_bytes = 5,
161 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::LT_8) } },
163 { .exec_opcode = ExecutionOpCode::LT,
164 .size_in_bytes = 8,
165 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::LT_16) } },
167 { .exec_opcode = ExecutionOpCode::LTE,
168 .size_in_bytes = 5,
169 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::LTE_8) } },
171 { .exec_opcode = ExecutionOpCode::LTE,
172 .size_in_bytes = 8,
173 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::LTE_16) } },
175 { .exec_opcode = ExecutionOpCode::AND,
176 .size_in_bytes = 5,
177 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::AND_8) } },
179 { .exec_opcode = ExecutionOpCode::AND,
180 .size_in_bytes = 8,
181 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::AND_16) } },
183 { .exec_opcode = ExecutionOpCode::OR,
184 .size_in_bytes = 5,
185 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::OR_8) } },
187 { .exec_opcode = ExecutionOpCode::OR,
188 .size_in_bytes = 8,
189 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::OR_16) } },
191 { .exec_opcode = ExecutionOpCode::XOR,
192 .size_in_bytes = 5,
193 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::XOR_8) } },
195 { .exec_opcode = ExecutionOpCode::XOR,
196 .size_in_bytes = 8,
197 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::XOR_16) } },
199 { .exec_opcode = ExecutionOpCode::NOT,
200 .size_in_bytes = 4,
201 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::NOT_8) } },
203 { .exec_opcode = ExecutionOpCode::NOT,
204 .size_in_bytes = 6,
205 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::NOT_16) } },
207 { .exec_opcode = ExecutionOpCode::SHL,
208 .size_in_bytes = 5,
209 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SHL_8) } },
211 { .exec_opcode = ExecutionOpCode::SHL,
212 .size_in_bytes = 8,
213 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SHL_16) } },
215 { .exec_opcode = ExecutionOpCode::SHR,
216 .size_in_bytes = 5,
217 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SHR_8) } },
219 { .exec_opcode = ExecutionOpCode::SHR,
220 .size_in_bytes = 8,
221 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SHR_16) } },
223 {
224 .exec_opcode = ExecutionOpCode::CAST,
225 .size_in_bytes = 5,
226 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::CAST_8),
227 .tag_operand_idx = 3, // op3
228 } },
230 {
231 .exec_opcode = ExecutionOpCode::CAST,
232 .size_in_bytes = 7,
233 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::CAST_16),
234 .tag_operand_idx = 3, // op3
235 } },
236
237 // Execution Environment
239 { .exec_opcode = ExecutionOpCode::GETENVVAR,
240 .size_in_bytes = 5,
241 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::GETENVVAR_16) } },
242 // Execution Environment - Calldata
244 { .exec_opcode = ExecutionOpCode::CALLDATACOPY,
245 .size_in_bytes = 8,
246 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::CALLDATACOPY) } },
248 { .exec_opcode = ExecutionOpCode::SUCCESSCOPY,
249 .size_in_bytes = 4,
250 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SUCCESSCOPY) } },
252 { .exec_opcode = ExecutionOpCode::RETURNDATASIZE,
253 .size_in_bytes = 4,
254 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::RETURNDATASIZE) } },
256 { .exec_opcode = ExecutionOpCode::RETURNDATACOPY,
257 .size_in_bytes = 8,
258 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::RETURNDATACOPY) } },
259
260 // Machine State
261 // Machine State - Internal Control Flow
263 { .exec_opcode = ExecutionOpCode::JUMP,
264 .size_in_bytes = 5,
265 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::JUMP_32) } },
267 { .exec_opcode = ExecutionOpCode::JUMPI,
268 .size_in_bytes = 8,
269 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::JUMPI_32) } },
271 { .exec_opcode = ExecutionOpCode::INTERNALCALL,
272 .size_in_bytes = 5,
273 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::INTERNALCALL) } },
275 { .exec_opcode = ExecutionOpCode::INTERNALRETURN,
276 .size_in_bytes = 1,
277 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::INTERNALRETURN) } },
278 // Machine State - Memory
280 {
281 .exec_opcode = ExecutionOpCode::SET,
282 .size_in_bytes = 5,
283 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_8),
284 .tag_operand_idx = 2, // op2
285 } },
287 {
288 .exec_opcode = ExecutionOpCode::SET,
289 .size_in_bytes = 7,
290 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_16),
291 .tag_operand_idx = 2, // op2
292 } },
294 {
295 .exec_opcode = ExecutionOpCode::SET,
296 .size_in_bytes = 9,
297 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_32),
298 .tag_operand_idx = 2, // op2
299 } },
301 {
302 .exec_opcode = ExecutionOpCode::SET,
303 .size_in_bytes = 13,
304 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_64),
305 .tag_operand_idx = 2, // op2
306 } },
308 {
309 .exec_opcode = ExecutionOpCode::SET,
310 .size_in_bytes = 21,
311 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_128),
312 .tag_operand_idx = 2, // op2
313 } },
315 {
316 .exec_opcode = ExecutionOpCode::SET,
317 .size_in_bytes = 37,
318 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SET_FF),
319 .tag_operand_idx = 2, // op2
320 } },
322 { .exec_opcode = ExecutionOpCode::MOV,
323 .size_in_bytes = 4,
324 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::MOV_8) } },
326 { .exec_opcode = ExecutionOpCode::MOV,
327 .size_in_bytes = 6,
328 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::MOV_16) } },
329
330 // World State
332 { .exec_opcode = ExecutionOpCode::SLOAD,
333 .size_in_bytes = 6,
334 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SLOAD) } },
336 { .exec_opcode = ExecutionOpCode::SSTORE,
337 .size_in_bytes = 6,
338 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SSTORE) } },
340 { .exec_opcode = ExecutionOpCode::NOTEHASHEXISTS,
341 .size_in_bytes = 8,
342 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::NOTEHASHEXISTS) } },
344 { .exec_opcode = ExecutionOpCode::EMITNOTEHASH,
345 .size_in_bytes = 4,
346 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::EMITNOTEHASH) } },
348 { .exec_opcode = ExecutionOpCode::NULLIFIEREXISTS,
349 .size_in_bytes = 8,
350 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::NULLIFIEREXISTS) } },
352 { .exec_opcode = ExecutionOpCode::EMITNULLIFIER,
353 .size_in_bytes = 4,
354 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::EMITNULLIFIER) } },
356 { .exec_opcode = ExecutionOpCode::L1TOL2MSGEXISTS,
357 .size_in_bytes = 8,
358 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::L1TOL2MSGEXISTS) } },
361 .size_in_bytes = 7,
362 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::GETCONTRACTINSTANCE) } },
363
364 // Accrued Substate
367 .size_in_bytes = 6,
368 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::EMITUNENCRYPTEDLOG) } },
370 { .exec_opcode = ExecutionOpCode::SENDL2TOL1MSG,
371 .size_in_bytes = 6,
372 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SENDL2TOL1MSG) } },
373
374 // Control Flow - Contract Calls
376 { .exec_opcode = ExecutionOpCode::CALL,
377 .size_in_bytes = 13,
378 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::CALL) } },
380 { .exec_opcode = ExecutionOpCode::STATICCALL,
381 .size_in_bytes = 13,
382 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::STATICCALL) } },
384 { .exec_opcode = ExecutionOpCode::RETURN,
385 .size_in_bytes = 6,
386 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::RETURN) } },
388 { .exec_opcode = ExecutionOpCode::REVERT,
389 .size_in_bytes = 4,
390 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::REVERT_8) } },
392 { .exec_opcode = ExecutionOpCode::REVERT,
393 .size_in_bytes = 6,
394 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::REVERT_16) } },
395
396 // Misc
398 { .exec_opcode = ExecutionOpCode::DEBUGLOG,
399 .size_in_bytes = 12,
400 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::DEBUGLOG) } },
401
402 // Gadgets
404 { .exec_opcode = ExecutionOpCode::POSEIDON2PERM,
405 .size_in_bytes = 6,
406 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::POSEIDON2PERM) } },
408 { .exec_opcode = ExecutionOpCode::SHA256COMPRESSION,
409 .size_in_bytes = 8,
410 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::SHA256COMPRESSION) } },
412 { .exec_opcode = ExecutionOpCode::KECCAKF1600,
413 .size_in_bytes = 6,
414 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::KECCAKF1600) } },
416 { .exec_opcode = ExecutionOpCode::ECADD,
417 .size_in_bytes = 17,
418 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::ECADD) } },
419 // Conversions
421 { .exec_opcode = ExecutionOpCode::TORADIXBE,
422 .size_in_bytes = 13,
423 .op_dc_selectors = WireOpCode_DC_SELECTORS.at(WireOpCode::TORADIXBE) } },
424};
425
427
429{
430 inputs.push_back(tag);
431 return *this;
432}
433
435{
436 inputs.insert(inputs.end(), tags.begin(), tags.end());
437 return *this;
438}
439
441{
442 has_output = true;
443 return *this;
444}
445
446bool RegisterInfo::is_active(size_t index) const
447{
448 return index < total_registers();
449}
450
451bool RegisterInfo::is_write(size_t index) const
452{
453 return index >= inputs.size() && index < total_registers();
454}
455
456bool RegisterInfo::need_tag_check(size_t index) const
457{
458 return index < inputs.size() && inputs.at(index).has_value();
459}
460
462{
463 return index < inputs.size() ? inputs.at(index) : std::nullopt;
464}
465
466// Ordered to match ExecutionOpCode enum
469 { .num_addresses = 3,
470 .gas_cost = { .opcode_gas = AVM_ADD_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
471 .register_info = RegisterInfo()
473 /*b*/ RegisterInfo::ANY_TAG })
474 .add_output(/*c*/) } },
476 { .num_addresses = 3,
477 .gas_cost = { .opcode_gas = AVM_SUB_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
478 .register_info = RegisterInfo()
480 /*b*/ RegisterInfo::ANY_TAG })
481 .add_output(/*c*/) } },
483 { .num_addresses = 3,
484 .gas_cost = { .opcode_gas = AVM_MUL_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
485 .register_info = RegisterInfo()
487 /*b*/ RegisterInfo::ANY_TAG })
488 .add_output(/*c*/) } },
490 { .num_addresses = 3,
491 .gas_cost = { .opcode_gas = AVM_DIV_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
492 .register_info = RegisterInfo()
494 /*b*/ RegisterInfo::ANY_TAG })
495 .add_output(/*c*/) } },
497 { .num_addresses = 3,
498 .gas_cost = { .opcode_gas = AVM_FDIV_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
499 .register_info = RegisterInfo()
500 .add_inputs({ /*a*/ ValueTag::FF,
501 /*b*/ ValueTag::FF })
502 .add_output(/*c*/) } },
504 { .num_addresses = 3,
505 .gas_cost = { .opcode_gas = AVM_EQ_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
506 .register_info = RegisterInfo()
508 /*b*/ RegisterInfo::ANY_TAG })
509 .add_output(/*c*/) } },
511 { .num_addresses = 3,
512 .gas_cost = { .opcode_gas = AVM_LT_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
513 .register_info = RegisterInfo()
515 /*b*/ RegisterInfo::ANY_TAG })
516 .add_output(/*c*/) } },
518 { .num_addresses = 3,
519 .gas_cost = { .opcode_gas = AVM_LTE_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
520 .register_info = RegisterInfo()
522 /*b*/ RegisterInfo::ANY_TAG })
523 .add_output(/*c*/) } },
525 { .num_addresses = 3,
526 .gas_cost = { .opcode_gas = AVM_AND_BASE_L2_GAS, .base_da = 0, .dyn_l2 = AVM_BITWISE_DYN_L2_GAS, .dyn_da = 0 },
527 .dyn_gas_id = AVM_DYN_GAS_ID_BITWISE,
528 .register_info = RegisterInfo()
530 .add_output(/*c*/) } },
532 { .num_addresses = 3,
533 .gas_cost = { .opcode_gas = AVM_OR_BASE_L2_GAS, .base_da = 0, .dyn_l2 = AVM_BITWISE_DYN_L2_GAS, .dyn_da = 0 },
534 .dyn_gas_id = AVM_DYN_GAS_ID_BITWISE,
535 .register_info = RegisterInfo()
537 .add_output(/*c*/) } },
539 { .num_addresses = 3,
540 .gas_cost = { .opcode_gas = AVM_XOR_BASE_L2_GAS, .base_da = 0, .dyn_l2 = AVM_BITWISE_DYN_L2_GAS, .dyn_da = 0 },
541 .dyn_gas_id = AVM_DYN_GAS_ID_BITWISE,
542 .register_info = RegisterInfo()
544 .add_output(/*c*/) } },
546 { .num_addresses = 2,
547 .gas_cost = { .opcode_gas = AVM_NOT_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
548 .register_info = RegisterInfo().add_inputs({ /*a*/ RegisterInfo::ANY_TAG }).add_output(/*b*/) } },
550 { .num_addresses = 3,
551 .gas_cost = { .opcode_gas = AVM_SHL_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
552 .register_info = RegisterInfo()
554 /*b*/ RegisterInfo::ANY_TAG })
555 .add_output(/*c*/) } },
557 { .num_addresses = 3,
558 .gas_cost = { .opcode_gas = AVM_SHR_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
559 .register_info = RegisterInfo()
561 /*b*/ RegisterInfo::ANY_TAG })
562 .add_output(/*c*/) } },
564 { .num_addresses = 2,
565 .gas_cost = { .opcode_gas = AVM_CAST_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
566 .register_info = RegisterInfo().add_input(/*a*/ RegisterInfo::ANY_TAG).add_output(/*c*/) } },
568 { .num_addresses = 1,
569 .gas_cost = { .opcode_gas = AVM_GETENVVAR_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
570 .register_info = RegisterInfo().add_output(/*dst*/) } },
572 { .num_addresses = 3,
573 .gas_cost = { .opcode_gas = AVM_CALLDATACOPY_BASE_L2_GAS,
574 .base_da = 0,
576 .dyn_da = 0 },
577 .dyn_gas_id = AVM_DYN_GAS_ID_CALLDATACOPY,
578 .register_info =
579 RegisterInfo().add_inputs({ /*cd_copy_size*/ ValueTag::U32, /*cd_offset_read*/ ValueTag::U32 }) } },
581 { .num_addresses = 1,
582 .gas_cost = { .opcode_gas = AVM_SUCCESSCOPY_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
583 .register_info = RegisterInfo().add_output(/*dst*/) } },
585 { .num_addresses = 1,
586 .gas_cost = { .opcode_gas = AVM_RETURNDATASIZE_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
587 .register_info = RegisterInfo().add_output(/*dst*/) } },
589 { .num_addresses = 3,
590 .gas_cost = { .opcode_gas = AVM_RETURNDATACOPY_BASE_L2_GAS,
591 .base_da = 0,
593 .dyn_da = 0 },
594 .dyn_gas_id = AVM_DYN_GAS_ID_RETURNDATACOPY,
595 .register_info =
596 RegisterInfo().add_inputs({ /*rd_copy_size*/ ValueTag::U32, /*rd_offset_read*/ ValueTag::U32 }) } },
598 { .num_addresses = 0,
599 .gas_cost = { .opcode_gas = AVM_JUMP_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 } } },
601 { .num_addresses = 1,
602 .gas_cost = { .opcode_gas = AVM_JUMPI_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
603 .register_info = RegisterInfo().add_input(/*cond*/ ValueTag::U1) } },
605 {
606 .num_addresses = 0,
607 .gas_cost = { .opcode_gas = AVM_INTERNALCALL_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
608 } },
610 { .num_addresses = 0,
611 .gas_cost = { .opcode_gas = AVM_INTERNALRETURN_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 } } },
613 { .num_addresses = 1,
614 .gas_cost = { .opcode_gas = AVM_SET_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
615 .register_info = RegisterInfo().add_output(/*dst*/) } },
617 { .num_addresses = 2,
618 .gas_cost = { .opcode_gas = AVM_MOV_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
619 .register_info = RegisterInfo().add_input(/*src*/).add_output(/*dst*/) } },
621 { .num_addresses = 2,
622 .gas_cost = { .opcode_gas = AVM_SLOAD_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
623 .register_info = RegisterInfo().add_input(/*slot*/ ValueTag::FF).add_output(/*dst*/) } },
625 { .num_addresses = 2,
626 .gas_cost = { .opcode_gas = AVM_SSTORE_BASE_L2_GAS,
627 .base_da = 0,
628 .dyn_l2 = 0,
629 .dyn_da = AVM_SSTORE_DYN_DA_GAS },
630 .dyn_gas_id = AVM_DYN_GAS_ID_SSTORE,
631 .register_info = RegisterInfo().add_inputs({ /*src*/ ValueTag::FF, /*slot*/ ValueTag::FF }) } },
633 { .num_addresses = 3,
634 .gas_cost = { .opcode_gas = AVM_NOTEHASHEXISTS_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
635 .register_info = RegisterInfo()
636 .add_inputs({ /*unique_note_hash*/ ValueTag::FF, /*leaf_index*/ ValueTag::U64 })
637 .add_output(/*exists*/) } },
639 { .num_addresses = 1,
640 .gas_cost = { .opcode_gas = AVM_EMITNOTEHASH_BASE_L2_GAS,
642 .dyn_l2 = 0,
643 .dyn_da = 0 },
644 .register_info = RegisterInfo().add_input(/*note_hash*/ ValueTag::FF) } },
646 { .num_addresses = 3,
647 .gas_cost = { .opcode_gas = AVM_NULLIFIEREXISTS_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
648 .register_info = RegisterInfo()
649 .add_inputs({ /*nullifier*/ ValueTag::FF,
650 /*address*/ ValueTag::FF })
651 .add_output(/*exists*/) } },
653 { .num_addresses = 1,
654 .gas_cost = { .opcode_gas = AVM_EMITNULLIFIER_BASE_L2_GAS,
656 .dyn_l2 = 0,
657 .dyn_da = 0 },
658 .register_info = RegisterInfo().add_input(/*nullifier*/ ValueTag::FF) } },
660 { .num_addresses = 3,
661 .gas_cost = { .opcode_gas = AVM_L1TOL2MSGEXISTS_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
662 .register_info = RegisterInfo()
663 .add_inputs({ /*msg_hash*/ ValueTag::FF, /*leaf_index*/ ValueTag::U64 })
664 .add_output(/*exists*/) } },
666 { .num_addresses = 2,
667 .gas_cost = { .opcode_gas = AVM_GETCONTRACTINSTANCE_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
668 .register_info = RegisterInfo().add_input(/*contract_address*/ ValueTag::FF) } },
670 { .num_addresses = 2,
671 .gas_cost = { .opcode_gas = AVM_EMITUNENCRYPTEDLOG_BASE_L2_GAS,
676 .register_info = RegisterInfo().add_inputs({ ValueTag::U32 }) } },
678 { .num_addresses = 2,
679 .gas_cost = { .opcode_gas = AVM_SENDL2TOL1MSG_BASE_L2_GAS,
681 .dyn_l2 = 0,
682 .dyn_da = 0 },
683 .register_info = RegisterInfo().add_inputs({ /* recipient */ ValueTag::FF, /* content */ ValueTag::FF }) } },
685 { .num_addresses = 5,
686 .gas_cost = { .opcode_gas = AVM_CALL_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
687 .register_info = RegisterInfo().add_inputs({ /*l2_gas*/ ValueTag::U32,
688 /*da_gas*/ ValueTag::U32,
689 /*contract_address*/ ValueTag::FF,
690 /*cd_size*/ ValueTag::U32 }) } },
692 { .num_addresses = 5,
693 .gas_cost = { .opcode_gas = AVM_STATICCALL_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
694 .register_info = RegisterInfo().add_inputs({ /*l2_gas*/ ValueTag::U32,
695 /*da_gas*/ ValueTag::U32,
696 /*contract_address*/ ValueTag::FF,
697 /*cd_size*/ ValueTag::U32 }) } },
699 { .num_addresses = 2,
700 .gas_cost = { .opcode_gas = AVM_RETURN_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
701 .register_info = RegisterInfo().add_input(/*rd_size*/ ValueTag::U32) } },
703 { .num_addresses = 2,
704 .gas_cost = { .opcode_gas = AVM_REVERT_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
705 .register_info = RegisterInfo().add_input(/*rev_size*/ ValueTag::U32) } },
707 { .num_addresses = 4,
708 .gas_cost = { .opcode_gas = AVM_DEBUGLOG_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
709 // We don't set the right inputs for debuglog because we make it a noop.
710 .register_info = RegisterInfo() } },
712 { .num_addresses = 2,
713 .gas_cost = { .opcode_gas = AVM_POSEIDON2_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 } } },
715 { .num_addresses = 3,
716 .gas_cost = { .opcode_gas = AVM_SHA256COMPRESSION_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 } } },
718 { .num_addresses = 2,
719 .gas_cost = { .opcode_gas = AVM_KECCAKF1600_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 } } },
721 { .num_addresses = 7,
722 .gas_cost = { .opcode_gas = AVM_ECADD_BASE_L2_GAS, .base_da = 0, .dyn_l2 = 0, .dyn_da = 0 },
723 .register_info = RegisterInfo().add_inputs({ /*p_x=*/ValueTag::FF,
724 /*p_y=*/ValueTag::FF,
725 /*p_inf*/ ValueTag::U1,
726 /*q_x*/ ValueTag::FF,
727 /*q_y*/ ValueTag::FF,
728 /*q_inf*/ ValueTag::U1 }) } },
730 { .num_addresses = 5,
731 .gas_cost = { .opcode_gas = AVM_TORADIXBE_BASE_L2_GAS,
732 .base_da = 0,
733 .dyn_l2 = AVM_TORADIXBE_DYN_L2_GAS,
734 .dyn_da = 0 },
735 .dyn_gas_id = AVM_DYN_GAS_ID_TORADIX,
736 .register_info = RegisterInfo().add_inputs({ /*value*/ ValueTag::FF,
737 /*radix*/ ValueTag::U32,
738 /*num_limbs*/ ValueTag::U32,
739 /*is_output_bit*/ ValueTag::U1 }) } },
740};
741
742} // namespace bb::avm2
#define AVM_JUMPI_BASE_L2_GAS
#define AVM_DYN_GAS_ID_RETURNDATACOPY
#define AVM_SHL_BASE_L2_GAS
#define AVM_RETURN_BASE_L2_GAS
#define AVM_MUL_BASE_L2_GAS
#define AVM_CAST_BASE_L2_GAS
#define AVM_POSEIDON2_BASE_L2_GAS
#define AVM_CALLDATACOPY_DYN_L2_GAS
#define AVM_TORADIXBE_DYN_L2_GAS
#define AVM_SUCCESSCOPY_BASE_L2_GAS
#define AVM_NOT_BASE_L2_GAS
#define AVM_GETENVVAR_BASE_L2_GAS
#define AVM_OR_BASE_L2_GAS
#define AVM_SLOAD_BASE_L2_GAS
#define AVM_DYN_GAS_ID_SSTORE
#define AVM_EMITUNENCRYPTEDLOG_DYN_DA_GAS
#define AVM_EMITUNENCRYPTEDLOG_BASE_DA_GAS
#define AVM_ADD_BASE_L2_GAS
#define AVM_STATICCALL_BASE_L2_GAS
#define AVM_BITWISE_DYN_L2_GAS
#define AVM_RETURNDATACOPY_DYN_L2_GAS
#define AVM_DYN_GAS_ID_TORADIX
#define AVM_INTERNALRETURN_BASE_L2_GAS
#define AVM_REVERT_BASE_L2_GAS
#define AVM_EMITUNENCRYPTEDLOG_BASE_L2_GAS
#define AVM_EMITNULLIFIER_BASE_DA_GAS
#define AVM_SENDL2TOL1MSG_BASE_L2_GAS
#define AVM_EMITNOTEHASH_BASE_L2_GAS
#define AVM_RETURNDATASIZE_BASE_L2_GAS
#define AVM_JUMP_BASE_L2_GAS
#define AVM_INTERNALCALL_BASE_L2_GAS
#define AVM_NOTEHASHEXISTS_BASE_L2_GAS
#define AVM_NULLIFIEREXISTS_BASE_L2_GAS
#define AVM_XOR_BASE_L2_GAS
#define AVM_EMITUNENCRYPTEDLOG_DYN_L2_GAS
#define AVM_AND_BASE_L2_GAS
#define AVM_DEBUGLOG_BASE_L2_GAS
#define AVM_EMITNULLIFIER_BASE_L2_GAS
#define AVM_DYN_GAS_ID_CALLDATACOPY
#define AVM_SET_BASE_L2_GAS
#define AVM_EQ_BASE_L2_GAS
#define AVM_DIV_BASE_L2_GAS
#define AVM_SENDL2TOL1MSG_BASE_DA_GAS
#define AVM_EMITNOTEHASH_BASE_DA_GAS
#define AVM_KECCAKF1600_BASE_L2_GAS
#define AVM_LT_BASE_L2_GAS
#define AVM_SSTORE_BASE_L2_GAS
#define AVM_DYN_GAS_ID_EMITUNENCRYPTEDLOG
#define AVM_DYN_GAS_ID_BITWISE
#define AVM_SUB_BASE_L2_GAS
#define AVM_CALLDATACOPY_BASE_L2_GAS
#define AVM_TORADIXBE_BASE_L2_GAS
#define AVM_FDIV_BASE_L2_GAS
#define AVM_CALL_BASE_L2_GAS
#define AVM_L1TOL2MSGEXISTS_BASE_L2_GAS
#define AVM_ECADD_BASE_L2_GAS
#define AVM_SSTORE_DYN_DA_GAS
#define AVM_SHA256COMPRESSION_BASE_L2_GAS
#define AVM_RETURNDATACOPY_BASE_L2_GAS
#define AVM_SHR_BASE_L2_GAS
#define AVM_LTE_BASE_L2_GAS
#define AVM_MOV_BASE_L2_GAS
#define AVM_GETCONTRACTINSTANCE_BASE_L2_GAS
RegisterInfo & add_inputs(const std::vector< std::optional< ValueTag > > &tags)
std::optional< ValueTag > expected_tag(size_t index) const
RegisterInfo & add_input(std::optional< ValueTag > tag=std::nullopt)
std::vector< std::optional< ValueTag > > inputs
const std::unordered_map< WireOpCode, WireInstructionSpec > WIRE_INSTRUCTION_SPEC
const std::unordered_map< ExecutionOpCode, ExecInstructionSpec > EXEC_INSTRUCTION_SPEC
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13