1
+ //! Utility macros to help implementementing opcode instruction functions.
2
+
3
+ /// Fails the instruction if the current call is static.
4
+ #[ macro_export]
1
5
macro_rules! check_staticcall {
2
6
( $interp: expr) => {
3
7
if $interp. is_static {
4
- $interp. instruction_result = InstructionResult :: StateChangeDuringStaticCall ;
8
+ $interp. instruction_result = $crate :: InstructionResult :: StateChangeDuringStaticCall ;
5
9
return ;
6
10
}
7
11
} ;
8
12
}
9
13
14
+ /// Fails the instruction if the `min` is not enabled in `SPEC`.
15
+ #[ macro_export]
10
16
macro_rules! check {
11
17
( $interp: expr, $min: ident) => {
12
18
// TODO: Force const-eval on the condition with a `const {}` block once they are stable
13
19
if !<SPEC as $crate:: primitives:: Spec >:: enabled( $crate:: primitives:: SpecId :: $min) {
14
- $interp. instruction_result = InstructionResult :: NotActivated ;
20
+ $interp. instruction_result = $crate :: InstructionResult :: NotActivated ;
15
21
return ;
16
22
}
17
23
} ;
18
24
}
19
25
26
+ /// Records a `gas` cost and fails the instruction if it would exceed the available gas.
20
27
#[ macro_export]
21
28
macro_rules! gas {
22
29
( $interp: expr, $gas: expr) => {
23
- gas!( $interp, $gas, ( ) )
30
+ $crate :: gas!( $interp, $gas, ( ) )
24
31
} ;
25
32
( $interp: expr, $gas: expr, $ret: expr) => {
26
33
if !$interp. gas. record_cost( $gas) {
27
- $interp. instruction_result = InstructionResult :: OutOfGas ;
34
+ $interp. instruction_result = $crate :: InstructionResult :: OutOfGas ;
28
35
return $ret;
29
36
}
30
37
} ;
31
38
}
32
39
40
+ /// Records a `gas` refund.
41
+ #[ macro_export]
33
42
macro_rules! refund {
34
43
( $interp: expr, $gas: expr) => {
35
44
$interp. gas. record_refund( $gas)
36
45
} ;
37
46
}
38
47
48
+ /// Same as [`gas!`], but with `gas` as an option.
49
+ #[ macro_export]
39
50
macro_rules! gas_or_fail {
40
51
( $interp: expr, $gas: expr) => {
41
52
match $gas {
42
- Some ( gas_used) => gas!( $interp, gas_used) ,
53
+ Some ( gas_used) => $crate :: gas!( $interp, gas_used) ,
43
54
None => {
44
- $interp. instruction_result = InstructionResult :: OutOfGas ;
55
+ $interp. instruction_result = $crate :: InstructionResult :: OutOfGas ;
45
56
return ;
46
57
}
47
58
}
48
59
} ;
49
60
}
50
61
62
+ /// Resizes the interpreter memory if necessary. Fails the instruction if the memory or gas limit
63
+ /// is exceeded.
51
64
#[ macro_export]
52
- macro_rules! shared_memory_resize {
65
+ macro_rules! resize_memory {
53
66
( $interp: expr, $offset: expr, $len: expr) => {
54
- shared_memory_resize !( $interp, $offset, $len, ( ) )
67
+ $crate :: resize_memory !( $interp, $offset, $len, ( ) )
55
68
} ;
56
69
( $interp: expr, $offset: expr, $len: expr, $ret: expr) => {
57
70
let size = $offset. saturating_add( $len) ;
@@ -61,7 +74,7 @@ macro_rules! shared_memory_resize {
61
74
62
75
#[ cfg( feature = "memory_limit" ) ]
63
76
if $interp. shared_memory. limit_reached( size) {
64
- $interp. instruction_result = InstructionResult :: MemoryLimitOOG ;
77
+ $interp. instruction_result = $crate :: InstructionResult :: MemoryLimitOOG ;
65
78
return $ret;
66
79
}
67
80
@@ -71,34 +84,43 @@ macro_rules! shared_memory_resize {
71
84
. gas
72
85
. record_memory( $crate:: gas:: memory_gas( words_num) )
73
86
{
74
- $interp. instruction_result = InstructionResult :: MemoryLimitOOG ;
87
+ $interp. instruction_result = $crate :: InstructionResult :: MemoryLimitOOG ;
75
88
return $ret;
76
89
}
77
90
$interp. shared_memory. resize( rounded_size) ;
78
91
}
79
92
} ;
80
93
}
81
94
95
+ /// Pops `Address` values from the stack. Fails the instruction if the stack is too small.
96
+ #[ macro_export]
82
97
macro_rules! pop_address {
83
98
( $interp: expr, $x1: ident) => {
84
99
if $interp. stack. len( ) < 1 {
85
- $interp. instruction_result = InstructionResult :: StackUnderflow ;
100
+ $interp. instruction_result = $crate :: InstructionResult :: StackUnderflow ;
86
101
return ;
87
102
}
88
103
// SAFETY: Length is checked above.
89
- let $x1 = Address :: from_word( B256 :: from( unsafe { $interp. stack. pop_unsafe( ) } ) ) ;
104
+ let $x1 = $crate:: primitives:: Address :: from_word( $crate:: primitives:: B256 :: from( unsafe {
105
+ $interp. stack. pop_unsafe( )
106
+ } ) ) ;
90
107
} ;
91
108
( $interp: expr, $x1: ident, $x2: ident) => {
92
109
if $interp. stack. len( ) < 2 {
93
- $interp. instruction_result = InstructionResult :: StackUnderflow ;
110
+ $interp. instruction_result = $crate :: InstructionResult :: StackUnderflow ;
94
111
return ;
95
112
}
96
113
// SAFETY: Length is checked above.
97
- let $x1 = Address :: from_word( B256 :: from( unsafe { $interp. stack. pop_unsafe( ) } ) ) ;
98
- let $x2 = Address :: from_word( B256 :: from( unsafe { $interp. stack. pop_unsafe( ) } ) ) ;
114
+ let $x1 = $crate:: primitives:: Address :: from_word( $crate:: primitives:: B256 :: from( unsafe {
115
+ $interp. stack. pop_unsafe( )
116
+ } ) ) ;
117
+ let $x2 = $crate:: primitives:: Address :: from_word( $crate:: primitives:: B256 :: from( unsafe {
118
+ $interp. stack. pop_unsafe( )
119
+ } ) ) ;
99
120
} ;
100
121
}
101
122
123
+ /// Pops `U256` values from the stack. Fails the instruction if the stack is too small.
102
124
#[ macro_export]
103
125
macro_rules! pop {
104
126
( $interp: expr, $x1: ident) => {
@@ -115,69 +137,75 @@ macro_rules! pop {
115
137
} ;
116
138
}
117
139
140
+ /// Pops `U256` values from the stack, and returns `ret`.
141
+ /// Fails the instruction if the stack is too small.
118
142
#[ macro_export]
119
143
macro_rules! pop_ret {
120
144
( $interp: expr, $x1: ident, $ret: expr) => {
121
145
if $interp. stack. len( ) < 1 {
122
- $interp. instruction_result = InstructionResult :: StackUnderflow ;
146
+ $interp. instruction_result = $crate :: InstructionResult :: StackUnderflow ;
123
147
return $ret;
124
148
}
125
149
// SAFETY: Length is checked above.
126
150
let $x1 = unsafe { $interp. stack. pop_unsafe( ) } ;
127
151
} ;
128
152
( $interp: expr, $x1: ident, $x2: ident, $ret: expr) => {
129
153
if $interp. stack. len( ) < 2 {
130
- $interp. instruction_result = InstructionResult :: StackUnderflow ;
154
+ $interp. instruction_result = $crate :: InstructionResult :: StackUnderflow ;
131
155
return $ret;
132
156
}
133
157
// SAFETY: Length is checked above.
134
158
let ( $x1, $x2) = unsafe { $interp. stack. pop2_unsafe( ) } ;
135
159
} ;
136
160
( $interp: expr, $x1: ident, $x2: ident, $x3: ident, $ret: expr) => {
137
161
if $interp. stack. len( ) < 3 {
138
- $interp. instruction_result = InstructionResult :: StackUnderflow ;
162
+ $interp. instruction_result = $crate :: InstructionResult :: StackUnderflow ;
139
163
return $ret;
140
164
}
141
165
// SAFETY: Length is checked above.
142
166
let ( $x1, $x2, $x3) = unsafe { $interp. stack. pop3_unsafe( ) } ;
143
167
} ;
144
168
( $interp: expr, $x1: ident, $x2: ident, $x3: ident, $x4: ident, $ret: expr) => {
145
169
if $interp. stack. len( ) < 4 {
146
- $interp. instruction_result = InstructionResult :: StackUnderflow ;
170
+ $interp. instruction_result = $crate :: InstructionResult :: StackUnderflow ;
147
171
return $ret;
148
172
}
149
173
// SAFETY: Length is checked above.
150
174
let ( $x1, $x2, $x3, $x4) = unsafe { $interp. stack. pop4_unsafe( ) } ;
151
175
} ;
152
176
}
153
177
178
+ /// Pops `U256` values from the stack, and returns a reference to the top of the stack.
179
+ /// Fails the instruction if the stack is too small.
180
+ #[ macro_export]
154
181
macro_rules! pop_top {
155
182
( $interp: expr, $x1: ident) => {
156
183
if $interp. stack. len( ) < 1 {
157
- $interp. instruction_result = InstructionResult :: StackUnderflow ;
184
+ $interp. instruction_result = $crate :: InstructionResult :: StackUnderflow ;
158
185
return ;
159
186
}
160
187
// SAFETY: Length is checked above.
161
188
let $x1 = unsafe { $interp. stack. top_unsafe( ) } ;
162
189
} ;
163
190
( $interp: expr, $x1: ident, $x2: ident) => {
164
191
if $interp. stack. len( ) < 2 {
165
- $interp. instruction_result = InstructionResult :: StackUnderflow ;
192
+ $interp. instruction_result = $crate :: InstructionResult :: StackUnderflow ;
166
193
return ;
167
194
}
168
195
// SAFETY: Length is checked above.
169
196
let ( $x1, $x2) = unsafe { $interp. stack. pop_top_unsafe( ) } ;
170
197
} ;
171
198
( $interp: expr, $x1: ident, $x2: ident, $x3: ident) => {
172
199
if $interp. stack. len( ) < 3 {
173
- $interp. instruction_result = InstructionResult :: StackUnderflow ;
200
+ $interp. instruction_result = $crate :: InstructionResult :: StackUnderflow ;
174
201
return ;
175
202
}
176
203
// SAFETY: Length is checked above.
177
204
let ( $x1, $x2, $x3) = unsafe { $interp. stack. pop2_top_unsafe( ) } ;
178
205
} ;
179
206
}
180
207
208
+ /// Pushes `B256` values onto the stack. Fails the instruction if the stack is full.
181
209
#[ macro_export]
182
210
macro_rules! push_b256 {
183
211
( $interp: expr, $( $x: expr) ,* $( , ) ?) => ( $(
@@ -191,6 +219,7 @@ macro_rules! push_b256 {
191
219
) * )
192
220
}
193
221
222
+ /// Pushes a `B256` value onto the stack. Fails the instruction if the stack is full.
194
223
#[ macro_export]
195
224
macro_rules! push {
196
225
( $interp: expr, $( $x: expr) ,* $( , ) ?) => ( $(
@@ -204,6 +233,8 @@ macro_rules! push {
204
233
) * )
205
234
}
206
235
236
+ /// Converts a `U256` value to a `u64`, saturating to `MAX` if the value is too large.
237
+ #[ macro_export]
207
238
macro_rules! as_u64_saturated {
208
239
( $v: expr) => { {
209
240
let x: & [ u64 ; 4 ] = $v. as_limbs( ) ;
@@ -215,24 +246,36 @@ macro_rules! as_u64_saturated {
215
246
} } ;
216
247
}
217
248
249
+ /// Converts a `U256` value to a `usize`, saturating to `MAX` if the value is too large.
250
+ #[ macro_export]
218
251
macro_rules! as_usize_saturated {
219
252
( $v: expr) => {
220
- usize :: try_from( as_u64_saturated!( $v) ) . unwrap_or( usize :: MAX )
253
+ usize :: try_from( $crate :: as_u64_saturated!( $v) ) . unwrap_or( usize :: MAX )
221
254
} ;
222
255
}
223
256
257
+ /// Converts a `U256` value to a `usize`, failing the instruction if the value is too large.
258
+ #[ macro_export]
224
259
macro_rules! as_usize_or_fail {
225
260
( $interp: expr, $v: expr) => {
226
- as_usize_or_fail_ret!( $interp, $v, ( ) )
261
+ $crate :: as_usize_or_fail_ret!( $interp, $v, ( ) )
227
262
} ;
228
263
( $interp: expr, $v: expr, $reason: expr) => {
229
- as_usize_or_fail_ret!( $interp, $v, $reason, ( ) )
264
+ $crate :: as_usize_or_fail_ret!( $interp, $v, $reason, ( ) )
230
265
} ;
231
266
}
232
267
268
+ /// Converts a `U256` value to a `usize` and returns `ret`,
269
+ /// failing the instruction if the value is too large.
270
+ #[ macro_export]
233
271
macro_rules! as_usize_or_fail_ret {
234
272
( $interp: expr, $v: expr, $ret: expr) => {
235
- as_usize_or_fail_ret!( $interp, $v, InstructionResult :: InvalidOperandOOG , $ret)
273
+ $crate:: as_usize_or_fail_ret!(
274
+ $interp,
275
+ $v,
276
+ $crate:: InstructionResult :: InvalidOperandOOG ,
277
+ $ret
278
+ )
236
279
} ;
237
280
238
281
( $interp: expr, $v: expr, $reason: expr, $ret: expr) => { {
0 commit comments