Skip to content

refactor[codegen]: split codegen packages#4925

Open
charles-cooper wants to merge 27 commits into
vyperlang:masterfrom
charles-cooper:feat/venom-default
Open

refactor[codegen]: split codegen packages#4925
charles-cooper wants to merge 27 commits into
vyperlang:masterfrom
charles-cooper:feat/venom-default

Conversation

@charles-cooper

@charles-cooper charles-cooper commented Apr 21, 2026

Copy link
Copy Markdown
Member

co-authored by claude opus 4.6

What I did

Split the legacy IRnode codegen package from helpers shared with the direct Venom codegen pipeline.

This PR no longer changes the default codegen pipeline: legacy remains the default, and Venom remains opt-in via the existing experimental codegen setting and CLI/API flags.

How I did it

  1. Renamed vyper/codegen/vyper/codegen_legacy/ — legacy IRnode codegen remains isolated under the new package name, with imports updated across the codebase.

  2. Created vyper/codegen_shared/ — ABI helpers, safe arithmetic bounds, function metadata, and selector table utilities now live in a shared package used by both codegen pipelines.

  3. Decoupled Venom source tracking from IRnodeIRFunction no longer owns codegen source/error stacks; VenomBuilder does. IRInstruction.ast_source is typed as Optional[VyperNode], and vyper/venom/ no longer imports legacy codegen types.

How to verify it

# Legacy codegen remains the default
vyper contract.vy

# Venom remains opt-in
vyper --experimental-codegen contract.vy

# Focused checks
pytest tests/unit/compiler/test_default_settings.py
pytest tests/unit/cli/vyper_json/test_compile_json.py
pytest tests/functional/codegen/test_selector_table.py

Commit message

the legacy IRnode codegen and direct Venom codegen now share several
concepts, but the old vyper/codegen package mixed legacy-only IRnode
implementation details with helpers that both pipelines need. That made
shared code hard to identify and caused vyper/venom to depend on
legacy codegen types for source tracking.

split the legacy pipeline into vyper/codegen_legacy and move common
ABI, arithmetic, function metadata, and selector table helpers into
vyper/codegen_shared. The Venom pipeline imports those shared helpers
directly instead of reaching through legacy codegen.

also move source/error tracking ownership from IRFunction to
VenomBuilder, so source attribution remains a codegen concern and
IRInstruction.ast_source can hold the frontend VyperNode directly.

this is intentionally a refactor-only change: legacy codegen remains the
default pipeline and Venom remains opt-in via the existing experimental
codegen setting and CLI/API flags. The default-pipeline switch is left
for a follow-up PR.

Description for the changelog

Split legacy codegen into vyper/codegen_legacy and move shared helpers into vyper/codegen_shared. Venom remains opt-in.

Cute Animal Picture

Axolotl

Move source tracking (ast_source/error_msg stacks) from IRFunction to
VenomBuilder. IRInstruction.ast_source is now correctly typed as
Optional[VyperNode] instead of Optional[IRnode]. Builder passes source
info explicitly to append_instruction/insert_instruction instead of
IRBasicBlock reading it from IRFunction.

This removes the last dependency of vyper/venom/ on vyper/codegen/ir_node.
…codegen_shared

Rename vyper/codegen/ to vyper/codegen_legacy/ to make room for venom
as the default codegen. Extract shared utilities into vyper/codegen_shared/:

- abi_utils.py: is_tuple_like, needs_external_call_wrap,
  calculate_type_for_external_return, abi_encoding_matches_vyper,
  DYNAMIC_ARRAY_OVERHEAD
- arithmetic.py: calculate_largest_base, calculate_largest_power
- function_info.py: _FuncIRInfo, EntryPointInfo, init_ir_info
- jumptable_utils.py: selector dispatch utilities

codegen_venom now imports from codegen_shared instead of codegen_legacy.
All references to vyper.codegen updated to vyper.codegen_legacy.
Venom codegen is now the default. Use --legacy or pragma legacy to
use the old IRnode-based codegen. The --experimental-codegen and
--venom-experimental flags are deprecated (they still work but are
hidden from --help).

CI matrix updated: default tests use venom, legacy tests use --legacy.
Fuzzing runs on venom by default.
Support 'legacy: true' in the JSON settings, as a counterpart to
the CLI --legacy flag. When set, forces the legacy IRnode codegen.
…antics)

Settings.experimental_codegen -> Settings.legacy_codegen.
  True = legacy IRnode codegen, False (default) = Venom.

