Skip to content

Preserve checked constants and exact array indexes - #158

Merged
itsfuad merged 4 commits into
mainfrom
fix/constant-numeric-publication
Oct 6, 2026
Merged

itsfuad merged 4 commits into
mainfrom
fix/constant-numeric-publication

Conversation

@itsfuad

@itsfuad itsfuad commented Oct 6, 2026

Copy link
Copy Markdown
Member

Summary

  • What changed: Preserve checked numeric conversions during constant evaluation/publication; materialize statics using declared types; retain exact fixed-array index values and bounds; fix narrow unsigned LLVM GEP offsets and qualified imported constant evaluation.
  • Why needed: Accepted constants could produce missing symbols/backend failures, wide indexes could truncate into valid indexes, and narrow unsigned indexes could access the wrong element.
  • Owning components: Typechecker constant evaluation/bounds, MIR static materialization, LLVM index lowering, and runtime type-table ABI identity.
  • Scope boundaries: Includes regression tests, eight Peeper fixture directories, architecture updates, and a separately committed repo review skill. Parser Disambiguate qualified range endpoints from loop bodies #157 and remaining compiler-audit work stay separate.

Fixes #154.
Fixes #155.
Depends on #156; retarget to main after that PR merges.

Production ownership

  • Current non-test consumers: Existing constant initializers, defaults, index/shift/range queries, CFG constant evidence, MIR statics, and LLVM reads/stores/borrows.
  • Execution path: Resolved occurrence bindings → checked expression/conversion evidence → constant evaluation/publication → THIR/MIR evidence and statics → LLVM validation/address generation.
  • Existing implementation reused: Bound-symbol lookup, defining-module publication, numeric value conversion, semantic type lowering, canonical type equality, and existing LLVM emitCast.
  • Removed: staticEntryForConst, reverse ABI lookup/cache, LookupABIKey, single-use abiKeyLocked, repeated test setup, and redundant locals.
  • New production symbols without consumers: None. Test-local helpers consolidate repeated compilation/import setup and evidence assertions.

Design and behavior

  • Previous behavior: Constant folding could lose checked source widths or declared static types. Bounds queries could narrow wide values; host-sized parsing could change bounds handling. LLVM sign-extended narrow unsigned GEP operands. Qualified constants lacked equivalent folding evidence.
  • New behavior: Fold at checked source width, then apply destination conversion. Verify declared static type before publication. Compare constant bounds exactly. Normalize validated constant GEP offsets through existing casts. Read qualified constants through their bound defining owner.
  • Key invariants preserved: Intermediate overflow/truncation, narrowing before widening, IEEE rounding/infinity/signed zero, aliases and nominal identity, private caches/cycles, owner publication, source diagnostic locations, reserved-type ABI identity, and trap-before-access ordering.
  • Intentional behavioral changes: Known invalid imported indexes/shifts now reject before MIR; known imported range/condition values produce existing entry/warning evidence. Negative runtime indexes trap independently of unsigned upper-bound checks.
  • Error/edge cases: Missing or mismatched required statics produce diagnostics and suppress partial MIR. Invalid float-to-integer values remain unpublished. Module discard constants remain source-checked without addressable statics.
  • Layer ownership: Typechecker owns checked constant evidence/source bounds; MIR owns declared static materialization; LLVM owns physical offsets and defensive/runtime guards. Existing owners remain canonical.

Validation

Latest checks after final production cleanup:

CCACHE_DISABLE=1 go test -count=1 ./internal/ir ./internal/semantics/typechecker
PASS

CCACHE_DISABLE=1 go test -count=1 ./internal/ir/... ./internal/pipeline ./internal/backend/llvm
PASS, including Linux/386 and amd64 LLVM/Clang controls

CCACHE_DISABLE=1 go run ./scripts/bundle.go
PASS

CCACHE_DISABLE=1 PEEPER_BIN=/home/itsfuad/Dev/Peeper/compiler/build/bin/peeper go test -count=1 ./...
PASS, including executed source fixtures

gofmt -d internal/ir/types.go internal/semantics/typechecker/check_expr.go
Clean

git diff --check 80b3fd3..HEAD
PASS

Earlier validation, before the final two-local inlining cleanup:

CCACHE_DISABLE=1 go vet ./...
PASS

CCACHE_DISABLE=1 go test -race -count=1 ./internal/ir ./internal/semantics/typechecker ./internal/project ./internal/pipeline ./internal/backend/llvm
PASS
  • Targeted coverage: Mixed-width folding/statics, integer-to-float rounding/overflow, invalid conversions, exact bounds, narrow unsigned GEPs, imported constants, owner/cache isolation, and reserved-shell ABI identity.
  • Existing regressions exercised: Defaults/caller shadowing, cache/cycles/finalization, fingerprints, enums/recursive types, interfaces, places/borrows, slices, and static-address identity.
  • Verification: Native amd64 runtime/trap fixtures; 386 LLVM/Clang object validation; exact commit scopes, ancestry, empty index, and protected file hashes. Repo skill metadata/discovery checks passed. Author confirmed final diff review.
  • Checks not run: Native 386 execution and huge-object allocation. Vet/race were not repeated after behavior-neutral two-local cleanup. Hosted CI remains pending PR publication.

Diff sanity

  • Unrelated production changes: None. User-requested review skill is isolated in its own commit.
  • Duplicated logic introduced: None; source admission and defensive backend validation retain distinct responsibilities.
  • Dead/unreachable code introduced: None.
  • Temporary/debug code remaining: None.
  • Documentation: Updated architecture handoffs. Local plans, journals, user edits, and generated artifacts are excluded.

Risks and follow-up

  • Known assumptions: Wide constant bounds must be validated before physical offset narrowing. Foreign constants must retain defining-owner publication. ABI keys must remain available for reserved incomplete named types.
  • Behavior intentionally changed: Correct publication/addressing and existing constant diagnostics/evidence applied consistently to qualified values.
  • Behavior intentionally not changed: Numeric intermediate semantics, ownership rules, evaluation order, and pipeline boundaries.
  • Remaining gaps: Default-value snapshots, MIR typed-nil/backend-independent validation, redundant provenance copies, and test-only checker boundary cleanup remain separate audit tasks.
  • Linked follow-up: Disambiguate qualified range endpoints from loop bodies #157 tracks qualified range-endpoint parser ambiguity. Large-array coverage is symbolic and does not establish huge-object allocation support.
  • Merge requirements: Land predecessor Preserve resolved bindings during constant evaluation #156, retarget this PR to main, pass hosted checks, and obtain current-head approval from a non-author human collaborator.

Fold numeric constants at checked source widths before destination conversion, and materialize statics using declared runtime types. Read qualified constants from defining-module publication.

Keep exact fixed-array bounds and located diagnostics, reject negative runtime indexes, and normalize validated constant GEP offsets through existing casts. Remove obsolete reverse ABI state and redundant locals.

Reuse test setup and evidence assertions; add numeric, imported-index, wide-bounds and discard source fixtures. Validate both target widths and the rebuilt executable-fixture suite.

Refs #154, #155
Capture deletion-first, reuse-first review preferences with Standards and Spec evidence, explicit worktree scope and smallest equivalent remedies.

Link the skill from AGENTS.md and expose only its intended path through narrow ignore exceptions. Reuse existing engineering rules and validation tools.
@itsfuad
itsfuad changed the base branch from fix/constant-binding-identity to main October 6, 2026 15:13
@itsfuad
itsfuad merged commit 57e7995 into main Oct 6, 2026
1 check passed
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.

Preserve checked numeric conversions during constant publication Evaluate wide constant indexes without truncation

1 participant