revm_interpreter/instructions/
control.rs1use crate::{
2 gas,
3 interpreter::Interpreter,
4 interpreter_types::{InterpreterTypes, Jumps, LoopControl, MemoryTr, RuntimeFlag, StackTr},
5 InstructionResult, InterpreterAction,
6};
7use primitives::{Bytes, U256};
8
9use crate::InstructionContext;
10
11pub fn jump<ITy: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, ITy>) {
15 gas!(context.interpreter, gas::MID);
16 popn!([target], context.interpreter);
17 jump_inner(context.interpreter, target);
18}
19
20pub fn jumpi<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
24 gas!(context.interpreter, gas::HIGH);
25 popn!([target, cond], context.interpreter);
26
27 if !cond.is_zero() {
28 jump_inner(context.interpreter, target);
29 }
30}
31
32#[inline(always)]
33fn jump_inner<WIRE: InterpreterTypes>(interpreter: &mut Interpreter<WIRE>, target: U256) {
37 let target = as_usize_or_fail!(interpreter, target, InstructionResult::InvalidJump);
38 if !interpreter.bytecode.is_valid_legacy_jump(target) {
39 interpreter.halt(InstructionResult::InvalidJump);
40 return;
41 }
42 interpreter.bytecode.absolute_jump(target);
44}
45
46pub fn jumpdest<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
50 gas!(context.interpreter, gas::JUMPDEST);
51}
52
53pub fn pc<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
57 gas!(context.interpreter, gas::BASE);
58 push!(
60 context.interpreter,
61 U256::from(context.interpreter.bytecode.pc() - 1)
62 );
63}
64
65#[inline]
66fn return_inner(
70 interpreter: &mut Interpreter<impl InterpreterTypes>,
71 instruction_result: InstructionResult,
72) {
73 popn!([offset, len], interpreter);
76 let len = as_usize_or_fail!(interpreter, len);
77 let mut output = Bytes::default();
79 if len != 0 {
80 let offset = as_usize_or_fail!(interpreter, offset);
81 resize_memory!(interpreter, offset, len);
82 output = interpreter.memory.slice_len(offset, len).to_vec().into()
83 }
84
85 interpreter
86 .bytecode
87 .set_action(InterpreterAction::new_return(
88 instruction_result,
89 output,
90 interpreter.gas,
91 ));
92}
93
94pub fn ret<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
98 return_inner(context.interpreter, InstructionResult::Return);
99}
100
101pub fn revert<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
103 check!(context.interpreter, BYZANTIUM);
104 return_inner(context.interpreter, InstructionResult::Revert);
105}
106
107pub fn stop<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
109 context.interpreter.halt(InstructionResult::Stop);
110}
111
112pub fn invalid<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
114 context.interpreter.halt(InstructionResult::InvalidFEOpcode);
115}
116
117pub fn unknown<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
119 context.interpreter.halt(InstructionResult::OpcodeNotFound);
120}