CLI: --legacy sets legacy_codegen=True.
  --experimental-codegen still works (deprecated, hidden).

Pragmas: pragma legacy -> legacy_codegen=True.
  pragma experimental-codegen still works (deprecated).

JSON API: legacyCodegen/legacy key supported.
  experimentalCodegen still works (inverted: True -> legacy_codegen=False).

All internal checks flipped: 'if experimental_codegen' -> 'if not legacy_codegen'.
Test fixture 'experimental_codegen' kept for compat (returns True=venom).
Comment thread vyper/builtins/_convert.py Fixed
from vyper.ast.validation import validate_call_args
from vyper.codegen.expr import Expr
from vyper.codegen.ir_node import IRnode
from vyper.codegen_legacy.expr import Expr
from vyper.codegen.abi_encoder import abi_encode
from vyper.codegen.context import Context
from vyper.codegen.core import (
from vyper.codegen_legacy.abi_encoder import abi_encode
Comment thread vyper/builtins/functions.py Outdated
Comment thread vyper/builtins/functions.py Outdated
Comment thread vyper/codegen_legacy/function_definitions/common.py Fixed

from vyper.codegen.core import bytes_data_ptr, ensure_in_memory, get_bytearray_length
from vyper.codegen.ir_node import IRnode
from vyper.codegen_legacy.core import bytes_data_ptr, ensure_in_memory, get_bytearray_length
from vyper import ast as vy_ast
from vyper.codegen.core import _freshname, eval_once_check, make_setter
from vyper.codegen.ir_node import IRnode
from vyper.codegen_legacy.core import _freshname, eval_once_check, make_setter

def ir_for_self_call(stmt_expr: vy_ast.Call, context):
from vyper.codegen.expr import Expr # TODO rethink this circular import
from vyper.codegen_legacy.expr import Expr # TODO rethink this circular import
Comment thread vyper/codegen_shared/function_info.py Fixed
@github-actions

github-actions Bot commented Apr 21, 2026

Copy link
Copy Markdown

📊 Bytecode Size Changes (venom)

No changes detected.

Full bytecode sizes

Contract legacy-O2 legacy-Os -O2 -O3 -Os
curvefi/amm/stableswap/meta_implementation/meta_implementation_v_700.vy 23610 22805 20801 19770 19330
curvefi/legacy/CurveStableSwapMetaNG.vy 24952 23578 20644 20025 19329
curvefi/amm/stableswap/implementation/implementation_v_700.vy 24962 23769 20467 19596 19048
curvefi/legacy/CurveStableSwapNG.vy 24473 23298 19860 19016 18497
curvefi/amm/tricryptoswap/implementation/implementation_v_200.vy 20724 19959 18018 17516 16959
yearnfi/VaultV3.vy 19972 19063 17017 15131 14477
curvefi/amm/twocryptoswap/implementation/implementation_v_210.vy 17634 16894 15685 15132 14648
curvefi/legacy/CurveCryptoSwap2.vy 18947 18382 15622 15068 14699
yearnfi/VaultV2.vy 16676 15763 13863 13405 12574
curvefi/amm/stableswap/factory/factory_v_100.vy 14558 13978 13250 11856 11829
curvefi/amm/stableswap/views/views_v_120.vy 12784 12368 10291 9734 9853
curvefi/gauge/child_gauge/implementation/implementation_v_110.vy 12338 11561 10270 9775 9182
curvefi/gauge/child_gauge/implementation/implementation_v_100.vy 12017 11249 9998 9502 8920
curvefi/amm/tricryptoswap/math/math_v_200.vy 11189 11126 9506 8143 8410
curvefi/legacy/CurveCryptoMathOptimized3.vy 11188 11125 9505 8143 8410
curvefi/gauge/child_gauge/implementation/implementation_v_020.vy 10665 9947 9013 8565 8028
curvefi/helpers/router/router_v_110.vy 6717 6717 7003 6376 6607
curvefi/amm/tricryptoswap/views/views_v_200.vy 7821 7776 6717 6465 6534
curvefi/registries/metaregistry/metaregistry_v_110.vy 7590 6732 6657 5894 5733
curvefi/helpers/stable_swap_meta_zap/stable_swap_meta_zap_v_100.vy 7302 7067 6540 6173 6275
curvefi/amm/twocryptoswap/views/views_v_200.vy 6991 6946 6274 6028 6091
curvefi/registries/metaregistry/registry_handlers/stableswap/handler_v_110.vy 6633 6259 5859 5094 5562
curvefi/amm/tricryptoswap/factory/factory_v_200.vy 5246 5021 5816 4849 4953
curvefi/amm/twocryptoswap/factory/factory_v_200.vy 5540 5252 5816 4579 4740
curvefi/amm/twocryptoswap/math/math_v_210.vy 6800 6800 5581 5107 5112
curvefi/gauge/child_gauge/factory/factory_v_201.vy 4844 4547 4266 4014 3780
yearnfi/VaultFactory.vy 3765 3617 3901 2453 2913
curvefi/registries/metaregistry/registry_handlers/tricryptoswap/handler_v_110.vy 4241 3939 3838 3547 3547
curvefi/registries/metaregistry/registry_handlers/twocryptoswap/handler_v_110.vy 4186 3884 3777 3417 3433
curvefi/gauge/child_gauge/factory/factory_v_100.vy 4183 3914 3694 3428 3213
curvefi/helpers/rate_provider/rate_provider_v_101.vy 3260 3260 2807 2465 2478
curvefi/registries/address_provider/address_provider_v_201.vy 2973 2782 2719 2575 2430
curvefi/amm/stableswap/math/math_v_100.vy 3067 3046 2598 2403 2423
curvefi/helpers/rate_provider/rate_provider_v_100.vy 2847 2841 2373 2066 2074
curvefi/helpers/deposit_and_stake_zap/deposit_and_stake_zap_v_100.vy 2322 2316 2123 1889 1921
curvefi/governance/relayer/taiko/relayer_v_001.vy 2068 2064 1647 1532 1565
curvefi/governance/relayer/polygon_cdk/relayer_v_101.vy 1556 1523 1454 1362 1363
curvefi/governance/relayer/arb_orbit/relayer_v_101.vy 1266 1262 1147 1081 1112
curvefi/governance/relayer/op_stack/relayer_v_101.vy 1186 1182 1086 1023 1051
curvefi/governance/relayer/not_rollup/relayer_v_100.vy 1168 1153 1075 1018 1030
curvefi/governance/vault/vault_v_100.vy 964 941 885 866 864
curvefi/governance/relayer/relayer_v_100.vy 496 496 467 462 467
curvefi/governance/agent/agent_v_100.vy 541 541 443 415 419
curvefi/governance/agent/agent_v_101.vy 541 541 443 415 419

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0498268e04

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread vyper/cli/vyper_json.py Outdated
Comment on lines +312 to +314
legacy_codegen = input_dict["settings"].get("legacyCodegen")
if legacy_codegen is None:
legacy_codegen = input_dict["settings"].get("legacy")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Wire legacyCodegen into venom output gating

This adds legacyCodegen/legacy parsing, but get_output_formats() still decides whether cfg/cfg_runtime are allowed using only deprecated venomExperimental/experimentalCodegen keys. As a result, JSON inputs like {"settings": {"legacyCodegen": false, "outputSelection": {"*": ["cfg_runtime"]}}} still fail with “experimentalCodegen not selected” even though venom is explicitly selected, making the new settings API internally inconsistent.

Useful? React with 👍 / 👎.

Module.py reads global _settings via _opt_none()/_opt_codesize(), but
generate_venom_runtime/deploy never anchored settings. This caused
AttributeError when _settings was None.
Tests for asm optimizer DCE and selector table stability assume legacy
codegen output but didn't specify legacy_codegen=True. Now that venom
is default, they need explicit opt-in. Also fix Black formatting in
pre_parser.py and test_liveness_simple_loop.py.
code, output_formats=["asm_runtime"], settings=Settings(optimize=OptimizationLevel.CODESIZE)
code,
output_formats=["asm_runtime"],
settings=Settings(optimize=OptimizationLevel.CODESIZE, legacy_codegen=True),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Does this test only work on the legacy codegen, and if so, why ?

Check all examples round trip
"""
if not compiler_settings.experimental_codegen:
if not compiler_settings.legacy_codegen:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
if not compiler_settings.legacy_codegen:
if compiler_settings.legacy_codegen:

At least to correspond to the text

Test vyper_sources round trip
"""
if not compiler_settings.experimental_codegen:
if not compiler_settings.legacy_codegen:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
if not compiler_settings.legacy_codegen:
if compiler_settings.legacy_codegen:

same as above

@pytest.mark.parametrize("code", codes)
def test_dead_code_eliminator(code):
c = CompilerData(code, settings=Settings(optimize=OptimizationLevel.NONE))
c = CompilerData(code, settings=Settings(optimize=OptimizationLevel.NONE, legacy_codegen=True))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why only legacy ?

"""

settings = Settings(experimental_codegen=True, optimize=OptimizationLevel.O3)
settings = Settings(legacy_codegen=False, optimize=OptimizationLevel.O3)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Default, so unneeded ?
(applies to others below)

Comment thread tests/conftest.py Outdated
)
parser.addoption("--enable-compiler-debug-mode", action="store_true")
parser.addoption("--experimental-codegen", action="store_true")
parser.addoption("--experimental-codegen", action="store_true", default=True)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should be removed/deprecated, no ?

@charles-cooper charles-cooper requested a review from harkal May 14, 2026 08:38
# Conflicts:
#	.github/workflows/test.yml
#	vyper/codegen/function_definitions/common.py
@github-actions

github-actions Bot commented May 14, 2026

Copy link
Copy Markdown

Gas Changes

No changes detected.

Summary

  • Total tests measured: 803
  • Changed: 0
  • Regressions (gas up): 0
  • Improvements (gas down): 0
  • New tests: 0
  • Deleted tests: 0
  • Newly failing: 0
  • Newly passing: 0

@harkal

harkal commented May 14, 2026

Copy link
Copy Markdown
Collaborator

is vyper/codegen_legacy/jumptable_utils.py still required?

@harkal

harkal commented May 14, 2026

Copy link
Copy Markdown
Collaborator

Stale docs/strings still recommend the deprecated flag vyper/codegen_venom/__init__.py, vyper/venom/README.md: "Enable via: vyper --experimental-codegen"

@harkal

harkal commented May 14, 2026

Copy link
Copy Markdown
Collaborator

vyper/cli/vyper_json.py has some errors for not specifing experimentalCodegen I guess not required?

@charles-cooper

Copy link
Copy Markdown
Member Author

related: #4862

@charles-cooper charles-cooper added this to the v0.5.0 milestone May 15, 2026
Comment thread tests/functional/builtins/codegen/test_convert.py Fixed
@charles-cooper charles-cooper modified the milestones: v0.5.0, v0.4.4 May 26, 2026
@charles-cooper

Copy link
Copy Markdown
Member Author

i think this should be split into two PRs, the refactor PR and making venom the default

# Conflicts:
#	tests/functional/builtins/codegen/test_convert.py
Comment thread vyper/builtins/_convert.py Outdated
@codecov

codecov Bot commented May 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.38754% with 22 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.94%. Comparing base (0cc5c4a) to head (e1d3b49).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
vyper/codegen_shared/arithmetic.py 75.00% 7 Missing and 3 partials ⚠️
vyper/codegen_shared/function_info.py 92.30% 3 Missing and 1 partial ⚠️
vyper/venom/basicblock.py 66.66% 2 Missing and 2 partials ⚠️
vyper/venom/builder.py 80.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4925      +/-   ##
==========================================
+ Coverage   92.92%   92.94%   +0.01%     
==========================================
  Files         188      191       +3     
  Lines       27818    27816       -2     
  Branches     4827     4827              
==========================================
+ Hits        25851    25854       +3     
+ Misses       1316     1311       -5     
  Partials      651      651              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e1d3b49f59

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread vyper/compiler/phases.py
from vyper.ast import natspec
from vyper.codegen import module
from vyper.codegen.ir_node import IRnode
from vyper.codegen_legacy import module

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Default to Venom when no codegen flag is set

For callers that do not pass --experimental-codegen or a pragma, CompilerData.settings still turns an unset experimental_codegen into False, and this renamed import keeps generate_ir_nodes() wired to codegen_legacy.module.generate_ir_for_module. As a result the default API/CLI path still produces vyper.codegen_legacy.ir_node.IRnode output and bytecode from the legacy pipeline; Venom is only used when explicitly opted in, so the new default codegen behavior is not actually enabled.

Useful? React with 👍 / 👎.

@charles-cooper charles-cooper changed the title feat[venom]: make venom the default codegen refactor[codegen]: split codegen packages May 30, 2026
@charles-cooper charles-cooper requested a review from Sporarum May 30, 2026 23:17
Comment thread vyper/ast/parse.py
self._source_code,
node.target.lineno,
node.target.col_offset,
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Did this sneak in from a different PR ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

b4145b7 this one but it seems like a diff viewing issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants