Skip to content

fix(types): correct Felt252DictEntry and U96LimbsLessThanGuarantee layouts - #1671

Merged
TomerStarkware merged 1 commit into
mainfrom
tomer/fix-type-layout-mismatches
Oct 26, 2026
Merged

TomerStarkware merged 1 commit into
mainfrom
tomer/fix-type-layout-mismatches

Conversation

@TomerStarkware

@TomerStarkware TomerStarkware commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

What

Two Sierra types reported a TypeBuilder::layout that disagreed with the MLIR type TypeBuilder::build emits for them. Codegen bakes layout() into array strides, enum payload offsets and argument marshalling, while the generated code reads and writes memory according to the emitted LLVM type. The mismatch let valid programs access aggregate elements at the wrong offsets.

  • Felt252DictEntry<T> is emitted as two pointers but its layout reported a felt252 followed by two pointers (48 bytes / align 16 instead of 16 / 8). An array or struct of entries then used the wrong stride and offsets.
  • U96LimbsLessThanGuarantee<N> is emitted as 2 * N u96 limbs but was declared zero-sized with an empty layout. Boxing it allocated zero bytes in the arena and the store clobbered the previous allocation, which right after eval_circuit is the outputs array.

Regression guard

Both bugs are the same class: build and layout are maintained by hand and drifted apart. This adds find_type_layout_mismatches, which builds every type a program declares, lowers it to LLVM IR and compares LLVM's ABI size and alignment against layout(). A new test runs it over every Sierra snippet in the cairo repo's e2e libfunc test data, so any type a libfunc touches is checked, and new types are covered as soon as any snippet declares them.

Also factors the repeated LLVM target initialization into a shared ffi::initialize_llvm_targets helper.

Testing

  • e2e_libfunc_type_layouts_match_llvm fails on the old layouts and passes with the fixes.
  • Full dict suite, e2e compile test, and the circuit guarantee test pass.

🤖 Generated with Claude Code


This change is Reviewable

…youts, add a type layout check

Two Sierra types reported a `TypeBuilder::layout` that disagreed with the MLIR
type `TypeBuilder::build` emits for them. Codegen bakes `layout()` into array
strides, enum payload offsets and argument marshalling while the generated code
reads and writes memory according to the emitted LLVM type, so the mismatch let
valid programs access aggregate elements at the wrong offsets.

- `Felt252DictEntry<T>` is emitted as two pointers but its layout reported a
  felt252 followed by two pointers (48 bytes / align 16 instead of 16 / 8). An
  array or struct of entries then used the wrong stride and offsets.

- `U96LimbsLessThanGuarantee<N>` is emitted as 2 * N u96 limbs but was declared
  zero-sized with an empty layout. Boxing it allocated zero bytes in the arena
  and the store clobbered the previous allocation, which right after
  `eval_circuit` is the outputs array.

To stop this class of drift from recurring, add `find_type_layout_mismatches`,
which builds every type a program declares, lowers it to LLVM IR and compares
LLVM's ABI size and alignment against `layout()`, and a test that runs it over
every Sierra snippet in the cairo repo's e2e libfunc test data. New types are
covered as soon as any snippet declares them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@TomerStarkware
TomerStarkware requested a review from orizi October 26, 2026 13:43

@orizi orizi left a comment

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.

:lgtm:

@orizi reviewed 6 files and all commit messages, and made 1 comment.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on TomerStarkware).

@github-actions

Copy link
Copy Markdown

Benchmarking results

Benchmark for program dict_insert

