1macro_rules! matrix_tests {
2 ($run:ident) => {
3 #[cfg(feature = "llvm")]
4 mod llvm {
5 use super::*;
6 #[allow(unused_imports)]
7 use similar_asserts::assert_eq;
8
9 fn run_llvm(compiler: &mut EvmCompiler<revmc_llvm::EvmLlvmBackend>) {
10 if std::env::var_os("REVMC_TEST_DUMP").is_some() {
11 crate::tests::set_test_dump(compiler, module_path!());
12 }
13 $run(compiler);
14 }
15
16 #[test]
17 fn unopt() {
18 crate::tests::with_jit_compiler(revmc_backend::OptimizationLevel::None, run_llvm);
19 }
20
21 #[test]
22 fn opt() {
23 crate::tests::with_jit_compiler(
24 revmc_backend::OptimizationLevel::default(),
25 run_llvm,
26 );
27 }
28 }
29 };
30
31 ($name:ident = | $compiler:ident | $e:expr) => {
32 mod $name {
33 use super::*;
34 #[allow(unused_imports)]
35 use similar_asserts::assert_eq;
36
37 fn run_generic<B: Backend>($compiler: &mut EvmCompiler<B>) {
38 $e;
39 }
40
41 matrix_tests!(run_generic);
42 }
43 };
44 ($name:ident = $run:ident) => {
45 mod $name {
46 use super::*;
47 #[allow(unused_imports)]
48 use similar_asserts::assert_eq;
49
50 matrix_tests!($run);
51 }
52 };
53}
54
55macro_rules! build_push32 {
56 ($code:ident[$i:ident], $x:expr) => {{
57 $code[$i] = op::PUSH32;
58 $i += 1;
59 $code[$i..$i + 32].copy_from_slice(&$x.to_be_bytes::<32>());
60 $i += 32;
61 }};
62}
63
64macro_rules! tests {
65 ($($group:ident { $($t:tt)* })*) => { uint! {
66 $(
67 mod $group {
68 use super::*;
69 #[allow(unused_imports)]
70 use similar_asserts::assert_eq;
71
72 tests!(@cases $($t)*);
73 }
74 )*
75 }};
76
77 (@cases $( $name:ident($($t:tt)*) ),* $(,)?) => {
78 $(
79 matrix_tests!($name = |jit| run_test_case(tests!(@case $($t)*), jit));
80 tests!(@maybe_opaque $name($($t)*));
81 )*
82 };
83
84 (@maybe_opaque $name:ident(@raw { $($fields:tt)* })) => {};
87 (@maybe_opaque $name:ident($op:expr, $a:expr => $($ret:expr),* $(; $($_r1:tt)*)?)) => {
88 paste::paste! {
89 matrix_tests!([<$name _dyn>] = |jit| run_test_case(
90 &TestCase {
91 bytecode: &bytecode_unop_opaque($op, $a),
92 expected_stack: &[$($ret),*],
93 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
94 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
95 ..Default::default()
96 },
97 jit,
98 ));
99 }
100 };
101 (@maybe_opaque $name:ident($op:expr, $a:expr, $b:expr => $($ret:expr),* $(; $($_r2:tt)*)?)) => {
102 paste::paste! {
103 tests!(@mixed_binop [<$name _const_dyn>] $op, $a, $b, true, false => $($ret),*);
104 tests!(@mixed_binop [<$name _dyn_const>] $op, $a, $b, false, true => $($ret),*);
105 tests!(@mixed_binop [<$name _dyn_dyn>] $op, $a, $b, false, false => $($ret),*);
106 }
107 };
108 (@maybe_opaque $name:ident($op:expr, $a:expr, $b:expr, $c:expr => $($ret:expr),* $(; $($_r3:tt)*)?)) => {
109 paste::paste! {
110 tests!(@mixed_ternop [<$name _const_const_dyn>] $op, $a, $b, $c, true, true, false => $($ret),*);
111 tests!(@mixed_ternop [<$name _const_dyn_const>] $op, $a, $b, $c, true, false, true => $($ret),*);
112 tests!(@mixed_ternop [<$name _const_dyn_dyn>] $op, $a, $b, $c, true, false, false => $($ret),*);
113 tests!(@mixed_ternop [<$name _dyn_const_const>] $op, $a, $b, $c, false, true, true => $($ret),*);
114 tests!(@mixed_ternop [<$name _dyn_const_dyn>] $op, $a, $b, $c, false, true, false => $($ret),*);
115 tests!(@mixed_ternop [<$name _dyn_dyn_const>] $op, $a, $b, $c, false, false, true => $($ret),*);
116 tests!(@mixed_ternop [<$name _dyn_dyn_dyn>] $op, $a, $b, $c, false, false, false => $($ret),*);
117 }
118 };
119
120 (@mixed_binop $name:ident $op:expr, $a:expr, $b:expr, $a_const:expr, $b_const:expr => $($ret:expr),*) => {
121 matrix_tests!($name = |jit| run_test_case(
122 &TestCase {
123 bytecode: &bytecode_binop_mixed($op, $a, $b, $a_const, $b_const),
124 expected_stack: &[$($ret),*],
125 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
126 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
127 ..Default::default()
128 },
129 jit,
130 ));
131 };
132
133 (@mixed_ternop $name:ident $op:expr, $a:expr, $b:expr, $c:expr, $a_const:expr, $b_const:expr, $c_const:expr => $($ret:expr),*) => {
134 matrix_tests!($name = |jit| run_test_case(
135 &TestCase {
136 bytecode: &bytecode_ternop_mixed($op, $a, $b, $c, $a_const, $b_const, $c_const),
137 expected_stack: &[$($ret),*],
138 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
139 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
140 ..Default::default()
141 },
142 jit,
143 ));
144 };
145
146 (@case @raw { $($fields:tt)* }) => { &TestCase { $($fields)* ..Default::default() } };
147
148 (@case $op:expr $(, $args:expr)* $(,)? => $($ret:expr),* $(,)? $(; op_gas($op_gas:expr))?) => {
149 &TestCase {
150 bytecode: &tests!(@bytecode $op, $($args),*),
151 expected_stack: &[$($ret),*],
152 expected_gas: tests!(@gas $op $(, $op_gas)?; $($args),*),
153 ..Default::default()
154 }
155 };
156
157 (@bytecode $op:expr, $a:expr) => { bytecode_unop($op, $a) };
158 (@bytecode $op:expr, $a:expr, $b:expr) => { bytecode_binop($op, $a, $b) };
159 (@bytecode $op:expr, $a:expr, $b:expr, $c:expr) => { bytecode_ternop($op, $a, $b, $c) };
160
161 (@gas $op:expr; $($args:expr),+) => {
162 tests!(@gas
163 $op,
164 DEF_OPINFOS[$op as usize].base_gas() as u64;
165 $($args),+
166 )
167 };
168 (@gas $op:expr, $op_gas:expr; $($args:expr),+) => {
169 $op_gas + tests!(@gas_base $($args),+)
170 };
171 (@gas_base $a:expr) => { 3 };
172 (@gas_base $a:expr, $b:expr) => { 6 };
173 (@gas_base $a:expr, $b:expr, $c:expr) => { 9 };
174}