revm_interpreter/instructions/
control.rs1use crate::{
2    interpreter::Interpreter,
3    interpreter_types::{InterpreterTypes, Jumps, LoopControl, MemoryTr, RuntimeFlag, StackTr},
4    InstructionResult, InterpreterAction,
5};
6use primitives::{Bytes, U256};
7
8use crate::InstructionContext;
9
10pub fn jump<ITy: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, ITy>) {
14    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);
25
26    if !cond.is_zero() {
27        jump_inner(context.interpreter, target);
28    }
29}
30
31#[inline(always)]
35fn jump_inner<WIRE: InterpreterTypes>(interpreter: &mut Interpreter<WIRE>, target: U256) {
36    let target = as_usize_or_fail!(interpreter, target, InstructionResult::InvalidJump);
37    if !interpreter.bytecode.is_valid_legacy_jump(target) {
38        interpreter.halt(InstructionResult::InvalidJump);
39        return;
40    }
41    interpreter.bytecode.absolute_jump(target);
43}
44
45pub fn jumpdest<WIRE: InterpreterTypes, H: ?Sized>(_context: InstructionContext<'_, H, WIRE>) {
49    }
51
52pub fn pc<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
56    push!(
59        context.interpreter,
60        U256::from(context.interpreter.bytecode.pc() - 1)
61    );
62}
63
64#[inline]
65fn return_inner(
69    interpreter: &mut Interpreter<impl InterpreterTypes>,
70    instruction_result: InstructionResult,
71) {
72    popn!([offset, len], interpreter);
75    let len = as_usize_or_fail!(interpreter, len);
76    let mut output = Bytes::default();
78    if len != 0 {
79        let offset = as_usize_or_fail!(interpreter, offset);
80        resize_memory!(interpreter, offset, len);
81        output = interpreter.memory.slice_len(offset, len).to_vec().into()
82    }
83
84    interpreter
85        .bytecode
86        .set_action(InterpreterAction::new_return(
87            instruction_result,
88            output,
89            interpreter.gas,
90        ));
91}
92
93pub fn ret<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
97    return_inner(context.interpreter, InstructionResult::Return);
98}
99
100pub fn revert<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
102    check!(context.interpreter, BYZANTIUM);
103    return_inner(context.interpreter, InstructionResult::Revert);
104}
105
106pub fn stop<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
108    context.interpreter.halt(InstructionResult::Stop);
109}
110
111pub fn invalid<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
113    context.interpreter.halt(InstructionResult::InvalidFEOpcode);
114}
115
116pub fn unknown<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
118    context.interpreter.halt(InstructionResult::OpcodeNotFound);
119}