Skip to content

Merge upstream - #158

Open
tlively wants to merge 3220 commits into
mainfrom
merge-upstream-2026-10-23
Open

tlively wants to merge 3220 commits into
mainfrom
merge-upstream-2026-10-23

Conversation

@tlively

@tlively tlively commented Oct 24, 2026

Copy link
Copy Markdown
Member

No description provided.

tlively and others added 30 commits February 2, 2026 15:39
Merge both the move from wasm-3.0 to a temporary directory and the move
of wasm-3.0 to wasm-latest, preserving git history in both directories.
In the upstream spec repo, the contents of wasm-latest must always be
the same as the highest numbered wasm-X.Y spec directory. Add a CI
script to enforce this.
It was previously numbered 6.3, incorrectly conflicting with
6.3-text.instructions.spectec.
This will reduce the number of changes necessary when we cut new
releases in the future.
rossberg and others added 27 commits October 9, 2026 15:25
… (#2248)

Co-authored-by: Zongyuan Liu <liuzongyuan0505@gmail.com>
…-10-23

# Conflicts:
#	.github/workflows/ci-interpreter.yml
#	README.md
#	interpreter/binary/decode.ml
#	interpreter/binary/encode.ml
#	interpreter/exec/eval.ml
#	interpreter/exec/eval.mli
#	interpreter/runtime/global.ml
#	interpreter/runtime/table.ml
#	interpreter/script/js.ml
#	interpreter/script/run.ml
#	interpreter/syntax/ast.ml
#	interpreter/syntax/free.ml
#	interpreter/syntax/types.ml
#	interpreter/text/arrange.ml
#	interpreter/text/parser.mly
#	interpreter/valid/match.ml
#	interpreter/valid/match.mli
#	interpreter/valid/valid.ml
#	test/core/exceptions/tag.wast
#	test/core/run.py
@tlively

tlively commented Oct 24, 2026

Copy link
Copy Markdown
Member Author

Another attempt to merge upstream. If this looks good, we should not land it via the "Squash and merge" button. I will instead push the branch directly to main to preserve the merge history.

Here's the diff from upstream: https://gist.github.com/tlively/0d99efd46212cfef34acf74a0885bf66

Here's the git show --remerge-diff HEAD diff, showing how merge conflicts were resolved: https://gist.github.com/tlively/f8574a1dc7e6a1a429da60e4d0a9f9c6

Here's a report on how semantic and concrete merge conflicts were resolved:

Upstream Merge Report (upstream/main into stack-switching)

Overview

  • Base (HEAD / origin/main): c7be39053
  • Upstream (upstream/main): aa4dcf44b
  • Merge Base: 62893c285
  • Verification:
    • make -C interpreter builds cleanly with zero warnings or errors.
    • python3 test/core/run.py passes all 262 test suites (including stack-switching, exceptions, gc, memory64, multi-memory, bulk-memory, simd, and relaxed-simd).

Upstream Architectural Refactorings Driving Conflicts

Between the merge base (62893c285) and upstream/main (aa4dcf44b), upstream landed several sweeping refactorings across the OCaml reference interpreter and test suite:

  1. Type & AST Representation Overhaul (22fa77030)

    • Type names were aligned with the specification grammar by removing underscores: heap_type $\to$ heaptype, ref_type $\to$ reftype, val_type $\to$ valtype, str_type (DefStructT / DefArrayT / DefFuncT) $\to$ comptype (StructT / ArrayT / FuncT), def_type $\to$ deftype.
    • var_2 (StatX of int32 | RecX of int32) and VarHT / DefHT were unified into typeuse (Idx of typeidx | Rec of int32 | Def of deftype) and UseHT of typeuse in heaptype.
    • tagtype changed from TagT of deftype to TagT of typeuse.
    • Ast.var was renamed to Ast.idx (with specialized aliases typeidx, tagidx, labelidx, etc.), and module-level AST records (func, global, table, memory, tag, import, export) became single-constructor variants.
    • Value.NullRef no longer carries a heaptype payload (NullRef instead of NullRef of heap_type).
  2. Validator deftype Closure Invariant (4aaa12c58)

    • In check_rectype, c.types now closes each rolled deftype via subst_deftype (subst_of c.types) so that references to earlier module types inside c.types are stored as Def dt rather than Idx x.
  3. Embedder Interface & Script Runner Split

    • interpreter/script/run.ml was split into an Embed.Engine module signature, a functorized script runner in Runner.Make, and a thin instantiation in run.ml.
    • Eval.Exception now carries Source.region * Exn.t instead of Source.region * string, and runtime tag references inside Exn.t use Tag.t (taginst) directly instead of Tag.t ref.

Semantic Merge Conflicts Resolved

Important

Several semantic conflicts occurred either in files that Git auto-merged without conflict markers or across module boundaries due to upstream invariant changes.

1. ContT, ContHT, and NoContHT Adapted to typeuse and comptype

2. Runtime Global.store and Table.store Dynamic Type Checks for ContRef

  • global.ml & table.ml:
    • Upstream added runtime assertions if not (Match.match_valtype [] (Value.type_of_value v) t) then raise Type in Global.store and Match.match_reftype [] (Value.type_of_ref r) t in Table.store.
    • However, in stack-switching, ContRef does not carry its concrete deftype at runtime, so Value.type_of_ref returns the abstract top type (NoNull, ContHT). Storing a ContRef into a global or table of concrete type (ref $ct) would fail Match.match_reftype [] (NoNull, ContHT) (NoNull, UseHT (Def dt)).
    • Preserved stack-switching's omission of the redundant runtime subtype check in Global.store and Table.store.

3. assert_suspension Across the New Embed / Runner / Run / Js Architecture

4. Runtime Tag Identity (taginst) and NullRef in Eval

  • eval.ml:
    • Upstream changed Instance.taginst from Tag.t ref to Tag.t. Updated Suspending and handle_table to use Tag.t (taginst) directly and compare tag instances with physical equality a == a' (matching upstream's Catch / CatchRef in try_table).
    • Updated ContBind, Resume, and ResumeThrow trap handlers for null continuation references to match Value.NullRef without a heaptype argument, and updated Switch to construct Value.NullRef and extract function types via functype_of_cont_reftype.

