From 6bbd151a972329744e99523062fed15daed38edc Mon Sep 17 00:00:00 2001 From: Harry Kalogirou Date: Sat, 30 Dec 2023 19:02:51 +0200 Subject: [PATCH 01/10] Legendary bb output mode resurection --- vyper/compiler/__init__.py | 2 ++ vyper/compiler/output.py | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/vyper/compiler/__init__.py b/vyper/compiler/__init__.py index 0f7d7a8014..30354707f9 100644 --- a/vyper/compiler/__init__.py +++ b/vyper/compiler/__init__.py @@ -23,6 +23,8 @@ # requires ir_node "external_interface": output.build_external_interface_output, "interface": output.build_interface_output, + "bb": output.build_bb_output, + "bb_runtime": output.build_bb_runtime_output, "ir": output.build_ir_output, "ir_runtime": output.build_ir_runtime_output, "ir_dict": output.build_ir_dict_output, diff --git a/vyper/compiler/output.py b/vyper/compiler/output.py index 8ccf6abee1..b4f22ba843 100644 --- a/vyper/compiler/output.py +++ b/vyper/compiler/output.py @@ -84,6 +84,16 @@ def build_interface_output(compiler_data: CompilerData) -> str: return out +def build_bb_output(compiler_data: CompilerData) -> IRnode: + compiler_data.experimental_codegen = True + return compiler_data.ir_nodes + + +def build_bb_runtime_output(compiler_data: CompilerData) -> IRnode: + compiler_data.experimental_codegen = True + return compiler_data.ir_runtime + + def build_ir_output(compiler_data: CompilerData) -> IRnode: if compiler_data.show_gas_estimates: IRnode.repr_show_gas = True From 3e4b562fd0a0096e0c69ad02438bc599a220494c Mon Sep 17 00:00:00 2001 From: Harry Kalogirou Date: Sun, 31 Dec 2023 19:26:59 +0200 Subject: [PATCH 02/10] disable specific outputs for experimental codegen --- tests/conftest.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 51b4b4459a..e33b1bb1e0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -281,15 +281,26 @@ def ir_compiler(ir, *args, **kwargs): def _get_contract( - w3, source_code, optimize, *args, override_opt_level=None, input_bundle=None, **kwargs + w3, + source_code, + optimize, + *args, + override_opt_level=None, + input_bundle=None, + experimental_codegen=False, + **kwargs, ): settings = Settings() settings.evm_version = kwargs.pop("evm_version", None) settings.optimize = override_opt_level or optimize + output_formats = list(compiler.OUTPUT_FORMATS.keys()) + if experimental_codegen is False: + output_formats.remove("bb") + output_formats.remove("bb_runtime") out = compiler.compile_code( source_code, # test that all output formats can get generated - output_formats=list(compiler.OUTPUT_FORMATS.keys()), + output_formats=output_formats, settings=settings, input_bundle=input_bundle, show_gas_estimates=True, # Enable gas estimates for testing @@ -355,13 +366,19 @@ def get_contract_module(source_code, *args, **kwargs): return get_contract_module -def _deploy_blueprint_for(w3, source_code, optimize, initcode_prefix=b"", **kwargs): +def _deploy_blueprint_for( + w3, source_code, optimize, initcode_prefix=b"", experimental_codegen=False, **kwargs +): settings = Settings() settings.evm_version = kwargs.pop("evm_version", None) settings.optimize = optimize + output_formats = list(compiler.OUTPUT_FORMATS.keys()) + if experimental_codegen is False: + output_formats.remove("bb") + output_formats.remove("bb_runtime") out = compiler.compile_code( source_code, - output_formats=list(compiler.OUTPUT_FORMATS.keys()), + output_formats=output_formats, settings=settings, show_gas_estimates=True, # Enable gas estimates for testing ) From bfece8b0ff8b0bcfe5aec42929a963adec522661 Mon Sep 17 00:00:00 2001 From: Harry Kalogirou Date: Sun, 31 Dec 2023 20:20:48 +0200 Subject: [PATCH 03/10] Remove venom outputs from test_compile_json --- .../unit/cli/vyper_json/test_compile_json.py | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/tests/unit/cli/vyper_json/test_compile_json.py b/tests/unit/cli/vyper_json/test_compile_json.py index a50946ba21..3abfca837e 100644 --- a/tests/unit/cli/vyper_json/test_compile_json.py +++ b/tests/unit/cli/vyper_json/test_compile_json.py @@ -113,18 +113,32 @@ def test_keyerror_becomes_jsonerror(input_json): def test_compile_json(input_json, input_bundle): foo_input = input_bundle.load_file("contracts/foo.vy") + # remove bb and bb_runtime from output formats + # because they require venom (experimental) + output_formats = OUTPUT_FORMATS.copy() + del output_formats["bb"] + del output_formats["bb_runtime"] foo = compile_from_file_input( - foo_input, output_formats=OUTPUT_FORMATS, input_bundle=input_bundle + foo_input, + output_formats=output_formats, + input_bundle=input_bundle, + experimental_codegen=False, ) library_input = input_bundle.load_file("contracts/library.vy") library = compile_from_file_input( - library_input, output_formats=OUTPUT_FORMATS, input_bundle=input_bundle + library_input, + output_formats=output_formats, + input_bundle=input_bundle, + experimental_codegen=False, ) bar_input = input_bundle.load_file("contracts/bar.vy") bar = compile_from_file_input( - bar_input, output_formats=OUTPUT_FORMATS, input_bundle=input_bundle + bar_input, + output_formats=output_formats, + input_bundle=input_bundle, + experimental_codegen=False, ) compile_code_results = { From 88b4830d0f00f37512e7964d09cf6300d2ff4075 Mon Sep 17 00:00:00 2001 From: Harry Kalogirou Date: Sun, 31 Dec 2023 20:31:26 +0200 Subject: [PATCH 04/10] Add experimental codegen flag --- vyper/compiler/phases.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vyper/compiler/phases.py b/vyper/compiler/phases.py index 850adcfea3..76b88d241b 100644 --- a/vyper/compiler/phases.py +++ b/vyper/compiler/phases.py @@ -71,6 +71,8 @@ class CompilerData: Runtime bytecode """ + experimental_codegen: bool = False + def __init__( self, file_input: FileInput | str, From 232e29ed4da3d35aec7af3c7d66fe788d27fef98 Mon Sep 17 00:00:00 2001 From: Harry Kalogirou Date: Wed, 3 Jan 2024 12:27:37 +0200 Subject: [PATCH 05/10] Refactor output format handling in _get_contract and _deploy_blueprint_for functions --- tests/conftest.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index e33b1bb1e0..38550c472f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -280,6 +280,18 @@ def ir_compiler(ir, *args, **kwargs): return ir_compiler +def _get_output_formats(experimental_codegen): + """ + Returns a list of output formats supported. If not running the experimental + codegen path, the bb and bb_runtime formats are removed. + """ + output_formats = list(compiler.OUTPUT_FORMATS.keys()) + if experimental_codegen is False: + output_formats.remove("bb") + output_formats.remove("bb_runtime") + return output_formats + + def _get_contract( w3, source_code, @@ -293,14 +305,10 @@ def _get_contract( settings = Settings() settings.evm_version = kwargs.pop("evm_version", None) settings.optimize = override_opt_level or optimize - output_formats = list(compiler.OUTPUT_FORMATS.keys()) - if experimental_codegen is False: - output_formats.remove("bb") - output_formats.remove("bb_runtime") out = compiler.compile_code( source_code, # test that all output formats can get generated - output_formats=output_formats, + output_formats=_get_output_formats(experimental_codegen), settings=settings, input_bundle=input_bundle, show_gas_estimates=True, # Enable gas estimates for testing @@ -372,13 +380,9 @@ def _deploy_blueprint_for( settings = Settings() settings.evm_version = kwargs.pop("evm_version", None) settings.optimize = optimize - output_formats = list(compiler.OUTPUT_FORMATS.keys()) - if experimental_codegen is False: - output_formats.remove("bb") - output_formats.remove("bb_runtime") out = compiler.compile_code( source_code, - output_formats=output_formats, + output_formats=_get_output_formats(experimental_codegen), settings=settings, show_gas_estimates=True, # Enable gas estimates for testing ) From 408ff31929691e4228a2520a9861e5c42962434b Mon Sep 17 00:00:00 2001 From: Harry Kalogirou Date: Wed, 3 Jan 2024 12:30:33 +0200 Subject: [PATCH 06/10] Add experimental codegen option to compile_from_file_input function --- vyper/compiler/__init__.py | 4 ++++ vyper/compiler/phases.py | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/vyper/compiler/__init__.py b/vyper/compiler/__init__.py index 30354707f9..d7f5fc3bfb 100644 --- a/vyper/compiler/__init__.py +++ b/vyper/compiler/__init__.py @@ -57,6 +57,7 @@ def compile_from_file_input( no_bytecode_metadata: bool = False, show_gas_estimates: bool = False, exc_handler: Optional[Callable] = None, + experimental_codegen: bool = False, ) -> dict: """ Main entry point into the compiler. @@ -86,6 +87,8 @@ def compile_from_file_input( two arguments - the name of the contract, and the exception that was raised no_bytecode_metadata: bool, optional Do not add metadata to bytecode. Defaults to False + experimental_codegen: bool + Use experimental codegen. Defaults to False Returns ------- @@ -110,6 +113,7 @@ def compile_from_file_input( storage_layout_override, show_gas_estimates, no_bytecode_metadata, + experimental_codegen, ) ret = {} diff --git a/vyper/compiler/phases.py b/vyper/compiler/phases.py index 76b88d241b..e779af26ce 100644 --- a/vyper/compiler/phases.py +++ b/vyper/compiler/phases.py @@ -71,8 +71,6 @@ class CompilerData: Runtime bytecode """ - experimental_codegen: bool = False - def __init__( self, file_input: FileInput | str, @@ -81,6 +79,7 @@ def __init__( storage_layout: StorageLayout = None, show_gas_estimates: bool = False, no_bytecode_metadata: bool = False, + experimental_codegen: bool = False, ) -> None: """ Initialization method. @@ -114,6 +113,7 @@ def __init__( self.no_bytecode_metadata = no_bytecode_metadata self.settings = settings or Settings() self.input_bundle = input_bundle or FilesystemInputBundle([Path(".")]) + self.experimental_codegen = experimental_codegen _ = self._generate_ast # force settings to be calculated From e1c53487e21ae8beb03122549b91312f8a73f6f7 Mon Sep 17 00:00:00 2001 From: Harry Kalogirou Date: Wed, 3 Jan 2024 13:37:47 +0200 Subject: [PATCH 07/10] Bring back bb output --- vyper/compiler/output.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vyper/compiler/output.py b/vyper/compiler/output.py index b4f22ba843..2ce8a29466 100644 --- a/vyper/compiler/output.py +++ b/vyper/compiler/output.py @@ -86,12 +86,12 @@ def build_interface_output(compiler_data: CompilerData) -> str: def build_bb_output(compiler_data: CompilerData) -> IRnode: compiler_data.experimental_codegen = True - return compiler_data.ir_nodes + return compiler_data.venom_functions[0] def build_bb_runtime_output(compiler_data: CompilerData) -> IRnode: compiler_data.experimental_codegen = True - return compiler_data.ir_runtime + return compiler_data.venom_functions[1] def build_ir_output(compiler_data: CompilerData) -> IRnode: From ea77d7c8cf89a823b2d8ca07fd3a532b81df56a7 Mon Sep 17 00:00:00 2001 From: Harry Kalogirou Date: Wed, 3 Jan 2024 17:06:03 +0200 Subject: [PATCH 08/10] Remove direct experimental_codegen --- tests/conftest.py | 23 +++++++------------ .../unit/cli/vyper_json/test_compile_json.py | 15 +++--------- vyper/compiler/__init__.py | 2 -- vyper/compiler/output.py | 2 -- vyper/compiler/phases.py | 10 ++------ 5 files changed, 13 insertions(+), 39 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 38550c472f..f0e29331f1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -280,18 +280,6 @@ def ir_compiler(ir, *args, **kwargs): return ir_compiler -def _get_output_formats(experimental_codegen): - """ - Returns a list of output formats supported. If not running the experimental - codegen path, the bb and bb_runtime formats are removed. - """ - output_formats = list(compiler.OUTPUT_FORMATS.keys()) - if experimental_codegen is False: - output_formats.remove("bb") - output_formats.remove("bb_runtime") - return output_formats - - def _get_contract( w3, source_code, @@ -299,16 +287,18 @@ def _get_contract( *args, override_opt_level=None, input_bundle=None, - experimental_codegen=False, **kwargs, ): settings = Settings() settings.evm_version = kwargs.pop("evm_version", None) settings.optimize = override_opt_level or optimize + output_formats = compiler.OUTPUT_FORMATS.copy() + del output_formats["bb"] + del output_formats["bb_runtime"] out = compiler.compile_code( source_code, # test that all output formats can get generated - output_formats=_get_output_formats(experimental_codegen), + output_formats=output_formats, settings=settings, input_bundle=input_bundle, show_gas_estimates=True, # Enable gas estimates for testing @@ -380,9 +370,12 @@ def _deploy_blueprint_for( settings = Settings() settings.evm_version = kwargs.pop("evm_version", None) settings.optimize = optimize + output_formats = compiler.OUTPUT_FORMATS.copy() + del output_formats["bb"] + del output_formats["bb_runtime"] out = compiler.compile_code( source_code, - output_formats=_get_output_formats(experimental_codegen), + output_formats=output_formats, settings=settings, show_gas_estimates=True, # Enable gas estimates for testing ) diff --git a/tests/unit/cli/vyper_json/test_compile_json.py b/tests/unit/cli/vyper_json/test_compile_json.py index 3abfca837e..c805e2b5b1 100644 --- a/tests/unit/cli/vyper_json/test_compile_json.py +++ b/tests/unit/cli/vyper_json/test_compile_json.py @@ -119,26 +119,17 @@ def test_compile_json(input_json, input_bundle): del output_formats["bb"] del output_formats["bb_runtime"] foo = compile_from_file_input( - foo_input, - output_formats=output_formats, - input_bundle=input_bundle, - experimental_codegen=False, + foo_input, output_formats=output_formats, input_bundle=input_bundle ) library_input = input_bundle.load_file("contracts/library.vy") library = compile_from_file_input( - library_input, - output_formats=output_formats, - input_bundle=input_bundle, - experimental_codegen=False, + library_input, output_formats=output_formats, input_bundle=input_bundle ) bar_input = input_bundle.load_file("contracts/bar.vy") bar = compile_from_file_input( - bar_input, - output_formats=output_formats, - input_bundle=input_bundle, - experimental_codegen=False, + bar_input, output_formats=output_formats, input_bundle=input_bundle ) compile_code_results = { diff --git a/vyper/compiler/__init__.py b/vyper/compiler/__init__.py index d7f5fc3bfb..9297f9e3c3 100644 --- a/vyper/compiler/__init__.py +++ b/vyper/compiler/__init__.py @@ -57,7 +57,6 @@ def compile_from_file_input( no_bytecode_metadata: bool = False, show_gas_estimates: bool = False, exc_handler: Optional[Callable] = None, - experimental_codegen: bool = False, ) -> dict: """ Main entry point into the compiler. @@ -113,7 +112,6 @@ def compile_from_file_input( storage_layout_override, show_gas_estimates, no_bytecode_metadata, - experimental_codegen, ) ret = {} diff --git a/vyper/compiler/output.py b/vyper/compiler/output.py index 2ce8a29466..5e11a20139 100644 --- a/vyper/compiler/output.py +++ b/vyper/compiler/output.py @@ -85,12 +85,10 @@ def build_interface_output(compiler_data: CompilerData) -> str: def build_bb_output(compiler_data: CompilerData) -> IRnode: - compiler_data.experimental_codegen = True return compiler_data.venom_functions[0] def build_bb_runtime_output(compiler_data: CompilerData) -> IRnode: - compiler_data.experimental_codegen = True return compiler_data.venom_functions[1] diff --git a/vyper/compiler/phases.py b/vyper/compiler/phases.py index e779af26ce..ba6ccbda20 100644 --- a/vyper/compiler/phases.py +++ b/vyper/compiler/phases.py @@ -79,7 +79,6 @@ def __init__( storage_layout: StorageLayout = None, show_gas_estimates: bool = False, no_bytecode_metadata: bool = False, - experimental_codegen: bool = False, ) -> None: """ Initialization method. @@ -113,7 +112,6 @@ def __init__( self.no_bytecode_metadata = no_bytecode_metadata self.settings = settings or Settings() self.input_bundle = input_bundle or FilesystemInputBundle([Path(".")]) - self.experimental_codegen = experimental_codegen _ = self._generate_ast # force settings to be calculated @@ -176,9 +174,7 @@ def global_ctx(self) -> ModuleT: @cached_property def _ir_output(self): # fetch both deployment and runtime IR - return generate_ir_nodes( - self.global_ctx, self.settings.optimize, self.settings.experimental_codegen - ) + return generate_ir_nodes(self.global_ctx, self.settings.optimize) @property def ir_nodes(self) -> IRnode: @@ -274,9 +270,7 @@ def generate_annotated_ast( return vyper_module, symbol_tables -def generate_ir_nodes( - global_ctx: ModuleT, optimize: OptimizationLevel, experimental_codegen: bool -) -> tuple[IRnode, IRnode]: +def generate_ir_nodes(global_ctx: ModuleT, optimize: OptimizationLevel) -> tuple[IRnode, IRnode]: """ Generate the intermediate representation (IR) from the contextualized AST. From 8ea6d3449c570a902668cb088e84f075e6e9bbc0 Mon Sep 17 00:00:00 2001 From: Harry Kalogirou Date: Wed, 3 Jan 2024 17:17:42 +0200 Subject: [PATCH 09/10] lint --- tests/conftest.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index f0e29331f1..906d90ee3e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -281,13 +281,7 @@ def ir_compiler(ir, *args, **kwargs): def _get_contract( - w3, - source_code, - optimize, - *args, - override_opt_level=None, - input_bundle=None, - **kwargs, + w3, source_code, optimize, *args, override_opt_level=None, input_bundle=None, **kwargs ): settings = Settings() settings.evm_version = kwargs.pop("evm_version", None) From e142ae77d95f713aebdf805c1a1b82f7f1dfba17 Mon Sep 17 00:00:00 2001 From: Harry Kalogirou Date: Mon, 8 Jan 2024 11:25:58 +0200 Subject: [PATCH 10/10] output_formats fixture --- tests/conftest.py | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 906d90ee3e..e673f17b35 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -58,6 +58,14 @@ def pytest_addoption(parser): parser.addoption("--enable-compiler-debug-mode", action="store_true") +@pytest.fixture(scope="module") +def output_formats(): + output_formats = compiler.OUTPUT_FORMATS.copy() + del output_formats["bb"] + del output_formats["bb_runtime"] + return output_formats + + @pytest.fixture(scope="module") def optimize(pytestconfig): flag = pytestconfig.getoption("optimize") @@ -281,14 +289,18 @@ def ir_compiler(ir, *args, **kwargs): def _get_contract( - w3, source_code, optimize, *args, override_opt_level=None, input_bundle=None, **kwargs + w3, + source_code, + optimize, + output_formats, + *args, + override_opt_level=None, + input_bundle=None, + **kwargs, ): settings = Settings() settings.evm_version = kwargs.pop("evm_version", None) settings.optimize = override_opt_level or optimize - output_formats = compiler.OUTPUT_FORMATS.copy() - del output_formats["bb"] - del output_formats["bb_runtime"] out = compiler.compile_code( source_code, # test that all output formats can get generated @@ -312,17 +324,17 @@ def _get_contract( @pytest.fixture(scope="module") -def get_contract(w3, optimize): +def get_contract(w3, optimize, output_formats): def fn(source_code, *args, **kwargs): - return _get_contract(w3, source_code, optimize, *args, **kwargs) + return _get_contract(w3, source_code, optimize, output_formats, *args, **kwargs) return fn @pytest.fixture -def get_contract_with_gas_estimation(tester, w3, optimize): +def get_contract_with_gas_estimation(tester, w3, optimize, output_formats): def get_contract_with_gas_estimation(source_code, *args, **kwargs): - contract = _get_contract(w3, source_code, optimize, *args, **kwargs) + contract = _get_contract(w3, source_code, optimize, output_formats, *args, **kwargs) for abi_ in contract._classic_contract.functions.abi: if abi_["type"] == "function": set_decorator_to_contract_function(w3, tester, contract, source_code, abi_["name"]) @@ -332,15 +344,15 @@ def get_contract_with_gas_estimation(source_code, *args, **kwargs): @pytest.fixture -def get_contract_with_gas_estimation_for_constants(w3, optimize): +def get_contract_with_gas_estimation_for_constants(w3, optimize, output_formats): def get_contract_with_gas_estimation_for_constants(source_code, *args, **kwargs): - return _get_contract(w3, source_code, optimize, *args, **kwargs) + return _get_contract(w3, source_code, optimize, output_formats, *args, **kwargs) return get_contract_with_gas_estimation_for_constants @pytest.fixture(scope="module") -def get_contract_module(optimize): +def get_contract_module(optimize, output_formats): """ This fixture is used for Hypothesis tests to ensure that the same contract is called over multiple runs of the test. @@ -353,20 +365,15 @@ def get_contract_module(optimize): w3.eth.set_gas_price_strategy(zero_gas_price_strategy) def get_contract_module(source_code, *args, **kwargs): - return _get_contract(w3, source_code, optimize, *args, **kwargs) + return _get_contract(w3, source_code, optimize, output_formats, *args, **kwargs) return get_contract_module -def _deploy_blueprint_for( - w3, source_code, optimize, initcode_prefix=b"", experimental_codegen=False, **kwargs -): +def _deploy_blueprint_for(w3, source_code, optimize, output_formats, initcode_prefix=b"", **kwargs): settings = Settings() settings.evm_version = kwargs.pop("evm_version", None) settings.optimize = optimize - output_formats = compiler.OUTPUT_FORMATS.copy() - del output_formats["bb"] - del output_formats["bb_runtime"] out = compiler.compile_code( source_code, output_formats=output_formats, @@ -402,9 +409,9 @@ def factory(address): @pytest.fixture(scope="module") -def deploy_blueprint_for(w3, optimize): +def deploy_blueprint_for(w3, optimize, output_formats): def deploy_blueprint_for(source_code, *args, **kwargs): - return _deploy_blueprint_for(w3, source_code, optimize, *args, **kwargs) + return _deploy_blueprint_for(w3, source_code, optimize, output_formats, *args, **kwargs) return deploy_blueprint_for