revmc_builtins/
macros.rs

1#[allow(unused_macros)]
2macro_rules! tri {
3    ($e:expr) => {
4        match $e {
5            Ok(x) => x,
6            Err(_) => return InstructionResult::InvalidOperandOOG,
7        }
8    };
9}
10
11macro_rules! try_opt {
12    ($e:expr) => {
13        match $e {
14            Some(x) => x,
15            None => return InstructionResult::InvalidOperandOOG,
16        }
17    };
18}
19
20macro_rules! try_host {
21    ($e:expr) => {
22        match $e {
23            Some(x) => x,
24            None => return InstructionResult::FatalExternalError,
25        }
26    };
27}
28
29macro_rules! try_ir {
30    ($e:expr) => {
31        match $e {
32            InstructionResult::Stop => {}
33            ir => return ir,
34        }
35    };
36}
37
38macro_rules! gas {
39    ($ecx:expr, $gas:expr) => {
40        if !$ecx.gas.record_cost($gas) {
41            return InstructionResult::OutOfGas;
42        }
43    };
44}
45
46macro_rules! gas_opt {
47    ($ecx:expr, $gas:expr) => {
48        match $gas {
49            Some(gas) => gas!($ecx, gas),
50            None => return InstructionResult::OutOfGas,
51        }
52    };
53}
54
55macro_rules! ensure_non_staticcall {
56    ($ecx:expr) => {
57        if $ecx.is_static {
58            return InstructionResult::StateChangeDuringStaticCall;
59        }
60    };
61}
62
63macro_rules! ensure_memory {
64    ($ecx:expr, $offset:expr, $len:expr) => {
65        try_ir!(ensure_memory($ecx, $offset, $len))
66    };
67}
68
69/// Same as `read_words_rev`, but returns the arguments in the order they were passed.
70macro_rules! read_words {
71    ($sp:expr, $($words:ident),+ $(,)?) => {
72        let rev![$($words),+] = unsafe { read_words_rev($sp) };
73    };
74}
75
76macro_rules! pop {
77    ($sp:expr; $($x:ident),* $(,)?) => {
78        $(
79            $sp = $sp.sub(1);
80            let $x = &mut *$sp;
81        )*
82    };
83}
84
85macro_rules! try_into_usize {
86    ($x:expr) => {
87        match $x.to_u256().as_limbs() {
88            x => {
89                if (x[0] > usize::MAX as u64) | (x[1] != 0) | (x[2] != 0) | (x[3] != 0) {
90                    return InstructionResult::InvalidOperandOOG;
91                }
92                x[0] as usize
93            }
94        }
95    };
96}
97
98// Credits: <https://github.com/AuroransSolis/rustconf-2023/blob/665a645d751dfe0e483261e3abca25ab4bb9e13a/reverse-tokens/src/main.rs>
99macro_rules! rev {
100	(@rev [$first:tt$(, $rest:tt)*] [$($rev:tt),*]) => {
101		rev! {
102			@rev [$($rest),*][$first $(, $rev)*]
103		}
104	};
105	(@rev [] [$($rev:tt),*]) => {
106		[$($rev)*] // NOTE: Extra `[]` to make this an array pattern.
107	};
108	($($tt:tt)+) => {
109		rev! {
110			@rev [$($tt),+] []
111		}
112	};
113}
114
115macro_rules! debug_unreachable {
116    ($($t:tt)*) => {
117        if cfg!(debug_assertions) {
118            unreachable!($($t)*);
119        } else {
120            unsafe { core::hint::unreachable_unchecked() };
121        }
122    };
123}
124
125macro_rules! assume {
126    ($e:expr $(,)?) => {
127        if !$e {
128            debug_unreachable!(stringify!($e));
129        }
130    };
131
132    ($e:expr, $($t:tt)+) => {
133        if !$e {
134            debug_unreachable!($($t)+);
135        }
136    };
137}