Context
typed-wasm proposal 0002 (access-site carrier) reached [review] 2026-05-30 via hyperpolymath/typed-wasm PR #104. The codec + verifier pass + spec doc landed in:
Promoting proposal 0002 to [accepted] requires §Gate 6: cross-repo codegen issues filed against producers. Reviewed and signed off via #449; this issue is the codegen counterpart.
Wire format
Per typed-wasm/docs/proposals/0002-access-site-carrier.adoc §"Wire format":
u16le version (= 1)
u32le_leb128 entry_count
for each entry (in producer-emission order):
u32le_leb128 func_idx (index into wasm function section)
u32le_leb128 instruction_byte_offset (offset within function body bytecode;
FIRST byte of typed access opcode)
u32le_leb128 region_id (foreign key into typedwasm.regions
region table)
u32le_leb128 field_id (foreign key into that region's
field table)
Custom-section name: typedwasm.access-sites (companion to typedwasm.regions and typedwasm.ownership).
Producer obligations (proposal 0002 §"Producer obligations")
- Emit AFTER any post-codegen wasm rewrite (
wasm-opt, snip, wasm-gc, custom passes). The instruction_byte_offset field is fragile — any pass that reorders, removes, or inserts instructions desyncs the offset space. Emitting before such a pass produces an unverifiable module; the verifier flags AccessSiteMisalignment.
- Companion
typedwasm.regions is mandatory — the region_id / field_id fields are dangling pointers otherwise. v1 verifier rejects access-sites without regions with MissingDependentCarrier (now enforced by typed-wasm#109).
- Stable region indices across both sections (proposal 0001 §"Producer obligations" ¶2).
- All-or-nothing per module: entry for EVERY typed access in EVERY function, OR for NONE. Partial emission triggers
AccessSiteUnbound on unlisted accesses.
- NOT emit entries for non-typed accesses (e.g., raw memory the producer chose to leave outside the type system). An entry is a producer assertion that the access IS typed.
Where this lands in affinescript
The AffineScript codegen pipeline emits typedwasm.ownership today at lib/codegen.ml (build_ownership_section, called at codegen.ml:~2778). The new section emit point is the same vicinity, alongside the regions/capabilities emit points to be added per proposal 0001 codegen issue:
- New helper:
build_access_sites_section : (int * int * int * int) list -> bytes (mirroring the existing build_section shape; LEB128 per field).
- Hook into the codegen pass: every typed access (
region.get $r .f, region.set $r .f, …) records its emission position. The hook needs the post-rewrite byte offset within the function body, so the access-list construction has to happen AFTER wasm-opt (or whatever final-pass lib/codegen.ml runs).
- Emit
typedwasm.access-sites AFTER typedwasm.regions in the section order (matching the verifier's two-section dependency, though section order is technically free).
Tw_section.encode dedup intersects here
#444 extracts Tw_section.Encode from the existing 2-copy build_section pattern in preparation for proposal 0001's regions + capabilities sections. Adding access-sites makes it 4 sections × 2 copies = 8 encoders without the dedup — even more reason to do #444 first, or fold this work into the same Tw_section.Encode module:
module Tw_section : sig
module Encode : sig
val ownership : Tw_ownership_section.t -> bytes
val regions : Tw_regions_section.t -> bytes (* from #444's prep *)
val capabilities : Tw_capabilities_section.t -> bytes (* from #444's prep *)
val access_sites : (int * int * int * int) list -> bytes (* this issue *)
end
module Decode : sig
(* symmetric *)
end
end
Acceptance
Sequencing
This issue is OPEN but not blocking the typed-wasm [accepted] flip — per the proposal 0001 / 0002 acceptance criteria, "cross-repo codegen issues filed" is a Gate-6-satisfied state, not "codegen shipped." Sequence after #444 (encoder dedup) lands.
Related
- typed-wasm#34 (proposal 0001 umbrella) / typed-wasm#78 (proposal 0002 RFC)
- typed-wasm#106 (
[review] → [accepted] roadmap tracker)
- affinescript#444 (Tw_section encoder dedup — prerequisite cleanup)
- affinescript#449 (proposal 0002 review request — satisfied)
- ephapax companion issue (filed concurrently)
🤖 Filed 2026-05-30 to satisfy proposal 0002 §Gate 6 producer-side acceptance criterion.
Context
typed-wasm proposal 0002 (access-site carrier) reached
[review]2026-05-30 via hyperpolymath/typed-wasm PR #104. The codec + verifier pass + spec doc landed in:parse_/build_access_sites_section_payload)verify_access_sites_from_modulepassPromoting proposal 0002 to
[accepted]requires §Gate 6: cross-repo codegen issues filed against producers. Reviewed and signed off via #449; this issue is the codegen counterpart.Wire format
Per typed-wasm/docs/proposals/0002-access-site-carrier.adoc §"Wire format":
Custom-section name:
typedwasm.access-sites(companion totypedwasm.regionsandtypedwasm.ownership).Producer obligations (proposal 0002 §"Producer obligations")
wasm-opt,snip,wasm-gc, custom passes). Theinstruction_byte_offsetfield is fragile — any pass that reorders, removes, or inserts instructions desyncs the offset space. Emitting before such a pass produces an unverifiable module; the verifier flagsAccessSiteMisalignment.typedwasm.regionsis mandatory — theregion_id/field_idfields are dangling pointers otherwise. v1 verifier rejects access-sites without regions withMissingDependentCarrier(now enforced by typed-wasm#109).AccessSiteUnboundon unlisted accesses.Where this lands in affinescript
The AffineScript codegen pipeline emits
typedwasm.ownershiptoday atlib/codegen.ml(build_ownership_section, called at codegen.ml:~2778). The new section emit point is the same vicinity, alongside the regions/capabilities emit points to be added per proposal 0001 codegen issue:build_access_sites_section : (int * int * int * int) list -> bytes(mirroring the existingbuild_sectionshape; LEB128 per field).region.get $r .f,region.set $r .f, …) records its emission position. The hook needs the post-rewrite byte offset within the function body, so the access-list construction has to happen AFTERwasm-opt(or whatever final-passlib/codegen.mlruns).typedwasm.access-sitesAFTERtypedwasm.regionsin the section order (matching the verifier's two-section dependency, though section order is technically free).Tw_section.encode dedup intersects here
#444 extracts
Tw_section.Encodefrom the existing 2-copybuild_sectionpattern in preparation for proposal 0001's regions + capabilities sections. Adding access-sites makes it 4 sections × 2 copies = 8 encoders without the dedup — even more reason to do #444 first, or fold this work into the sameTw_section.Encodemodule:Acceptance
Tw_section.Encode.access_sitesand.Decode.access_sitesimplemented (round-trip property test passes).typedwasm.access-sitesAFTER post-codegen rewrite, with one entry per typed access.typedwasm.regions(cross-section consistency).--emit-typedwasm-regionsflag)..affinetest program with multiple typed accesses; feed the resulting.wasmtotyped-wasm-verify(withunstable-l2); confirmverify_access_sites_from_modulereturnsOk(vec![])..affinetest that exercises access-sites alongside regions; commit the expected.wasmandtypedwasm.access-sitesbytes for regression detection.Sequencing
This issue is OPEN but not blocking the typed-wasm
[accepted]flip — per the proposal 0001 / 0002 acceptance criteria, "cross-repo codegen issues filed" is a Gate-6-satisfied state, not "codegen shipped." Sequence after #444 (encoder dedup) lands.Related
[review] → [accepted]roadmap tracker)🤖 Filed 2026-05-30 to satisfy proposal 0002 §Gate 6 producer-side acceptance criterion.