diff --git a/interpreter/runtime/global.ml b/interpreter/runtime/global.ml index cf69d2ac..8775976f 100644 --- a/interpreter/runtime/global.ml +++ b/interpreter/runtime/global.ml @@ -9,7 +9,6 @@ exception NotMutable let alloc (GlobalT (_mut, t) as ty) v = assert Free.((val_type t).types = Set.empty); - if not (Match.match_val_type [] (type_of_value v) t) then raise Type; {ty; content = v} let type_of glob = diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml index aa6621ce..0cca2f22 100644 --- a/interpreter/valid/valid.ml +++ b/interpreter/valid/valid.ml @@ -1147,7 +1147,7 @@ let is_const (c : context) (e : instr) = | Const _ | VecConst _ | Binary (Value.I32 I32Op.(Add | Sub | Mul)) | Binary (Value.I64 I64Op.(Add | Sub | Mul)) - | RefNull _ | RefFunc _ + | RefNull _ | RefFunc _ | ContNew _ | RefI31 | StructNew _ | ArrayNew _ | ArrayNewFixed _ -> true | GlobalGet x -> let GlobalT (mut, _t) = global c x in mut = Cons | _ -> false diff --git a/proposals/stack-switching/Explainer.md b/proposals/stack-switching/Explainer.md index f370591c..d2196dbf 100644 --- a/proposals/stack-switching/Explainer.md +++ b/proposals/stack-switching/Explainer.md @@ -550,7 +550,8 @@ function. ``` It takes a reference to a function of type `[t1*] -> [t2*]` whose body -may perform non-local control flow. +may perform non-local control flow. `cont.new` is a constant +expression, so it can be used in places like global initializers. ### Invoking continuations @@ -1035,6 +1036,9 @@ where `rt` is the respective target type of the cast instruction, and the `casta - `rt castable` - iff not (rt <: (ref null cont)) + +Finally, `cont.new` is added to the set of constant expressions. + ### Execution The same control tag may be used simultaneously by `throw`, `suspend`, diff --git a/test/core/stack-switching/cont.new.wast b/test/core/stack-switching/cont.new.wast index 4e17fec5..a843577d 100644 --- a/test/core/stack-switching/cont.new.wast +++ b/test/core/stack-switching/cont.new.wast @@ -322,24 +322,21 @@ "type mismatch" ) -;; TODO: Make cont.new constant -;; https://github.com/WebAssembly/stack-switching/issues/145 - -;; ;; Constant expression in global definition. -;; (module -;; (type $f (func)) -;; (type $k (cont $f)) -;; (global $k (export "k") (ref $k) (cont.new $k (ref.func $f))) -;; (func $f (type $f)) -;; ) -;; (assert_return (get "k") (ref.cont)) - -;; ;; Constant expression in element segment definition. -;; (module -;; (type $f (func)) -;; (type $k (cont $f)) -;; (table $t (ref null $k) (elem (cont.new $k (ref.func $f)))) -;; (func $f (type $f)) -;; (func (export "get") (result (ref null $k)) (table.get $t (i32.const 0))) -;; ) -;; (assert_return (invoke "get") (ref.cont)) +;; Constant expression in global definition. +(module + (type $f (func)) + (type $k (cont $f)) + (global $k (export "k") (ref $k) (cont.new $k (ref.func $f))) + (func $f (type $f)) +) +(assert_return (get "k") (ref.cont)) + +;; Constant expression in element segment definition. +(module + (type $f (func)) + (type $k (cont $f)) + (table $t (ref null $k) (elem (cont.new $k (ref.func $f)))) + (func $f (type $f)) + (func (export "get") (result (ref null $k)) (table.get $t (i32.const 0))) +) +(assert_return (invoke "get") (ref.cont))