Skip to content

more codegen [wip]#1218

Draft
micahscopes wants to merge 37 commits intoargotorg:masterfrom
micahscopes:sonatina-codegen
Draft

more codegen [wip]#1218
micahscopes wants to merge 37 commits intoargotorg:masterfrom
micahscopes:sonatina-codegen

Conversation

@micahscopes
Copy link
Collaborator

No description provided.

@micahscopes micahscopes force-pushed the sonatina-codegen branch 2 times, most recently from c19da28 to b72d7fd Compare January 21, 2026 13:43
///
/// 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> {
Copy link
Collaborator

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 %entry will be automatically included. %include is 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

Comment on lines 14 to 16
sonatina-ir = { path = "../../../sonatina/crates/ir" }
sonatina-triple = { path = "../../../sonatina/crates/triple" }
sonatina-codegen = { path = "../../../sonatina/crates/codegen" }
Copy link
Collaborator

Choose a reason for hiding this comment

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

Point to github plz

@micahscopes
Copy link
Collaborator Author

micahscopes commented Feb 5, 2026

@sbillig quick heads up: if you want report bundles for failing Sonatina tests, run:

RUSTC_WRAPPER= RUST_BACKTRACE=full cargo run -p fe -- test --backend sonatina 'crates/fe/tests/fixtures/fe_test/*.fe' --report --report-out target/sonatina-fixtures-report.tar.gz

That writes a single tarball with passed/ and failed/ suites plus MIR/Sonatina IR/validate output and traces for the failing cases.

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).
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.
Sonatina's evm-codegen branch now implements EvmMalloc lowering,
so struct_init and match_enum_with_data fixtures compile successfully.
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.
micahscopes and others added 13 commits February 5, 2026 17:45
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`.
Stop forcing a Sonatina transient-malloc disable env var from ; the backend now handles allocation safety directly.
Make  accept multiple files/directories (like ), and expand quoted glob patterns via the  crate. Also namespace per-test EVM trace filenames by input suite to avoid collisions when running batches.
Add fe test --report[=<out.tar.gz>] to write a shareable report bundle containing inputs, Sonatina/Yul IR, compiled bytecode, and debug traces (EVM trace, Sonatina symtab, transient-malloc trace).
Add per-suite tarball reports for fe test (report-dir, report-failed-only), including MIR + backend artifacts; keep running on compile/codegen errors; capture codegen panics into the report.

Add Sonatina IR layout validation (used in reports) and fix internal-call argument masking after ZST erasure.
Add "fe check --report" (tar.gz) and "--report-failed-only", sharing the same report helpers used by fe test.

Reports include inputs, MIR, backend output (Yul or bytecode), Sonatina IR + validation, and captured codegen panics with backtraces.
Refresh Sonatina IR fixture snapshots after SSA/trivial-phi behavior changes upstream.
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.

2 participants