feat[venom]: add direct venom pipeline#4811
Draft
charles-cooper wants to merge 148 commits intovyperlang:masterfrom
Draft
feat[venom]: add direct venom pipeline#4811charles-cooper wants to merge 148 commits intovyperlang:masterfrom
charles-cooper wants to merge 148 commits intovyperlang:masterfrom
Conversation
Add vyper/venom/builder.py with VenomBuilder - a clean API wrapping IRBasicBlock.append_instruction() for explicit, type-safe IR emission. Includes block management, arithmetic/bitwise/comparison ops, memory/storage, control flow, internal/external calls, crypto, environment, and source tracking. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create new vyper/codegen_venom/ directory for direct AST-to-Venom code generation, bypassing legacy IRnode intermediate representation. - Add generate_venom_for_module() entry point returning (deploy_ctx, runtime_ctx) - Add VenomCodegenContext for tracking variables, scopes, and codegen state - Hook into CompilerData via _venom_direct property - Route venom_runtime/venom_deploytime through new path when experimental_codegen=True Currently emits minimal valid IR (just stop instruction). Foundation for subsequent tasks that will implement expression/statement lowering. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement codegen_venom/expr.py with literal expression lowering: - Int: direct integer value - Decimal: scaled by DECIMAL_DIVISOR (10^10) - Hex: addresses + bytesN (left-padded) - NameConstant: True/False to 1/0 - Bytes/HexBytes/Str: memory allocation with length + data chunks 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add arithmetic and bitwise operation lowering to Expr class: - Bitwise: and, or, xor (no overflow checks) - Shifts: shl, shr, sar (256-bit types only) - Arithmetic: safe_add/sub/mul/div/floordiv/mod/pow with overflow checks - Unary: not, invert, usub Overflow checks follow patterns from vyper/codegen/arithmetic.py: - 256-bit add/sub: check result vs operand - int256 mul/div: special case for MIN_INT * -1 - Decimal mul divides by divisor, div multiplies numerator - Power requires compile-time literal for bounds computation Tests are xfail pending lower_Name implementation (Task 06). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add expression lowering for: - lower_Compare: <, <=, >, >=, ==, != comparisons with signed/unsigned dispatch, plus flag membership (in/not in) - lower_BoolOp: short-circuit and/or via control flow blocks - lower_Name: local variables, self keyword, constants, immutables - lower_Attribute: environment vars (msg/block/tx/chain), address properties (.balance, .codesize, etc.), state variables (self.x) Fix Compare node access to use node.right (not node.comparators[0]). Fix test_rshift_signed to use unsigned shift amount. Add test helpers that register function parameters in VenomCodegenContext. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements statement lowering in codegen_venom: - lower_AnnAssign: variable declaration with initialization - lower_Assign: regular assignment (primitive types) - lower_AugAssign: augmented assignment with all operators Includes safe arithmetic operations with overflow checking for AugAssign. State variable assignment via sload/sstore is supported. Complex types (structs/arrays) and tuple unpacking are deferred to later tasks as planned. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add lower_If for if/elif/else statements and lower_IfExp for ternary expressions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add For loop support to direct AST-to-Venom codegen: - lower_For: dispatches to range or iter loop - _lower_range_loop: handles range(n), range(start, end), and bound kwarg - _lower_iter_loop: handles static and dynamic array iteration - lower_Break/lower_Continue: jump to exit/incr blocks - lower_Pass: no-op statement - forvars dict in context for loop variable tracking - _lower_array_membership: x in array using loop with early break 5-block CFG structure: entry, cond, body, incr, exit Uses loop_scope context manager for nested break/continue targets. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…cess Add support for subscript and attribute lowering in the Venom IR codegen: - lower_Subscript() for array[index], mapping[key] access - Extend lower_Attribute() for struct field access (point.x) - Handle subscript/attribute assignment in Stmt class - Bounds checking for array access (signed/unsigned indices) - sha3_64 for mapping slot computation - Proper word scale handling (storage=1, memory=32) - 28 new tests covering storage arrays, mappings, structs, and nested access 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add helper methods for memory operations in direct Venom codegen: - load_memory: load from memory ptr (primitive vs complex type handling) - store_memory: store to memory ptr with automatic copy for complex types - copy_memory: mcopy for Cancun+, word-by-word fallback for earlier EVMs - load_calldata: calldataload for primitives, calldatacopy for complex - allocate_buffer: allocate temporary scratch buffers 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add storage operation methods to support sload/sstore, tload/tstore, and iload/istore with proper handling of word-addressed storage vs byte-addressed memory. - load_storage / store_storage for primitive and multi-word types - load_transient / store_transient for EIP-1153 (Cancun+) - load_immutable / store_immutable for bytecode-stored values - get/set_storage_dyn_array_length helpers - Multi-word copy helpers with proper word_scale handling 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add support for internal function definitions and calls: - is_word_type(): check if type fits in 32-byte stack slot - pass_via_stack(): determine stack vs memory arg passing - returns_stack_count(): count return values via stack (0, 1, or 2) - emit_nonreentrant_lock/unlock(): reentrancy guard emission Expr changes: - lower_Call(): dispatch for internal/external/builtin calls - _lower_internal_call(): full invoke generation with arg staging Stmt changes: - lower_Return(): handle stack/memory return value placement 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add module-level code generation for external function dispatch: - VenomModuleCompiler: compiles Vyper module to Venom IR - Linear O(n) selector dispatch (simple and correct first) - External function entry point generation with kwargs support - Fallback/default function handling - Payable and calldatasize checks - Nonreentrant lock integration - Stmt: add external function return with ABI encoding - _lower_external_return for encoding return values - lower_Expr for expression statements (side-effect calls) - Expr: fix internal call to get func_t from correct metadata - Tests: 13 new tests for external function dispatch 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement the module assembly layer for direct-to-Venom codegen: - Restructure to two-phase compilation: generate_runtime_venom() produces runtime IR which is compiled to bytecode, then generate_deploy_venom() produces deploy IR with the runtime bytecode embedded as a data section - Add deploy epilogue (_emit_deploy_epilogue) that copies runtime bytecode from the data section to memory and returns it, with proper handling for immutables (Cancun mcopy vs pre-Cancun identity precompile) - Update phases.py to use the new two-phase API for experimental_codegen - Run fix_mem_loc() and run_passes_on() after IR generation to prepare for assembly generation (CFG normalization, optimizations) - Set entry_function on both contexts (required by function inliner pass) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements builtin dispatch infrastructure and initial builtin handlers: - Task 16a: Call dispatch infrastructure with modular builtins/ directory - Task 16b: Simple builtins (len, empty, min, max, abs) - Task 16c: Unsafe math ops (unsafe_add/sub/mul/div, pow_mod256, addmod, mulmod) - Task 16d: Hashing (keccak256, sha256) The builtins are organized into separate files by category: - simple.py: len, empty, min, max, abs - math.py: unsafe math operations - hashing.py: keccak256, sha256 Adds VenomBuilder.select() for branchless conditional selection using xor(b, mul(cond, xor(a, b))) - matches ir_node_to_venom.py implementation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Implement concat() for bytes/string concatenation - Implement slice() with adhoc support (msg.data, self.code, addr.code) - Implement extract32() with output type clamping - Add copy_memory_dynamic() to context for runtime-length copies - Restructure builtin tests into separate files by category 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement the convert(value, type) builtin function for direct Venom codegen. Handles all type conversions: - to_bool: any type -> bool (nonzero check) - to_int: bytes/decimal/address/flag -> integer with clamping - to_decimal: integer/bytes -> fixed-point (multiply by 10^10) - to_bytes_m: integer/bytes -> bytesM (left-align) - to_address: bytes/integer -> address (160-bit clamp) - to_bytes/to_string: bytestring pointer casts with length check - to_flag: integer -> flag type with range check 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Ports vyper/codegen/abi_encoder.py logic to Venom IR. Creates vyper/codegen_venom/abi_encoder.py with abi_encode_to_buf() function that handles all type cases: - Fast path: static types with matching Vyper/ABI layout (copy) - Bytestrings: copy + zero padding - Complex types (tuples, structs, static arrays): element-by-element - Dynamic arrays: length word + loop encoding Updates stmt.py to use the new encoder for external function returns. Adds unit tests covering all encoding paths. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create codegen_venom/abi/ directory structure - Move abi_encoder.py to abi/abi_encoder.py - Add abi_decoder.py with full decode implementation: - needs_clamp(), int_clamp(), bytes_clamp() for validation - clamp_bytestring(), clamp_dyn_array() with bounds checking - _getelemptr_abi() for double dereference pattern - abi_decode_to_buf() main entry point - Add abi/__init__.py with re-exports - Add 46 unit tests for decoder 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Wire up the abi_encode and abi_decode builtins to use the internal ABI encode/decode routines. Also register deprecated aliases _abi_encode and _abi_decode. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add system.py with low-level operation builtins: - raw_call: external call with full kwarg support (gas, value, max_outsize, is_delegate_call, is_static_call, revert_on_failure) - send: ether transfer with optional gas stipend - raw_log: emit LOG0-4 with variable topics - raw_revert: revert with custom data 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement create operation builtins for Venom IR: - raw_create: deploy from bytecode with optional ctor args - create_minimal_proxy_to: EIP-1167 minimal proxy creation - create_copy_of: copy another contract's bytecode - create_from_blueprint: deploy from EIP-5202 blueprint All support optional salt (CREATE2) and revert_on_failure kwargs. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement remaining builtin functions for venom codegen: - EC precompiles: ecrecover, ecadd, ecmul - Block info: blockhash, blobhash - Decimal truncation: floor, ceil - Wei conversion: as_wei_value - Type constants: min_value, max_value, epsilon - Numeric: isqrt (Babylonian method) - Debug: breakpoint 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement lower_Log in stmt.py to emit LOG0-LOG4 opcodes for events: - topic0: event signature hash (keccak256 of signature) - topic1-3: indexed parameters (up to 3) - data: non-indexed parameters, ABI-encoded as tuple Also fix VenomBuilder.log() interface to match EVM order: log(topic_count, offset, size, topic0, topic1, ...) The builder now handles internal reordering to match venom IR format. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement Assert and Raise statement lowering for the Venom IR: - lower_Assert: handles simple assert, UNREACHABLE, and assert with reason string - lower_Raise: handles bare raise, UNREACHABLE, and raise with reason string - _assert_with_reason: shared logic for assert with message - _revert_with_reason: encodes Error(string) for revert with reason Key implementation details: - Simple assert: jnz to ok/fail blocks, fail block reverts with 0,0 - UNREACHABLE: fail block uses invalid opcode - With reason: encodes Error(string) selector (0x08c379a0) + ABI-encoded message tuple, reverts from buf+28 with 4 + encoded_len bytes - Message evaluation happens in constant context to prevent state changes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements: - lower_Tuple() for tuple literal construction (a, b, c) - _lower_struct_constructor() for struct literals MyStruct(x=1, y=2) - _lower_interface_constructor() for interface constructors - _copy_complex_type() for multi-word assignment with temp buffer - _lower_tuple_unpack() for tuple unpacking (a, b = expr) Uses conservative temp buffer approach for overlap safety - the optimizer can eliminate unnecessary copies. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement external call lowering for the direct-to-Venom codegen: - Add `lower_ExtCall()` and `lower_StaticCall()` dispatch methods - Implement `_lower_external_call()` for full external call handling: - Argument ABI encoding with 4-byte method selector - CALL/STATICCALL dispatch based on function mutability - Return value ABI decoding with bounds checking - extcodesize contract existence check - Revert propagation on call failure - Support for kwargs: value, gas, skip_contract_check, default_return_value - Add 20 tests covering: - Basic staticcall/extcall - Return types (uint256, bool, address, bytes32) - Kwargs handling (value, gas, skip_contract_check, default_return_value) - Multiple calls, conditional calls, nested interface calls - Mutability handling (view/pure -> staticcall, nonpayable/payable -> call) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add memory DynArray length helpers to context.py - Implement _lower_dynarray_append() for storage and memory DynArrays - Implement _lower_dynarray_pop() for storage and memory DynArrays - Implement lower_List() for list literal lowering - Add comprehensive tests for all DynArray operations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fix bug in len(msg.data) handling: was checking for vy_ast.Attribute when msg is actually a vy_ast.Name node. Add comprehensive test suite for string/bytes operations: - len() for memory and storage bytes/string/dynarray - len(msg.data) special case - concat() for memory and storage sources - slice() for standard, adhoc, and storage sources - extract32() with various output types 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix Operand type alias in builder.py to use IROperand base class (eliminates ~265 mypy arg-type errors) - Add constants.py for magic number extraction - Add arithmetic.py skeleton for safe arithmetic extraction 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add defensive CompilerPanic for .code access outside slice() context, matching the pattern used for msg.data. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- raw_call: check if value kwarg is provided (not its value) for delegate/static - .code: only trigger error for address types, not struct fields named "code" Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- bytesm downcast: use bounds check (shl+iszero+assert) instead of mask - Add regression tests for extract32, create salt, dynarray overlap, internal args, and address.code Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Delete 492 unit tests (81%) that only checked isinstance(result, IRVariable) without verifying correctness. These tests would pass with broken codegen. Keep 114 tests that verify: - Handler registration (guards missing implementations) - Decision logic (needs_clamp, pass_via_stack, is_word_type) - Numeric invariants (EIP-1167 bytecode lengths, calldatasize) - Control flow structure (assert/raise/loop/if blocks) - Literal values (specific value verification) - Regression tests (bytesM downcast clamp) Functional tests (11,500+) already cover behavior comprehensively. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Delete 606 unit tests that were added during venom codegen development. After systematic audit, all were found redundant with the functional test suite (11,500+ tests). The tests fell into these categories: - 80% only checked isinstance(result, IRVariable) - passes with broken code - 15% tested helper functions covered by behavioral tests - 5% tested Python infrastructure or optimizations Key insight: codegen unit tests are inherently brittle (many valid IR representations) while functional tests verify actual behavior. The functional suite already covers all the behaviors these tests claimed to verify, including: - Default parameter entry point generation (test_default_param_abi) - bytesM downcast clamping (test_conversion_failures: 1488 cases) - ABI encode/decode correctness - Control flow behavior - Calling conventions Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace hardcoded DST_OFFSET=64 with dynamic alloca-based allocation. codegen_venom now uses 100% alloca-based memory management. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add `_generate_selector_section_sparse()` for O(1) average-case dispatch - Uses `jumptable_utils.generate_sparse_jumptable_buckets()` for bucket calculation - Creates "selector_buckets" data section with 2-byte offsets per bucket - Uses `djmp` instruction to dynamically jump to bucket label - Each bucket does linear search (typically 1-3 items) - Select sparse jumptable when >3 external functions, else linear - Fix `builder.offset()` signature to match Venom IR spec Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add _generate_selector_section_dense() for O(1) codesize-optimized selector dispatch using two-level perfect hash. Selection logic (matches legacy): - opt_none: linear search - opt_codesize with >4 functions: dense jumptable - >3 functions: sparse jumptable - otherwise: linear search Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…fsets The previous implementation used fixed literal offsets (256+) as a "staging area" for kwargs communication between entry points and common body. This could collide with allocator-assigned memory when positional args exceeded 256 bytes of allocations. Replace with shared allocas that are created before entry points and used by both entry points and common body. This matches how legacy ir_node_to_venom handles kwargs via _alloca_table, ensuring the allocator manages all memory without collisions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ntal flag - Delete vyper/venom/ir_node_to_venom.py (~860 LOC) - no longer needed since legacy path goes directly IRnode → assembly via compile_ir - Gate cfg/cfg_runtime output formats behind --experimental-codegen - Move _pass_via_stack/_returns_word helpers to codegen_venom/__init__.py - Clean up unused imports in venom/__init__.py and compiler/phases.py Co-Authored-By: Charles Cooper <cooper.charles.m@gmail.com>
There was a problem hiding this comment.
CodeQL found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.
Pre-Cancun copy_memory now uses identity precompile for copies >= 96 bytes (3 words) instead of unrolling. This produces smaller bytecode for large struct/array copies on pre-Cancun networks. Also removes test_convert_basicblock_simple.py which tested the deleted ir_node_to_venom module. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- abi_encode_to_buf now always returns encoded length (remove returns_len param) - Replace compile-time pointer arithmetic with runtime ops (optimizer folds) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move inline imports to module level (except circular import prevention) - Replace `T | None` with `Optional[T]` for type annotations - Fix mypy errors with proper type assertions and annotations - Fix flake8 errors (unused imports, line length, unused variables) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The test infrastructure uses parse_vyper_source() which runs the Lark grammar checker. Unlike Python's parser, Lark doesn't support implicit string concatenation, so byte strings must remain on single lines. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The test comment said "remove venom related from output formats" but never actually did. cfg/cfg_runtime require --experimental-codegen. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The ret instruction was only scheduling return_pc for stack reordering, leaving return values in arbitrary order on the stack. This caused struct return values to be swapped when functions were not inlined (--optimize codesize). Fix: schedule all ret operands (values + return_pc) so the stack scheduler places them in correct order per IR convention. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #4811 +/- ##
==========================================
- Coverage 93.29% 91.76% -1.54%
==========================================
Files 148 171 +23
Lines 20592 25318 +4726
Branches 3577 4285 +708
==========================================
+ Hits 19211 23232 +4021
- Misses 924 1443 +519
- Partials 457 643 +186 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
… storage When assigning empty values ([], b"", empty()) to storage DynArray or Bytestring, legacy codegen only writes 0 to the length slot. The experimental codegen was copying the entire buffer including potentially uninitialized element slots, causing hevm symbolic equivalence tests to fail due to different storage states. Fix: detect empty values at assignment time and only sstore/tstore 0 to the length slot, matching legacy behavior. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When copying DynArray to storage, legacy codegen writes only length + actual elements. Experimental codegen was writing full capacity (storage_size_in_words), including garbage beyond length. This caused hevm symbolic equivalence failures because the storage state after assignment differed between legacy and experimental. Fix: add _copy_dynarray_to_storage() that loops over actual length and writes only length + 1 words per element, matching legacy. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
📊 Bytecode Size Changes (venom)
Full bytecode sizes
|
added 2 commits
February 13, 2026 14:40
# Conflicts: # vyper/venom/__init__.py # vyper/venom/ir_node_to_venom.py
staticcall/call already writes min(returndatasize, ret_len) bytes to buf._ptr. The subsequent returndatacopy was overwriting the same data. payload_bound caps reads at size_bound() (== ret_len), so even when returndatasize > ret_len, the extra bytes are never accessed. This matches master's behavior which has zero returndatacopy in the external call success path.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Add experimental codegen pathway (
--experimental-codegen) that compiles Vyper AST directly to Venom IR, bypassing the legacy s-expression IR intermediate representation.What's New
New module:
vyper/codegen_venom/(~10,500 LOC)Core lowering:
expr.py- Expression lowering (literals, operators, subscripts, attributes, calls)stmt.py- Statement lowering (assignments, control flow, loops)context.py- Codegen context with memory/storage/transient abstractionsmodule.py- Module compilation with external function dispatchAbstractions:
value.py- VyperValue: explicit tagged union for stack values vs located pointersbuffer.py- Buffer/Ptr: memory allocation and pointer arithmeticBuiltins (
builtins/, ~3,400 LOC):simple.py,math.py,hashing.py,bytes.py,strings.pyconvert.py,create.py,system.py,misc.py,abi.pyABI (
abi/):abi_encoder.py- ABI encoding for calls/returnsabi_decoder.py- ABI decoding with bounds checkingAlso:
vyper/venom/builder.py(~580 LOC) - Type-safe API for IR constructionArchitecture
Why ~38% larger than legacy codegen?
The new codegen is more explicit:
Changes to Existing Code
vyper/compiler/phases.py- Hook to use new codegen when flag enabledvyper/venom/builder.py- New VenomBuilder class (~580 LOC)vyper/venom/ir_node_to_venom.py(~860 LOC) - legacy IRnode-to-Venom translation no longer neededcfg/cfg_runtimeoutput formats now require--experimental-codegenTest Status
--experimental-codegen