revm_interpreter/instructions/
control.rs1use crate::{
2 interpreter::Interpreter,
3 interpreter_types::{
4 InterpreterTypes as ITy, Jumps, LoopControl, MemoryTr, RuntimeFlag, StackTr,
5 },
6 InstructionExecResult as Result, InstructionResult, InterpreterAction,
7};
8use context_interface::{cfg::GasParams, Host};
9use primitives::{hints_util::cold_path, Bytes, U256};
10
11use crate::InstructionContext as Ictx;
12
13pub fn jump<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
17 popn!([target], context.interpreter);
18 jump_inner(context.interpreter, target)
19}
20
21pub fn jumpi<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
25 popn!([target, cond], context.interpreter);
26 if !cond.is_zero() {
27 jump_inner(context.interpreter, target)?;
28 }
29 Ok(())
30}
31
32#[inline(always)]
36fn jump_inner<IT: ITy>(
37 interpreter: &mut Interpreter<IT>,
38 target: U256,
39) -> Result<(), InstructionResult> {
40 let target = as_usize_saturated!(target);
41 if !interpreter.bytecode.is_valid_legacy_jump(target) {
42 cold_path();
43 return Err(InstructionResult::InvalidJump);
44 }
45 interpreter.bytecode.absolute_jump(target);
47 Ok(())
48}
49
50pub const fn jumpdest<IT: ITy, H: ?Sized>(_context: Ictx<'_, H, IT>) -> Result {
54 Ok(())
55}
56
57pub fn pc<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
61 push!(
63 context.interpreter,
64 U256::from(context.interpreter.bytecode.pc() - 1)
65 );
66 Ok(())
67}
68
69#[inline]
73fn return_inner(
74 interpreter: &mut Interpreter<impl ITy>,
75 gas_params: &GasParams,
76 instruction_result: InstructionResult,
77) -> Result<(), InstructionResult> {
78 popn!([offset, len], interpreter);
79 let len = as_usize_or_fail!(interpreter, len);
80 let mut output = Bytes::default();
82 if len != 0 {
83 let offset = as_usize_or_fail!(interpreter, offset);
84 interpreter.resize_memory(gas_params, offset, len)?;
85 output = interpreter.memory.slice_len(offset, len).to_vec().into()
86 }
87
88 interpreter
89 .bytecode
90 .set_action(InterpreterAction::new_return(
91 instruction_result,
92 output,
93 interpreter.gas,
94 ));
95 Err(instruction_result)
96}
97
98pub fn ret<IT: ITy, H: Host + ?Sized>(context: Ictx<'_, H, IT>) -> Result {
102 return_inner(
103 context.interpreter,
104 context.host.gas_params(),
105 InstructionResult::Return,
106 )
107}
108
109pub fn revert<IT: ITy, H: Host + ?Sized>(context: Ictx<'_, H, IT>) -> Result {
111 check!(context.interpreter, BYZANTIUM);
112 return_inner(
113 context.interpreter,
114 context.host.gas_params(),
115 InstructionResult::Revert,
116 )
117}
118
119pub const fn stop<IT: ITy, H: ?Sized>(_context: Ictx<'_, H, IT>) -> Result {
121 Err(InstructionResult::Stop)
122}
123
124pub const fn invalid<IT: ITy, H: ?Sized>(_context: Ictx<'_, H, IT>) -> Result {
126 Err(InstructionResult::InvalidFEOpcode)
127}
128
129pub const fn unknown<IT: ITy, H: ?Sized>(_context: Ictx<'_, H, IT>) -> Result {
131 Err(InstructionResult::OpcodeNotFound)
132}