From 92410d12712aafc65303bf541cc9d9a9179ef84d Mon Sep 17 00:00:00 2001 From: Francis McCabe Date: Thu, 16 Oct 2025 22:13:24 +0000 Subject: [PATCH 01/15] Initial implementation of resume_throw_ref Not tested. --- interpreter/binary/encode.ml | 2 +- interpreter/exec/eval.ml | 15 + interpreter/syntax/ast.ml | 1 + interpreter/syntax/free.ml | 1 + interpreter/syntax/operators.ml | 1 + interpreter/text/arrange.ml | 2 + interpreter/valid/valid.ml | 6 + test/core/stack-switching/resume_throw.wast | 286 ++++++++++++++++++++ test/core/throw_ref.wast | 3 +- 9 files changed, 315 insertions(+), 2 deletions(-) create mode 100644 test/core/stack-switching/resume_throw.wast diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml index f49423312..ca32b89bf 100644 --- a/interpreter/binary/encode.ml +++ b/interpreter/binary/encode.ml @@ -303,7 +303,7 @@ struct | Suspend x -> op 0xe2; var x | Resume (x, xls) -> op 0xe3; var x; resumetable xls | ResumeThrow (x, y, xls) -> op 0xe4; var x; var y; resumetable xls - (* TOOD: resume_throw_ref *) + | ResumeThrowRef (x, xls) -> op 0xe5; var x; resumetable xls | Switch (x, y) -> op 0xe6; var x; var y | Throw x -> op 0x08; var x diff --git a/interpreter/exec/eval.ml b/interpreter/exec/eval.ml index 3fb2176b6..0cf73eb57 100644 --- a/interpreter/exec/eval.ml +++ b/interpreter/exec/eval.ml @@ -407,6 +407,21 @@ let rec step (c : config) : config = cont := None; vs', [Prompt (hs, ctxt ([], [Throwing (tagt, args) @@ e.at])) @@ e.at] + | ResumeThrowRef (x, xls), Ref (NullRef _) :: vs -> + vs, [Trapping "null exception reference" @@ e.at] + + | ResumeThrowRef (x, xls), Ref _ :: Ref (NullRef _) :: vs -> + vs, [Trapping "null continuation reference" @@ e.at] + + | ResumeThrowRef (x, xls), Ref _ :: Ref (ContRef {contents = None}) :: vs -> + vs, [Trapping "continuation already consumed" @@ e.at] + + | ResumeThrowRef (x, xls), Ref (Exn.(ExnRef (Exn (tagt, args)))) :: + Ref (ContRef ({contents = Some (n, ctxt)} as cont)) :: vs -> + let hs = handle_table c xls in + cont := None; + vs, [Prompt (hs, ctxt ([], [Throwing (tagt, args) @@ e.at])) @@ e.at] + | Switch (x, y), Ref (NullRef _) :: vs -> vs, [Trapping "null continuation reference" @@ e.at] diff --git a/interpreter/syntax/ast.ml b/interpreter/syntax/ast.ml index 5ee382fde..30ea07dcd 100644 --- a/interpreter/syntax/ast.ml +++ b/interpreter/syntax/ast.ml @@ -177,6 +177,7 @@ and instr' = | Suspend of idx (* suspend continuation *) | Resume of idx * (idx * hdl) list (* resume continuation *) | ResumeThrow of idx * idx * (idx * hdl) list (* abort continuation *) + | ResumeThrowRef of idx * (idx * hdl) list (* abort continuation *) | Switch of idx * idx (* direct switch continuation *) | Throw of idx (* throw exception *) | ThrowRef (* rethrow exception *) diff --git a/interpreter/syntax/free.ml b/interpreter/syntax/free.ml index 8bfb0d405..ef6a181f8 100644 --- a/interpreter/syntax/free.ml +++ b/interpreter/syntax/free.ml @@ -181,6 +181,7 @@ let rec instr (e : instr) = | ContNew x -> types (idx x) | ContBind (x, y) -> types (idx x) ++ types (idx y) | ResumeThrow (x, y, xys) -> types (idx x) ++ tags (idx y) ++ list (fun (x, y) -> tags (idx x) ++ hdl y) xys + | ResumeThrowRef (x, xys) -> types (idx x) ++ list (fun (x, y) -> tags (idx x) ++ hdl y) xys | Resume (x, xys) -> types (idx x) ++ list (fun (x, y) -> tags (idx x) ++ hdl y) xys | Suspend x -> tags (idx x) | Switch (x, z) -> types (idx x) ++ tags (idx z) diff --git a/interpreter/syntax/operators.ml b/interpreter/syntax/operators.ml index e6b39aa31..42fa82cc9 100644 --- a/interpreter/syntax/operators.ml +++ b/interpreter/syntax/operators.ml @@ -54,6 +54,7 @@ let cont_bind x y = ContBind (x, y) let suspend x = Suspend x let resume x xys = Resume (x, xys) let resume_throw x y xys = ResumeThrow (x, y, xys) +let resume_throw_ref x xys = ResumeThrowRef (x, xys) let switch x y = Switch (x, y) let throw x = Throw x let throw_ref = ThrowRef diff --git a/interpreter/text/arrange.ml b/interpreter/text/arrange.ml index 9599265d8..d369554cb 100644 --- a/interpreter/text/arrange.ml +++ b/interpreter/text/arrange.ml @@ -561,6 +561,8 @@ let rec instr e = "resume " ^ var x, resumetable xys | ResumeThrow (x, y, xys) -> "resume_throw " ^ var x ^ " " ^ var y, resumetable xys + | ResumeThrowRef (x, xys) -> + "resume_throw_ref " ^ var x, resumetable xys | Switch (x, z) -> "switch " ^ var x ^ " " ^ var z, [] | Throw x -> "throw " ^ var x, [] diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml index 9173e3c68..085865dd8 100644 --- a/interpreter/valid/valid.ml +++ b/interpreter/valid/valid.ml @@ -658,6 +658,12 @@ let rec check_instr (c : context) (e : instr) (s : infer_result_type) : infer_in check_resume_table c ts2 xys e.at; (ts0 @ [RefT (Null, VarHT (StatX x.it))]) --> ts2, [] + | ResumeThrowRef (x, xys) -> + let ct = cont_type c x in + let FuncT (ts1, ts2) = func_type_of_cont_type c ct x.at in + check_resume_table c ts2 xys e.at; + ([RefT (Null, ExnHT); RefT (Null, VarHT (StatX x.it))]) --> ts2, [] + | Switch (x, y) -> let ct1 = cont_type c x in let FuncT (ts11, ts12) = func_type_of_cont_type c ct1 x.at in diff --git a/test/core/stack-switching/resume_throw.wast b/test/core/stack-switching/resume_throw.wast new file mode 100644 index 000000000..46114623a --- /dev/null +++ b/test/core/stack-switching/resume_throw.wast @@ -0,0 +1,286 @@ +;; Tests for resume_throw + +;; Test resume_throw on a continuation that is never resumed. +(module + (tag $exn) + + (type $f (func)) + (type $k (cont $f)) + + (func $never (unreachable)) + (elem declare func $never) + + (func (export "throw_never") + (block $h + (try_table (catch $exn $h) + (cont.new $k (ref.func $never)) + (resume_throw $k $exn) + (unreachable) + ) + ) + ) +) +(assert_return (invoke "throw_never")) + +;; Test resume_throw with a value type argument. +(module + (tag $exn_i32 (param i32)) + + (type $f (func)) + (type $k (cont $f)) + + (func $never (unreachable)) + (elem declare func $never) + + (func (export "throw_never_i32") (result i32) + (block $h (result i32) + (try_table (result i32) (catch $exn_i32 $h) + (i32.const 42) + (cont.new $k (ref.func $never)) + (resume_throw $k $exn_i32) + (unreachable) + ) + ) + ) +) + +(assert_return (invoke "throw_never_i32") (i32.const 42)) + +;; Test resume_throw with a reference type argument. +(module + (tag $exn_ref (param externref)) + + (type $f (func)) + (type $k (cont $f)) + + (func $never (unreachable)) + (elem declare func $never) + + (func (export "throw_never_ref") (param $val externref) (result externref) + (block $h (result externref) + (try_table (result externref) (catch $exn_ref $h) + (local.get $val) + (cont.new $k (ref.func $never)) + (resume_throw $k $exn_ref) + (unreachable) + ) + ) + ) +) +(assert_return (invoke "throw_never_ref" (ref.extern 1)) (ref.extern 1)) + +;; Test resume_throw where the continuation handles the exception. +(module + (tag $exn) + (tag $e1) + + (type $f (func)) + (type $k (cont $f)) + + (func $handler + (block $h + (try_table (catch $exn $h) + (suspend $e1) + ) + ) + ) + (elem declare func $handler) + + (func (export "throw_handled") + (block $h (result (ref $k)) + (resume $k (on $e1 $h) (cont.new $k (ref.func $handler))) + (unreachable) + ) + (resume_throw $k $exn) + ) +) +(assert_return (invoke "throw_handled")) + +;; Test resume_throw where the continuation does not handle the exception. +(module + (tag $exn) + (tag $e1) + + (type $f (func)) + (type $k (cont $f)) + + (func $no_handler + (suspend $e1) + ) + (elem declare func $no_handler) + + (func (export "throw_unhandled") + (block $h (result (ref $k)) + (resume $k (on $e1 $h) (cont.new $k (ref.func $no_handler))) + (unreachable) + ) + (resume_throw $k $exn) + ) +) +(assert_exception (invoke "throw_unhandled")) + +;; Test resume_throw on a consumed continuation. +(module + (tag $exn) + + (type $f (func)) + (type $k (cont $f)) + + (func $f1) + (elem declare func $f1) + + (func (export "throw_consumed") + (local $k_ref (ref $k)) + (local.set $k_ref (cont.new $k (ref.func $f1))) + (resume $k (local.get $k_ref)) ;; consume it + (resume_throw $k $exn (local.get $k_ref)) ;; should trap + ) +) +(assert_trap (invoke "throw_consumed") "continuation already consumed") + +;; Test resume_throw on a null continuation reference. +(module + (tag $exn) + (type $f (func)) + (type $k (cont $f)) + (func (export "throw_null") + (resume_throw $k $exn (ref.null $k)) + ) +) +(assert_trap (invoke "throw_null") "null continuation reference") + +;; Test resume_throw_ref where the continuation handles the exception. +(module + (tag $e0 (param i32)) + + (type $f (func (result i32))) + (type $k (cont $f)) + + (func (export "throw_handled_ref") (result i32) + (block $h (result exnref) + (try_table (catch_ref $e0 $h) (throw $e0 (i32.const 42))) + (unreachable) + ) + (resume_throw_ref $k (cont.new $k (ref.func $handler))) + ) + + (func $handler (result i32) + (block $h (result i32) + (try_table (catch_ref $e0 $h) + (unreachable) + ) + ) + ) + (elem declare func $handler) +) +(assert_return (invoke "throw_handled_ref") (i32.const 42)) + + +;; Test resume_throw_ref where the continuation does not handle the exception. +(module + (tag $e0) + + (type $f (func)) + (type $k (cont $f)) + + (func $no_handler + (unreachable) ;; We only throw into this function + ) + (elem declare func $no_handler) + + (func (export "throw_unhandled_ref") + (block $h (result exnref) + (try_table (catch_ref $e0 $h) (throw $e0)) + (unreachable) + ) + (resume_throw_ref $k (cont.new $k (ref.func $no_handler))) + ) +) +(assert_exception (invoke "throw_unhandled_ref")) + +;; Test resume_throw_ref on a consumed continuation. +(module + (tag $e0) + + (type $f (func)) + (type $k (cont $f)) + + (func $f1) + (elem declare func $f1) + + (func (export "throw_consumed_ref") + (local $k_ref (ref $k)) + (local.set $k_ref (cont.new $k (ref.func $f1))) + (resume $k (local.get $k_ref)) ;; consume it + (resume_throw_ref $k (local.get $k_ref)) ;; should trap + ) +) +(assert_trap (invoke "throw_consumed_ref") "continuation already consumed") + +;; Test resume_throw_ref on a null continuation reference. +(module + (tag $e0) + (type $f (func)) + (type $k (cont $f)) + (func (export "throw_null_ref") + (resume_throw_ref $k (ref.null $k)) + ) +) +(assert_trap (invoke "throw_null_ref") "null continuation reference") + +;; ---- Validation ---- + +(assert_invalid + (module + (type $ft (func)) + (type $ct (cont $ft)) + (tag $exn (param i32)) + (func + (i64.const 0) + (resume_throw $ct $exn (ref.null $ct)) + (unreachable))) + "type mismatch") + +(assert_invalid + (module + (type $ft (func)) + (type $ct (cont $ft)) + (tag $exn) + (func + (ref.null $ct) + (i32.const 0) + (resume_throw $ct $exn) + (unreachable))) + "type mismatch") + +(assert_invalid + (module + (type $ft (func)) + (type $ct (cont $ft)) + (tag $exn (param i32)) + (func + (resume_throw $ct $exn (ref.null $ct)) + (unreachable))) + "type mismatch") + + +(assert_invalid + (module + (type $ft (func)) + (type $ct (cont $ft)) + (tag $exn (param externref)) + (func + (i64.const 0) + (resume_throw_ref $ct $exn (ref.null $ct)) + (unreachable))) + "type mismatch") + +(assert_invalid + (module + (type $ft (func)) + (type $ct (cont $ft)) + (tag $exn (param externref)) + (func + (resume_throw_ref $ct $exn (ref.null $ct)) + (unreachable))) + "type mismatch") \ No newline at end of file diff --git a/test/core/throw_ref.wast b/test/core/throw_ref.wast index f59710a1f..47216e2e3 100644 --- a/test/core/throw_ref.wast +++ b/test/core/throw_ref.wast @@ -17,7 +17,8 @@ (try_table (result i32) (catch_ref $e0 $h) (throw $e0)) (return) ) - (if (param exnref) (i32.eqz (local.get 0)) + (if (param exnref + ) (i32.eqz (local.get 0)) (then (throw_ref)) (else (drop)) ) From 5ef83f2835bb51916a85bcab910c278c7908ad30 Mon Sep 17 00:00:00 2001 From: Francis McCabe Date: Thu, 16 Oct 2025 22:24:35 +0000 Subject: [PATCH 02/15] Add parsing of resume_throw_ref --- interpreter/text/lexer.mll | 1 + interpreter/text/parser.mly | 12 +++++++++++- test/core/stack-switching/resume_throw.wast | 5 ++--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/interpreter/text/lexer.mll b/interpreter/text/lexer.mll index cb124af83..001b42946 100644 --- a/interpreter/text/lexer.mll +++ b/interpreter/text/lexer.mll @@ -230,6 +230,7 @@ rule token = parse | "suspend" -> SUSPEND | "resume" -> RESUME | "resume_throw" -> RESUME_THROW + | "resume_throw_ref" -> RESUME_THROW_REF | "switch" -> SWITCH diff --git a/interpreter/text/parser.mly b/interpreter/text/parser.mly index c7f400e2e..617b299b5 100644 --- a/interpreter/text/parser.mly +++ b/interpreter/text/parser.mly @@ -304,7 +304,7 @@ let parse_annots (m : module_) : Custom.section list = %token MUT FIELD STRUCT ARRAY SUB FINAL REC %token UNREACHABLE NOP DROP SELECT %token BLOCK END IF THEN ELSE LOOP -%token CONT_NEW CONT_BIND SUSPEND RESUME RESUME_THROW SWITCH +%token CONT_NEW CONT_BIND SUSPEND RESUME RESUME_THROW RESUME_THROW_REF SWITCH %token BR BR_IF BR_TABLE BR_ON_NON_NULL %token Ast.instr'> BR_ON_NULL %token Types.ref_type -> Types.ref_type -> Ast.instr'> BR_ON_CAST @@ -789,6 +789,11 @@ resume_instr_instr_list : let x = $2 c type_ in let tag = $3 c tag in let hs, es = $4 c in (resume_throw x tag hs @@ loc1) :: es } + | RESUME_THROW_REF var resume_instr_handler_instr + { let loc1 = $loc($1) in + fun c -> + let x = $2 c type_ in + let hs, es = $3 c in (resume_throw_ref x hs @@ loc1) :: es } resume_instr_handler_instr : | LPAR ON var var RPAR resume_instr_handler_instr @@ -907,6 +912,11 @@ expr1 : /* Sugar */ let tag = $3 c tag in let hs, es = $4 c in es, resume_throw x tag hs } + | RESUME_THROW_REF var resume_expr_handler + { fun c -> + let x = $2 c type_ in + let hs, es = $3 c in + es, resume_throw_ref x hs } | BLOCK labeling_opt block { fun c -> let c' = $2 c [] in let bt, es = $3 c' in [], block bt es } | LOOP labeling_opt block diff --git a/test/core/stack-switching/resume_throw.wast b/test/core/stack-switching/resume_throw.wast index 46114623a..046d115cc 100644 --- a/test/core/stack-switching/resume_throw.wast +++ b/test/core/stack-switching/resume_throw.wast @@ -271,7 +271,7 @@ (tag $exn (param externref)) (func (i64.const 0) - (resume_throw_ref $ct $exn (ref.null $ct)) + (resume_throw_ref $ct (ref.null $ct)) (unreachable))) "type mismatch") @@ -279,8 +279,7 @@ (module (type $ft (func)) (type $ct (cont $ft)) - (tag $exn (param externref)) (func - (resume_throw_ref $ct $exn (ref.null $ct)) + (resume_throw_ref $ct (ref.null $ct)) (unreachable))) "type mismatch") \ No newline at end of file From a95b9a93d42a88c22bf63c75f566b958c12648d5 Mon Sep 17 00:00:00 2001 From: Francis McCabe Date: Thu, 16 Oct 2025 22:36:12 +0000 Subject: [PATCH 03/15] Fix funny in resume_throw_test (Still not right though) --- test/core/stack-switching/resume_throw.wast | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/core/stack-switching/resume_throw.wast b/test/core/stack-switching/resume_throw.wast index 046d115cc..58b231a01 100644 --- a/test/core/stack-switching/resume_throw.wast +++ b/test/core/stack-switching/resume_throw.wast @@ -158,7 +158,7 @@ (func (export "throw_handled_ref") (result i32) (block $h (result exnref) - (try_table (catch_ref $e0 $h) (throw $e0 (i32.const 42))) + (try_table (catch_ref $e0 $h) (i32.const 42) (throw $e0)) (unreachable) ) (resume_throw_ref $k (cont.new $k (ref.func $handler))) From 3bc454809179e8103a94bfc8bc973d8e490fc581 Mon Sep 17 00:00:00 2001 From: Francis McCabe Date: Fri, 17 Oct 2025 18:40:19 +0000 Subject: [PATCH 04/15] Fixed issues. --- interpreter/exec/eval.ml | 11 +++--- test/core/stack-switching/resume_throw.wast | 44 +++++++++++++++++---- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/interpreter/exec/eval.ml b/interpreter/exec/eval.ml index 0cf73eb57..c49f9fdf3 100644 --- a/interpreter/exec/eval.ml +++ b/interpreter/exec/eval.ml @@ -407,17 +407,18 @@ let rec step (c : config) : config = cont := None; vs', [Prompt (hs, ctxt ([], [Throwing (tagt, args) @@ e.at])) @@ e.at] - | ResumeThrowRef (x, xls), Ref (NullRef _) :: vs -> + | ResumeThrowRef (x, xls), Ref _ :: Ref (NullRef _) :: vs -> vs, [Trapping "null exception reference" @@ e.at] - | ResumeThrowRef (x, xls), Ref _ :: Ref (NullRef _) :: vs -> + | ResumeThrowRef (x, xls), Ref (NullRef _) :: vs -> vs, [Trapping "null continuation reference" @@ e.at] - | ResumeThrowRef (x, xls), Ref _ :: Ref (ContRef {contents = None}) :: vs -> + | ResumeThrowRef (x, xls), Ref (ContRef {contents = None}) :: Ref _ :: vs -> vs, [Trapping "continuation already consumed" @@ e.at] - | ResumeThrowRef (x, xls), Ref (Exn.(ExnRef (Exn (tagt, args)))) :: - Ref (ContRef ({contents = Some (n, ctxt)} as cont)) :: vs -> + | ResumeThrowRef (x, xls), + Ref (ContRef ({contents = Some (n, ctxt)} as cont)) :: + Ref (Exn.(ExnRef (Exn (tagt, args)))) :: vs -> let hs = handle_table c xls in cont := None; vs, [Prompt (hs, ctxt ([], [Throwing (tagt, args) @@ e.at])) @@ e.at] diff --git a/test/core/stack-switching/resume_throw.wast b/test/core/stack-switching/resume_throw.wast index 58b231a01..64b676cfb 100644 --- a/test/core/stack-switching/resume_throw.wast +++ b/test/core/stack-switching/resume_throw.wast @@ -152,26 +152,41 @@ ;; Test resume_throw_ref where the continuation handles the exception. (module (tag $e0 (param i32)) + (tag $yield) (type $f (func (result i32))) (type $k (cont $f)) (func (export "throw_handled_ref") (result i32) - (block $h (result exnref) - (try_table (catch_ref $e0 $h) (i32.const 42) (throw $e0)) + (local $k_ref (ref $k)) + (local.set $k_ref (cont.new $k (ref.func $yield42))) + + (block $y (result (ref $k)) + (resume $k (on $yield $y) + (local.get $k_ref)) + (return)) + (local.set $k_ref) + + (block $h (result i32 exnref) + (try_table (catch_ref $e0 $h) + (i32.const 42) + (throw $e0)) (unreachable) ) - (resume_throw_ref $k (cont.new $k (ref.func $handler))) + + (resume_throw_ref $k (local.get $k_ref)) + (return) ) - (func $handler (result i32) + (func $yield42 (result i32) (block $h (result i32) - (try_table (catch_ref $e0 $h) - (unreachable) + (try_table (result i32) (catch $e0 $h) + (suspend $yield) + (unreachable) ) ) ) - (elem declare func $handler) + (elem declare func $yield42) ) (assert_return (invoke "throw_handled_ref") (i32.const 42)) @@ -212,7 +227,15 @@ (local $k_ref (ref $k)) (local.set $k_ref (cont.new $k (ref.func $f1))) (resume $k (local.get $k_ref)) ;; consume it - (resume_throw_ref $k (local.get $k_ref)) ;; should trap + + (block $h (result exnref) + (try_table (catch_ref $e0 $h) + (throw $e0)) + (unreachable) + ) + (local.get $k_ref) + + (resume_throw_ref $k) ;; should trap ) ) (assert_trap (invoke "throw_consumed_ref") "continuation already consumed") @@ -223,6 +246,11 @@ (type $f (func)) (type $k (cont $f)) (func (export "throw_null_ref") + (block $h (result exnref) + (try_table (catch_ref $e0 $h) + (throw $e0)) + (unreachable) + ) (resume_throw_ref $k (ref.null $k)) ) ) From 62a58cc3b6a7702f1102872af69122f2131c388d Mon Sep 17 00:00:00 2001 From: Francis McCabe Date: Fri, 17 Oct 2025 19:56:14 +0000 Subject: [PATCH 05/15] Implement resume_throw_ref in decoder --- interpreter/binary/decode.ml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml index 68bddd9ba..2ee875fea 100644 --- a/interpreter/binary/decode.ml +++ b/interpreter/binary/decode.ml @@ -646,7 +646,10 @@ let rec instr s = let tag = at var s in let xls = vec on_clause s in resume_throw x tag xls - (* TODO: resume_throw_ref *) + | 0xe5 -> + let x = at var s in + let xls = vec on_clause s in + resume_throw_ref x xls | 0xe6 -> let x = at var s in let y = at var s in From 7882f678e65052737b3c6899ccef3946b7dc87d2 Mon Sep 17 00:00:00 2001 From: Francis McCabe Date: Mon, 20 Oct 2025 09:09:16 -0700 Subject: [PATCH 06/15] Update interpreter/binary/decode.ml remove extra space Co-authored-by: Andreas Rossberg --- interpreter/binary/decode.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml index 2ee875fea..749007f32 100644 --- a/interpreter/binary/decode.ml +++ b/interpreter/binary/decode.ml @@ -647,7 +647,7 @@ let rec instr s = let xls = vec on_clause s in resume_throw x tag xls | 0xe5 -> - let x = at var s in + let x = at var s in let xls = vec on_clause s in resume_throw_ref x xls | 0xe6 -> From a1dee474716d5d108681d7cdf4fd4325fe5aa239 Mon Sep 17 00:00:00 2001 From: Francis McCabe Date: Mon, 20 Oct 2025 09:10:21 -0700 Subject: [PATCH 07/15] Update interpreter/valid/valid.ml mark pattern variable as not used Co-authored-by: Thomas Lively --- interpreter/valid/valid.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml index 085865dd8..7754c7bbc 100644 --- a/interpreter/valid/valid.ml +++ b/interpreter/valid/valid.ml @@ -660,7 +660,7 @@ let rec check_instr (c : context) (e : instr) (s : infer_result_type) : infer_in | ResumeThrowRef (x, xys) -> let ct = cont_type c x in - let FuncT (ts1, ts2) = func_type_of_cont_type c ct x.at in + let FuncT (_ts1, ts2) = func_type_of_cont_type c ct x.at in check_resume_table c ts2 xys e.at; ([RefT (Null, ExnHT); RefT (Null, VarHT (StatX x.it))]) --> ts2, [] From 433effcf00f5493ed79aa30b748856b243674ccc Mon Sep 17 00:00:00 2001 From: Francis McCabe Date: Mon, 20 Oct 2025 09:13:44 -0700 Subject: [PATCH 08/15] Update test/core/stack-switching/resume_throw.wast Co-authored-by: Thomas Lively --- test/core/stack-switching/resume_throw.wast | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/core/stack-switching/resume_throw.wast b/test/core/stack-switching/resume_throw.wast index 64b676cfb..42cd8f58f 100644 --- a/test/core/stack-switching/resume_throw.wast +++ b/test/core/stack-switching/resume_throw.wast @@ -182,7 +182,7 @@ (block $h (result i32) (try_table (result i32) (catch $e0 $h) (suspend $yield) - (unreachable) + (unreachable) ) ) ) From 39ce64382301f9656bf5489df2c0cc328a5d6268 Mon Sep 17 00:00:00 2001 From: Francis McCabe Date: Mon, 20 Oct 2025 09:14:08 -0700 Subject: [PATCH 09/15] Update test/core/stack-switching/resume_throw.wast Co-authored-by: Thomas Lively --- test/core/stack-switching/resume_throw.wast | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/core/stack-switching/resume_throw.wast b/test/core/stack-switching/resume_throw.wast index 42cd8f58f..47c7c74d8 100644 --- a/test/core/stack-switching/resume_throw.wast +++ b/test/core/stack-switching/resume_throw.wast @@ -310,4 +310,4 @@ (func (resume_throw_ref $ct (ref.null $ct)) (unreachable))) - "type mismatch") \ No newline at end of file + "type mismatch") From b6612c1c4555c12ffffdfa78240a68e85ef8efe2 Mon Sep 17 00:00:00 2001 From: Francis McCabe Date: Mon, 20 Oct 2025 09:16:02 -0700 Subject: [PATCH 10/15] Update test/core/stack-switching/resume_throw.wast Co-authored-by: Thomas Lively --- test/core/stack-switching/resume_throw.wast | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/core/stack-switching/resume_throw.wast b/test/core/stack-switching/resume_throw.wast index 47c7c74d8..c34c0711c 100644 --- a/test/core/stack-switching/resume_throw.wast +++ b/test/core/stack-switching/resume_throw.wast @@ -229,9 +229,9 @@ (resume $k (local.get $k_ref)) ;; consume it (block $h (result exnref) - (try_table (catch_ref $e0 $h) - (throw $e0)) - (unreachable) + (try_table (result exnref) (catch_ref $e0 $h) + (throw $e0) + ) ) (local.get $k_ref) From a95dcb4d08ec77c7b312a90d4fde79ec05b8faf7 Mon Sep 17 00:00:00 2001 From: Francis McCabe Date: Mon, 20 Oct 2025 09:16:28 -0700 Subject: [PATCH 11/15] Update test/core/throw_ref.wast Co-authored-by: Thomas Lively --- test/core/throw_ref.wast | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/core/throw_ref.wast b/test/core/throw_ref.wast index 47216e2e3..a920ff1db 100644 --- a/test/core/throw_ref.wast +++ b/test/core/throw_ref.wast @@ -17,8 +17,8 @@ (try_table (result i32) (catch_ref $e0 $h) (throw $e0)) (return) ) - (if (param exnref - ) (i32.eqz (local.get 0)) + (if (param exnref) + (i32.eqz (local.get 0)) (then (throw_ref)) (else (drop)) ) From 1e71133bf8d952672f659914d4fc4750642b827d Mon Sep 17 00:00:00 2001 From: Francis McCabe Date: Mon, 20 Oct 2025 09:16:54 -0700 Subject: [PATCH 12/15] Update test/core/stack-switching/resume_throw.wast Co-authored-by: Thomas Lively --- test/core/stack-switching/resume_throw.wast | 1 - 1 file changed, 1 deletion(-) diff --git a/test/core/stack-switching/resume_throw.wast b/test/core/stack-switching/resume_throw.wast index c34c0711c..29e3b561d 100644 --- a/test/core/stack-switching/resume_throw.wast +++ b/test/core/stack-switching/resume_throw.wast @@ -43,7 +43,6 @@ ) ) ) - (assert_return (invoke "throw_never_i32") (i32.const 42)) ;; Test resume_throw with a reference type argument. From 8aded36cfb9cff0a2303f9838b63af056f9fa20b Mon Sep 17 00:00:00 2001 From: Francis McCabe Date: Mon, 20 Oct 2025 11:22:07 -0700 Subject: [PATCH 13/15] Update test/core/stack-switching/resume_throw.wast Co-authored-by: Thomas Lively --- test/core/stack-switching/resume_throw.wast | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/core/stack-switching/resume_throw.wast b/test/core/stack-switching/resume_throw.wast index 29e3b561d..e674add8a 100644 --- a/test/core/stack-switching/resume_throw.wast +++ b/test/core/stack-switching/resume_throw.wast @@ -163,7 +163,7 @@ (block $y (result (ref $k)) (resume $k (on $yield $y) (local.get $k_ref)) - (return)) + (unreachable)) (local.set $k_ref) (block $h (result i32 exnref) From 4d84e15eb38a780115f39d8828726a87d9b23ada Mon Sep 17 00:00:00 2001 From: Francis McCabe Date: Mon, 20 Oct 2025 11:22:51 -0700 Subject: [PATCH 14/15] Update interpreter/exec/eval.ml Co-authored-by: Andreas Rossberg --- interpreter/exec/eval.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interpreter/exec/eval.ml b/interpreter/exec/eval.ml index c49f9fdf3..3993697d9 100644 --- a/interpreter/exec/eval.ml +++ b/interpreter/exec/eval.ml @@ -418,10 +418,10 @@ let rec step (c : config) : config = | ResumeThrowRef (x, xls), Ref (ContRef ({contents = Some (n, ctxt)} as cont)) :: - Ref (Exn.(ExnRef (Exn (tagt, args)))) :: vs -> + v :: vs -> let hs = handle_table c xls in cont := None; - vs, [Prompt (hs, ctxt ([], [Throwing (tagt, args) @@ e.at])) @@ e.at] + vs, [Prompt (hs, ctxt ([v], [ThrowRef @@ e.at])) @@ e.at] | Switch (x, y), Ref (NullRef _) :: vs -> vs, [Trapping "null continuation reference" @@ e.at] From 586ae27b2f42282f1fb4514002bcb4fdbe7b123f Mon Sep 17 00:00:00 2001 From: Francis McCabe Date: Mon, 20 Oct 2025 18:42:43 +0000 Subject: [PATCH 15/15] Refactor implementation of ResumeThrowRef and add some comments to tests. --- interpreter/exec/eval.ml | 2 +- test/core/stack-switching/resume_throw.wast | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/interpreter/exec/eval.ml b/interpreter/exec/eval.ml index 3993697d9..32b80606a 100644 --- a/interpreter/exec/eval.ml +++ b/interpreter/exec/eval.ml @@ -421,7 +421,7 @@ let rec step (c : config) : config = v :: vs -> let hs = handle_table c xls in cont := None; - vs, [Prompt (hs, ctxt ([v], [ThrowRef @@ e.at])) @@ e.at] + vs, [Prompt (hs, ctxt ([v], [Plain ThrowRef @@ e.at])) @@ e.at] | Switch (x, y), Ref (NullRef _) :: vs -> vs, [Trapping "null continuation reference" @@ e.at] diff --git a/test/core/stack-switching/resume_throw.wast b/test/core/stack-switching/resume_throw.wast index e674add8a..2b19f3671 100644 --- a/test/core/stack-switching/resume_throw.wast +++ b/test/core/stack-switching/resume_throw.wast @@ -264,7 +264,7 @@ (tag $exn (param i32)) (func (i64.const 0) - (resume_throw $ct $exn (ref.null $ct)) + (resume_throw $ct $exn (ref.null $ct)) ;; null continuation (unreachable))) "type mismatch") @@ -276,7 +276,7 @@ (func (ref.null $ct) (i32.const 0) - (resume_throw $ct $exn) + (resume_throw $ct $exn) ;; exception tag does not take paramter (unreachable))) "type mismatch") @@ -286,7 +286,7 @@ (type $ct (cont $ft)) (tag $exn (param i32)) (func - (resume_throw $ct $exn (ref.null $ct)) + (resume_throw $ct $exn (ref.null $ct)) ;; missing exception payload (unreachable))) "type mismatch") @@ -298,7 +298,7 @@ (tag $exn (param externref)) (func (i64.const 0) - (resume_throw_ref $ct (ref.null $ct)) + (resume_throw_ref $ct (ref.null $ct)) ;; expecting an exception ref (unreachable))) "type mismatch") @@ -307,6 +307,6 @@ (type $ft (func)) (type $ct (cont $ft)) (func - (resume_throw_ref $ct (ref.null $ct)) + (resume_throw_ref $ct (ref.null $ct)) ;; expecting an exception ref (unreachable))) "type mismatch")