Skip to content

Subroutines and Static Jumps for the EVM #184

@gcolvin

Description

@gcolvin
eip: 2315
title: Simple Subroutines for the EVM
status: Draft
type: Standards Track
category: Core
author: Greg Colvin
discussions-to: https://github.com/ethereum/EIPs/issues/2315
created: 2019-10-17

Simple Summary

Subroutines.

Abstract

This proposal introduces two opcodes to support subroutines: JUMPSUB and RETSUB.

Motivation

The EVM does not provide subroutines as a primitive. Instead, calls must be synthesized by fetching, adjusting and pushing the current program counter and jumping to the subroutine address; returns must be synthesized by getting the return address to the top of stack and jumping back to it.

Specification

Proposal

JUMPSUB

Jumps to the address on top of the stack. This must be a JUMPDEST.

RETSUB

Returns to the most recently executed JUMPSUB instruction.

Backwards Compatibility

These changes do not affect existing VM code..

Rationale

This is the smallest possible change that provides native subroutines without breaking backwards compatibility. It does not enforce validity like #615, but code that
_ pushes constants argument before every JUMP and JUMPI and
_ ensures that the data stack is the same size at the end of every basic block
is valid and will meet all of the #615 safety conditions. In particular, the Yellow paper defines five exceptional halting states. Valid code cannot violate states 3, 4, or 5.

1 Insufficient gas

2 More than 1024 stack items

3 Insufficient stack items

4 Invalid jump destination

5 Invalid instruction

Implementation

Jumps to and returns from subroutines are described here in terms of

  • The EVM data stack, (as defined in the Yellow Paper).
  • A return stack of program counters.
  • The program counter PC which is the byte offset of the currently executing instruction.

Execution of EVM bytecode begins with one value on the return stack—code_size. Executing the virtual byte of 0 at this offset causes an EVM to stop. Thus executing a RETSUB with no prior JUMPSUB executes a STOP. A STOP or RETURN ends the execution of a subroutine.

Semantics are defined by the following pseudo-C code.

   uint256 data_stack[1024];
   uint16 return_stack[1024] = {code_size};
   byte code[code_size];

   while (PC < code_size) {
      switch opcode = code[PC];
      case jumpsub:
         push(return_stack,PC);
         PC = pop(data_stack);
         break;
      cast retsub:
         PC = pop(return_stack);
         break;
      ...
      case 0:
         stop();
      default:
         invalid_instruction();
      }
      ++PC;
   }

Costs & Codes

We suggest the cost of JUMPSUB should be low, and RETSUB should be verylow.
Measurement will tell.

We suggest the following opcodes:

0xbe JUMPSUB
0xbf RETSUB

Copyright and related rights waived via CC0.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions