Skip to content

Commit

Permalink
feat[ir]: add eval_once sanity fences to more builtins (#3835)
Browse files Browse the repository at this point in the history
some builtins with side effects didn't have the sanity fences, add them.
refactor `STORE()` to use `ensure_eval_once()`
  • Loading branch information
charles-cooper committed Mar 8, 2024
1 parent 541b2e7 commit 5825e12
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 23 deletions.
32 changes: 12 additions & 20 deletions vyper/builtins/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from vyper.codegen.core import (
STORE,
IRnode,
_freshname,
add_ofst,
bytes_data_ptr,
calculate_type_for_external_return,
Expand All @@ -21,8 +20,8 @@
clamp_nonzero,
copy_bytes,
dummy_node_for_type,
ensure_eval_once,
ensure_in_memory,
eval_once_check,
eval_seq,
get_bytearray_length,
get_type_for_exact_size,
Expand Down Expand Up @@ -1164,6 +1163,7 @@ def build_IR(self, expr, args, kwargs, context):
else:
call_op = ["call", gas, to, value, *common_call_args]

call_op = ensure_eval_once("raw_call_builtin", call_op)
call_ir += [call_op]
call_ir = b1.resolve(call_ir)

Expand Down Expand Up @@ -1220,9 +1220,8 @@ def build_IR(self, expr, args, kwargs, context):
to, value = args
gas = kwargs["gas"]
context.check_is_not_constant("send ether", expr)
return IRnode.from_list(
["assert", ["call", gas, to, value, 0, 0, 0, 0]], error_msg="send failed"
)
send_op = ensure_eval_once("send_builtin", ["call", gas, to, value, 0, 0, 0, 0])
return IRnode.from_list(["assert", send_op], error_msg="send failed")


class SelfDestruct(BuiltinFunctionT):
Expand All @@ -1240,9 +1239,7 @@ def build_IR(self, expr, args, kwargs, context):
self._warned = True

context.check_is_not_constant("selfdestruct", expr)
return IRnode.from_list(
["seq", eval_once_check(_freshname("selfdestruct")), ["selfdestruct", args[0]]]
)
return IRnode.from_list(ensure_eval_once("selfdestruct", ["selfdestruct", args[0]]))


class BlockHash(BuiltinFunctionT):
Expand Down Expand Up @@ -1308,27 +1305,24 @@ def build_IR(self, expr, args, kwargs, context):

data = args[1]

log_op = "log" + str(topics_length)

if data.typ == BYTES32_T:
placeholder = context.new_internal_variable(BYTES32_T)
log_ir = [log_op, placeholder, 32] + topics
return IRnode.from_list(
[
"seq",
# TODO use make_setter
["mstore", placeholder, unwrap_location(data)],
["log" + str(topics_length), placeholder, 32] + topics,
ensure_eval_once("raw_log", log_ir),
]
)

input_buf = ensure_in_memory(data, context)

return IRnode.from_list(
[
"with",
"_sub",
input_buf,
["log" + str(topics_length), ["add", "_sub", 32], ["mload", "_sub"], *topics],
]
)
log_ir = [log_op, ["add", "_sub", 32], ["mload", "_sub"], *topics]
return IRnode.from_list(["with", "_sub", input_buf, ensure_eval_once("raw_log", log_ir)])


class BitwiseAnd(BuiltinFunctionT):
Expand Down Expand Up @@ -1591,9 +1585,7 @@ def _create_ir(value, buf, length, salt, checked=True):
create_op = "create2"
args.append(salt)

ret = IRnode.from_list(
["seq", eval_once_check(_freshname("create_builtin")), [create_op, *args]]
)
ret = IRnode.from_list(ensure_eval_once("create_builtin", [create_op, *args]))

if not checked:
return ret
Expand Down
8 changes: 5 additions & 3 deletions vyper/codegen/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -653,22 +653,24 @@ def eval_once_check(name):
return IRnode.from_list(["unique_symbol", name])


def ensure_eval_once(name, irnode):
return ["seq", eval_once_check(_freshname(name)), irnode]


def STORE(ptr: IRnode, val: IRnode) -> IRnode:
if ptr.location is None: # pragma: nocover
raise CompilerPanic("cannot dereference non-pointer type")
op = ptr.location.store_op
if op is None: # pragma: nocover
raise CompilerPanic(f"unreachable {ptr.location}")

_check = _freshname(f"{op}_")

store = [op, ptr, val]
# don't use eval_once_check for memory, immutables because it interferes
# with optimizer
if ptr.location in (MEMORY, IMMUTABLES):
return IRnode.from_list(store)

return IRnode.from_list(["seq", eval_once_check(_check), store])
return IRnode.from_list(ensure_eval_once(_freshname(f"{op}_"), store))


# Unwrap location
Expand Down

0 comments on commit 5825e12

Please sign in to comment.