Open benchmarks
Command Mean [s] Min [s] Max [s] Relative
Cairo-vm (Rust, Cairo 1) 11.048 ± 0.052 10.964 11.138 5.99 ± 0.05
cairo-native (embedded AOT) 1.844 ± 0.014 1.819 1.862 1.00
cairo-native (embedded JIT using LLVM's ORC Engine) 1.872 ± 0.017 1.846 1.900 1.02 ± 0.01

Benchmark for program dict_snapshot

Open benchmarks
Command Mean [ms] Min [ms] Max [ms] Relative
Cairo-vm (Rust, Cairo 1) 534.4 ± 8.3 523.8 546.8 1.00
cairo-native (embedded AOT) 1659.9 ± 11.1 1645.8 1681.7 3.11 ± 0.05
cairo-native (embedded JIT using LLVM's ORC Engine) 1691.4 ± 16.1 1671.5 1712.5 3.17 ± 0.06

Benchmark for program factorial_2M

Open benchmarks
Command Mean [s] Min [s] Max [s] Relative
Cairo-vm (Rust, Cairo 1) 4.930 ± 0.017 4.892 4.952 2.84 ± 0.04
cairo-native (embedded AOT) 1.734 ± 0.023 1.701 1.778 1.00
cairo-native (embedded JIT using LLVM's ORC Engine) 1.755 ± 0.011 1.741 1.780 1.01 ± 0.02

Benchmark for program fib_2M

Open benchmarks
Command Mean [s] Min [s] Max [s] Relative
Cairo-vm (Rust, Cairo 1) 4.842 ± 0.023 4.814 4.887 2.92 ± 0.02
cairo-native (embedded AOT) 1.658 ± 0.012 1.634 1.672 1.00
cairo-native (embedded JIT using LLVM's ORC Engine) 1.689 ± 0.019 1.665 1.724 1.02 ± 0.01

Benchmark for program linear_search

Open benchmarks
Command Mean [ms] Min [ms] Max [ms] Relative
Cairo-vm (Rust, Cairo 1) 582.5 ± 9.0 570.2 596.7 1.00
cairo-native (embedded AOT) 1703.0 ± 11.6 1687.4 1721.7 2.92 ± 0.05
cairo-native (embedded JIT using LLVM's ORC Engine) 1737.5 ± 16.6 1718.8 1775.0 2.98 ± 0.05

Benchmark for program logistic_map

Open benchmarks
Command Mean [ms] Min [ms] Max [ms] Relative
Cairo-vm (Rust, Cairo 1) 482.8 ± 7.6 469.6 493.9 1.00
cairo-native (embedded AOT) 1675.2 ± 12.0 1645.7 1688.3 3.47 ± 0.06
cairo-native (embedded JIT using LLVM's ORC Engine) 1697.6 ± 11.0 1676.7 1715.5 3.52 ± 0.06

@github-actions

Copy link
Copy Markdown

Benchmark results Main vs HEAD.

Base

Command Mean [s] Min [s] Max [s] Relative
base dict_insert.cairo (JIT) 1.784 ± 0.012 1.769 1.808 1.01 ± 0.01
base dict_insert.cairo (AOT) 1.765 ± 0.010 1.754 1.786 1.00

Head

Command Mean [s] Min [s] Max [s] Relative
head dict_insert.cairo (JIT) 1.866 ± 0.021 1.838 1.895 1.01 ± 0.02
head dict_insert.cairo (AOT) 1.856 ± 0.028 1.813 1.897 1.00

Base

Command Mean [s] Min [s] Max [s] Relative
base dict_snapshot.cairo (JIT) 1.627 ± 0.012 1.610 1.645 1.02 ± 0.01
base dict_snapshot.cairo (AOT) 1.595 ± 0.010 1.580 1.610 1.00

Head

Command Mean [s] Min [s] Max [s] Relative
head dict_snapshot.cairo (JIT) 1.720 ± 0.023 1.688 1.764 1.00
head dict_snapshot.cairo (AOT) 1.723 ± 0.026 1.692 1.773 1.00 ± 0.02

Base

Command Mean [s] Min [s] Max [s] Relative
base factorial_2M.cairo (JIT) 1.687 ± 0.010 1.666 1.695 1.01 ± 0.01
base factorial_2M.cairo (AOT) 1.670 ± 0.005 1.661 1.679 1.00

Head

Command Mean [s] Min [s] Max [s] Relative
head factorial_2M.cairo (JIT) 1.805 ± 0.022 1.781 1.839 1.03 ± 0.02
head factorial_2M.cairo (AOT) 1.758 ± 0.023 1.722 1.782 1.00

Base

Command Mean [s] Min [s] Max [s] Relative
base fib_2M.cairo (JIT) 1.629 ± 0.011 1.615 1.646 1.01 ± 0.01
base fib_2M.cairo (AOT) 1.609 ± 0.009 1.594 1.626 1.00

Head

Command Mean [s] Min [s] Max [s] Relative
head fib_2M.cairo (JIT) 1.730 ± 0.015 1.704 1.756 1.03 ± 0.02
head fib_2M.cairo (AOT) 1.680 ± 0.030 1.650 1.732 1.00

Base

Command Mean [s] Min [s] Max [s] Relative
base linear_search.cairo (JIT) 1.660 ± 0.007 1.643 1.668 1.02 ± 0.01
base linear_search.cairo (AOT) 1.633 ± 0.017 1.607 1.675 1.00

Head

Command Mean [s] Min [s] Max [s] Relative
head linear_search.cairo (JIT) 1.699 ± 0.031 1.656 1.760 1.01 ± 0.02
head linear_search.cairo (AOT) 1.688 ± 0.021 1.664 1.742 1.00

Base

Command Mean [s] Min [s] Max [s] Relative
base logistic_map.cairo (JIT) 1.626 ± 0.012 1.599 1.646 1.02 ± 0.01
base logistic_map.cairo (AOT) 1.601 ± 0.013 1.581 1.623 1.00

Head

Command Mean [s] Min [s] Max [s] Relative
head logistic_map.cairo (JIT) 1.680 ± 0.023 1.647 1.708 1.00 ± 0.02
head logistic_map.cairo (AOT) 1.680 ± 0.018 1.635 1.700 1.00

@TomerStarkware
TomerStarkware added this pull request to the merge queue Oct 26, 2026
Merged via the queue into main with commit 65bd6fe Oct 26, 2026
15 checks passed
@TomerStarkware
TomerStarkware deleted the tomer/fix-type-layout-mismatches branch October 26, 2026 19:07
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