revm_interpreter/instructions/
control.rs1use crate::{
2 interpreter::Interpreter,
3 interpreter_types::{InterpreterTypes, Jumps, LoopControl, MemoryTr, RuntimeFlag, StackTr},
4 InstructionResult, InterpreterAction,
5};
6use context_interface::{cfg::GasParams, Host};
7use primitives::{Bytes, U256};
8
9use crate::InstructionContext;
10
11pub fn jump<ITy: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, ITy>) {
15 popn!([target], context.interpreter);
16 jump_inner(context.interpreter, target);
17}
18
19pub fn jumpi<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
23 popn!([target, cond], context.interpreter);
24 if !cond.is_zero() {
25 jump_inner(context.interpreter, target);
26 }
27}
28
29#[inline(always)]
33fn jump_inner<WIRE: InterpreterTypes>(interpreter: &mut Interpreter<WIRE>, target: U256) {
34 let target = as_usize_or_fail!(interpreter, target, InstructionResult::InvalidJump);
35 if !interpreter.bytecode.is_valid_legacy_jump(target) {
36 interpreter.halt(InstructionResult::InvalidJump);
37 return;
38 }
39 interpreter.bytecode.absolute_jump(target);
41}
42
43pub fn jumpdest<WIRE: InterpreterTypes, H: ?Sized>(_context: InstructionContext<'_, H, WIRE>) {}
47
48pub fn pc<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
52 push!(
54 context.interpreter,
55 U256::from(context.interpreter.bytecode.pc() - 1)
56 );
57}
58
59#[inline]
60fn return_inner(
64 interpreter: &mut Interpreter<impl InterpreterTypes>,
65 gas_params: &GasParams,
66 instruction_result: InstructionResult,
67) {
68 popn!([offset, len], interpreter);
69 let len = as_usize_or_fail!(interpreter, len);
70 let mut output = Bytes::default();
72 if len != 0 {
73 let offset = as_usize_or_fail!(interpreter, offset);
74 if !interpreter.resize_memory(gas_params, offset, len) {
75 return;
76 }
77 output = interpreter.memory.slice_len(offset, len).to_vec().into()
78 }
79
80 interpreter
81 .bytecode
82 .set_action(InterpreterAction::new_return(
83 instruction_result,
84 output,
85 interpreter.gas,
86 ));
87}
88
89pub fn ret<WIRE: InterpreterTypes, H: Host + ?Sized>(context: InstructionContext<'_, H, WIRE>) {
93 return_inner(
94 context.interpreter,
95 context.host.gas_params(),
96 InstructionResult::Return,
97 );
98}
99
100pub fn revert<WIRE: InterpreterTypes, H: Host + ?Sized>(context: InstructionContext<'_, H, WIRE>) {
102 check!(context.interpreter, BYZANTIUM);
103 return_inner(
104 context.interpreter,
105 context.host.gas_params(),
106 InstructionResult::Revert,
107 );
108}
109
110pub fn stop<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
112 context.interpreter.halt(InstructionResult::Stop);
113}
114
115pub fn invalid<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
117 context.interpreter.halt(InstructionResult::InvalidFEOpcode);
118}
119
120pub fn unknown<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
122 context.interpreter.halt(InstructionResult::OpcodeNotFound);
123}