Skip to content

Graf compiler hardening — module identity and scalar values

September 14, 2026 — unreleased development work. Three compiler corrections pass focused native regressions: distinct module function identity, scalar values inferred from pointer indexing, and signed right-shift widening. The initial repairs are committed locally as 1b7725fa and 2f6d70c6. Full Graf validation exposed a dereference regression in the latter; its follow-up is committed as 72a6003a after focused tests, source review, and clean preflight. The retry produced a runnable Graf executable, but the native Git consumer fixture fails at global -c options. Integration and consumer qualification remain pending; no release is announced.

Graf’s context/state.jan and matchmaker/state.jan both define appendSlice with different parameter types. Basename-only internal naming collapsed them into state__appendSlice, selecting incompatible parameter metadata. Graf hit Gap48PointerToI64Alloca; a minimized pointer/integer pair also compiled into a crashing program.

Commit 1b7725fa1d0716b12d0625012ee3cd73b41ad46f assigns each resolved import a per-compilation identity before lowering its dependencies. Repeated aliases and diamond imports reuse that identity. Ordinary calls, generic helpers, re-exports, and generated runtime calls follow the alias mapping.

This restores the module contract. Import syntax and source aliases are unchanged. Internal prefixes are not a persistent module identifier or public ABI.

Pointer-index inference and signed shifts — Gaps 182 and 183

Section titled “Pointer-index inference and signed shifts — Gaps 182 and 183”

The first repaired Graf build exposed four invalid LLVM pointer shifts in git_import.parseObjectHeader, git_import.readOfsDistanceAt, git_import.readRefDeltaBaseOid, and git_local.packParseHeader. For pack: [*]const u8, var byte = pack[pos] loaded an i8, then stored an inttoptr conversion in a pointer-typed local. Chained mask temporaries also lost their scalar element type.

Commit 2f6d70c6188b355ae3695b6226120ac91773f243 preserves concrete scalar pointee semantics before lowering the function body and through local pointer bindings. This restores indexed value inference.

The negative signed-byte control exposed a separate defect: a narrow signed operand was zero-extended to the wider shift-count type before AShr, turning an i8 value of -16 shifted right by four into 15 instead of -1. The same commit sign-extends that signed operand before the arithmetic shift. See the bitwise operator contract. Neither correction relaxes arithmetic typing or the pointer-store guard.

On the Linux x86_64 development host, both regression scripts passed with the compiler built from the matching 2f6d70c6 source tree. Its SHA-256 is:

38d1ebc4a0eef677aca5ab2e49a69b34b51684d923cd6eed532f259ce23715b8

The module-identity suite builds and runs six executable fixtures: same-name modules, reversed import order, generic helpers, actor helpers, the existing Gap 163 canonical-alias fixture, and the Gap 140 CLI diamond fixture. Generated Katana test contexts and benchmark contexts also pass.

The scalar suite exercises a byte-decoding loop, chained masks, reassignment, negative signed bytes, immutable and explicit annotations, wider annotations, and local pointer binding/writeback. The existing Gap 160 signed/unsigned shift regression also compiles and exits successfully.

Reproduce the suites through the safe build wrapper:

Terminal window
./scripts/zb test-module-basename-identity test-mutable-pointer-index -j4 -Dtrace-gap163=true
  • Opaque pointer elements are tracked separately, Gap 184. The September 14 compiler loaded a byte of the stored pointer when indexing [*]ptr. tests/regression/opaque_pointer_index.jan preserved the failure: expected exit 0, observed exit 7. It was outside the concrete-scalar correction. The September 17 correction below passes its bounded native regression; integration remains pending.
  • The actor fixture has a narrower scope. Adding root-level pub const exported_load = persist.load_slots_u64 produced E2010 for unresolved type persist before lowering. That alias was removed; the generated persistence callback checks do not claim to fix it.
  • DebugAllocator leak diagnostics remain untriaged. Focused script success does not establish a clean compiler release.

Opaque-pointer element indexing follow-up — September 17, 2026

Section titled “Opaque-pointer element indexing follow-up — September 17, 2026”

Verified locally; integration pending. The correction on feature/codex/gap184-opaque-pointer-index preserves pointer-valued storage when reading and writing elements of [*]ptr parameters. Its bounded scope also includes inferred local aliases of those parameters and *ptr dereferences. These operations restore existing behavior; they introduce no new syntax, public API, or profile availability.

