-
Notifications
You must be signed in to change notification settings - Fork 210
more codegen [wip] #1218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
micahscopes
wants to merge
26
commits into
argotorg:master
Choose a base branch
from
micahscopes:sonatina-codegen
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
more codegen [wip] #1218
+14,281
−297
Conversation
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
Introduce codegen backend abstraction for multi-target support: - Backend trait with compile() method returning Yul or Bytecode - YulBackend wrapping existing emit_module_yul - SonatinaBackend stub (not yet implemented) - --backend flag for fe check command (yul/sonatina)
Implement the core structure for lowering Fe MIR to Sonatina IR: - Add sonatina-ir and sonatina-triple dependencies - Create sonatina module with ModuleLowerer for translating functions - Implement type mapping (all EVM values are I256) - Implement basic terminator lowering (Return, Goto, Branch) - Wire up SonatinaBackend to call the new compile_module function The lowering currently handles function declarations, block structure, and control flow. MIR instruction lowering is stubbed for Phase 2.
Add comprehensive MIR-to-Sonatina IR lowering: - Lower synthetic values (integers, booleans, bytes) to I256 immediates - Lower unary operations (not, minus, bitnot, plus) - Lower binary operations (arithmetic, comparison, logical) - Lower basic rvalues (ZeroInit, Value, Load) - Lower terminators with proper value resolution - Add num-bigint dependency for BigUint handling - Use EVM-specific division/modulo instructions (EvmSdiv, EvmSmod) Instruction lowering is scaffolded with TODOs for: - Function calls, memory allocation, intrinsics - Aggregate initialization, stores, discriminants - Control flow phi nodes
- Match MIR IntrinsicOp::Mload shape - Preserve local mapping when lowering terminators - Align shift operand order with EVM semantics - Use unsigned div/mod and big-endian bytes immediates - Use Osaka target triple and wire EvmExp
Add proper dispatching for load/store operations based on address space: - Memory: Mload/Mstore - Storage: EvmSload/EvmSstore - TransientStorage: EvmTload/EvmTstore - Calldata: EvmCalldataLoad (read-only) Places with projections are rejected for now.
Add name_map to track symbol name → FuncRef mappings, enabling calls to be resolved by their monomorphized symbol names. Lowers both regular arguments and effect arguments, emitting Sonatina Call instructions.
Add the full compilation pipeline from Fe MIR to EVM bytecode: - Add sonatina-codegen dependency for EVM code generation - Create Sonatina Objects with runtime sections after lowering - Wire up EvmObjectBackend and compile_object in SonatinaBackend - Extract bytecode from compiled runtime section artifact The Sonatina backend now produces actual EVM bytecode instead of returning an error stub.
ControlFlowResult values are converted to Local values during MIR lowering (in lower_if). If one reaches codegen, it indicates a bug in the MIR lowering pipeline, so return an error instead of silently returning zero.
Add support for projections in load/store operations: - Add lower_place_address function that walks projection paths - Handle Field, VariantField, Discriminant, and Index projections - Use slot-based offsets for storage, byte-based for memory - Support both constant and dynamic array indices - Thread database and layout through function signatures This enables the Sonatina backend to handle struct field access, enum variant access, and array indexing for both memory and storage.
Address reviewer feedback on the Sonatina backend: - Fix call signature mismatch: include effect_param_locals in signatures and argument mapping - Fix call return type: track callee return types instead of hardcoding I256 - Fix PlaceRef projections: use lower_place_address for full path computation - Make InitAggregate/SetDiscriminant return Unsupported instead of silent no-op - Fix Terminator::Unreachable to emit EvmInvalid instead of clean return - Fix ValueOrigin::FuncItem to error instead of silently returning 0 - Use body.place_address_space() instead of custom helper with wrong default - Thread db/target_layout through lower_value for projection address computation - Add TODO documentation for SSA phi nodes, entry block, and object semantics Also add docs/backend-equivalence-testing.md proposal for differential testing between Yul and Sonatina backends using revm and Halmos.
Add from_word and to_word conversions matching Yul emitter semantics: - from_word (after load): - bool: convert to 0 or 1 via Ne comparison - unsigned sub-word: Trunc then Zext to mask high bits - signed sub-word: Trunc then Sext for sign extension - to_word (before store): - bool: iszero(iszero(value)) to normalize - unsigned sub-word: Trunc then Zext to mask - signed: pass through (already sign-extended) Deep-copy for by-ref aggregates is not yet implemented and returns an Unsupported error. This matches the Yul emitter's recursive field-by-field copy logic which needs separate implementation.
Add emit_module_sonatina_ir() to export human-readable Sonatina IR text, and create snapshot tests for all 74 codegen fixtures. Snapshots are stored in fixtures/sonatina_ir/ to avoid conflicting with Yul snapshots. This provides visibility into the IR structure between MIR and bytecode, making it easier to debug lowering issues and review generated IR. 72 fixtures generate IR successfully; 2 are skipped due to missing intrinsics (create2, child contract init).
a3a40c4 to
11f2ce4
Compare
Contract runtime entrypoints (dispatch functions) are now executed directly by the EVM without a wrapper function. They emit `evm_stop` instead of internal `Return` since the EVM needs an explicit halt opcode. Simple test files still use the wrapper approach to preserve internal function call semantics for functions that return values. Also adds optional EVM instruction tracing via FE_TRACE_EVM env var.
Replace manual Solidity-style memory allocation (mload/mstore 0x40) with Sonatina's EvmMalloc instruction. This delegates memory management to Sonatina's codegen, avoiding conflicts with its stack frame handling. Note: EvmMalloc lowering is not yet implemented in Sonatina's EVM backend, so tests requiring memory allocation are temporarily disabled. Once Sonatina implements EvmMalloc, these tests should pass.
c19da28 to
b72d7fd
Compare
sbillig
reviewed
Jan 22, 2026
| /// | ||
| /// For simple test files (no explicit contract): A wrapper function calls the entry | ||
| /// and then does `evm_stop`, preserving internal function call semantics. | ||
| fn create_objects(&mut self) -> Result<(), LowerError> { |
Collaborator
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- all functions reachable via calls from
%entrywill be automatically included.%includeis for including functions that don't appear in the call graph - to find the contract runtime and ini functions, you should look for the
contract_init(Foo)/contract_runtime(Foo)attributes (or whatever they are). Look elsewhere in MIR/codegen for how these are found, and share code. - contract init objects aren't currently being created
Sonatina's evm-codegen branch now implements EvmMalloc lowering, so struct_init and match_enum_with_data fixtures compile successfully.
sbillig
reviewed
Jan 25, 2026
Comment on lines
+14
to
+16
| sonatina-ir = { path = "../../../sonatina/crates/ir" } | ||
| sonatina-triple = { path = "../../../sonatina/crates/triple" } | ||
| sonatina-codegen = { path = "../../../sonatina/crates/codegen" } |
Collaborator
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Point to github plz
Remove FE_TEST_SONATINA gating in contract-harness tests, fix StorageMap scratch memory for Sonatina runs, and add a build script to rerun codegen tests when fixtures change.
Add Sonatina test-module emission for , including runtime bytecode plumbing and necessary layout/codegen adjustments.
- Add `fe test` flags for Sonatina backend and debug outputs (EVM trace, symtab, stackify)\n- Write traces/symtabs to files via `--debug-dir` for easier human debugging\n- Adjust stdlib allocator to avoid backend-reserved memory\n- Update codegen snapshots and add Sonatina operand collection regression tests
- Sort code-region reachability and embeds for deterministic section layout\n- Sort cycle-detection traversal for stable errors\n- Ignore local stackify/trace artifacts
Set `SONATINA_DISABLE_TRANSIENT_MALLOC=1` for the `fe test --backend sonatina` runner to avoid transient-allocation overlap corrupting heap-backed values during Fe tests.
Only default `SONATINA_DISABLE_TRANSIENT_MALLOC=1` when not already set, so developers can repro transient-malloc issues with `SONATINA_DISABLE_TRANSIENT_MALLOC=0`.
Expose Sonatina's transient malloc analysis trace via `fe test` flags and support writing it to `--debug-dir/sonatina_transient_malloc_trace.txt`.
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.
No description provided.