|
1 | 1 | import vyper.codegen.events as events |
2 | 2 | import vyper.utils as util |
3 | 3 | from vyper import ast as vy_ast |
| 4 | +from vyper.codegen.abi_encoder import abi_encode |
4 | 5 | from vyper.codegen.context import Constancy, Context |
5 | 6 | from vyper.codegen.core import ( |
6 | 7 | LOAD, |
|
9 | 10 | clamp_le, |
10 | 11 | get_dyn_array_count, |
11 | 12 | get_element_ptr, |
12 | | - make_byte_array_copier, |
| 13 | + get_type_for_exact_size, |
13 | 14 | make_setter, |
14 | | - zero_pad, |
| 15 | + wrap_value_for_external_return, |
15 | 16 | ) |
16 | 17 | from vyper.codegen.expr import Expr |
17 | 18 | from vyper.codegen.return_ import make_return_stmt |
18 | 19 | from vyper.evm.address_space import MEMORY, STORAGE |
19 | | -from vyper.exceptions import ( |
20 | | - CodegenPanic, |
21 | | - CompilerPanic, |
22 | | - StructureException, |
23 | | - TypeCheckFailure, |
24 | | - tag_exceptions, |
25 | | -) |
| 20 | +from vyper.exceptions import CodegenPanic, StructureException, TypeCheckFailure, tag_exceptions |
26 | 21 | from vyper.semantics.types import DArrayT |
27 | 22 | from vyper.semantics.types.shortcuts import UINT256_T |
28 | 23 |
|
@@ -132,39 +127,26 @@ def _assert_reason(self, test_expr, msg): |
132 | 127 | finally: |
133 | 128 | self.context.constancy = tmp |
134 | 129 |
|
135 | | - # TODO this is probably useful in codegen.core |
136 | | - # compare with eval_seq. |
137 | | - def _get_last(ir): |
138 | | - if len(ir.args) == 0: |
139 | | - return ir.value |
140 | | - return _get_last(ir.args[-1]) |
141 | | - |
142 | | - # TODO maybe use ensure_in_memory |
143 | | - if msg_ir.location != MEMORY: |
144 | | - buf = self.context.new_internal_variable(msg_ir.typ) |
145 | | - instantiate_msg = make_byte_array_copier(buf, msg_ir) |
146 | | - else: |
147 | | - buf = _get_last(msg_ir) |
148 | | - if not isinstance(buf, int): # pragma: nocover |
149 | | - raise CompilerPanic(f"invalid bytestring {buf}\n{self}") |
150 | | - instantiate_msg = msg_ir |
| 130 | + msg_ir = wrap_value_for_external_return(msg_ir) |
| 131 | + bufsz = 64 + msg_ir.typ.memory_bytes_required |
| 132 | + buf = self.context.new_internal_variable(get_type_for_exact_size(bufsz)) |
151 | 133 |
|
152 | 134 | # offset of bytes in (bytes,) |
153 | 135 | method_id = util.method_id_int("Error(string)") |
154 | 136 |
|
155 | | - # abi encode method_id + bytestring |
156 | | - assert buf >= 36, "invalid buffer" |
157 | | - # we don't mind overwriting other memory because we are |
158 | | - # getting out of here anyway. |
159 | | - _runtime_length = ["mload", buf] |
160 | | - revert_seq = [ |
161 | | - "seq", |
162 | | - instantiate_msg, |
163 | | - zero_pad(buf), |
164 | | - ["mstore", buf - 64, method_id], |
165 | | - ["mstore", buf - 32, 0x20], |
166 | | - ["revert", buf - 36, ["add", 4 + 32 + 32, ["ceil32", _runtime_length]]], |
167 | | - ] |
| 137 | + # abi encode method_id + bytestring to `buf+32`, then |
| 138 | + # write method_id to `buf` and get out of here |
| 139 | + payload_buf = buf + 32 |
| 140 | + bufsz -= 32 # reduce buffer by size of `method_id` slot |
| 141 | + encoded_length = abi_encode(payload_buf, msg_ir, self.context, bufsz, returns_len=True) |
| 142 | + with encoded_length.cache_when_complex("encoded_len") as (b1, encoded_length): |
| 143 | + revert_seq = [ |
| 144 | + "seq", |
| 145 | + ["mstore", buf, method_id], |
| 146 | + ["revert", buf + 28, ["add", 4, encoded_length]], |
| 147 | + ] |
| 148 | + revert_seq = b1.resolve(revert_seq) |
| 149 | + |
168 | 150 | if is_raise: |
169 | 151 | ir_node = revert_seq |
170 | 152 | else: |
|
0 commit comments