The original regression returned exit 7 because an indexed read loaded a byte instead of the stored pointer. The expanded regression now returns exit 0, including nonzero-index reads, write-back with neighboring slot preservation, inferred aliases, and dereference controls. The scalar pointer and module-identity targets also pass with the same rebuilt compiler. The protected compiler build and regression invocation exit 0. Debug allocator diagnostics remain untriaged.

The expanded fixture and new test target are on the compiler feature branch at 94237fc7; they are not yet on the integration branch.

Local verification evidence:

  • Compiler source revision: 94237fc74441f6d14beb02bbd42f7137c265a92b.
  • Compiler executable SHA-256: 5990bbf1d02ec50996f6c4ff103b0a0ad2d4dfd9f1ade10b5d4e08db2b060ced.
  • Tested profile and target: x86_64 Linux, default build profile without overrides.
  • Native regression command (exit 0): ./scripts/zb test-opaque-pointer-index test-mutable-pointer-index test-module-basename-identity -j4.
  • Integration state: pending; no release or deployment is announced.

Generic [*]T instantiations, explicitly annotated local [*]ptr declarations, and general pointer support are outside this bounded claim. The regression is a standalone target; aggregate CI wiring remains a separate follow-up, as for the earlier scalar and module-identity targets. This correction does not establish Graf Git consumer compatibility, remove the documented -c blocker, or qualify Graf recovery and network behavior. Those require their own consumer evidence.

The build with the module-identity repair alone failed at four lshr ptr instructions. The next protected build, at 2f6d70c6, passed those functions but failed in adapt_cmd.entryInfo at a pointer-to-integer store guard. The new scalar pointer semantics were retained on a dereferenced rvalue: var end_pos = path_start.* inferred pointer storage instead of usize.

This remains a Gap 182 regression follow-up. Commit 72a6003a normalizes the dereference Load to its pointee type and adds a byte-scan fixture with *usize input and output stores. Combined module-identity, scalar, and Gap 160 targets pass on the matching compiler SHA-256:

1246131c1e99cf4835e197287e56384b9ac40866ce60979d3373273f2d216d25

Independent source review found no blocking issue and local preflight was clean. The protected retry produced a Graf executable with SHA-256:

dc0c9894b687c7ae35e02f47645a7e396a87e6278db6285e3a8e4e5c5cc42836

The protected build wrapper and harness exit successfully. The retained executable includes its manifest and reports graf 0.7.0-alpha; git help also runs. Compiler and source inputs remain unchanged during the build. The harness still records compiler_source_match: unverified and reproducibility: not_qualified, so the successful build does not by itself close those provenance gates. DebugAllocator diagnostics remain untriaged.

The native Git consumer fixture returns failure (gate_b_fixture_pass: false). All four ordinary root/subdirectory cases exit 2 because graf git treats -c as a subcommand. The two unsupported-flag cases only satisfy a generic nonzero-exit check; they do not establish flag-specific validation. The fixture remains unchanged, no Git tripwire fires, and the separate Git oracle passes for both directory scopes. Consumer integration, recovery, and network transport remain unqualified.

These changes restore existing behavior. They introduce no syntax, public API, profile availability, or new language feature.

Annotated opaque-pointer locals — October 1, 2026

Section titled “Annotated opaque-pointer locals — October 1, 2026”

Verified locally; integration pending. The September 17 parameter correction is now integrated at 4f7a3ffc. Its local-alias follow-up preserves pointer element metadata for var cursor: [*]ptr, let cursor: [*]const ptr, and let cursor: *ptr. The LLVM layout converter now recognizes the exact builtin ptr instead of treating it as an unknown name and falling back to an integer. The existing pointer-to-integer store guard remains enabled.

The native regression checks nonzero indexing, pointer identity, indexed write-back with the neighboring element unchanged, and dereferencing. The first candidate failed compilation at the store guard; the corrected candidate and existing mutable-pointer and module-identity controls all pass under ./scripts/zb test-opaque-pointer-index test-mutable-pointer-index test-module-basename-identity. The compiler was built with Zig development build 2264 and LLVM 22.1.8 on x86_64 Linux, using the protected portable toolchain wrapper without a compilation deadline. Compiler SHA-256: b5c628a74fc5fe64e0eb307c9fa4bf5b60e377af7eef33c04142f46275d0b7a0.

Compiler candidate: b45c24218dbf0bce5853b5e47b9ff5f653616802. The fixture is compiler/qtjir/pointer_elements/tests/annotated_locals.jan. This repairs existing syntax; generic element types, other architectures, general pointer support and Graf consumer qualification remain outside this result. Debug allocator leak diagnostics remain untriaged. No release or deployment is announced.