Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat[venom]: add effects to instructions #4264

Merged
7 changes: 7 additions & 0 deletions vyper/venom/basicblock.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import TYPE_CHECKING, Any, Iterator, Optional, Union

import vyper.venom.effects as effects
from vyper.codegen.ir_node import IRnode
from vyper.utils import OrderedSet

Expand Down Expand Up @@ -238,6 +239,12 @@ def is_volatile(self) -> bool:
def is_bb_terminator(self) -> bool:
return self.opcode in BB_TERMINATORS

def get_read_effects(self):
return effects.reads.get(self.opcode, effects.EMPTY)

def get_write_effects(self):
return effects.writes.get(self.opcode, effects.EMPTY)

def get_label_operands(self) -> Iterator[IRLabel]:
"""
Get all labels in instruction.
Expand Down
85 changes: 85 additions & 0 deletions vyper/venom/effects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
from enum import Flag, auto


class Effects(Flag):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

modeling code (e.g., for code copy) isn't useful?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not that useful, since it can't change during execution

Copy link
Member Author

@charles-cooper charles-cooper Oct 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(At least that I know of)

STORAGE = auto()
TRANSIENT = auto()
MEMORY = auto()
MSIZE = auto()
IMMUTABLES = auto()
RETURNDATA = auto()
LOG = auto()
BALANCE = auto()
EXTCODE = auto()


EMPTY = Effects(0)
ALL = ~EMPTY
STORAGE = Effects.STORAGE
TRANSIENT = Effects.TRANSIENT
MEMORY = Effects.MEMORY
MSIZE = Effects.MSIZE
IMMUTABLES = Effects.IMMUTABLES
RETURNDATA = Effects.RETURNDATA
LOG = Effects.LOG
BALANCE = Effects.BALANCE
EXTCODE = Effects.EXTCODE


_writes = {
"sstore": STORAGE,
"tstore": TRANSIENT,
"mstore": MEMORY,
"istore": IMMUTABLES,
"call": ALL ^ IMMUTABLES,
"delegatecall": ALL ^ IMMUTABLES,
"staticcall": MEMORY | RETURNDATA,
"create": ALL ^ (MEMORY | IMMUTABLES),
"create2": ALL ^ (MEMORY | IMMUTABLES),
"invoke": ALL, # could be smarter, look up the effects of the invoked function
"log": LOG,
"dloadbytes": MEMORY,
"returndatacopy": MEMORY,
"calldatacopy": MEMORY,
"codecopy": MEMORY,
"extcodecopy": MEMORY,
"mcopy": MEMORY,
}

_reads = {
"sload": STORAGE,
"tload": TRANSIENT,
"iload": IMMUTABLES,
"mload": MEMORY,
"mcopy": MEMORY,
"call": ALL,
"delegatecall": ALL,
"staticcall": ALL,
"create": ALL,
"create2": ALL,
"invoke": ALL,
"returndatasize": RETURNDATA,
"returndatacopy": RETURNDATA,
"balance": BALANCE,
"selfbalance": BALANCE,
"extcodecopy": EXTCODE,
"selfdestruct": BALANCE, # may modify code, but after the transaction
"log": MEMORY,
"revert": MEMORY,
"return": MEMORY,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return has an offset to memory, right? so in theory you might be forced to zero-extend the memory

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

applies to other opcodes as well

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we really care about zero extension? i think gas is an effect we don't need to preserve

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about msize?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm that's true. but return can't be reordered past other instructions anyways

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you have the same for eg mload

"sha3": MEMORY,
"msize": MSIZE,
}

reads = _reads.copy()
writes = _writes.copy()

for k, v in reads.items():
if MEMORY in v:
if k not in writes:
writes[k] = EMPTY
writes[k] |= MSIZE

for k, v in writes.items():
if MEMORY in v:
writes[k] |= MSIZE
Loading