diff --git a/boa/vyper/compiler_utils.py b/boa/vyper/compiler_utils.py index 4a9e905b..bfd1120b 100644 --- a/boa/vyper/compiler_utils.py +++ b/boa/vyper/compiler_utils.py @@ -20,6 +20,7 @@ def compile_vyper_function(vyper_function, contract): contract. This is useful for vyper `eval` and internal functions, where the runtime bytecode must be changed to add more runtime functionality (such as eval, and calling internal functions) + (performance note: this function is very very slow!) """ compiler_data = contract.compiler_data @@ -38,8 +39,10 @@ def compile_vyper_function(vyper_function, contract): external_func_info = generate_ir_for_function(ast, global_ctx, False) ir = external_func_info.common_ir - base_signature = func_t.abi_signature_for_kwargs([]) - ir = IRnode.from_list(["with", _METHOD_ID_VAR, method_id_int(base_signature), ir]) + ir = ["seq", ["goto", func_t._ir_info.external_function_base_entry_label], ir] + + # use a dummy method id + ir = IRnode.from_list(["with", _METHOD_ID_VAR, 0, ir]) ir = optimizer.optimize(ir) # extend IR with contract's unoptimized assembly to avoid stripping @@ -54,7 +57,9 @@ def compile_vyper_function(vyper_function, contract): # generate the IR executor # first mush it with the rest of the IR in the contract to ensure # all labels are present - ir = IRnode.from_list(["seq", ir, contract.compiler_data.ir_runtime]) + # (use unoptimized IR as ir_executor can't handle optimized selector tables) + _, contract_runtime = contract.unoptimized_ir + ir = IRnode.from_list(["seq", ir, contract_runtime]) # now compile. ir_executor = executor_from_ir(ir, compiler_data) diff --git a/boa/vyper/contract.py b/boa/vyper/contract.py index 2536eeb6..448c0b8f 100644 --- a/boa/vyper/contract.py +++ b/boa/vyper/contract.py @@ -821,9 +821,13 @@ def unoptimized_bytecode(self): return s + self.data_section @cached_property - def ir_executor(self): + def unoptimized_ir(self): with anchor_opt_level(OptimizationLevel.NONE): - _, ir_runtime = generate_ir_for_module(self.compiler_data.global_ctx) + return generate_ir_for_module(self.compiler_data.global_ctx) + + @cached_property + def ir_executor(self): + _, ir_runtime = self.unoptimized_ir return executor_from_ir(ir_runtime, self.compiler_data) @contextlib.contextmanager