5. Validator deftype Closure Invariant Impact on cont.wast

6. Non-Empty Tag Results and Duplicate Tests in test/core/

  • check_tagtype & tag.wast:
    • Upstream enforces ts2 = [] ("non-empty tag result type") in check_tagtype and added a second assert_invalid test for imported tags with results in test/core/exceptions/tag.wast.
    • Since stack-switching allows non-empty tag result types for control tags used with suspend/switch, kept ts2 unconstrained in check_tagtype and commented out both "non-empty tag result type" assertions in tag.wast.
  • table.wast:
    • Git's auto-merge duplicated three assert_invalid blocks in table.wast; removed the duplicate copy.

Summary of Other Conflict Resolutions

File Resolution Summary
.github/workflows/ci-interpreter.yml Kept push triggers on main alongside pull_request and workflow_dispatch; took upstream CI build steps.
README.md Preserved the Stack Switching proposal note at the top of README.md with upstream's updated links.
ast.ml Preserved type hdl = OnLabel of labelidx | OnSwitch and stack-switching instructions (ContNew, ContBind, Suspend, Resume, ResumeThrow, Switch) updated to use typeidx / tagidx.
decode.ml & encode.ml Integrated ContHT (-0x18), NoContHT (-0x0b), ContT (-0x23), on_clause, and opcodes 0xe0..0xe6 using typeuse and idx, and removed the duplicate tag section encoder.
arrange.ml & parser.mly Updated cont composite type printing/parsing and stack-switching instruction rules (cont.new, cont.bind, suspend, resume, resume_throw, switch, on clauses) to typeuse and idx.
match.ml & match.mli Added ContT, ContHT, and NoContHT to extrema (abs_of_comptype, top_of_heaptype, bot_of_heaptype), subtyping (match_heaptype, match_comptype), and GLB (both_heaptype), and exported match_functype.
run.py Combined upstream's memory64_test_files, exception_test_files, and bulk_memory_test_files with stack_switching_test_files.

@tlively
tlively requested a review from fgmccabe October 24, 2026 00:49

@rossberg rossberg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

From my (slightly superficial) passes over the various diffs, this looks plausible.

The main thing I noticed that wasn't adjusted adequately is the treatment of suspensions at the evaluator/embedder boundary. We'll want the same change that happened upstream for exceptions wrt to exposing them as legal results instead of unconditional errors, since there might well be embedders that can handle them, unlike control-challenged JS. But we can fix that later.

A few nits below. I also noticed various formatting issues or spurious formatting changes that were already in the code, so can also be cleaned up separately.

(x, OnLabel y)
| 0x01 ->
let x = at var s in
let x = at idx s in
(x, OnSwitch)
| _ -> error s (pos s) "ON opcode expected"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
| _ -> error s (pos s) "ON opcode expected"
| _ -> error s (pos s) "malformed handler clause"

Comment on lines 422 to 425

@rossberg rossberg Oct 24, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

These (the extra cases for legacy exceptions below, which somehow the suggestions can't span over) are obsolete now.

Suggested change
| (0x16 | 0x17 | 0x18 | 0x19) as b -> illegal s pos b

Comment on lines 182 to 184
(* TODO(dhil): This might need to change again in the future as a
different proposal might claim this opcode! GC proposal claimed
the previous opcode we were using. *)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we can drop this TODO at this point.

Suggested change
(* TODO(dhil): This might need to change again in the future as a
different proposal might claim this opcode! GC proposal claimed
the previous opcode we were using. *)

| Trap (at, msg) -> error at "runtime trap" msg
| Crash (at, msg) -> error at "runtime crash" msg
| Exception (at, msg) -> error at "uncaught exception" msg
| Suspension (at, msg) -> error at "suspension error" msg

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
| Suspension (at, msg) -> error at "suspension error" msg
| Suspension (at, msg) -> error at "unhandled suspension" msg

Comment thread interpreter/syntax/ast.ml
| ResumeThrowRef of typeidx * (tagidx * hdl) list (* abort continuation *)
| Switch of typeidx * tagidx (* direct switch continuation *)
| Throw of tagidx (* throw exception *)
| ThrowRef (* rethrow exception *)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
| ThrowRef (* rethrow exception *)
| ThrowRef (* rethrow exception *)

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.