From 551e8761352eb0b3f36879342d360cc0f1b69950 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 7 May 2020 09:38:24 +0200 Subject: [PATCH] Remove subtyping (#87) Per the vote on #69, this PR removes subtyping from the proposal. List of changes: * Syntax: - remove `nullref` type - rename `anyref` type to `externref` - extend `ref.null` and `ref.is_null` instructions with new immediate of the form `func` or `extern` (this will later have to generalise to a `constype` per the [typed references proposal](https://github.com/WebAssembly/function-references)) * Typing rules: - `ref.null`, `ref.is_null`: determine reference type based on new immediate - `select`, `call_indirect`, `table.copy`, `table.init`: drop subtyping - `br_table`: revert to rule requiring same label types - `elem` segment: drop subtyping - `global` import: drop subtyping (link time) * Remove subtyping rules and bottom type. * Revert typing algorithm (interpreter and spec appendix). * JS API: - remove `"nullref"` - rename `"anyref"` to `"externref"` * Scripts: - rename `ref` result to `ref.extern` - rename `ref.host` value to `ref.extern` - drop subtyping from invocation type check * JS translation: - extend harness with separate eq functions for each ref type * Adjust tests: - apply syntax changes - remove tests for subtyping - change tests exercising subtyping in other ways --- document/core/appendix/algorithm.rst | 47 ++++--- document/core/appendix/index-instructions.rst | 4 +- document/core/appendix/index-rules.rst | 4 - document/core/appendix/index-types.rst | 5 +- document/core/appendix/properties.rst | 34 ++--- document/core/binary/instructions.rst | 4 +- document/core/binary/types.rst | 3 +- document/core/exec/instructions.rst | 22 ++-- document/core/exec/modules.rst | 26 ++-- document/core/exec/runtime.rst | 22 ++-- document/core/syntax/instructions.rst | 4 +- document/core/syntax/types.rst | 18 +-- document/core/text/instructions.rst | 4 +- document/core/text/types.rst | 7 +- document/core/util/macros.def | 15 +-- document/core/valid/instructions.rst | 64 ++++------ document/core/valid/modules.rst | 10 +- document/core/valid/types.rst | 117 +---------------- document/js-api/index.bs | 20 +-- interpreter/README.md | 13 +- interpreter/binary/decode.ml | 7 +- interpreter/binary/encode.ml | 8 +- interpreter/exec/eval.ml | 19 +-- interpreter/host/spectest.ml | 6 +- interpreter/runtime/global.ml | 4 +- interpreter/runtime/table.ml | 2 +- interpreter/script/js.ml | 89 +++++++------ interpreter/script/run.ml | 20 ++- interpreter/script/script.ml | 9 +- interpreter/syntax/ast.ml | 4 +- interpreter/syntax/free.ml | 2 +- interpreter/syntax/operators.ml | 4 +- interpreter/syntax/types.ml | 69 ++++------ interpreter/syntax/values.ml | 9 +- interpreter/text/arrange.ml | 12 +- interpreter/text/lexer.mll | 7 +- interpreter/text/parser.mly | 23 ++-- interpreter/valid/valid.ml | 62 ++++----- proposals/reference-types/Overview.md | 37 +++--- test/core/binary.wast | 4 +- test/core/br_table.wast | 93 ++------------ test/core/bulk.wast | 2 +- test/core/elem.wast | 22 ++-- test/core/global.wast | 10 +- test/core/linking.wast | 75 +++-------- test/core/ref_func.wast | 8 +- test/core/ref_is_null.wast | 53 +++----- test/core/ref_null.wast | 15 +-- test/core/select.wast | 51 ++------ test/core/table-sub.wast | 14 +-- test/core/table_fill.wast | 118 +++++++++--------- test/core/table_get.wast | 40 +++--- test/core/table_grow.wast | 88 ++++++------- test/core/table_set.wast | 62 ++++----- test/core/table_size.wast | 20 +-- 55 files changed, 580 insertions(+), 931 deletions(-) diff --git a/document/core/appendix/algorithm.rst b/document/core/appendix/algorithm.rst index 19ec29a0..7fd3da33 100644 --- a/document/core/appendix/algorithm.rst +++ b/document/core/appendix/algorithm.rst @@ -22,21 +22,16 @@ Data Structures ~~~~~~~~~~~~~~~ Types are representable as an enumeration. -A simple subtyping check can be defined on these types. .. code-block:: pseudo - type val_type = I32 | I64 | F32 | F64 | Anyref | Funcref | Nullref | Bot + type val_type = I32 | I64 | F32 | F64 | Funcref | Externref func is_num(t : val_type) : bool = - return t = I32 || t = I64 || t = F32 || t = F64 || t = Bot + return t = I32 || t = I64 || t = F32 || t = F64 func is_ref(t : val_type) : bool = - return t = Anyref || t = Funcref || t = Nullref || t = Bot - - func matches(t1 : val_type, t2 : val_type) : bool = - return t1 = t2 || t1 = Bot || - (t1 = Nullref && is_ref(t2)) || (is_ref(t1) && t2 = Anyref) + return t = Funcref || t = Externref The algorithm uses two separate stacks: the *value stack* and the *control stack*. The former tracks the :ref:`types ` of operand values on the :ref:`stack `, @@ -44,7 +39,7 @@ the latter surrounding :ref:`structured control instructions `. +For each value, the value stack records its :ref:`value type `, or :code:`Unknown` when the type is not known. + For each entered block, the control stack records a *control frame* with the type of the associated :ref:`label ` (used to type-check branches), the result type of the block (used to check its result), the height of the operand stack at the start of the block (used to check that operands do not underflow the current block), and a flag recording whether the remainder of the block is unreachable (used to handle :ref:`stack-polymorphic ` typing after branches). @@ -73,17 +69,19 @@ However, these variables are not manipulated directly by the main checking funct .. code-block:: pseudo - func push_val(type : val_type) = + func push_val(type : val_type | Unknown) = vals.push(type) - func pop_val() : val_type = - if (vals.size() = ctrls[0].height && ctrls[0].unreachable) return Bot + func pop_val() : val_type | Unknown = + if (vals.size() = ctrls[0].height && ctrls[0].unreachable) return Unknown error_if(vals.size() = ctrls[0].height) return vals.pop() - func pop_val(expect : val_type) : val_type = + func pop_val(expect : val_type | Unknown) : val_type | Unknown = let actual = pop_val() - error_if(not matches(actual, expect)) + if (actual = Unknown) return expect + if (expect = Unknown) return actual + error_if(actual =/= expect) return actual func push_vals(types : list(val_type)) = foreach (t in types) push_val(t) @@ -97,10 +95,10 @@ Pushing an operand value simply pushes the respective type to the value stack. Popping an operand value checks that the value stack does not underflow the current block and then removes one type. But first, a special case is handled where the block contains no known values, but has been marked as unreachable. That can occur after an unconditional branch, when the stack is typed :ref:`polymorphically `. -In that case, the :code:`Bot` type is returned, because that is a *principal* choice trivially satisfying all use constraints. +In that case, an unknown type is returned. A second function for popping an operand value takes an expected type, which the actual operand type is checked against. -The types may differ by subtyping, including the case where the actual type is :code:`Bot`, and thereby matches unconditionally. +The types may differ in case one of them is Unknown. The function returns the actual type popped from the stack. Finally, there are accumulative functions for pushing or popping multiple operand types. @@ -143,7 +141,7 @@ In that case, all existing operand types are purged from the value stack, in ord .. note:: Even with the unreachable flag set, consecutive operands are still pushed to and popped from the operand stack. That is necessary to detect invalid :ref:`examples ` like :math:`(\UNREACHABLE~(\I32.\CONST)~\I64.\ADD)`. - However, a polymorphic stack cannot underflow, but instead generates :code:`Bot` types as needed. + However, a polymorphic stack cannot underflow, but instead generates :code:`Unknown` types as needed. .. index:: opcode @@ -175,8 +173,8 @@ Other instructions are checked in a similar manner. let t1 = pop_val() let t2 = pop_val() error_if(not (is_num(t1) && is_num(t2))) - error_if(t1 =/= t2 && t1 =/= Bot && t2 =/= Bot) - push_val(if (t1 = Bot) t2 else t1) + error_if(t1 =/= t2 && t1 =/= Unknown && t2 =/= Unknown) + push_val(if (t1 = Unknown) t2 else t1) case (select t) pop_val(I32) @@ -217,14 +215,11 @@ Other instructions are checked in a similar manner.       push_vals(ctrls[n].label_types)    case (br_table n* m) - pop_val(I32)       error_if(ctrls.size() < m) - let arity = ctrls[m].label_types.size()       foreach (n in n*) -         error_if(ctrls.size() < n) -         error_if(ctrls[n].label_types.size() =/= arity) - push_vals(pop_vals(ctrls[n].label_types)) - pop_vals(ctrls[m].label_types) +         error_if(ctrls.size() < n || ctrls[n].label_types =/= ctrls[m].label_types) + pop_val(I32) +       pop_vals(ctrls[m].label_types)       unreachable() .. note:: diff --git a/document/core/appendix/index-instructions.rst b/document/core/appendix/index-instructions.rst index f54363c7..dbb02002 100644 --- a/document/core/appendix/index-instructions.rst +++ b/document/core/appendix/index-instructions.rst @@ -215,8 +215,8 @@ Instruction Binary Opcode Type (reserved) :math:`\hex{CD}` (reserved) :math:`\hex{CE}` (reserved) :math:`\hex{CF}` -:math:`\REFNULL` :math:`\hex{D0}` :math:`[] \to [\NULLREF]` :ref:`validation ` :ref:`execution ` -:math:`\REFISNULL` :math:`\hex{D1}` :math:`[\ANYREF] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\REFNULL~t` :math:`\hex{D0}` :math:`[] \to [t]` :ref:`validation ` :ref:`execution ` +:math:`\REFISNULL~t` :math:`\hex{D1}` :math:`[t] \to [\I32]` :ref:`validation ` :ref:`execution ` :math:`\REFFUNC~x` :math:`\hex{D2}` :math:`[] \to [\FUNCREF]` :ref:`validation ` :ref:`execution ` :math:`\MEMORYINIT` :math:`\hex{FC08}` :math:`[\I32~\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` :math:`\DATADROP` :math:`\hex{FC09}` :math:`[] \to []` :ref:`validation ` :ref:`execution ` diff --git a/document/core/appendix/index-rules.rst b/document/core/appendix/index-rules.rst index 525fe139..1beabe35 100644 --- a/document/core/appendix/index-rules.rst +++ b/document/core/appendix/index-rules.rst @@ -82,10 +82,6 @@ Matching =============================================== =============================================================================== Construct Judgement =============================================== =============================================================================== -:ref:`Number type ` :math:`\vdashnumtypematch \numtype_1 \matchesvaltype \numtype_2` -:ref:`Reference type ` :math:`\vdashreftypematch \reftype_1 \matchesvaltype \reftype_2` -:ref:`Value type ` :math:`\vdashvaltypematch \valtype_1 \matchesvaltype \valtype_2` -:ref:`Result type ` :math:`\vdashresulttypematch [t_1^?] \matchesresulttype [t_2^?]` :ref:`External type ` :math:`\vdashexterntypematch \externtype_1 \matchesexterntype \externtype_2` :ref:`Limits ` :math:`\vdashlimitsmatch \limits_1 \matcheslimits \limits_2` =============================================== =============================================================================== diff --git a/document/core/appendix/index-types.rst b/document/core/appendix/index-types.rst index 37f33c7b..413e6f0b 100644 --- a/document/core/appendix/index-types.rst +++ b/document/core/appendix/index-types.rst @@ -14,9 +14,8 @@ Category Constructor :ref:`Number type ` |F64| :math:`\hex{7C}` (-4 as |Bs7|) (reserved) :math:`\hex{7B}` .. :math:`\hex{71}` :ref:`Reference type ` |FUNCREF| :math:`\hex{70}` (-16 as |Bs7|) -:ref:`Reference type ` |ANYREF| :math:`\hex{6F}` (-17 as |Bs7|) -:ref:`Reference type ` |NULLREF| :math:`\hex{6E}` (-18 as |Bs7|) -(reserved) :math:`\hex{6D}` .. :math:`\hex{61}` +:ref:`Reference type ` |EXTERNREF| :math:`\hex{6F}` (-17 as |Bs7|) +(reserved) :math:`\hex{6E}` .. :math:`\hex{61}` :ref:`Function type ` :math:`[\valtype^\ast] \to [\valtype^\ast]` :math:`\hex{60}` (-32 as |Bs7|) (reserved) :math:`\hex{5F}` .. :math:`\hex{41}` :ref:`Result type ` :math:`[\epsilon]` :math:`\hex{40}` (-64 as |Bs7|) diff --git a/document/core/appendix/properties.rst b/document/core/appendix/properties.rst index 76e47b74..f62e02b3 100644 --- a/document/core/appendix/properties.rst +++ b/document/core/appendix/properties.rst @@ -215,9 +215,7 @@ Module instances are classified by *module contexts*, which are regular :ref:`co * For each :ref:`reference ` :math:`\reff_i` in the table's elements :math:`\reff^n`: - * The :ref:`reference ` :math:`\reff_i` must be :ref:`valid ` with some :ref:`reference type ` :math:`t'_i`. - - * The :ref:`reference type ` :math:`t'_i` must :ref:`match ` the :ref:`reference type ` :math:`t`. + * The :ref:`reference ` :math:`\reff_i` must be :ref:`valid ` with :ref:`reference type ` :math:`t`. * Then the table instance is valid with :ref:`table type ` :math:`\limits~t`. @@ -227,9 +225,7 @@ Module instances are classified by *module contexts*, which are regular :ref:`co \qquad n = \limits.\LMIN \qquad - (S \vdash \reff : t')^n - \qquad - (\vdashreftypematch t' \matchesvaltype t)^n + (S \vdash \reff : t)^n }{ S \vdashtableinst \{ \TITYPE~(\limits~t), \TIELEM~\reff^n \} : \limits~t } @@ -265,9 +261,7 @@ Module instances are classified by *module contexts*, which are regular :ref:`co * The :ref:`global type ` :math:`\mut~t` must be :ref:`valid `. -* The :ref:`value ` :math:`\val` must be :ref:`valid ` with some :ref:`value type ` :math:`t'`. - -* The :ref:`value type ` :math:`t'` must :ref:`match ` the :ref:`value type ` :math:`t`. +* The :ref:`value ` :math:`\val` must be :ref:`valid ` with :ref:`value type ` :math:`t`. * Then the global instance is valid with :ref:`global type ` :math:`\mut~t`. @@ -275,9 +269,7 @@ Module instances are classified by *module contexts*, which are regular :ref:`co \frac{ \vdashglobaltype \mut~t \ok \qquad - S \vdashval \val : t' - \qquad - \vdashvaltypematch t' \matchesvaltype t + S \vdashval \val : t }{ S \vdashglobalinst \{ \GITYPE~(\mut~t), \GIVALUE~\val \} : \mut~t } @@ -291,17 +283,13 @@ Module instances are classified by *module contexts*, which are regular :ref:`co * For each :ref:`reference ` :math:`\reff_i` in the elements :math:`\reff^n`: - * The :ref:`reference ` :math:`\reff_i` must be :ref:`valid ` with some :ref:`reference type ` :math:`t'_i`. - - * The :ref:`reference type ` :math:`t'_i` must :ref:`match ` the :ref:`reference type ` :math:`t`. + * The :ref:`reference ` :math:`\reff_i` must be :ref:`valid ` with :ref:`reference type ` :math:`t`. * Then the table instance is valid. .. math:: \frac{ - (S \vdash \reff : t')^\ast - \qquad - (\vdashreftypematch t' \matchesvaltype t)^\ast + (S \vdash \reff : t)^\ast }{ S \vdasheleminst \{ \EITYPE~t, \EIELEM~\reff^\ast \} \ok } @@ -535,17 +523,17 @@ To that end, all previous typing judgements :math:`C \vdash \X{prop}` are genera } -.. index:: host address +.. index:: extern address -:math:`\REFHOST~\hostaddr` -.......................... +:math:`\REFEXTERNADDR~\externaddr` +.................................. -* The instruction is valid with type :math:`[] \to [\ANYREF]`. +* The instruction is valid with type :math:`[] \to [\EXTERNREF]`. .. math:: \frac{ }{ - S; C \vdashadmininstr \REFHOST~\hostaddr : [] \to [\ANYREF] + S; C \vdashadmininstr \REFEXTERNADDR~\externaddr : [] \to [\EXTERNREF] } diff --git a/document/core/binary/instructions.rst b/document/core/binary/instructions.rst index cb34bba1..a6fba132 100644 --- a/document/core/binary/instructions.rst +++ b/document/core/binary/instructions.rst @@ -76,8 +76,8 @@ Reference Instructions .. math:: \begin{array}{llclll} \production{instruction} & \Binstr &::=& \dots \\ &&|& - \hex{D0} &\Rightarrow& \REFNULL \\ &&|& - \hex{D1} &\Rightarrow& \REFISNULL \\ &&|& + \hex{D0}~~t{:}\Breftype &\Rightarrow& \REFNULL~t \\ &&|& + \hex{D1}~~t{:}\Breftype &\Rightarrow& \REFISNULL~t \\ &&|& \hex{D2}~~x{:}\Bfuncidx &\Rightarrow& \REFFUNC~x \\ \end{array} diff --git a/document/core/binary/types.rst b/document/core/binary/types.rst index e7a7f8ed..5154e4d8 100644 --- a/document/core/binary/types.rst +++ b/document/core/binary/types.rst @@ -42,8 +42,7 @@ Reference Types \begin{array}{llclll@{\qquad\qquad}l} \production{reference type} & \Breftype &::=& \hex{70} &\Rightarrow& \FUNCREF \\ &&|& - \hex{6F} &\Rightarrow& \ANYREF \\ &&|& - \hex{6E} &\Rightarrow& \NULLREF \\ + \hex{6F} &\Rightarrow& \EXTERNREF \\ \end{array} diff --git a/document/core/exec/instructions.rst b/document/core/exec/instructions.rst index ef8dd5e6..ba0ade50 100644 --- a/document/core/exec/instructions.rst +++ b/document/core/exec/instructions.rst @@ -192,10 +192,10 @@ Reference Instructions .. _exec-ref.null: -:math:`\REFNULL` -................ +:math:`\REFNULL~t` +.................. -1. Push the value :math:`\REFNULL` to the stack. +1. Push the value :math:`\REFNULL~t` to the stack. .. note:: No formal reduction rule is required for this instruction, since the |REFNULL| instruction is already a :ref:`value `. @@ -203,14 +203,14 @@ Reference Instructions .. _exec-ref.is_null: -:math:`\REFISNULL` -.................. +:math:`\REFISNULL~t` +.................... 1. Assert: due to :ref:`validation `, a :ref:`reference value ` is on the top of the stack. 2. Pop the value :math:`\val` from the stack. -3. If :math:`\val` is |REFNULL|, then: +3. If :math:`\val` is :math:`\REFNULL~t`, then: a. Push the value :math:`\I32.\CONST~1` to the stack. @@ -220,10 +220,10 @@ Reference Instructions .. math:: \begin{array}{lcl@{\qquad}l} - \val~\REFISNULL &\stepto& \I32.\CONST~1 - & (\iff \val = \REFNULL) \\ - \val~\REFISNULL &\stepto& \I32.\CONST~0 - & (\iff \val \neq \REFNULL) \\ + \val~\REFISNULL~t &\stepto& \I32.\CONST~1 + & (\iff \val = \REFNULL~t) \\ + \val~\REFISNULL~t &\stepto& \I32.\CONST~0 + & (\otherwise) \\ \end{array} @@ -1768,7 +1768,7 @@ Control Instructions 11. Let :math:`r` be the :ref:`reference ` :math:`\X{tab}.\TIELEM[i]`. -12. If :math:`r` is |REFNULL|, then: +12. If :math:`r` is :math:`\REFNULL~t`, then: a. Trap. diff --git a/document/core/exec/modules.rst b/document/core/exec/modules.rst index eb46eb68..35df503d 100644 --- a/document/core/exec/modules.rst +++ b/document/core/exec/modules.rst @@ -110,15 +110,15 @@ The following auxiliary typing rules specify this typing relation relative to a .. _valid-ref: -:ref:`Null References ` :math:`\REFNULL` -.................................................... +:ref:`Null References ` :math:`\REFNULL~t` +...................................................... -* The value is valid with :ref:`reference type ` :math:`\NULLREF`. +* The value is valid with :ref:`reference type ` :math:`t`. .. math:: \frac{ }{ - S \vdashval \REFNULL : \NULLREF + S \vdashval \REFNULL~t : t } @@ -137,15 +137,15 @@ The following auxiliary typing rules specify this typing relation relative to a } -:ref:`Host References ` :math:`\REFHOST~a` -........................................................... +:ref:`External References ` :math:`\REFEXTERNADDR~a` +....................................................................... -* The value is valid with :ref:`reference type ` :math:`\ANYREF`. +* The value is valid with :ref:`reference type ` :math:`\EXTERNREF`. .. math:: \frac{ }{ - S \vdashval \REFHOST~a : \ANYREF + S \vdashval \REFEXTERNADDR~a : \EXTERNREF } @@ -447,7 +447,10 @@ and list of :ref:`reference ` vectors for the module's :ref:`element 3. For each :ref:`table ` :math:`\table_i` in :math:`\module.\MTABLES`, do: - a. Let :math:`\tableaddr_i` be the :ref:`table address ` resulting from :ref:`allocating ` :math:`\table_i.\TTYPE`. + a. Let :math:`\limits_i~t_i` be the :ref:`table type ` :math:`\table_i.\TTYPE`. + + b. Let :math:`\tableaddr_i` be the :ref:`table address ` resulting from :ref:`allocating ` :math:`\table_i.\TTYPE` + with initialization value :math:`\REFNULL~t_i`. 4. For each :ref:`memory ` :math:`\mem_i` in :math:`\module.\MMEMS`, do: @@ -526,8 +529,9 @@ where: \MIEXPORTS~\exportinst^\ast ~\} \end{array} \\[1ex] S_1, \funcaddr^\ast &=& \allocfunc^\ast(S, \module.\MFUNCS, \moduleinst) \\ - S_2, \tableaddr^\ast &=& \alloctable^\ast(S_1, (\table.\TTYPE)^\ast, \REFNULL) - \qquad\qquad\qquad~ (\where \table^\ast = \module.\MTABLES) \\ + S_2, \tableaddr^\ast &=& \alloctable^\ast(S_1, (\table.\TTYPE)^\ast, \REFNULL~t) + \qquad\qquad\qquad~ (\where \table^\ast = \module.\MTABLES \\ && + \qquad\qquad\qquad~~ \wedge (\table.\TTYPE)^\ast = (\limits~t)^\ast) \\ S_3, \memaddr^\ast &=& \allocmem^\ast(S_2, (\mem.\MTYPE)^\ast) \qquad\qquad\qquad~ (\where \mem^\ast = \module.\MMEMS) \\ S_4, \globaladdr^\ast &=& \allocglobal^\ast(S_3, (\global.\GTYPE)^\ast, \val^\ast) diff --git a/document/core/exec/runtime.rst b/document/core/exec/runtime.rst index 757cf3f6..568739e4 100644 --- a/document/core/exec/runtime.rst +++ b/document/core/exec/runtime.rst @@ -11,7 +11,7 @@ Runtime Structure pair: abstract syntax; value .. _syntax-num: .. _syntax-ref: -.. _syntax-ref.host: +.. _syntax-ref.extern: .. _syntax-val: Values @@ -25,7 +25,7 @@ It is convenient to reuse the same notation as for the |CONST| :ref:`instruction References other than null are represented with additional :ref:`administrative instructions `. They either are *function references*, pointing to a specific :ref:`function address `, -or *host references* pointing to an uninterpreted form of :ref:`host address ` that can be defined by the :ref:`embedder `. +or *external references* pointing to an uninterpreted form of :ref:`extern address ` that can be defined by the :ref:`embedder ` to represent its own objects. .. math:: \begin{array}{llcl} @@ -35,9 +35,9 @@ or *host references* pointing to an uninterpreted form of :ref:`host address ` an .. math:: \begin{array}{lcl@{\qquad}l} \default_t &=& t{.}\CONST~0 & (\iff t = \numtype) \\ - \default_t &=& \REFNULL & (\iff t = \reftype) \\ + \default_t &=& \REFNULL~t & (\iff t = \reftype) \\ \end{array} @@ -145,7 +145,7 @@ Convention .. _syntax-globaladdr: .. _syntax-elemaddr: .. _syntax-dataaddr: -.. _syntax-hostaddr: +.. _syntax-externaddr: .. _syntax-addr: Addresses @@ -171,7 +171,7 @@ In addition, an :ref:`embedder ` may supply an uninterpreted set of *h \addr \\ \production{(data address)} & \dataaddr &::=& \addr \\ - \production{(host address)} & \hostaddr &::=& + \production{(extern address)} & \externaddr &::=& \addr \\ \end{array} @@ -274,7 +274,7 @@ It records its :ref:`type ` and holds a vector of :ref:`refere Table elements can be mutated through :ref:`table instructions `, the execution of an active :ref:`element segment `, or by external means provided by the :ref:`embedder `. -It is an invariant of the semantics that all table elements have a type :ref:`matching ` the element type of :math:`\tabletype`. +It is an invariant of the semantics that all table elements have a type equal to the element type of :math:`\tabletype`. It also is an invariant that the length of the element vector never exceeds the maximum size of :math:`\tabletype`, if present. @@ -322,7 +322,7 @@ It records its :ref:`type ` and holds an individual :ref:`val The value of mutable globals can be mutated through :ref:`variable instructions ` or by external means provided by the :ref:`embedder `. -It is an invariant of the semantics that the value has a type :ref:`matching ` the :ref:`value type ` of :math:`\globaltype`. +It is an invariant of the semantics that the value has a type equal to the :ref:`value type ` of :math:`\globaltype`. .. index:: ! element instance, element segment, embedder, element expression @@ -526,7 +526,7 @@ In order to express the reduction of :ref:`traps `, :ref:`calls `, :ref:`calls `. Similarly, |REFHOST| represents :ref:`host references `. +The |REFFUNCADDR| instruction represents :ref:`function reference values `. Similarly, |REFEXTERNADDR| represents :ref:`external references `. The |INVOKE| instruction represents the imminent invocation of a :ref:`function instance `, identified by its :ref:`address `. It unifies the handling of different forms of calls. diff --git a/document/core/syntax/instructions.rst b/document/core/syntax/instructions.rst index 87a11b17..fd29a890 100644 --- a/document/core/syntax/instructions.rst +++ b/document/core/syntax/instructions.rst @@ -183,8 +183,8 @@ Instructions in this group are concerned with accessing :ref:`references ` of all other reference types. - The type |FUNCREF| denotes the infinite union of all references to :ref:`functions `, regardless of their :ref:`function types `. -The type |NULLREF| only contains a single value: the :ref:`null ` reference. -It is a :ref:`subtype ` of all other reference types. - -.. note:: - Future versions of WebAssembly may include reference types that do not include null and hence are not supertypes of |NULLREF|. +The type |EXTERNREF| denotes the infinite union of all references to objects owned by the :ref:`embedder ` and that can be passed into WebAssembly under this type. Reference types are *opaque*, meaning that neither their size nor their bit pattern can be observed. Values of reference type can be stored in :ref:`tables `. @@ -80,16 +74,12 @@ Value Types ~~~~~~~~~~~ *Value types* classify the individual values that WebAssembly code can compute with and the values that a variable accepts. -They are either :ref:`number types `, :ref:`reference type `, or the unique *bottom type*, written :math:`\BOT`. - -The type :math:`\BOT` is a :ref:`subtype ` of all other types. -By virtue of being representable in neither the :ref:`binary format ` nor the :ref:`text format `, it cannot be used in a program; -it only occurs during :ref:`validation `. +They are either :ref:`number types ` or :ref:`reference types `. .. math:: \begin{array}{llll} \production{value type} & \valtype &::=& - \numtype ~|~ \reftype ~|~ \BOT \\ + \numtype ~|~ \reftype \\ \end{array} Conventions diff --git a/document/core/text/instructions.rst b/document/core/text/instructions.rst index dad0d02e..d27370fe 100644 --- a/document/core/text/instructions.rst +++ b/document/core/text/instructions.rst @@ -143,8 +143,8 @@ Reference Instructions .. math:: \begin{array}{llclll} \production{instruction} & \Tplaininstr_I &::=& \dots \\ &&|& - \text{ref.null} &\Rightarrow& \REFNULL \\ &&|& - \text{ref.is\_null} &\Rightarrow& \REFISNULL \\ &&|& + \text{ref.null}~~t{:}\Trefedtype &\Rightarrow& \REFNULL~t \\ &&|& + \text{ref.is\_null}~~t{:}\Trefedtype &\Rightarrow& \REFISNULL~t \\ &&|& \text{ref.func}~~x{:}\Tfuncidx &\Rightarrow& \REFFUNC~x \\ &&|& \end{array} diff --git a/document/core/text/types.rst b/document/core/text/types.rst index 569e7f21..5711fb54 100644 --- a/document/core/text/types.rst +++ b/document/core/text/types.rst @@ -25,6 +25,7 @@ Number Types .. index:: reference type pair: text format; reference type .. _text-reftype: +.. _text-refedtype: Reference Types ~~~~~~~~~~~~~~~ @@ -32,9 +33,11 @@ Reference Types .. math:: \begin{array}{llcll@{\qquad\qquad}l} \production{reference type} & \Treftype &::=& - \text{anyref} &\Rightarrow& \ANYREF \\ &&|& \text{funcref} &\Rightarrow& \FUNCREF \\ &&|& - \text{nullref} &\Rightarrow& \NULLREF \\ + \text{externref} &\Rightarrow& \EXTERNREF \\ + \production{referenced type} & \Trefedtype &::=& + \text{func} &\Rightarrow& \FUNCREF \\ &&|& + \text{extern} &\Rightarrow& \EXTERNREF \\ \end{array} diff --git a/document/core/util/macros.def b/document/core/util/macros.def index 4151d7a5..a74a9f56 100644 --- a/document/core/util/macros.def +++ b/document/core/util/macros.def @@ -179,9 +179,8 @@ .. |F32| mathdef:: \xref{syntax/types}{syntax-valtype}{\K{f32}} .. |F64| mathdef:: \xref{syntax/types}{syntax-valtype}{\K{f64}} -.. |ANYREF| mathdef:: \xref{syntax/types}{syntax-reftype}{\K{anyref}} .. |FUNCREF| mathdef:: \xref{syntax/types}{syntax-reftype}{\K{funcref}} -.. |NULLREF| mathdef:: \xref{syntax/types}{syntax-reftype}{\K{nullref}} +.. |EXTERNREF| mathdef:: \xref{syntax/types}{syntax-reftype}{\K{externref}} .. |MVAR| mathdef:: \xref{syntax/types}{syntax-mut}{\K{var}} .. |MCONST| mathdef:: \xref{syntax/types}{syntax-mut}{\K{const}} @@ -659,6 +658,7 @@ .. |Tnumtype| mathdef:: \xref{text/types}{text-numtype}{\T{numtype}} .. |Treftype| mathdef:: \xref{text/types}{text-reftype}{\T{reftype}} +.. |Trefedtype| mathdef:: \xref{text/types}{text-refedtype}{\T{refedtype}} .. |Tvaltype| mathdef:: \xref{text/types}{text-valtype}{\T{valtype}} .. |Tresulttype| mathdef:: \xref{text/types}{text-resulttype}{\T{resulttype}} .. |Tblocktype| mathdef:: \xref{text/types}{text-blocktype}{\T{blocktype}} @@ -767,8 +767,6 @@ .. |ok| mathdef:: \mathrel{\mbox{ok}} .. |const| mathdef:: \xref{valid/instructions}{valid-constant}{\mathrel{\mbox{const}}} -.. |matchesvaltype| mathdef:: \xref{valid/types}{match-valtype}{\leq} -.. |matchesresulttype| mathdef:: \xref{valid/types}{match-resulttype}{\leq} .. Contexts @@ -795,11 +793,6 @@ .. |vdashglobaltype| mathdef:: \xref{valid/types}{valid-globaltype}{\vdash} .. |vdashexterntype| mathdef:: \xref{valid/types}{valid-externtype}{\vdash} -.. |vdashnumtypematch| mathdef:: \xref{valid/types}{match-numtype}{\vdash} -.. |vdashreftypematch| mathdef:: \xref{valid/types}{match-reftype}{\vdash} -.. |vdashvaltypematch| mathdef:: \xref{valid/types}{match-valtype}{\vdash} -.. |vdashresulttypematch| mathdef:: \xref{valid/types}{match-resulttype}{\vdash} - .. |vdashinstr| mathdef:: \xref{valid/instructions}{valid-instr}{\vdash} .. |vdashinstrseq| mathdef:: \xref{valid/instructions}{valid-instr-seq}{\vdash} .. |vdashexpr| mathdef:: \xref{valid/instructions}{valid-expr}{\vdash} @@ -857,7 +850,7 @@ .. |globaladdr| mathdef:: \xref{exec/runtime}{syntax-globaladdr}{\X{globaladdr}} .. |elemaddr| mathdef:: \xref{exec/runtime}{syntax-elemaddr}{\X{elemaddr}} .. |dataaddr| mathdef:: \xref{exec/runtime}{syntax-dataaddr}{\X{dataaddr}} -.. |hostaddr| mathdef:: \xref{exec/runtime}{syntax-hostaddr}{\X{hostaddr}} +.. |externaddr| mathdef:: \xref{exec/runtime}{syntax-externaddr}{\X{externaddr}} .. Instances, terminals @@ -954,7 +947,7 @@ .. Administrative Instructions, terminals .. |REFFUNCADDR| mathdef:: \xref{exec/runtime}{syntax-ref}{\K{ref}} -.. |REFHOST| mathdef:: \xref{exec/runtime}{syntax-ref.host}{\K{ref{.}host}} +.. |REFEXTERNADDR| mathdef:: \xref{exec/runtime}{syntax-ref.extern}{\K{ref{.}extern}} .. |TRAP| mathdef:: \xref{exec/runtime}{syntax-trap}{\K{trap}} .. |INVOKE| mathdef:: \xref{exec/runtime}{syntax-invoke}{\K{invoke}} diff --git a/document/core/valid/instructions.rst b/document/core/valid/instructions.rst index c125c8bc..19821395 100644 --- a/document/core/valid/instructions.rst +++ b/document/core/valid/instructions.rst @@ -166,29 +166,31 @@ Reference Instructions .. _valid-ref.null: -:math:`\REFNULL` -................ +:math:`\REFNULL~t` +.................. -* The instruction is valid with type :math:`[] \to [\NULLREF]`. +* The instruction is valid with type :math:`[] \to [t]`. .. math:: \frac{ }{ - C \vdashinstr \REFNULL : [] \to [\NULLREF] + C \vdashinstr \REFNULL~t : [] \to [t] } +.. note:: + In future versions of WebAssembly, there may be reference types for which no null reference is allowed. .. _valid-ref.is_null: -:math:`\REFISNULL` -.................. +:math:`\REFISNULL~t` +.................... -* The instruction is valid with type :math:`[\ANYREF] \to [\I32]`. +* The instruction is valid with type :math:`[t] \to [\I32]`. .. math:: \frac{ }{ - C \vdashinstr \REFISNULL : [\ANYREF] \to [\I32] + C \vdashinstr \REFISNULL~t : [t] \to [\I32] } .. _valid-ref.func: @@ -251,7 +253,7 @@ Parametric Instructions * Else: - * The instruction is valid with type :math:`[t~t~\I32] \to [t]`, for any :ref:`value type ` :math:`t` that :ref:`matches ` some :ref:`number type `. + * The instruction is valid with type :math:`[t~t~\I32] \to [t]`, for any :ref:`number type ` :math:`t`. .. math:: \frac{ @@ -260,7 +262,7 @@ Parametric Instructions } \qquad \frac{ - \vdashvaltypematch t \matchesvaltype \numtype + t = \numtype }{ C \vdashinstr \SELECT : [t~t~\I32] \to [t] } @@ -488,17 +490,15 @@ Table Instructions * Let :math:`\limits_2~t_2` be the :ref:`table type ` :math:`C.\CTABLES[y]`. -* The :ref:`reference type ` :math:`t_2` must :ref:`match ` :math:`t_1`. +* The :ref:`reference type ` :math:`t_1` must be the same as :math:`t_2`. * Then the instruction is valid with type :math:`[\I32~\I32~\I32] \to []`. .. math:: \frac{ - C.\CTABLES[x] = \limits_1~t_1 + C.\CTABLES[x] = \limits_1~t \qquad - C.\CTABLES[x] = \limits_2~t_2 - \qquad - \vdashreftypematch t_2 \matchesvaltype t_1 + C.\CTABLES[x] = \limits_2~t }{ C \vdashinstr \TABLECOPY~x~y : [\I32~\I32~\I32] \to [] } @@ -517,17 +517,15 @@ Table Instructions * Let :math:`t_2` be the :ref:`reference type ` :math:`C.\CELEMS[y]`. -* The :ref:`reference type ` :math:`t_2` must :ref:`match ` :math:`t_1`. +* The :ref:`reference type ` :math:`t_1` must be the same as :math:`t_2`. * Then the instruction is valid with type :math:`[\I32~\I32~\I32] \to []`. .. math:: \frac{ - C.\CTABLES[x] = \limits_1~t_1 - \qquad - C.\CELEMS[y] = t_2 + C.\CTABLES[x] = \limits_1~t \qquad - \vdashreftypematch t_2 \matchesvaltype t_1 + C.\CELEMS[y] = t }{ C \vdashinstr \TABLEINIT~x~y : [\I32~\I32~\I32] \to [] } @@ -926,20 +924,16 @@ Control Instructions * For all :math:`l_i` in :math:`l^\ast`, the label :math:`C.\CLABELS[l_i]` must be defined in the context. -* There must be a :ref:`result type ` :math:`[t^?]`, such that: - - * The result type :math:`[t^?]` :ref:`matches ` :math:`C.\CLABELS[l_N]`. - - * For all :math:`l_i` in :math:`l^\ast`, - the result type :math:`[t^?]` :ref:`matches ` :math:`C.\CLABELS[l_i]`. +* For all :math:`l_i` in :math:`l^\ast`, + :math:`C.\CLABELS[l_i]` must be :math:`[t^?]`. * Then the instruction is valid with type :math:`[t_1^\ast~t^?~\I32] \to [t_2^\ast]`, for any sequences of :ref:`value types ` :math:`t_1^\ast` and :math:`t_2^\ast`. .. math:: \frac{ - (\vdashresulttypematch [t^?] \matchesresulttype C.\CLABELS[l])^\ast + (C.\CLABELS[l] = [t^?])^\ast \qquad - \vdashresulttypematch [t^?] \matchesresulttype C.\CLABELS[l_N] + C.\CLABELS[l_N] = [t^?] }{ C \vdashinstr \BRTABLE~l^\ast~l_N : [t_1^\ast~t^?~\I32] \to [t_2^\ast] } @@ -1002,7 +996,7 @@ Control Instructions * Let :math:`\limits~t` be the :ref:`table type ` :math:`C.\CTABLES[x]`. -* The :ref:`reference type ` :math:`t` must :ref:`match ` type |FUNCREF|. +* The :ref:`reference type ` :math:`t` must be |FUNCREF|. * The type :math:`C.\CTYPES[y]` must be defined in the context. @@ -1012,9 +1006,7 @@ Control Instructions .. math:: \frac{ - C.\CTABLES[x] = \limits~t - \qquad - \vdashvaltypematch t \leq \FUNCREF + C.\CTABLES[x] = \limits~\FUNCREF \qquad C.\CTYPES[y] = [t_1^\ast] \to [t_2^\ast] }{ @@ -1054,17 +1046,13 @@ Non-empty Instruction Sequence: :math:`\instr^\ast~\instr_N` for some sequences of :ref:`value types ` :math:`t^\ast` and :math:`t_3^\ast`. * There must be a sequence of :ref:`value types ` :math:`t_0^\ast`, - such that :math:`t_2^\ast = t_0^\ast~{t'}^\ast` where the type sequence :math:`{t'}^\ast` is as long as :math:`t^\ast`. - -* For each :ref:`value type ` :math:`t'_i` in :math:`{t'}^\ast` and corresponding type :math:`t_i` in :math:`t^\ast`, the type :math:`t'_i` must :ref:`match ` :math:`t_i`. + such that :math:`t_2^\ast = t_0^\ast~t^\ast`. * Then the combined instruction sequence is valid with type :math:`[t_1^\ast] \to [t_0^\ast~t_3^\ast]`. .. math:: \frac{ - C \vdashinstrseq \instr^\ast : [t_1^\ast] \to [t_0^\ast~{t'}^\ast] - \qquad - (\vdashvaltypematch t' \matchesvaltype t)^\ast + C \vdashinstrseq \instr^\ast : [t_1^\ast] \to [t_0^\ast~t^\ast] \qquad C \vdashinstr \instr_N : [t^\ast] \to [t_3^\ast] }{ diff --git a/document/core/valid/modules.rst b/document/core/valid/modules.rst index 374cfddb..40b25a76 100644 --- a/document/core/valid/modules.rst +++ b/document/core/valid/modules.rst @@ -156,9 +156,7 @@ Element segments :math:`\elem` are classified by the :ref:`reference type `. -* The element mode :math:`\elemmode` must be valid with :ref:`reference type ` :math:`t'`. - -* The :ref:`reference type ` :math:`t` must :ref:`match ` the reference type :math:`t'`. +* The element mode :math:`\elemmode` must be valid with :ref:`reference type ` :math:`t`. * Then the element segment is valid with :ref:`reference type ` :math:`t`. @@ -169,9 +167,7 @@ Element segments :math:`\elem` are classified by the :ref:`reference type ` are universally valid. However, restrictions apply to :ref:`function types ` as well as the :ref:`limits ` of :ref:`table types ` and :ref:`memory types `, which must be checked during validation. -On :ref:`value types `, a simple notion of subtyping is defined. - .. index:: limits pair: validation; limits @@ -200,107 +198,6 @@ External Types } -.. index:: subtyping - -Value Subtyping -~~~~~~~~~~~~~~~ - -.. index:: number type - -.. _match-numtype: - -Number Types -............ - -A :ref:`number type ` :math:`\numtype_1` matches a :ref:`number type ` :math:`\numtype_2` if and only if: - -* Both :math:`\numtype_1` and :math:`\numtype_2` are the same. - -.. math:: - ~\\[-1ex] - \frac{ - }{ - \vdashnumtypematch \numtype \matchesvaltype \numtype - } - - -.. index:: reference type - -.. _match-reftype: - -Reference Types -............... - -A :ref:`reference type ` :math:`\reftype_1` matches a :ref:`reference type ` :math:`\reftype_2` if and only if: - -* Either both :math:`\reftype_1` and :math:`\reftype_2` are the same. - -* Or :math:`\reftype_1` is |NULLREF|. - -* Or :math:`\reftype_2` is |ANYREF|. - -.. math:: - ~\\[-1ex] - \frac{ - }{ - \vdashreftypematch \reftype \matchesvaltype \reftype - } - \qquad - \frac{ - }{ - \vdashreftypematch \NULLREF \matchesvaltype \reftype - } - \qquad - \frac{ - }{ - \vdashreftypematch \reftype \matchesvaltype \ANYREF - } - - -.. index:: value type, number type, reference type - -.. _match-valtype: - -Value Types -........... - -A :ref:`value type ` :math:`\valtype_1` matches a :ref:`value type ` :math:`\valtype_2` if and only if: - -* Either both :math:`\valtype_1` and :math:`\valtype_2` are :ref:`number types ` and :math:`\valtype_1` :ref:`matches ` :math:`\valtype_2`. - -* Or both :math:`\valtype_1` and :math:`\valtype_2` are :ref:`reference types ` and :math:`\valtype_1` :ref:`matches ` :math:`\valtype_2`. - -* Or :math:`\valtype_1` is :math:`\BOT`. - -.. math:: - ~\\[-1ex] - \frac{ - }{ - \vdashvaltypematch \BOT \matchesvaltype \valtype - } - - -.. _match-resulttype: - -Result Types -............ - -Subtyping is lifted to :ref:`result types ` in a pointwise manner. -That is, a :ref:`result type ` :math:`[t_1^?]` matches a :ref:`result type ` :math:`[t_2^?]` if and only if: - -* Either both :math:`t_1^?` and :math:`t_2^?` are empty. - -* Or :ref:`value type ` :math:`t_1` :ref:`matches ` :ref:`value type ` :math:`t_2`. - -.. math:: - ~\\[-1ex] - \frac{ - (\vdashvaltypematch t_1 \matchesvaltype t_2)^? - }{ - \vdashresulttypematch [t_1^?] \matchesresulttype [t_2^?] - } - - .. index:: ! matching, external type .. _exec-import: .. _match: @@ -414,21 +311,13 @@ An :ref:`external type ` :math:`\ETMEM~\limits_1` matches :ma Globals ....... -An :ref:`external type ` :math:`\ETGLOBAL~(\mut_1~t_1)` matches :math:`\ETGLOBAL~(\mut_2~t_2)` if and only if: +An :ref:`external type ` :math:`\ETGLOBAL~\globaltype_1` matches :math:`\ETGLOBAL~\globaltype_2` if and only if: -* Either both :math:`\mut_1` and :math:`\mut_2` are |MVAR| and :math:`t_1` and :math:`t_2` are the same. - -* Or both :math:`\mut_1` and :math:`\mut_2` are |MCONST| and :math:`t_1` :ref:`matches ` :math:`t_2`. +* Both :math:`\globaltype_1` and :math:`\globaltype_2` are the same. .. math:: ~\\[-1ex] \frac{ }{ - \vdashexterntypematch \ETGLOBAL~(\MVAR~t) \matchesexterntype \ETGLOBAL~(\MVAR~t) - } - \qquad - \frac{ - \vdashvaltypematch t_1 \matchesvaltype t_2 - }{ - \vdashexterntypematch \ETGLOBAL~(\MCONST~t_1) \matchesexterntype \ETGLOBAL~(\MCONST~t_2) + \vdashexterntypematch \ETGLOBAL~\globaltype \matchesexterntype \ETGLOBAL~\globaltype } diff --git a/document/js-api/index.bs b/document/js-api/index.bs index 14bd1b59..4ab7e0e5 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -150,9 +150,8 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df text: 𝖿𝟥𝟤 text: 𝖿𝟨𝟦 url: syntax/types.html#syntax-reftype - text: anyref + text: externref text: funcref - text: nullref text: function element; url: exec/runtime.html#syntax-funcelem text: import component; url: syntax/modules.html#imports text: external value; url: exec/runtime.html#syntax-externval @@ -707,8 +706,7 @@ Immediately after a WebAssembly [=memory.grow=] instruction executes, perform th
 enum TableKind {
-  "nullref",
-  "anyref",
+  "externref",
   "anyfunc",
   // Note: More values may be added in future iterations,
   // e.g., typed function references, typed GC references
@@ -836,8 +834,7 @@ enum ValueType {
   "i64",
   "f32",
   "f64",
-  "nullref",
-  "anyref",
+  "externref",
   "anyfunc",
 };
 
@@ -890,9 +887,8 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each 1. If |s| equals "i64", return [=𝗂𝟨𝟦=]. 1. If |s| equals "f32", return [=𝖿𝟥𝟤=]. 1. If |s| equals "f64", return [=𝖿𝟨𝟦=]. - 1. If |s| equals "anyref", return [=anyref=]. 1. If |s| equals "funcref", return [=funcref=]. - 1. If |s| equals "nullref", return [=nullref=]. + 1. If |s| equals "externref", return [=externref=]. 1. Assert: This step is not reached. @@ -902,9 +898,7 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each 1. If |valuetype| equals [=𝗂𝟨𝟦=], return [=𝗂𝟨𝟦.𝖼𝗈𝗇𝗌𝗍=] 0. 1. If |valuetype| equals [=𝖿𝟥𝟤=], return [=𝖿𝟥𝟤.𝖼𝗈𝗇𝗌𝗍=] 0. 1. If |valuetype| equals [=𝖿𝟨𝟦=], return [=𝖿𝟨𝟦.𝖼𝗈𝗇𝗌𝗍=] 0. - 1. If |valuetype| equals [=nullref=], return [=ref.null=]. - 1. If |valuetype| equals [=anyref=], return [=ToWebAssemblyValue=](undefined, |valuetype|). - 1. If |valuetype| equals [=nullref=], return [=ref.null=]. + 1. If |valuetype| equals [=externref=], return [=ToWebAssemblyValue=](undefined, |valuetype|). 1. Assert: This step is not reached. @@ -1093,12 +1087,10 @@ The algorithm ToWebAssemblyValue(|v|, |type|) coerces a JavaScript va 1. Let |f64| be ? [=ToNumber=](|v|). 1. Return [=𝖿𝟨𝟦.𝖼𝗈𝗇𝗌𝗍=] |f64|. 1. Assert: |type| is a reference type. -1. If |type| is [=anyref=], +1. If |type| is [=externref=], 1. Do nothing. 1. If |type| is [=funcref=], 1. If |v| is not an [=Exported function=] or null, throw a {{TypeError}}. -1. If |type| is [=nullref=], - 1. If |v| is not null, throw a {{TypeError}}. 1. Return the result of [=allocating a host address=] for |v|. diff --git a/interpreter/README.md b/interpreter/README.md index 2c320f16..8af4fd77 100644 --- a/interpreter/README.md +++ b/interpreter/README.md @@ -178,13 +178,14 @@ var: | unop: ctz | clz | popcnt | ... binop: add | sub | mul | ... relop: eq | ne | lt | ... -sign: s|u +sign: s | u offset: offset= align: align=(1|2|4|8|...) cvtop: trunc | extend | wrap | ... num_type: i32 | i64 | f32 | f64 -ref_type: anyref | funcref | nullref +ref_kind: func | extern +ref_type: funcref | externref val_type: num_type | ref_type block_type : ( result * )* func_type: ( type )? * * @@ -240,8 +241,8 @@ op: memory.copy memory.init data.drop - ref.null - ref.isnull + ref.null + ref.is_null ref.func .const . @@ -349,7 +350,7 @@ action: const: ( .const ) ;; number value - ( ref.null ) ;; null reference + ( ref.null ) ;; null reference ( ref.host ) ;; host reference assertion: @@ -363,7 +364,7 @@ assertion: result: ( .const ) - ( ref.any ) + ( ref.extern ) ( ref.func ) numpat: diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml index af687e86..4c1b135f 100644 --- a/interpreter/binary/decode.ml +++ b/interpreter/binary/decode.ml @@ -144,8 +144,7 @@ let num_type s = let ref_type s = match vs7 s with | -0x10 -> FuncRefType - | -0x11 -> AnyRefType - | -0x12 -> NullRefType + | -0x11 -> ExternRefType | _ -> error s (pos s - 1) "malformed reference type" let value_type s = @@ -444,8 +443,8 @@ let rec instr s = | 0xc0 | 0xc1 | 0xc2 | 0xc3 | 0xc4 | 0xc5 | 0xc6 | 0xc7 | 0xc8 | 0xc9 | 0xca | 0xcb | 0xcc | 0xcd | 0xce | 0xcf as b -> illegal s pos b - | 0xd0 -> ref_null - | 0xd1 -> ref_is_null + | 0xd0 -> ref_null (ref_type s) + | 0xd1 -> ref_is_null (ref_type s) | 0xd2 -> ref_func (at var s) | 0xfc as b1 -> diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml index 6910cf42..c0263df5 100644 --- a/interpreter/binary/encode.ml +++ b/interpreter/binary/encode.ml @@ -98,13 +98,11 @@ let encode m = let ref_type = function | FuncRefType -> vs7 (-0x10) - | AnyRefType -> vs7 (-0x11) - | NullRefType -> vs7 (-0x12) + | ExternRefType -> vs7 (-0x11) let value_type = function | NumType t -> num_type t | RefType t -> ref_type t - | BotType -> assert false let stack_type = function | [] -> vs7 (-0x40) @@ -233,8 +231,8 @@ let encode m = | MemoryInit x -> op 0xfc; op 0x08; var x; u8 0x00 | DataDrop x -> op 0xfc; op 0x09; var x - | RefNull -> op 0xd0 - | RefIsNull -> op 0xd1 + | RefNull t -> op 0xd0; ref_type t + | RefIsNull t -> op 0xd1; ref_type t | RefFunc x -> op 0xd2; var x | Const {it = I32 c; _} -> op 0x41; vs32 c diff --git a/interpreter/exec/eval.ml b/interpreter/exec/eval.ml index 58802850..aae2a0ce 100644 --- a/interpreter/exec/eval.ml +++ b/interpreter/exec/eval.ml @@ -97,7 +97,7 @@ let any_ref inst x i at = let func_ref inst x i at = match any_ref inst x i at with | FuncRef f -> f - | NullRef -> Trap.error at ("uninitialized element " ^ Int32.to_string i) + | NullRef _ -> Trap.error at ("uninitialized element " ^ Int32.to_string i) | _ -> Crash.error at ("type mismatch for element " ^ Int32.to_string i) let take n (vs : 'a stack) at = @@ -407,14 +407,16 @@ let rec step (c : config) : config = seg := ""; vs, [] - | RefNull, vs' -> - Ref NullRef :: vs', [] + | RefNull t, vs' -> + Ref (NullRef t) :: vs', [] - | RefIsNull, Ref r :: vs' -> - if r = NullRef then + | RefIsNull _, Ref r :: vs' -> + (match r with + | NullRef _ -> Num (I32 1l) :: vs', [] - else + | _ -> Num (I32 0l) :: vs', [] + ) | RefFunc x, vs' -> let f = func frame.inst x in @@ -534,7 +536,7 @@ let invoke (func : func_inst) (vs : value list) : value list = let FuncType (ins, out) = Func.type_of func in if List.length vs <> List.length ins then Crash.error at "wrong number of arguments"; - if not (List.for_all2 (fun v -> match_value_type (type_of_value v)) vs ins) then + if not (List.for_all2 (fun v -> (=) (type_of_value v)) vs ins) then Crash.error at "wrong types of arguments"; let c = config empty_module_inst (List.rev vs) [Invoke func @@ at] in try List.rev (eval c) with Stack_overflow -> @@ -554,7 +556,8 @@ let create_func (inst : module_inst) (f : func) : func_inst = let create_table (inst : module_inst) (tab : table) : table_inst = let {ttype} = tab.it in - Table.alloc ttype NullRef + let TableType (_lim, t) = ttype in + Table.alloc ttype (NullRef t) let create_memory (inst : module_inst) (mem : memory) : memory_inst = let {mtype} = mem.it in diff --git a/interpreter/host/spectest.ml b/interpreter/host/spectest.ml index a8d32aa5..8d67b3b7 100644 --- a/interpreter/host/spectest.ml +++ b/interpreter/host/spectest.ml @@ -14,12 +14,12 @@ let global (GlobalType (t, _) as gt) = | NumType I64Type -> Num (I64 666L) | NumType F32Type -> Num (F32 (F32.of_float 666.6)) | NumType F64Type -> Num (F64 (F64.of_float 666.6)) - | RefType _ -> Ref NullRef - | BotType -> assert false + | RefType t -> Ref (NullRef t) in Global.alloc gt v let table = - Table.alloc (TableType ({min = 10l; max = Some 20l}, FuncRefType)) NullRef + Table.alloc (TableType ({min = 10l; max = Some 20l}, FuncRefType)) + (NullRef FuncRefType) let memory = Memory.alloc (MemoryType {min = 1l; max = Some 2l}) let func f t = Func.alloc_host t (f t) diff --git a/interpreter/runtime/global.ml b/interpreter/runtime/global.ml index 181399e0..5e172995 100644 --- a/interpreter/runtime/global.ml +++ b/interpreter/runtime/global.ml @@ -8,7 +8,7 @@ exception Type exception NotMutable let alloc (GlobalType (t, _) as ty) v = - if not (match_value_type (type_of_value v) t) then raise Type; + if type_of_value v <> t then raise Type; {ty; content = v} let type_of glob = @@ -20,5 +20,5 @@ let load glob = let store glob v = let GlobalType (t, mut) = glob.ty in if mut <> Mutable then raise NotMutable; - if not (match_value_type (type_of_value v) t) then raise Type; + if type_of_value v <> t then raise Type; glob.content <- v diff --git a/interpreter/runtime/table.ml b/interpreter/runtime/table.ml index 8da0090e..bb10cab8 100644 --- a/interpreter/runtime/table.ml +++ b/interpreter/runtime/table.ml @@ -51,7 +51,7 @@ let load tab i = let store tab i r = let TableType (lim, t) = tab.ty in - if not (match_ref_type (type_of_ref r) t) then raise Type; + if type_of_ref r <> t then raise Type; try Lib.Array32.set tab.content i r with Invalid_argument _ -> raise Bounds let blit tab offset rs = diff --git a/interpreter/script/js.ml b/interpreter/script/js.ml index f0eeb114..66efeb73 100644 --- a/interpreter/script/js.ml +++ b/interpreter/script/js.ml @@ -10,25 +10,28 @@ let harness = {| 'use strict'; -let hostrefs = {}; -let hostsym = Symbol("hostref"); -function hostref(s) { - if (! (s in hostrefs)) hostrefs[s] = {[hostsym]: s}; - return hostrefs[s]; +let externrefs = {}; +let externsym = Symbol("externref"); +function externref(s) { + if (! (s in externrefs)) externrefs[s] = {[externsym]: s}; + return externrefs[s]; } -function is_hostref(x) { - return (x !== null && hostsym in x) ? 1 : 0; +function is_externref(x) { + return (x !== null && externsym in x) ? 1 : 0; } function is_funcref(x) { return typeof x === "function" ? 1 : 0; } -function eq_ref(x, y) { +function eq_externref(x, y) { + return x === y ? 1 : 0; +} +function eq_funcref(x, y) { return x === y ? 1 : 0; } let spectest = { - hostref: hostref, - is_hostref: is_hostref, + externref: externref, + is_externref: is_externref, is_funcref: is_funcref, eq_ref: eq_ref, print: console.log.bind(console), @@ -157,7 +160,7 @@ function assert_return(action, expected) { throw new Error("Wasm function return value expected, got " + actual); }; return; - case "ref.any": + case "ref.extern": if (actual === null) { throw new Error("Wasm reference return value expected, got " + actual); }; @@ -211,11 +214,12 @@ let lookup (mods : modules) x_opt name at = (* Wrappers *) let subject_idx = 0l -let hostref_idx = 1l -let _is_hostref_idx = 2l +let externref_idx = 1l +let is_externref_idx = 2l let is_funcref_idx = 3l -let eq_ref_idx = 4l -let subject_type_idx = 5l +let eq_externref_idx = 4l +let _eq_funcref_idx = 5l +let subject_type_idx = 6l let eq_of = function | I32Type -> Values.I32 I32Op.Eq @@ -244,9 +248,9 @@ let abs_mask_of = function let value v = match v.it with | Values.Num num -> [Const (num @@ v.at) @@ v.at] - | Values.Ref Values.NullRef -> [RefNull @@ v.at] - | Values.Ref (HostRef n) -> - [Const (Values.I32 n @@ v.at) @@ v.at; Call (hostref_idx @@ v.at) @@ v.at] + | Values.Ref (Values.NullRef t) -> [RefNull t @@ v.at] + | Values.Ref (ExternRef n) -> + [Const (Values.I32 n @@ v.at) @@ v.at; Call (externref_idx @@ v.at) @@ v.at] | Values.Ref _ -> assert false let invoke ft vs at = @@ -270,14 +274,14 @@ let assert_return ress ts at = Compare (eq_of t') @@ at; Test (Values.I32 I32Op.Eqz) @@ at; BrIf (0l @@ at) @@ at ] - | LitResult {it = Values.Ref Values.NullRef; _} -> - [ RefIsNull @@ at; + | LitResult {it = Values.Ref (Values.NullRef t); _} -> + [ RefIsNull t @@ at; Test (Values.I32 I32Op.Eqz) @@ at; BrIf (0l @@ at) @@ at ] - | LitResult {it = Values.Ref (HostRef n); _} -> + | LitResult {it = Values.Ref (ExternRef n); _} -> [ Const (Values.I32 n @@ at) @@ at; - Call (hostref_idx @@ at) @@ at; - Call (eq_ref_idx @@ at) @@ at; + Call (externref_idx @@ at) @@ at; + Call (eq_externref_idx @@ at) @@ at; Test (Values.I32 I32Op.Eqz) @@ at; BrIf (0l @@ at) @@ at ] | LitResult {it = Values.Ref _; _} -> @@ -302,11 +306,13 @@ let assert_return ress ts at = Compare (eq_of t') @@ at; Test (Values.I32 I32Op.Eqz) @@ at; BrIf (0l @@ at) @@ at ] - | RefResult -> - [ RefIsNull @@ at; - BrIf (0l @@ at) @@ at ] - | FuncResult -> - [ Call (is_funcref_idx @@ at) @@ at; + | RefResult t -> + let is_ref_idx = + match t with + | FuncRefType -> is_funcref_idx + | ExternRefType -> is_externref_idx + in + [ Call (is_ref_idx @@ at) @@ at; Test (Values.I32 I32Op.Eqz) @@ at; BrIf (0l @@ at) @@ at ] in [], List.flatten (List.rev_map test ress) @@ -316,22 +322,25 @@ let wrap item_name wrap_action wrap_assertion at = let locals, assertion = wrap_assertion at in let types = (FuncType ([], []) @@ at) :: - (FuncType ([NumType I32Type], [RefType AnyRefType]) @@ at) :: - (FuncType ([RefType AnyRefType], [NumType I32Type]) @@ at) :: - (FuncType ([RefType AnyRefType], [NumType I32Type]) @@ at) :: - (FuncType ([RefType AnyRefType; RefType AnyRefType], [NumType I32Type]) @@ at) :: + (FuncType ([NumType I32Type], [RefType ExternRefType]) @@ at) :: + (FuncType ([RefType ExternRefType], [NumType I32Type]) @@ at) :: + (FuncType ([RefType FuncRefType], [NumType I32Type]) @@ at) :: + (FuncType ([RefType ExternRefType; RefType ExternRefType], [NumType I32Type]) @@ at) :: + (FuncType ([RefType FuncRefType; RefType FuncRefType], [NumType I32Type]) @@ at) :: itypes in let imports = [ {module_name = Utf8.decode "module"; item_name; idesc} @@ at; - {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "hostref"; + {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "externref"; idesc = FuncImport (1l @@ at) @@ at} @@ at; - {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "is_hostref"; + {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "is_externref"; idesc = FuncImport (2l @@ at) @@ at} @@ at; {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "is_funcref"; idesc = FuncImport (3l @@ at) @@ at} @@ at; - {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "eq_ref"; - idesc = FuncImport (4l @@ at) @@ at} @@ at ] + {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "eq_externref"; + idesc = FuncImport (4l @@ at) @@ at} @@ at; + {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "eq_funcref"; + idesc = FuncImport (5l @@ at) @@ at} @@ at ] in let item = List.fold_left @@ -357,7 +366,6 @@ let is_js_num_type = function let is_js_value_type = function | NumType t -> is_js_num_type t | RefType t -> true - | BotType -> assert false let is_js_global_type = function | GlobalType (t, mut) -> is_js_value_type t && mut = Immutable @@ -407,8 +415,8 @@ let of_value v = | Num (I64 i) -> "int64(\"" ^ I64.to_string_s i ^ "\")" | Num (F32 z) -> of_float (F32.to_float z) | Num (F64 z) -> of_float (F64.to_float z) - | Ref NullRef -> "null" - | Ref (HostRef n) -> "hostref(" ^ Int32.to_string n ^ ")" + | Ref (NullRef _) -> "null" + | Ref (ExternRef n) -> "externref(" ^ Int32.to_string n ^ ")" | _ -> assert false let of_nan = function @@ -423,8 +431,7 @@ let of_result res = | Values.I32 _ | Values.I64 _ -> assert false | Values.F32 n | Values.F64 n -> of_nan n ) - | RefResult -> "\"ref.any\"" - | FuncResult -> "\"ref.func\"" + | RefResult t -> "\"ref." ^ string_of_refed_type t ^ "\"" let rec of_definition def = match def.it with diff --git a/interpreter/script/run.ml b/interpreter/script/run.ml index 11764e43..3eacacca 100644 --- a/interpreter/script/run.ml +++ b/interpreter/script/run.ml @@ -254,8 +254,7 @@ let type_of_result r = match r with | LitResult v -> Values.type_of_value v.it | NanResult n -> Types.NumType (Values.type_of_num n.it) - | RefResult -> Types.RefType Types.AnyRefType - | FuncResult -> Types.RefType Types.FuncRefType + | RefResult t -> Types.RefType t let string_of_result r = match r with @@ -265,8 +264,7 @@ let string_of_result r = | Values.I32 _ | Values.I64 _ -> assert false | Values.F32 n | Values.F64 n -> string_of_nan n ) - | RefResult -> "ref" - | FuncResult -> "func" + | RefResult t -> Types.string_of_refed_type t let string_of_results = function | [r] -> string_of_result r @@ -337,7 +335,7 @@ let run_action act : Values.value list = if List.length vs <> List.length ins then Script.error act.at "wrong number of arguments"; List.iter2 (fun v t -> - if not (Types.match_value_type (Values.type_of_value v.it) t) then + if Values.type_of_value v.it <> t then Script.error v.at "wrong type of argument" ) vs ins; Eval.invoke f (List.map (fun v -> v.it) vs) @@ -375,14 +373,10 @@ let assert_result at got expect = Int64.logand (F64.to_bits z) pos_nan <> pos_nan | _, _ -> false ) - | RefResult -> - (match v with - | Ref ref -> ref = NullRef - | _ -> true - ) - | FuncResult -> - (match v with - | Ref (Instance.FuncRef _) -> false + | RefResult t -> + (match t, v with + | Types.FuncRefType, Ref (Instance.FuncRef _) + | Types.ExternRefType, Ref (ExternRef _) -> false | _ -> true ) ) got expect diff --git a/interpreter/script/script.ml b/interpreter/script/script.ml index 0c664c01..50531b2f 100644 --- a/interpreter/script/script.ml +++ b/interpreter/script/script.ml @@ -1,6 +1,6 @@ type var = string Source.phrase -type Values.ref_ += HostRef of int32 +type Values.ref_ += ExternRef of int32 type value = Values.value Source.phrase type definition = definition' Source.phrase @@ -22,8 +22,7 @@ type result = result' Source.phrase and result' = | LitResult of Values.value Source.phrase | NanResult of nanop - | RefResult - | FuncResult + | RefResult of Types.ref_type type assertion = assertion' Source.phrase and assertion' = @@ -57,11 +56,11 @@ exception Syntax of Source.region * string let () = let type_of_ref' = !Values.type_of_ref' in Values.type_of_ref' := function - | HostRef _ -> Types.AnyRefType + | ExternRef _ -> Types.ExternRefType | r -> type_of_ref' r let () = let string_of_ref' = !Values.string_of_ref' in Values.string_of_ref' := function - | HostRef n -> "ref " ^ Int32.to_string n + | ExternRef n -> "ref " ^ Int32.to_string n | r -> string_of_ref' r diff --git a/interpreter/syntax/ast.ml b/interpreter/syntax/ast.ml index d3e1c6c0..c78a671a 100644 --- a/interpreter/syntax/ast.ml +++ b/interpreter/syntax/ast.ml @@ -102,8 +102,8 @@ and instr' = | MemoryCopy (* copy memory ranges *) | MemoryInit of var (* initialize memory range from segment *) | DataDrop of var (* drop passive data segment *) - | RefNull (* null reference *) - | RefIsNull (* null test *) + | RefNull of ref_type (* null reference *) + | RefIsNull of ref_type (* null test *) | RefFunc of var (* function reference *) | Const of num (* constant *) | Test of testop (* numeric test *) diff --git a/interpreter/syntax/free.ml b/interpreter/syntax/free.ml index af322f67..fb8973cf 100644 --- a/interpreter/syntax/free.ml +++ b/interpreter/syntax/free.ml @@ -62,7 +62,7 @@ let list free xs = List.fold_left union empty (List.map free xs) let rec instr (e : instr) = match e.it with | Unreachable | Nop | Drop | Select _ -> empty - | RefNull | RefIsNull -> empty + | RefNull _ | RefIsNull _ -> empty | RefFunc x -> funcs (var x) | Const _ | Test _ | Compare _ | Unary _ | Binary _ | Convert _ -> empty | Block (_, es) | Loop (_, es) -> block es diff --git a/interpreter/syntax/operators.ml b/interpreter/syntax/operators.ml index e804a413..4a5d5a48 100644 --- a/interpreter/syntax/operators.ml +++ b/interpreter/syntax/operators.ml @@ -9,9 +9,9 @@ let i32_const n = Const (I32 n.it @@ n.at) let i64_const n = Const (I64 n.it @@ n.at) let f32_const n = Const (F32 n.it @@ n.at) let f64_const n = Const (F64 n.it @@ n.at) -let ref_null = RefNull let ref_func x = RefFunc x -let ref_is_null = RefIsNull +let ref_null t = RefNull t +let ref_is_null t = RefIsNull t let unreachable = Unreachable let nop = Nop diff --git a/interpreter/syntax/types.ml b/interpreter/syntax/types.ml index fb3f13b1..82faaf6e 100644 --- a/interpreter/syntax/types.ml +++ b/interpreter/syntax/types.ml @@ -1,8 +1,8 @@ (* Types *) type num_type = I32Type | I64Type | F32Type | F64Type -type ref_type = NullRefType | AnyRefType | FuncRefType -type value_type = NumType of num_type | RefType of ref_type | BotType +type ref_type = FuncRefType | ExternRefType +type value_type = NumType of num_type | RefType of ref_type type stack_type = value_type list type func_type = FuncType of stack_type * stack_type @@ -24,24 +24,28 @@ let size = function | I32Type | F32Type -> 4 | I64Type | F64Type -> 8 +let is_num_type = function + | NumType _ -> true + | RefType _ -> false -(* Subtyping *) +let is_ref_type = function + | NumType _ -> false + | RefType _ -> true -let match_num_type t1 t2 = - t1 = t2 -let match_ref_type t1 t2 = - match t1, t2 with - | _, AnyRefType -> true - | NullRefType, _ -> true - | _, _ -> t1 = t2 +(* Filters *) -let match_value_type t1 t2 = - match t1, t2 with - | NumType t1', NumType t2' -> match_num_type t1' t2' - | RefType t1', RefType t2' -> match_ref_type t1' t2' - | BotType, _ -> true - | _, _ -> false +let funcs = + Lib.List.map_filter (function ExternFuncType t -> Some t | _ -> None) +let tables = + Lib.List.map_filter (function ExternTableType t -> Some t | _ -> None) +let memories = + Lib.List.map_filter (function ExternMemoryType t -> Some t | _ -> None) +let globals = + Lib.List.map_filter (function ExternGlobalType t -> Some t | _ -> None) + + +(* Subtyping *) let match_limits lim1 lim2 = I32.ge_u lim1.min lim2.min && @@ -59,9 +63,8 @@ let match_table_type (TableType (lim1, et1)) (TableType (lim2, et2)) = let match_memory_type (MemoryType lim1) (MemoryType lim2) = match_limits lim1 lim2 -let match_global_type (GlobalType (t1, mut1)) (GlobalType (t2, mut2)) = - mut1 = mut2 && - (t1 = t2 || mut2 = Immutable && match_value_type t1 t2) +let match_global_type gt1 gt2 = + gt1 = gt2 let match_extern_type et1 et2 = match et1, et2 with @@ -71,26 +74,6 @@ let match_extern_type et1 et2 = | ExternGlobalType gt1, ExternGlobalType gt2 -> match_global_type gt1 gt2 | _, _ -> false -let is_num_type = function - | NumType _ | BotType -> true - | RefType _ -> false - -let is_ref_type = function - | NumType _ -> false - | RefType _ | BotType -> true - - -(* Filters *) - -let funcs = - Lib.List.map_filter (function ExternFuncType t -> Some t | _ -> None) -let tables = - Lib.List.map_filter (function ExternTableType t -> Some t | _ -> None) -let memories = - Lib.List.map_filter (function ExternMemoryType t -> Some t | _ -> None) -let globals = - Lib.List.map_filter (function ExternGlobalType t -> Some t | _ -> None) - (* String conversion *) @@ -101,14 +84,16 @@ let string_of_num_type = function | F64Type -> "f64" let string_of_ref_type = function - | NullRefType -> "nullref" - | AnyRefType -> "anyref" | FuncRefType -> "funcref" + | ExternRefType -> "externref" + +let string_of_refed_type = function + | FuncRefType -> "func" + | ExternRefType -> "extern" let string_of_value_type = function | NumType t -> string_of_num_type t | RefType t -> string_of_ref_type t - | BotType -> "impossible" let string_of_value_types = function | [t] -> string_of_value_type t diff --git a/interpreter/syntax/values.ml b/interpreter/syntax/values.ml index 6907ae75..63416609 100644 --- a/interpreter/syntax/values.ml +++ b/interpreter/syntax/values.ml @@ -9,7 +9,7 @@ type ('i32, 'i64, 'f32, 'f64) op = type num = (I32.t, I64.t, F32.t, F64.t) op type ref_ = .. -type ref_ += NullRef +type ref_ += NullRef of ref_type type value = Num of num | Ref of ref_ @@ -22,7 +22,7 @@ let type_of_num = function | F32 _ -> F32Type | F64 _ -> F64Type -let type_of_ref' = ref (function NullRef -> NullRefType | _ -> AnyRefType) +let type_of_ref' = ref (function NullRef t -> t | _ -> assert false) let type_of_ref r = !type_of_ref' r let type_of_value = function @@ -50,12 +50,11 @@ let default_num = function | F64Type -> F64 F64.zero let default_ref = function - | _ -> NullRef + | t -> NullRef t let default_value = function | NumType t' -> Num (default_num t') | RefType t' -> Ref (default_ref t') - | BotType -> assert false (* Conversion *) @@ -68,7 +67,7 @@ let string_of_num = function | F32 z -> F32.to_string z | F64 z -> F64.to_string z -let string_of_ref' = ref (function NullRef -> "null" | _ -> "ref") +let string_of_ref' = ref (function NullRef t -> "null" | _ -> "ref") let string_of_ref r = !string_of_ref' r let string_of_value = function diff --git a/interpreter/text/arrange.ml b/interpreter/text/arrange.ml index 6fc76e93..a6733c1a 100644 --- a/interpreter/text/arrange.ml +++ b/interpreter/text/arrange.ml @@ -57,6 +57,7 @@ let break_string s = let num_type t = string_of_num_type t let ref_type t = string_of_ref_type t +let refed_type t = string_of_refed_type t let value_type t = string_of_value_type t let decls kind ts = tab kind (atom value_type) ts @@ -262,8 +263,8 @@ let rec instr e = | MemoryCopy -> "memory.copy", [] | MemoryInit x -> "memory.init " ^ var x, [] | DataDrop x -> "data.drop " ^ var x, [] - | RefNull -> "ref.null", [] - | RefIsNull -> "ref.is_null", [] + | RefNull t -> "ref.null", [Atom (refed_type t)] + | RefIsNull t -> "ref.is_null", [Atom (refed_type t)] | RefFunc x -> "ref.func " ^ var x, [] | Const n -> constop n ^ " " ^ num n, [] | Test op -> testop op, [] @@ -431,8 +432,8 @@ let value v = | Num (Values.I64 i) -> Node ("i64.const " ^ I64.to_string_s i, []) | Num (Values.F32 z) -> Node ("f32.const " ^ F32.to_string z, []) | Num (Values.F64 z) -> Node ("f64.const " ^ F64.to_string z, []) - | Ref NullRef -> Node ("ref.null", []) - | Ref (HostRef n) -> Node ("ref.host " ^ Int32.to_string n, []) + | Ref (NullRef t) -> Node ("ref.null", [Atom (refed_type t)]) + | Ref (ExternRef n) -> Node ("ref.extern " ^ Int32.to_string n, []) | _ -> assert false let definition mode x_opt def = @@ -483,8 +484,7 @@ let result res = | Values.F32 n -> Node ("f32.const " ^ nan n, []) | Values.F64 n -> Node ("f64.const " ^ nan n, []) ) - | RefResult -> Node ("ref", []) - | FuncResult -> Node ("ref.func", []) + | RefResult t -> Node ("ref." ^ refed_type t, []) let assertion mode ass = match ass.it with diff --git a/interpreter/text/lexer.mll b/interpreter/text/lexer.mll index 3a1c3f11..36524d23 100644 --- a/interpreter/text/lexer.mll +++ b/interpreter/text/lexer.mll @@ -160,9 +160,9 @@ rule token = parse | '"'character*'\\'_ { error_nest (Lexing.lexeme_end_p lexbuf) lexbuf "illegal escape" } - | "anyref" { ANYREF } + | "extern" { EXTERN } + | "externref" { EXTERNREF } | "funcref" { FUNCREF } - | "nullref" { NULLREF } | (nxx as t) { NUM_TYPE (num_type t) } | "mut" { MUT } @@ -180,7 +180,7 @@ rule token = parse } | "ref.null" { REF_NULL } | "ref.func" { REF_FUNC } - | "ref.host" { REF_HOST } + | "ref.extern" { REF_EXTERN } | "ref.is_null" { REF_IS_NULL } | "nop" { NOP } @@ -370,7 +370,6 @@ rule token = parse | "assert_exhaustion" { ASSERT_EXHAUSTION } | "nan:canonical" { NAN Script.CanonicalNan } | "nan:arithmetic" { NAN Script.ArithmeticNan } - | "ref.any" { REF_ANY } | "input" { INPUT } | "output" { OUTPUT } diff --git a/interpreter/text/parser.mly b/interpreter/text/parser.mly index 07be9cbc..445c6db3 100644 --- a/interpreter/text/parser.mly +++ b/interpreter/text/parser.mly @@ -164,7 +164,7 @@ let inline_type_explicit (c : context) x ft at = %token LPAR RPAR %token NAT INT FLOAT STRING VAR -%token ANYREF NULLREF FUNCREF NUM_TYPE MUT +%token NUM_TYPE FUNCREF EXTERNREF EXTERN MUT %token UNREACHABLE NOP DROP SELECT %token BLOCK END IF THEN ELSE LOOP BR BR_IF BR_TABLE %token CALL CALL_INDIRECT RETURN @@ -174,7 +174,7 @@ let inline_type_explicit (c : context) x ft at = %token MEMORY_SIZE MEMORY_GROW MEMORY_FILL MEMORY_COPY MEMORY_INIT DATA_DROP %token LOAD STORE OFFSET_EQ_NAT ALIGN_EQ_NAT %token CONST UNARY BINARY TEST COMPARE CONVERT -%token REF_ANY REF_NULL REF_FUNC REF_HOST REF_IS_NULL +%token REF_NULL REF_FUNC REF_EXTERN REF_IS_NULL %token FUNC START TYPE PARAM RESULT LOCAL GLOBAL %token TABLE ELEM MEMORY DATA DECLARE OFFSET ITEM IMPORT EXPORT %token MODULE BIN QUOTE @@ -226,10 +226,13 @@ string_list : /* Types */ +ref_kind : + | FUNC { FuncRefType } + | EXTERN { ExternRefType } + ref_type : - | ANYREF { AnyRefType } | FUNCREF { FuncRefType } - | NULLREF { NullRefType } + | EXTERNREF { ExternRefType } value_type : | NUM_TYPE { NumType $1 } @@ -372,8 +375,8 @@ plain_instr : | MEMORY_COPY { fun c -> memory_copy } | MEMORY_INIT var { fun c -> memory_init ($2 c data) } | DATA_DROP var { fun c -> data_drop ($2 c data) } - | REF_NULL { fun c -> ref_null } - | REF_IS_NULL { fun c -> ref_is_null } + | REF_NULL ref_kind { fun c -> ref_null $2 } + | REF_IS_NULL ref_kind { fun c -> ref_is_null $2 } | REF_FUNC var { fun c -> ref_func ($2 c func) } | CONST num { fun c -> fst (num $1 $2) } | TEST { fun c -> $1 } @@ -986,8 +989,8 @@ meta : const : | LPAR CONST num RPAR { Values.Num (snd (num $2 $3)) @@ at () } - | LPAR REF_NULL RPAR { Values.Ref Values.NullRef @@ at () } - | LPAR REF_HOST NAT RPAR { Values.Ref (HostRef (nat32 $3 (ati 3))) @@ at () } + | LPAR REF_NULL ref_kind RPAR { Values.Ref (Values.NullRef $3) @@ at () } + | LPAR REF_EXTERN NAT RPAR { Values.Ref (ExternRef (nat32 $3 (ati 3))) @@ at () } const_list : | /* empty */ { [] } @@ -996,8 +999,8 @@ const_list : result : | const { LitResult $1 @@ at () } | LPAR CONST NAN RPAR { NanResult (nanop $2 ($3 @@ ati 3)) @@ at () } - | LPAR REF_ANY RPAR { RefResult @@ at () } - | LPAR REF_FUNC RPAR { FuncResult @@ at () } + | LPAR REF_FUNC RPAR { RefResult FuncRefType @@ at () } + | LPAR REF_EXTERN RPAR { RefResult ExternRefType @@ at () } result_list : | /* empty */ { [] } diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml index 30de76a6..1eb6bcf1 100644 --- a/interpreter/valid/valid.ml +++ b/interpreter/valid/valid.ml @@ -70,25 +70,32 @@ let refer_func (c : context) x = refer "function" c.refs.Free.funcs x *) type ellipses = NoEllipses | Ellipses -type infer_stack_type = ellipses * value_type list +type infer_stack_type = ellipses * value_type option list type op_type = {ins : infer_stack_type; outs : infer_stack_type} -let stack ts = (NoEllipses, ts) -let (-->) ts1 ts2 = {ins = NoEllipses, ts1; outs = NoEllipses, ts2} -let (-->...) ts1 ts2 = {ins = Ellipses, ts1; outs = Ellipses, ts2} +let known = List.map (fun t -> Some t) +let stack ts = (NoEllipses, known ts) +let (-~>) ts1 ts2 = {ins = NoEllipses, ts1; outs = NoEllipses, ts2} +let (-->) ts1 ts2 = {ins = NoEllipses, known ts1; outs = NoEllipses, known ts2} +let (-->...) ts1 ts2 = {ins = Ellipses, known ts1; outs = Ellipses, known ts2} +let string_of_infer_type t = + Lib.Option.get (Lib.Option.map string_of_value_type t) "_" +let string_of_infer_types ts = + "[" ^ String.concat " " (List.map string_of_infer_type ts) ^ "]" + +let eq_ty t1 t2 = (t1 = t2 || t1 = None || t2 = None) let check_stack ts1 ts2 at = - require - (List.length ts1 = List.length ts2 && List.for_all2 match_value_type ts1 ts2) at - ("type mismatch: operator requires " ^ string_of_stack_type ts2 ^ - " but stack has " ^ string_of_stack_type ts1) + require (List.length ts1 = List.length ts2 && List.for_all2 eq_ty ts1 ts2) at + ("type mismatch: operator requires " ^ string_of_infer_types ts1 ^ + " but stack has " ^ string_of_infer_types ts2) let pop (ell1, ts1) (ell2, ts2) at = let n1 = List.length ts1 in let n2 = List.length ts2 in let n = min n1 n2 in let n3 = if ell2 = Ellipses then (n1 - n) else 0 in - check_stack (Lib.List.make n3 BotType @ Lib.List.drop (n2 - n) ts2) ts1 at; + check_stack ts1 (Lib.List.make n3 None @ Lib.List.drop (n2 - n) ts2) at; (ell2, if ell1 = Ellipses then [] else Lib.List.take (n2 - n) ts2) let push (ell1, ts1) (ell2, ts2) = @@ -97,7 +104,7 @@ let push (ell1, ts1) (ell2, ts2) = ts2 @ ts1 let peek i (ell, ts) = - try List.nth (List.rev ts) i with Failure _ -> BotType + try List.nth (List.rev ts) i with Failure _ -> None (* Type Synthesis *) @@ -191,14 +198,14 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type = [] --> [] | Drop -> - [peek 0 s] --> [] + [peek 0 s] -~> [] | Select None -> let t = peek 1 s in - require (is_num_type t) e.at + require (match t with None -> true | Some t -> is_num_type t) e.at ("type mismatch: instruction requires numeric type" ^ - " but stack has " ^ string_of_value_type t); - [t; t; NumType I32Type] --> [t] + " but stack has " ^ string_of_infer_type t); + [t; t; Some (NumType I32Type)] -~> [t] | Select (Some ts) -> check_arity (List.length ts) e.at; @@ -228,10 +235,8 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type = (label c x @ [NumType I32Type]) --> label c x | BrTable (xs, x) -> - let n = List.length (label c x) in - let ts = Lib.List.table n (fun i -> peek (i + 1) s) in - check_stack ts (label c x) x.at; - List.iter (fun x' -> check_stack ts (label c x') x'.at) xs; + let ts = label c x in + List.iter (fun x' -> check_stack (known ts) (known (label c x')) x'.at) xs; (ts @ [NumType I32Type]) -->... [] | Return -> @@ -244,7 +249,7 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type = | CallIndirect (x, y) -> let TableType (lim, t) = table c x in let FuncType (ins, out) = type_ c y in - require (match_ref_type t FuncRefType) x.at + require (t = FuncRefType) x.at ("type mismatch: instruction requires table of functions" ^ " but table has " ^ string_of_ref_type t); (ins @ [NumType I32Type]) --> out @@ -290,7 +295,7 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type = | TableCopy (x, y) -> let TableType (_lim1, t1) = table c x in let TableType (_lim2, t2) = table c y in - require (match_ref_type t2 t1) x.at + require (t1 = t2) x.at ("type mismatch: source element type " ^ string_of_ref_type t1 ^ " does not match destination element type " ^ string_of_ref_type t2); [NumType I32Type; NumType I32Type; NumType I32Type] --> [] @@ -298,7 +303,7 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type = | TableInit (x, y) -> let TableType (_lim1, t1) = table c x in let t2 = elem c y in - require (match_ref_type t2 t1) x.at + require (t1 = t2) x.at ("type mismatch: source element type " ^ string_of_ref_type t1 ^ " does not match destination element type " ^ string_of_ref_type t2); [NumType I32Type; NumType I32Type; NumType I32Type] --> [] @@ -342,11 +347,11 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type = ignore (data c x); [] --> [] - | RefNull -> - [] --> [RefType NullRefType] + | RefNull t -> + [] --> [RefType t] - | RefIsNull -> - [RefType AnyRefType] --> [NumType I32Type] + | RefIsNull t -> + [RefType t] --> [NumType I32Type] | RefFunc x -> let _ft = func c x in @@ -393,7 +398,7 @@ and check_block (c : context) (es : instr list) (ts : stack_type) at = let s' = pop (stack ts) s at in require (snd s' = []) at ("type mismatch: operator requires " ^ string_of_stack_type ts ^ - " but stack has " ^ string_of_stack_type (snd s)) + " but stack has " ^ string_of_infer_types (snd s)) (* Types *) @@ -417,7 +422,6 @@ let check_value_type (t : value_type) at = match t with | NumType t' -> check_num_type t' at | RefType t' -> check_ref_type t' at - | BotType -> () let check_func_type (ft : func_type) at = let FuncType (ins, out) = ft in @@ -466,7 +470,7 @@ let check_func (c : context) (f : func) = let is_const (c : context) (e : instr) = match e.it with - | RefNull + | RefNull _ | RefFunc _ | Const _ -> true | GlobalGet x -> let GlobalType (_, mut) = global c x in mut = Immutable @@ -493,7 +497,7 @@ let check_elem_mode (c : context) (t : ref_type) (mode : segment_mode) = | Passive -> () | Active {index; offset} -> let TableType (_, et) = table c index in - require (match_ref_type t et) mode.at + require (t = et) mode.at "type mismatch in active element segment"; check_const c offset (NumType I32Type) | Declarative -> () diff --git a/proposals/reference-types/Overview.md b/proposals/reference-types/Overview.md index 8e35ab71..14ff3b41 100644 --- a/proposals/reference-types/Overview.md +++ b/proposals/reference-types/Overview.md @@ -7,7 +7,7 @@ TODO: more text, motivation, explanation Motivation: * Easier and more efficient interop with host environment (see e.g. the [Interface Types proposal](https://github.com/WebAssembly/interface-types/blob/master/proposals/interface-types/Explainer.md)) - - allow host references to be represented directly by type `anyref` (see [here](https://github.com/WebAssembly/interface-types/issues/9)) + - allow host references to be represented directly by type `externref` (see [here](https://github.com/WebAssembly/interface-types/issues/9)) - without having to go through tables, allocating slots, and maintaining index bijections at the boundaries * Basic manipulation of tables inside Wasm @@ -25,8 +25,7 @@ by repurposing tables as a general memory for opaque data types Get the most important parts soon! Summary: - -* Add new types `anyref` and `nullref` that can be used as both a value types and a table element types. +* Add new type `externref` that can be used as both a value types and a table element type. * Also allow `funcref` as a value type. @@ -47,8 +46,8 @@ Notes: Typing extensions: -* Introduce `anyref`, `funcref`, and `nullref` as a new class of *reference types*. - - `reftype ::= anyref | funcref | nullref` +* Introduce `funcref` and `externref` as a new class of *reference types*. + - `reftype ::= funcref | externref` * Value types (of locals, globals, function parameters and results) can now be either numeric types or reference types. - `numtype ::= i32 | i64 | f32 | f64` @@ -58,21 +57,17 @@ Typing extensions: * Element types (of tables) are equated with reference types. - `elemtype ::= ` -* Introduce a simple subtype relation between reference types. - - reflexive transitive closure of the following rules - - `t <: anyref` for all reftypes `t` - - `nullref <: anyref` and `nullref <: funcref` - - Note: No rule `nullref <: t` for all reftypes `t` -- while that is derivable from the above given the current set of types it might not hold for future reference types which don't allow null. - New/extended instructions: * The new instruction `ref.null` evaluates to the null reference constant. - - `ref.null : [] -> [nullref]` + - `ref.null rt : [] -> [rtref]` + - iff `rt = func` or `rt = extern` - allowed in constant expressions * The new instruction `ref.is_null` checks for null. - - `ref.is_null : [anyref] -> [i32]` + - `ref.is_null rt : [rtref] -> [i32]` + - iff `rt = func` or `rt = extern` * The new instruction `ref.func` creates a reference to a given function. - `ref.func $x : [] -> [funcref]` @@ -137,7 +132,7 @@ Table extensions: API extensions: -* Any JS value can be passed as `anyref` to a Wasm function, stored in a global, or in a table. +* Any JS value can be passed as `externref` to a Wasm function, stored in a global, or in a table. * Any Wasm exported function object or `null` can be passed as `funcref` to a Wasm function, stored in a global, or in a table. @@ -145,6 +140,19 @@ API extensions: ## Possible Future Extensions +### Subtyping + +Motivation: + +* Enable various extensions (see below). + +Additions: + +* Introduce a simple subtype relation between reference types. + - reflexive transitive closure of the following rules + - `t <: anyref` for all reftypes `t` + + ### Equality on references Motivation: @@ -159,7 +167,6 @@ Additions: - `reftype ::= ... | eqref` * It is a subtype of `anyref` - `eqref < anyref` - - `nullref < eqref` * Add `ref.eq` instruction. - `ref.eq : [eqref eqref] -> [i32]` diff --git a/test/core/binary.wast b/test/core/binary.wast index 91cdd359..4b00271d 100644 --- a/test/core/binary.wast +++ b/test/core/binary.wast @@ -1116,10 +1116,10 @@ "\05\03\01\00\00" ;; Memory section - "\09\06\01" ;; Element section with one segment + "\09\07\01" ;; Element section with one segment "\05\70" ;; Passive, funcref "\01" ;; 1 element - "\d0\0b" ;; ref.null, end + "\d0\70\0b" ;; ref.null, end "\0a\04\01" ;; Code section diff --git a/test/core/br_table.wast b/test/core/br_table.wast index 48e7a874..fc84e2f0 100644 --- a/test/core/br_table.wast +++ b/test/core/br_table.wast @@ -1243,72 +1243,13 @@ ) ) - (func (export "meet-anyref") (param i32) (param anyref) (result anyref) - (block $l1 (result anyref) - (block $l2 (result anyref) + (func (export "meet-externref") (param i32) (param externref) (result externref) + (block $l1 (result externref) + (block $l2 (result externref) (br_table $l1 $l2 $l1 (local.get 1) (local.get 0)) ) ) ) - - (func (export "meet-funcref-1") (param i32) (result anyref) - (block $l1 (result anyref) - (block $l2 (result funcref) - (br_table $l1 $l1 $l2 (table.get 0 (i32.const 0)) (local.get 0)) - ) - ) - ) - (func (export "meet-funcref-2") (param i32) (result anyref) - (block $l1 (result anyref) - (block $l2 (result funcref) - (br_table $l2 $l2 $l1 (table.get 0 (i32.const 0)) (local.get 0)) - ) - ) - ) - (func (export "meet-funcref-3") (param i32) (result anyref) - (block $l1 (result anyref) - (block $l2 (result funcref) - (br_table $l2 $l1 $l2 (table.get 0 (i32.const 0)) (local.get 0)) - ) - ) - ) - (func (export "meet-funcref-4") (param i32) (result anyref) - (block $l1 (result anyref) - (block $l2 (result funcref) - (br_table $l1 $l2 $l1 (table.get 0 (i32.const 0)) (local.get 0)) - ) - ) - ) - - (func (export "meet-nullref") (param i32) (result funcref) - (block $l1 (result funcref) - (block $l2 (result nullref) - (br_table $l1 $l2 $l1 (ref.null) (local.get 0)) - ) - ) - ) - - (func (export "meet-multi-ref") (param i32) (result anyref) - (block $l1 (result anyref) - (block $l2 (result funcref) - (block $l3 (result nullref) - (br_table $l3 $l2 $l1 (ref.null) (local.get 0)) - ) - ) - ) - ) - - (func (export "meet-bottom") - (block (result f64) - (block (result f32) - (unreachable) - (br_table 0 1 1 (i32.const 1)) - ) - (drop) - (f64.const 0) - ) - (drop) - ) ) (assert_return (invoke "type-i32")) @@ -1492,22 +1433,9 @@ (assert_return (invoke "nested-br_table-loop-block" (i32.const 1)) (i32.const 3)) -(assert_return (invoke "meet-anyref" (i32.const 0) (ref.host 1)) (ref.host 1)) -(assert_return (invoke "meet-anyref" (i32.const 1) (ref.host 1)) (ref.host 1)) -(assert_return (invoke "meet-anyref" (i32.const 2) (ref.host 1)) (ref.host 1)) - -(assert_return (invoke "meet-funcref-1" (i32.const 0)) (ref.func)) -(assert_return (invoke "meet-funcref-1" (i32.const 1)) (ref.func)) -(assert_return (invoke "meet-funcref-1" (i32.const 2)) (ref.func)) -(assert_return (invoke "meet-funcref-2" (i32.const 0)) (ref.func)) -(assert_return (invoke "meet-funcref-2" (i32.const 1)) (ref.func)) -(assert_return (invoke "meet-funcref-2" (i32.const 2)) (ref.func)) -(assert_return (invoke "meet-funcref-3" (i32.const 0)) (ref.func)) -(assert_return (invoke "meet-funcref-3" (i32.const 1)) (ref.func)) -(assert_return (invoke "meet-funcref-3" (i32.const 2)) (ref.func)) -(assert_return (invoke "meet-funcref-4" (i32.const 0)) (ref.func)) -(assert_return (invoke "meet-funcref-4" (i32.const 1)) (ref.func)) -(assert_return (invoke "meet-funcref-4" (i32.const 2)) (ref.func)) +(assert_return (invoke "meet-externref" (i32.const 0) (ref.extern 1)) (ref.extern 1)) +(assert_return (invoke "meet-externref" (i32.const 1) (ref.extern 1)) (ref.extern 1)) +(assert_return (invoke "meet-externref" (i32.const 2) (ref.extern 1)) (ref.extern 1)) (assert_invalid (module (func $type-arg-void-vs-num (result i32) @@ -1636,15 +1564,16 @@ "type mismatch" ) + (assert_invalid - (module (func $meet-bottom (param i32) (result anyref) - (block $l1 (result anyref) + (module (func $meet-bottom (param i32) (result externref) + (block $l1 (result externref) (drop (block $l2 (result i32) - (br_table $l2 $l1 $l2 (ref.null) (local.get 0)) + (br_table $l2 $l1 $l2 (ref.null extern) (local.get 0)) ) ) - (ref.null) + (ref.null extern) ) )) "type mismatch" diff --git a/test/core/bulk.wast b/test/core/bulk.wast index fe71939d..1927461f 100644 --- a/test/core/bulk.wast +++ b/test/core/bulk.wast @@ -5,7 +5,7 @@ (module (table 3 funcref) - (elem funcref (ref.func 0) (ref.null) (ref.func 1)) + (elem funcref (ref.func 0) (ref.null func) (ref.func 1)) (func) (func)) diff --git a/test/core/elem.wast b/test/core/elem.wast index 6661c9a8..d0537aa2 100644 --- a/test/core/elem.wast +++ b/test/core/elem.wast @@ -8,18 +8,18 @@ ;; Passive (elem funcref) - (elem funcref (ref.func $f) (item ref.func $f) (item (ref.null)) (ref.func $g)) + (elem funcref (ref.func $f) (item ref.func $f) (item (ref.null func)) (ref.func $g)) (elem func) (elem func $f $f $g $g) (elem $p1 funcref) - (elem $p2 funcref (ref.func $f) (ref.func $f) (ref.null) (ref.func $g)) + (elem $p2 funcref (ref.func $f) (ref.func $f) (ref.null func) (ref.func $g)) (elem $p3 func) (elem $p4 func $f $f $g $g) ;; Active (elem (table $t) (i32.const 0) funcref) - (elem (table $t) (i32.const 0) funcref (ref.func $f) (ref.null)) + (elem (table $t) (i32.const 0) funcref (ref.func $f) (ref.null func)) (elem (table $t) (i32.const 0) func) (elem (table $t) (i32.const 0) func $f $g) (elem (table $t) (offset (i32.const 0)) funcref) @@ -33,16 +33,16 @@ (elem (table $t) (offset (i32.const 0)) func) (elem (table $t) (offset (i32.const 0)) func $f $f) (elem (offset (i32.const 0))) - (elem (offset (i32.const 0)) funcref (ref.func $f) (ref.null)) + (elem (offset (i32.const 0)) funcref (ref.func $f) (ref.null func)) (elem (offset (i32.const 0)) func $f $f) (elem (offset (i32.const 0)) $f $f) (elem (i32.const 0)) - (elem (i32.const 0) funcref (ref.func $f) (ref.null)) + (elem (i32.const 0) funcref (ref.func $f) (ref.null func)) (elem (i32.const 0) func $f $f) (elem (i32.const 0) $f $f) (elem $a1 (table $t) (i32.const 0) funcref) - (elem $a2 (table $t) (i32.const 0) funcref (ref.func $f) (ref.null)) + (elem $a2 (table $t) (i32.const 0) funcref (ref.func $f) (ref.null func)) (elem $a3 (table $t) (i32.const 0) func) (elem $a4 (table $t) (i32.const 0) func $f $g) (elem $a9 (table $t) (offset (i32.const 0)) funcref) @@ -56,22 +56,22 @@ (elem $a17 (table $t) (offset (i32.const 0)) func) (elem $a18 (table $t) (offset (i32.const 0)) func $f $f) (elem $a19 (offset (i32.const 0))) - (elem $a20 (offset (i32.const 0)) funcref (ref.func $f) (ref.null)) + (elem $a20 (offset (i32.const 0)) funcref (ref.func $f) (ref.null func)) (elem $a21 (offset (i32.const 0)) func $f $f) (elem $a22 (offset (i32.const 0)) $f $f) (elem $a23 (i32.const 0)) - (elem $a24 (i32.const 0) funcref (ref.func $f) (ref.null)) + (elem $a24 (i32.const 0) funcref (ref.func $f) (ref.null func)) (elem $a25 (i32.const 0) func $f $f) (elem $a26 (i32.const 0) $f $f) ;; Declarative (elem declare funcref) - (elem declare funcref (ref.func $f) (ref.func $f) (ref.null) (ref.func $g)) + (elem declare funcref (ref.func $f) (ref.func $f) (ref.null func) (ref.func $g)) (elem declare func) (elem declare func $f $f $g $g) (elem $d1 declare funcref) - (elem $d2 declare funcref (ref.func $f) (ref.func $f) (ref.null) (ref.func $g)) + (elem $d2 declare funcref (ref.func $f) (ref.func $f) (ref.null func) (ref.func $g)) (elem $d3 declare func) (elem $d4 declare func $f $f $g $g) ) @@ -80,7 +80,7 @@ (func $f) (func $g) - (table $t funcref (elem (ref.func $f) (ref.null) (ref.func $g))) + (table $t funcref (elem (ref.func $f) (ref.null func) (ref.func $g))) ) diff --git a/test/core/global.wast b/test/core/global.wast index 1326679e..a19ae5e7 100644 --- a/test/core/global.wast +++ b/test/core/global.wast @@ -11,12 +11,12 @@ (global (;6;) (mut f64) (f64.const -14)) (global $y (mut i64) (i64.const -15)) - (global $r anyref (ref.null)) - (global funcref (ref.null)) + (global $r externref (ref.null extern)) + (global funcref (ref.null func)) (func (export "get-a") (result i32) (global.get $a)) (func (export "get-b") (result i64) (global.get $b)) - (func (export "get-r") (result anyref) (global.get $r)) + (func (export "get-r") (result externref) (global.get $r)) (func (export "get-x") (result i32) (global.get $x)) (func (export "get-y") (result i64) (global.get $y)) (func (export "set-x") (param i32) (global.set $x (local.get 0))) @@ -184,7 +184,7 @@ (assert_return (invoke "get-a") (i32.const -2)) (assert_return (invoke "get-b") (i64.const -5)) -(assert_return (invoke "get-r") (ref.null)) +(assert_return (invoke "get-r") (ref.null extern)) (assert_return (invoke "get-x") (i32.const -12)) (assert_return (invoke "get-y") (i64.const -15)) @@ -294,7 +294,7 @@ ) (assert_invalid - (module (global (import "" "") anyref) (global funcref (global.get 0))) + (module (global (import "" "") externref) (global funcref (global.get 0))) "type mismatch" ) diff --git a/test/core/linking.wast b/test/core/linking.wast index 49d55723..ed551cb3 100644 --- a/test/core/linking.wast +++ b/test/core/linking.wast @@ -94,64 +94,37 @@ (module $Mref_ex - (global (export "g-const-null") nullref (ref.null)) - (global (export "g-var-null") (mut nullref) (ref.null)) - (global (export "g-const-func") funcref (ref.null)) - (global (export "g-var-func") (mut funcref) (ref.null)) - (global (export "g-const-any") anyref (ref.null)) - (global (export "g-var-any") (mut anyref) (ref.null)) + (global (export "g-const-func") funcref (ref.null func)) + (global (export "g-var-func") (mut funcref) (ref.null func)) + (global (export "g-const-extern") externref (ref.null extern)) + (global (export "g-var-extern") (mut externref) (ref.null extern)) ) (register "Mref_ex" $Mref_ex) (module $Mref_im - (global (import "Mref_ex" "g-const-null") nullref) - (global (import "Mref_ex" "g-const-null") funcref) - (global (import "Mref_ex" "g-const-null") anyref) (global (import "Mref_ex" "g-const-func") funcref) - (global (import "Mref_ex" "g-const-func") anyref) - (global (import "Mref_ex" "g-const-any") anyref) + (global (import "Mref_ex" "g-const-extern") externref) - (global (import "Mref_ex" "g-var-null") (mut nullref)) (global (import "Mref_ex" "g-var-func") (mut funcref)) - (global (import "Mref_ex" "g-var-any") (mut anyref)) + (global (import "Mref_ex" "g-var-extern") (mut externref)) ) (assert_unlinkable - (module (global (import "Mref_ex" "g-const-func") nullref)) + (module (global (import "Mref_ex" "g-const-extern") funcref)) "incompatible import type" ) (assert_unlinkable - (module (global (import "Mref_ex" "g-const-any") nullref)) - "incompatible import type" -) -(assert_unlinkable - (module (global (import "Mref_ex" "g-const-any") funcref)) + (module (global (import "Mref_ex" "g-const-func") externref)) "incompatible import type" ) (assert_unlinkable - (module (global (import "Mref_ex" "g-var-null") (mut funcref))) - "incompatible import type" -) -(assert_unlinkable - (module (global (import "Mref_ex" "g-var-null") (mut anyref))) - "incompatible import type" -) -(assert_unlinkable - (module (global (import "Mref_ex" "g-var-func") (mut nullref))) + (module (global (import "Mref_ex" "g-var-func") (mut externref))) "incompatible import type" ) (assert_unlinkable - (module (global (import "Mref_ex" "g-var-func") (mut anyref))) - "incompatible import type" -) -(assert_unlinkable - (module (global (import "Mref_ex" "g-var-any") (mut nullref))) - "incompatible import type" -) -(assert_unlinkable - (module (global (import "Mref_ex" "g-var-any") (mut funcref))) + (module (global (import "Mref_ex" "g-var-extern") (mut funcref))) "incompatible import type" ) @@ -315,40 +288,22 @@ (module $Mtable_ex - (table $t1 (export "t-null") 1 nullref) - (table $t2 (export "t-func") 1 funcref) - (table $t3 (export "t-any") 1 anyref) + (table $t1 (export "t-func") 1 funcref) + (table $t2 (export "t-extern") 1 externref) ) (register "Mtable_ex" $Mtable_ex) (module - (table (import "Mtable_ex" "t-null") 1 nullref) (table (import "Mtable_ex" "t-func") 1 funcref) - (table (import "Mtable_ex" "t-any") 1 anyref) + (table (import "Mtable_ex" "t-extern") 1 externref) ) (assert_unlinkable - (module (table (import "Mtable_ex" "t-null") 1 funcref)) - "incompatible import type" -) -(assert_unlinkable - (module (table (import "Mtable_ex" "t-null") 1 anyref)) - "incompatible import type" -) -(assert_unlinkable - (module (table (import "Mtable_ex" "t-func") 1 nullref)) - "incompatible import type" -) -(assert_unlinkable - (module (table (import "Mtable_ex" "t-func") 1 anyref)) - "incompatible import type" -) -(assert_unlinkable - (module (table (import "Mtable_ex" "t-any") 1 nullref)) + (module (table (import "Mtable_ex" "t-func") 1 externref)) "incompatible import type" ) (assert_unlinkable - (module (table (import "Mtable_ex" "t-any") 1 funcref)) + (module (table (import "Mtable_ex" "t-extern") 1 funcref)) "incompatible import type" ) diff --git a/test/core/ref_func.wast b/test/core/ref_func.wast index e9033a3b..436b3866 100644 --- a/test/core/ref_func.wast +++ b/test/core/ref_func.wast @@ -9,8 +9,6 @@ (i32.add (local.get $x) (i32.const 1)) ) - (global anyref (ref.func $f)) - (global anyref (ref.func $g)) (global funcref (ref.func $f)) (global funcref (ref.func $g)) (global $v (mut funcref) (ref.func $f)) @@ -26,13 +24,13 @@ (func $ff2) (func (export "is_null-f") (result i32) - (ref.is_null (ref.func $f)) + (ref.is_null func (ref.func $f)) ) (func (export "is_null-g") (result i32) - (ref.is_null (ref.func $g)) + (ref.is_null func (ref.func $g)) ) (func (export "is_null-v") (result i32) - (ref.is_null (global.get $v)) + (ref.is_null func (global.get $v)) ) (func (export "set-f") (global.set $v (ref.func $f))) diff --git a/test/core/ref_is_null.wast b/test/core/ref_is_null.wast index 7a42ca7d..7c01bb54 100644 --- a/test/core/ref_is_null.wast +++ b/test/core/ref_is_null.wast @@ -1,62 +1,49 @@ (module - (func $f1 (export "nullref") (param $x nullref) (result i32) - (ref.is_null (local.get $x)) + (func $f1 (export "funcref") (param $x funcref) (result i32) + (ref.is_null func (local.get $x)) ) - (func $f2 (export "anyref") (param $x anyref) (result i32) - (ref.is_null (local.get $x)) - ) - (func $f3 (export "funcref") (param $x funcref) (result i32) - (ref.is_null (local.get $x)) + (func $f2 (export "externref") (param $x externref) (result i32) + (ref.is_null extern (local.get $x)) ) - (table $t1 2 nullref) - (table $t2 2 anyref) - (table $t3 2 funcref) - (elem (table $t3) (i32.const 1) func $dummy) + (table $t1 2 funcref) + (table $t2 2 externref) + (elem (table $t1) (i32.const 1) func $dummy) (func $dummy) - (func (export "init") (param $r anyref) + (func (export "init") (param $r externref) (table.set $t2 (i32.const 1) (local.get $r)) ) (func (export "deinit") - (table.set $t1 (i32.const 1) (ref.null)) - (table.set $t2 (i32.const 1) (ref.null)) - (table.set $t3 (i32.const 1) (ref.null)) + (table.set $t1 (i32.const 1) (ref.null func)) + (table.set $t2 (i32.const 1) (ref.null extern)) ) - (func (export "nullref-elem") (param $x i32) (result i32) + (func (export "funcref-elem") (param $x i32) (result i32) (call $f1 (table.get $t1 (local.get $x))) ) - (func (export "anyref-elem") (param $x i32) (result i32) + (func (export "externref-elem") (param $x i32) (result i32) (call $f2 (table.get $t2 (local.get $x))) ) - (func (export "funcref-elem") (param $x i32) (result i32) - (call $f3 (table.get $t3 (local.get $x))) - ) ) -(assert_return (invoke "nullref" (ref.null)) (i32.const 1)) -(assert_return (invoke "anyref" (ref.null)) (i32.const 1)) -(assert_return (invoke "funcref" (ref.null)) (i32.const 1)) +(assert_return (invoke "funcref" (ref.null func)) (i32.const 1)) +(assert_return (invoke "externref" (ref.null extern)) (i32.const 1)) -(assert_return (invoke "anyref" (ref.host 1)) (i32.const 0)) +(assert_return (invoke "externref" (ref.extern 1)) (i32.const 0)) -(invoke "init" (ref.host 0)) +(invoke "init" (ref.extern 0)) -(assert_return (invoke "nullref-elem" (i32.const 0)) (i32.const 1)) -(assert_return (invoke "anyref-elem" (i32.const 0)) (i32.const 1)) (assert_return (invoke "funcref-elem" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "externref-elem" (i32.const 0)) (i32.const 1)) -(assert_return (invoke "nullref-elem" (i32.const 1)) (i32.const 1)) -(assert_return (invoke "anyref-elem" (i32.const 1)) (i32.const 0)) (assert_return (invoke "funcref-elem" (i32.const 1)) (i32.const 0)) +(assert_return (invoke "externref-elem" (i32.const 1)) (i32.const 0)) (invoke "deinit") -(assert_return (invoke "nullref-elem" (i32.const 0)) (i32.const 1)) -(assert_return (invoke "anyref-elem" (i32.const 0)) (i32.const 1)) (assert_return (invoke "funcref-elem" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "externref-elem" (i32.const 0)) (i32.const 1)) -(assert_return (invoke "nullref-elem" (i32.const 0)) (i32.const 1)) -(assert_return (invoke "anyref-elem" (i32.const 1)) (i32.const 1)) (assert_return (invoke "funcref-elem" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "externref-elem" (i32.const 1)) (i32.const 1)) diff --git a/test/core/ref_null.wast b/test/core/ref_null.wast index 96cac314..b88b0888 100644 --- a/test/core/ref_null.wast +++ b/test/core/ref_null.wast @@ -1,13 +1,10 @@ (module - (func (export "anyref") (result anyref) (ref.null)) - (func (export "funcref") (result funcref) (ref.null)) - (func (export "nullref") (result nullref) (ref.null)) + (func (export "externref") (result externref) (ref.null extern)) + (func (export "funcref") (result funcref) (ref.null func)) - (global anyref (ref.null)) - (global funcref (ref.null)) - (global nullref (ref.null)) + (global externref (ref.null extern)) + (global funcref (ref.null func)) ) -(assert_return (invoke "anyref") (ref.null)) -(assert_return (invoke "funcref") (ref.null)) -(assert_return (invoke "nullref") (ref.null)) +(assert_return (invoke "externref") (ref.null extern)) +(assert_return (invoke "funcref") (ref.null func)) diff --git a/test/core/select.wast b/test/core/select.wast index 267dd573..61edfd9e 100644 --- a/test/core/select.wast +++ b/test/core/select.wast @@ -29,32 +29,11 @@ (func (export "select-f64-t") (param f64 f64 i32) (result f64) (select (result f64) (local.get 0) (local.get 1) (local.get 2)) ) - (func (export "select-nullref") (param nullref nullref i32) (result nullref) - (select (result nullref) (local.get 0) (local.get 1) (local.get 2)) - ) (func (export "select-funcref") (param funcref funcref i32) (result funcref) (select (result funcref) (local.get 0) (local.get 1) (local.get 2)) ) - (func (export "select-anyref") (param anyref anyref i32) (result anyref) - (select (result anyref) (local.get 0) (local.get 1) (local.get 2)) - ) - - (func (export "join-nullref") (param i32) (result anyref) - (select (result nullref) (ref.null) (ref.null) (local.get 0)) - ) - (func (export "join-funcref") (param i32) (result anyref) - (select (result funcref) - (table.get $tab (i32.const 0)) - (ref.null) - (local.get 0) - ) - ) - (func (export "join-anyref") (param i32) (param anyref) (result anyref) - (select (result anyref) - (table.get $tab (i32.const 0)) - (local.get 1) - (local.get 0) - ) + (func (export "select-externref") (param externref externref i32) (result externref) + (select (result externref) (local.get 0) (local.get 1) (local.get 2)) ) ;; Check that both sides of the select are evaluated @@ -250,16 +229,15 @@ (assert_return (invoke "select-i64-t" (i64.const 2) (i64.const 1) (i32.const 1)) (i64.const 2)) (assert_return (invoke "select-f32-t" (f32.const 1) (f32.const 2) (i32.const 1)) (f32.const 1)) (assert_return (invoke "select-f64-t" (f64.const 1) (f64.const 2) (i32.const 1)) (f64.const 1)) -(assert_return (invoke "select-nullref" (ref.null) (ref.null) (i32.const 1)) (ref.null)) -(assert_return (invoke "select-funcref" (ref.null) (ref.null) (i32.const 1)) (ref.null)) -(assert_return (invoke "select-anyref" (ref.host 1) (ref.host 2) (i32.const 1)) (ref.host 1)) +(assert_return (invoke "select-funcref" (ref.null func) (ref.null func) (i32.const 1)) (ref.null func)) +(assert_return (invoke "select-externref" (ref.extern 1) (ref.extern 2) (i32.const 1)) (ref.extern 1)) (assert_return (invoke "select-i32-t" (i32.const 1) (i32.const 2) (i32.const 0)) (i32.const 2)) (assert_return (invoke "select-i32-t" (i32.const 2) (i32.const 1) (i32.const 0)) (i32.const 1)) (assert_return (invoke "select-i64-t" (i64.const 2) (i64.const 1) (i32.const -1)) (i64.const 2)) (assert_return (invoke "select-i64-t" (i64.const 2) (i64.const 1) (i32.const 0xf0f0f0f0)) (i64.const 2)) -(assert_return (invoke "select-anyref" (ref.host 1) (ref.host 2) (i32.const 0)) (ref.host 2)) -(assert_return (invoke "select-anyref" (ref.host 2) (ref.host 1) (i32.const 0)) (ref.host 1)) +(assert_return (invoke "select-externref" (ref.extern 1) (ref.extern 2) (i32.const 0)) (ref.extern 2)) +(assert_return (invoke "select-externref" (ref.extern 2) (ref.extern 1) (i32.const 0)) (ref.extern 1)) (assert_return (invoke "select-f32-t" (f32.const nan) (f32.const 1) (i32.const 1)) (f32.const nan)) (assert_return (invoke "select-f32-t" (f32.const nan:0x20304) (f32.const 1) (i32.const 1)) (f32.const nan:0x20304)) @@ -279,15 +257,6 @@ (assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan) (i32.const 0)) (f64.const nan)) (assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan:0x20304) (i32.const 0)) (f64.const nan:0x20304)) -(assert_return (invoke "join-nullref" (i32.const 1)) (ref.null)) -(assert_return (invoke "join-nullref" (i32.const 0)) (ref.null)) - -(assert_return (invoke "join-funcref" (i32.const 1)) (ref.func)) -(assert_return (invoke "join-funcref" (i32.const 0)) (ref.null)) - -(assert_return (invoke "join-anyref" (i32.const 1) (ref.host 1)) (ref.func)) -(assert_return (invoke "join-anyref" (i32.const 0) (ref.host 1)) (ref.host 1)) - (assert_trap (invoke "select-trap-left" (i32.const 1)) "unreachable") (assert_trap (invoke "select-trap-left" (i32.const 0)) "unreachable") (assert_trap (invoke "select-trap-right" (i32.const 1)) "unreachable") @@ -390,13 +359,7 @@ (assert_invalid - (module (func $type-nullref-implicit - (drop (select (ref.null) (ref.null) (i32.const 1))) - )) - "type mismatch" -) -(assert_invalid - (module (func $type-anyref-implicit (param $r anyref) + (module (func $type-externref-implicit (param $r externref) (drop (select (local.get $r) (local.get $r) (i32.const 1))) )) "type mismatch" diff --git a/test/core/table-sub.wast b/test/core/table-sub.wast index 66f18310..08787bdd 100644 --- a/test/core/table-sub.wast +++ b/test/core/table-sub.wast @@ -1,17 +1,7 @@ -(module - (table $t1 10 anyref) - (table $t2 10 funcref) - (elem $el funcref) - (func $f - (table.init $t1 $el (i32.const 0) (i32.const 1) (i32.const 2)) - (table.copy $t1 $t2 (i32.const 0) (i32.const 1) (i32.const 2)) - ) -) - (assert_invalid (module (table $t1 10 funcref) - (table $t2 10 anyref) + (table $t2 10 externref) (func $f (table.copy $t1 $t2 (i32.const 0) (i32.const 1) (i32.const 2)) ) @@ -22,7 +12,7 @@ (assert_invalid (module (table $t 10 funcref) - (elem $el anyref) + (elem $el externref) (func $f (table.init $t $el (i32.const 0) (i32.const 1) (i32.const 2)) ) diff --git a/test/core/table_fill.wast b/test/core/table_fill.wast index 7aff2024..29c556db 100644 --- a/test/core/table_fill.wast +++ b/test/core/table_fill.wast @@ -1,66 +1,66 @@ (module - (table $t 10 anyref) + (table $t 10 externref) - (func (export "fill") (param $i i32) (param $r anyref) (param $n i32) + (func (export "fill") (param $i i32) (param $r externref) (param $n i32) (table.fill $t (local.get $i) (local.get $r) (local.get $n)) ) - (func (export "get") (param $i i32) (result anyref) + (func (export "get") (param $i i32) (result externref) (table.get $t (local.get $i)) ) ) -(assert_return (invoke "get" (i32.const 1)) (ref.null)) -(assert_return (invoke "get" (i32.const 2)) (ref.null)) -(assert_return (invoke "get" (i32.const 3)) (ref.null)) -(assert_return (invoke "get" (i32.const 4)) (ref.null)) -(assert_return (invoke "get" (i32.const 5)) (ref.null)) - -(assert_return (invoke "fill" (i32.const 2) (ref.host 1) (i32.const 3))) -(assert_return (invoke "get" (i32.const 1)) (ref.null)) -(assert_return (invoke "get" (i32.const 2)) (ref.host 1)) -(assert_return (invoke "get" (i32.const 3)) (ref.host 1)) -(assert_return (invoke "get" (i32.const 4)) (ref.host 1)) -(assert_return (invoke "get" (i32.const 5)) (ref.null)) - -(assert_return (invoke "fill" (i32.const 4) (ref.host 2) (i32.const 2))) -(assert_return (invoke "get" (i32.const 3)) (ref.host 1)) -(assert_return (invoke "get" (i32.const 4)) (ref.host 2)) -(assert_return (invoke "get" (i32.const 5)) (ref.host 2)) -(assert_return (invoke "get" (i32.const 6)) (ref.null)) - -(assert_return (invoke "fill" (i32.const 4) (ref.host 3) (i32.const 0))) -(assert_return (invoke "get" (i32.const 3)) (ref.host 1)) -(assert_return (invoke "get" (i32.const 4)) (ref.host 2)) -(assert_return (invoke "get" (i32.const 5)) (ref.host 2)) - -(assert_return (invoke "fill" (i32.const 8) (ref.host 4) (i32.const 2))) -(assert_return (invoke "get" (i32.const 7)) (ref.null)) -(assert_return (invoke "get" (i32.const 8)) (ref.host 4)) -(assert_return (invoke "get" (i32.const 9)) (ref.host 4)) - -(assert_return (invoke "fill" (i32.const 9) (ref.null) (i32.const 1))) -(assert_return (invoke "get" (i32.const 8)) (ref.host 4)) -(assert_return (invoke "get" (i32.const 9)) (ref.null)) - -(assert_return (invoke "fill" (i32.const 10) (ref.host 5) (i32.const 0))) -(assert_return (invoke "get" (i32.const 9)) (ref.null)) +(assert_return (invoke "get" (i32.const 1)) (ref.null extern)) +(assert_return (invoke "get" (i32.const 2)) (ref.null extern)) +(assert_return (invoke "get" (i32.const 3)) (ref.null extern)) +(assert_return (invoke "get" (i32.const 4)) (ref.null extern)) +(assert_return (invoke "get" (i32.const 5)) (ref.null extern)) + +(assert_return (invoke "fill" (i32.const 2) (ref.extern 1) (i32.const 3))) +(assert_return (invoke "get" (i32.const 1)) (ref.null extern)) +(assert_return (invoke "get" (i32.const 2)) (ref.extern 1)) +(assert_return (invoke "get" (i32.const 3)) (ref.extern 1)) +(assert_return (invoke "get" (i32.const 4)) (ref.extern 1)) +(assert_return (invoke "get" (i32.const 5)) (ref.null extern)) + +(assert_return (invoke "fill" (i32.const 4) (ref.extern 2) (i32.const 2))) +(assert_return (invoke "get" (i32.const 3)) (ref.extern 1)) +(assert_return (invoke "get" (i32.const 4)) (ref.extern 2)) +(assert_return (invoke "get" (i32.const 5)) (ref.extern 2)) +(assert_return (invoke "get" (i32.const 6)) (ref.null extern)) + +(assert_return (invoke "fill" (i32.const 4) (ref.extern 3) (i32.const 0))) +(assert_return (invoke "get" (i32.const 3)) (ref.extern 1)) +(assert_return (invoke "get" (i32.const 4)) (ref.extern 2)) +(assert_return (invoke "get" (i32.const 5)) (ref.extern 2)) + +(assert_return (invoke "fill" (i32.const 8) (ref.extern 4) (i32.const 2))) +(assert_return (invoke "get" (i32.const 7)) (ref.null extern)) +(assert_return (invoke "get" (i32.const 8)) (ref.extern 4)) +(assert_return (invoke "get" (i32.const 9)) (ref.extern 4)) + +(assert_return (invoke "fill" (i32.const 9) (ref.null extern) (i32.const 1))) +(assert_return (invoke "get" (i32.const 8)) (ref.extern 4)) +(assert_return (invoke "get" (i32.const 9)) (ref.null extern)) + +(assert_return (invoke "fill" (i32.const 10) (ref.extern 5) (i32.const 0))) +(assert_return (invoke "get" (i32.const 9)) (ref.null extern)) (assert_trap - (invoke "fill" (i32.const 8) (ref.host 6) (i32.const 3)) + (invoke "fill" (i32.const 8) (ref.extern 6) (i32.const 3)) "out of bounds" ) -(assert_return (invoke "get" (i32.const 7)) (ref.null)) -(assert_return (invoke "get" (i32.const 8)) (ref.host 4)) -(assert_return (invoke "get" (i32.const 9)) (ref.null)) +(assert_return (invoke "get" (i32.const 7)) (ref.null extern)) +(assert_return (invoke "get" (i32.const 8)) (ref.extern 4)) +(assert_return (invoke "get" (i32.const 9)) (ref.null extern)) (assert_trap - (invoke "fill" (i32.const 11) (ref.null) (i32.const 0)) + (invoke "fill" (i32.const 11) (ref.null extern) (i32.const 0)) "out of bounds" ) (assert_trap - (invoke "fill" (i32.const 11) (ref.null) (i32.const 10)) + (invoke "fill" (i32.const 11) (ref.null extern) (i32.const 10)) "out of bounds" ) @@ -69,7 +69,7 @@ (assert_invalid (module - (table $t 10 anyref) + (table $t 10 externref) (func $type-index-value-length-empty-vs-i32-i32 (table.fill $t) ) @@ -78,16 +78,16 @@ ) (assert_invalid (module - (table $t 10 anyref) + (table $t 10 externref) (func $type-index-empty-vs-i32 - (table.fill $t (ref.null) (i32.const 1)) + (table.fill $t (ref.null extern) (i32.const 1)) ) ) "type mismatch" ) (assert_invalid (module - (table $t 10 anyref) + (table $t 10 externref) (func $type-value-empty-vs (table.fill $t (i32.const 1) (i32.const 1)) ) @@ -96,18 +96,18 @@ ) (assert_invalid (module - (table $t 10 anyref) + (table $t 10 externref) (func $type-length-empty-vs-i32 - (table.fill $t (i32.const 1) (ref.null)) + (table.fill $t (i32.const 1) (ref.null extern)) ) ) "type mismatch" ) (assert_invalid (module - (table $t 0 anyref) + (table $t 0 externref) (func $type-index-f32-vs-i32 - (table.fill $t (f32.const 1) (ref.null) (i32.const 1)) + (table.fill $t (f32.const 1) (ref.null extern) (i32.const 1)) ) ) "type mismatch" @@ -115,7 +115,7 @@ (assert_invalid (module (table $t 0 funcref) - (func $type-value-vs-funcref (param $r anyref) + (func $type-value-vs-funcref (param $r externref) (table.fill $t (i32.const 1) (local.get $r) (i32.const 1)) ) ) @@ -123,9 +123,9 @@ ) (assert_invalid (module - (table $t 0 anyref) + (table $t 0 externref) (func $type-length-f32-vs-i32 - (table.fill $t (i32.const 1) (ref.null) (f32.const 1)) + (table.fill $t (i32.const 1) (ref.null extern) (f32.const 1)) ) ) "type mismatch" @@ -133,9 +133,9 @@ (assert_invalid (module - (table $t1 1 anyref) + (table $t1 1 externref) (table $t2 1 funcref) - (func $type-value-anyref-vs-funcref-multi (param $r anyref) + (func $type-value-externref-vs-funcref-multi (param $r externref) (table.fill $t2 (i32.const 0) (local.get $r) (i32.const 1)) ) ) @@ -144,9 +144,9 @@ (assert_invalid (module - (table $t 1 anyref) + (table $t 1 externref) (func $type-result-empty-vs-num (result i32) - (table.fill $t (i32.const 0) (ref.null) (i32.const 1)) + (table.fill $t (i32.const 0) (ref.null extern) (i32.const 1)) ) ) "type mismatch" diff --git a/test/core/table_get.wast b/test/core/table_get.wast index c95fce72..3df7190e 100644 --- a/test/core/table_get.wast +++ b/test/core/table_get.wast @@ -1,15 +1,15 @@ (module - (table $t2 2 anyref) + (table $t2 2 externref) (table $t3 3 funcref) (elem (table $t3) (i32.const 1) func $dummy) (func $dummy) - (func (export "init") (param $r anyref) + (func (export "init") (param $r externref) (table.set $t2 (i32.const 1) (local.get $r)) (table.set $t3 (i32.const 2) (table.get $t3 (i32.const 1))) ) - (func (export "get-anyref") (param $i i32) (result anyref) + (func (export "get-externref") (param $i i32) (result externref) (table.get $t2 (local.get $i)) ) (func $f3 (export "get-funcref") (param $i i32) (result funcref) @@ -17,22 +17,22 @@ ) (func (export "is_null-funcref") (param $i i32) (result i32) - (ref.is_null (call $f3 (local.get $i))) + (ref.is_null func (call $f3 (local.get $i))) ) ) -(invoke "init" (ref.host 1)) +(invoke "init" (ref.extern 1)) -(assert_return (invoke "get-anyref" (i32.const 0)) (ref.null)) -(assert_return (invoke "get-anyref" (i32.const 1)) (ref.host 1)) +(assert_return (invoke "get-externref" (i32.const 0)) (ref.null extern)) +(assert_return (invoke "get-externref" (i32.const 1)) (ref.extern 1)) -(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null)) +(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func)) (assert_return (invoke "is_null-funcref" (i32.const 1)) (i32.const 0)) (assert_return (invoke "is_null-funcref" (i32.const 2)) (i32.const 0)) -(assert_trap (invoke "get-anyref" (i32.const 2)) "out of bounds") +(assert_trap (invoke "get-externref" (i32.const 2)) "out of bounds") (assert_trap (invoke "get-funcref" (i32.const 3)) "out of bounds") -(assert_trap (invoke "get-anyref" (i32.const -1)) "out of bounds") +(assert_trap (invoke "get-externref" (i32.const -1)) "out of bounds") (assert_trap (invoke "get-funcref" (i32.const -1)) "out of bounds") @@ -40,8 +40,8 @@ (assert_invalid (module - (table $t 10 anyref) - (func $type-index-empty-vs-i32 (result anyref) + (table $t 10 externref) + (func $type-index-empty-vs-i32 (result externref) (table.get $t) ) ) @@ -49,8 +49,8 @@ ) (assert_invalid (module - (table $t 10 anyref) - (func $type-index-f32-vs-i32 (result anyref) + (table $t 10 externref) + (func $type-index-f32-vs-i32 (result externref) (table.get $t (f32.const 1)) ) ) @@ -59,8 +59,8 @@ (assert_invalid (module - (table $t 10 anyref) - (func $type-result-anyref-vs-empty + (table $t 10 externref) + (func $type-result-externref-vs-empty (table.get $t (i32.const 0)) ) ) @@ -68,8 +68,8 @@ ) (assert_invalid (module - (table $t 10 anyref) - (func $type-result-anyref-vs-funcref (result funcref) + (table $t 10 externref) + (func $type-result-externref-vs-funcref (result funcref) (table.get $t (i32.const 1)) ) ) @@ -79,8 +79,8 @@ (assert_invalid (module (table $t1 1 funcref) - (table $t2 1 anyref) - (func $type-result-anyref-vs-funcref-multi (result funcref) + (table $t2 1 externref) + (func $type-result-externref-vs-funcref-multi (result funcref) (table.get $t2 (i32.const 0)) ) ) diff --git a/test/core/table_grow.wast b/test/core/table_grow.wast index 91fc096f..2b992ff7 100644 --- a/test/core/table_grow.wast +++ b/test/core/table_grow.wast @@ -1,43 +1,43 @@ (module - (table $t 0 anyref) + (table $t 0 externref) - (func (export "get") (param $i i32) (result anyref) (table.get $t (local.get $i))) - (func (export "set") (param $i i32) (param $r anyref) (table.set $t (local.get $i) (local.get $r))) + (func (export "get") (param $i i32) (result externref) (table.get $t (local.get $i))) + (func (export "set") (param $i i32) (param $r externref) (table.set $t (local.get $i) (local.get $r))) - (func (export "grow") (param $sz i32) (param $init anyref) (result i32) + (func (export "grow") (param $sz i32) (param $init externref) (result i32) (table.grow $t (local.get $init) (local.get $sz)) ) (func (export "size") (result i32) (table.size $t)) ) (assert_return (invoke "size") (i32.const 0)) -(assert_trap (invoke "set" (i32.const 0) (ref.host 2)) "out of bounds table access") +(assert_trap (invoke "set" (i32.const 0) (ref.extern 2)) "out of bounds table access") (assert_trap (invoke "get" (i32.const 0)) "out of bounds table access") -(assert_return (invoke "grow" (i32.const 1) (ref.null)) (i32.const 0)) +(assert_return (invoke "grow" (i32.const 1) (ref.null extern)) (i32.const 0)) (assert_return (invoke "size") (i32.const 1)) -(assert_return (invoke "get" (i32.const 0)) (ref.null)) -(assert_return (invoke "set" (i32.const 0) (ref.host 2))) -(assert_return (invoke "get" (i32.const 0)) (ref.host 2)) -(assert_trap (invoke "set" (i32.const 1) (ref.host 2)) "out of bounds table access") +(assert_return (invoke "get" (i32.const 0)) (ref.null extern)) +(assert_return (invoke "set" (i32.const 0) (ref.extern 2))) +(assert_return (invoke "get" (i32.const 0)) (ref.extern 2)) +(assert_trap (invoke "set" (i32.const 1) (ref.extern 2)) "out of bounds table access") (assert_trap (invoke "get" (i32.const 1)) "out of bounds table access") -(assert_return (invoke "grow" (i32.const 4) (ref.host 3)) (i32.const 1)) +(assert_return (invoke "grow" (i32.const 4) (ref.extern 3)) (i32.const 1)) (assert_return (invoke "size") (i32.const 5)) -(assert_return (invoke "get" (i32.const 0)) (ref.host 2)) -(assert_return (invoke "set" (i32.const 0) (ref.host 2))) -(assert_return (invoke "get" (i32.const 0)) (ref.host 2)) -(assert_return (invoke "get" (i32.const 1)) (ref.host 3)) -(assert_return (invoke "get" (i32.const 4)) (ref.host 3)) -(assert_return (invoke "set" (i32.const 4) (ref.host 4))) -(assert_return (invoke "get" (i32.const 4)) (ref.host 4)) -(assert_trap (invoke "set" (i32.const 5) (ref.host 2)) "out of bounds table access") +(assert_return (invoke "get" (i32.const 0)) (ref.extern 2)) +(assert_return (invoke "set" (i32.const 0) (ref.extern 2))) +(assert_return (invoke "get" (i32.const 0)) (ref.extern 2)) +(assert_return (invoke "get" (i32.const 1)) (ref.extern 3)) +(assert_return (invoke "get" (i32.const 4)) (ref.extern 3)) +(assert_return (invoke "set" (i32.const 4) (ref.extern 4))) +(assert_return (invoke "get" (i32.const 4)) (ref.extern 4)) +(assert_trap (invoke "set" (i32.const 5) (ref.extern 2)) "out of bounds table access") (assert_trap (invoke "get" (i32.const 5)) "out of bounds table access") ;; Reject growing to size outside i32 value range (module - (table $t 0x10 anyref) + (table $t 0x10 funcref) (elem declare func $f) (func $f (export "grow") (result i32) (table.grow $t (ref.func $f) (i32.const 0xffff_fff0)) @@ -48,9 +48,9 @@ (module - (table $t 0 anyref) + (table $t 0 externref) (func (export "grow") (param i32) (result i32) - (table.grow $t (ref.null) (local.get 0)) + (table.grow $t (ref.null extern) (local.get 0)) ) ) @@ -62,9 +62,9 @@ (module - (table $t 0 10 anyref) + (table $t 0 10 externref) (func (export "grow") (param i32) (result i32) - (table.grow $t (ref.null) (local.get 0)) + (table.grow $t (ref.null extern) (local.get 0)) ) ) @@ -79,18 +79,18 @@ (module - (table $t 10 anyref) + (table $t 10 funcref) (func (export "grow") (param i32) (result i32) - (table.grow $t (ref.null) (local.get 0)) + (table.grow $t (ref.null func) (local.get 0)) ) (elem declare func 1) - (func (export "check-table-null") (param i32 i32) (result anyref) - (local anyref) + (func (export "check-table-null") (param i32 i32) (result funcref) + (local funcref) (local.set 2 (ref.func 1)) (block (loop (local.set 2 (table.get $t (local.get 0))) - (br_if 1 (i32.eqz (ref.is_null (local.get 2)))) + (br_if 1 (i32.eqz (ref.is_null func (local.get 2)))) (br_if 1 (i32.ge_u (local.get 0) (local.get 1))) (local.set 0 (i32.add (local.get 0) (i32.const 1))) (br_if 0 (i32.le_u (local.get 0) (local.get 1))) @@ -100,17 +100,17 @@ ) ) -(assert_return (invoke "check-table-null" (i32.const 0) (i32.const 9)) (ref.null)) +(assert_return (invoke "check-table-null" (i32.const 0) (i32.const 9)) (ref.null func)) (assert_return (invoke "grow" (i32.const 10)) (i32.const 10)) -(assert_return (invoke "check-table-null" (i32.const 0) (i32.const 19)) (ref.null)) +(assert_return (invoke "check-table-null" (i32.const 0) (i32.const 19)) (ref.null func)) ;; Type errors (assert_invalid (module - (table $t 0 anyref) - (func $type-init-size-empty-vs-i32-anyref (result i32) + (table $t 0 externref) + (func $type-init-size-empty-vs-i32-externref (result i32) (table.grow $t) ) ) @@ -118,17 +118,17 @@ ) (assert_invalid (module - (table $t 0 anyref) + (table $t 0 externref) (func $type-size-empty-vs-i32 (result i32) - (table.grow $t (ref.null)) + (table.grow $t (ref.null extern)) ) ) "type mismatch" ) (assert_invalid (module - (table $t 0 anyref) - (func $type-init-empty-vs-anyref (result i32) + (table $t 0 externref) + (func $type-init-empty-vs-externref (result i32) (table.grow $t (i32.const 1)) ) ) @@ -136,9 +136,9 @@ ) (assert_invalid (module - (table $t 0 anyref) + (table $t 0 externref) (func $type-size-f32-vs-i32 (result i32) - (table.grow $t (ref.null) (f32.const 1)) + (table.grow $t (ref.null extern) (f32.const 1)) ) ) "type mismatch" @@ -146,7 +146,7 @@ (assert_invalid (module (table $t 0 funcref) - (func $type-init-anyref-vs-funcref (param $r anyref) (result i32) + (func $type-init-externref-vs-funcref (param $r externref) (result i32) (table.grow $t (local.get $r) (i32.const 1)) ) ) @@ -155,18 +155,18 @@ (assert_invalid (module - (table $t 1 anyref) + (table $t 1 externref) (func $type-result-i32-vs-empty - (table.grow $t (ref.null) (i32.const 0)) + (table.grow $t (ref.null extern) (i32.const 0)) ) ) "type mismatch" ) (assert_invalid (module - (table $t 1 anyref) + (table $t 1 externref) (func $type-result-i32-vs-f32 (result f32) - (table.grow $t (ref.null) (i32.const 0)) + (table.grow $t (ref.null extern) (i32.const 0)) ) ) "type mismatch" diff --git a/test/core/table_set.wast b/test/core/table_set.wast index 848830e2..6da9db87 100644 --- a/test/core/table_set.wast +++ b/test/core/table_set.wast @@ -1,17 +1,17 @@ (module - (table $t2 1 anyref) + (table $t2 1 externref) (table $t3 2 funcref) (elem (table $t3) (i32.const 1) func $dummy) (func $dummy) - (func (export "get-anyref") (param $i i32) (result anyref) + (func (export "get-externref") (param $i i32) (result externref) (table.get $t2 (local.get $i)) ) (func $f3 (export "get-funcref") (param $i i32) (result funcref) (table.get $t3 (local.get $i)) ) - (func (export "set-anyref") (param $i i32) (param $r anyref) + (func (export "set-externref") (param $i i32) (param $r externref) (table.set $t2 (local.get $i) (local.get $r)) ) (func (export "set-funcref") (param $i i32) (param $r funcref) @@ -22,30 +22,30 @@ ) (func (export "is_null-funcref") (param $i i32) (result i32) - (ref.is_null (call $f3 (local.get $i))) + (ref.is_null func (call $f3 (local.get $i))) ) ) -(assert_return (invoke "get-anyref" (i32.const 0)) (ref.null)) -(assert_return (invoke "set-anyref" (i32.const 0) (ref.host 1))) -(assert_return (invoke "get-anyref" (i32.const 0)) (ref.host 1)) -(assert_return (invoke "set-anyref" (i32.const 0) (ref.null))) -(assert_return (invoke "get-anyref" (i32.const 0)) (ref.null)) +(assert_return (invoke "get-externref" (i32.const 0)) (ref.null extern)) +(assert_return (invoke "set-externref" (i32.const 0) (ref.extern 1))) +(assert_return (invoke "get-externref" (i32.const 0)) (ref.extern 1)) +(assert_return (invoke "set-externref" (i32.const 0) (ref.null extern))) +(assert_return (invoke "get-externref" (i32.const 0)) (ref.null extern)) -(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null)) +(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func)) (assert_return (invoke "set-funcref-from" (i32.const 0) (i32.const 1))) (assert_return (invoke "is_null-funcref" (i32.const 0)) (i32.const 0)) -(assert_return (invoke "set-funcref" (i32.const 0) (ref.null))) -(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null)) +(assert_return (invoke "set-funcref" (i32.const 0) (ref.null func))) +(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func)) -(assert_trap (invoke "set-anyref" (i32.const 2) (ref.null)) "out of bounds") -(assert_trap (invoke "set-funcref" (i32.const 3) (ref.null)) "out of bounds") -(assert_trap (invoke "set-anyref" (i32.const -1) (ref.null)) "out of bounds") -(assert_trap (invoke "set-funcref" (i32.const -1) (ref.null)) "out of bounds") +(assert_trap (invoke "set-externref" (i32.const 2) (ref.null extern)) "out of bounds") +(assert_trap (invoke "set-funcref" (i32.const 3) (ref.null func)) "out of bounds") +(assert_trap (invoke "set-externref" (i32.const -1) (ref.null extern)) "out of bounds") +(assert_trap (invoke "set-funcref" (i32.const -1) (ref.null func)) "out of bounds") -(assert_trap (invoke "set-anyref" (i32.const 2) (ref.host 0)) "out of bounds") +(assert_trap (invoke "set-externref" (i32.const 2) (ref.extern 0)) "out of bounds") (assert_trap (invoke "set-funcref-from" (i32.const 3) (i32.const 1)) "out of bounds") -(assert_trap (invoke "set-anyref" (i32.const -1) (ref.host 0)) "out of bounds") +(assert_trap (invoke "set-externref" (i32.const -1) (ref.extern 0)) "out of bounds") (assert_trap (invoke "set-funcref-from" (i32.const -1) (i32.const 1)) "out of bounds") @@ -53,8 +53,8 @@ (assert_invalid (module - (table $t 10 anyref) - (func $type-index-value-empty-vs-i32-anyref + (table $t 10 externref) + (func $type-index-value-empty-vs-i32-externref (table.set $t) ) ) @@ -62,17 +62,17 @@ ) (assert_invalid (module - (table $t 10 anyref) + (table $t 10 externref) (func $type-index-empty-vs-i32 - (table.set $t (ref.null)) + (table.set $t (ref.null extern)) ) ) "type mismatch" ) (assert_invalid (module - (table $t 10 anyref) - (func $type-value-empty-vs-anyref + (table $t 10 externref) + (func $type-value-empty-vs-externref (table.set $t (i32.const 1)) ) ) @@ -80,9 +80,9 @@ ) (assert_invalid (module - (table $t 10 anyref) + (table $t 10 externref) (func $type-size-f32-vs-i32 - (table.set $t (f32.const 1) (ref.null)) + (table.set $t (f32.const 1) (ref.null extern)) ) ) "type mismatch" @@ -90,7 +90,7 @@ (assert_invalid (module (table $t 10 funcref) - (func $type-value-anyref-vs-funcref (param $r anyref) + (func $type-value-externref-vs-funcref (param $r externref) (table.set $t (i32.const 1) (local.get $r)) ) ) @@ -99,9 +99,9 @@ (assert_invalid (module - (table $t1 1 anyref) + (table $t1 1 externref) (table $t2 1 funcref) - (func $type-value-anyref-vs-funcref-multi (param $r anyref) + (func $type-value-externref-vs-funcref-multi (param $r externref) (table.set $t2 (i32.const 0) (local.get $r)) ) ) @@ -110,9 +110,9 @@ (assert_invalid (module - (table $t 10 anyref) + (table $t 10 externref) (func $type-result-empty-vs-num (result i32) - (table.set $t (i32.const 0) (ref.null)) + (table.set $t (i32.const 0) (ref.null extern)) ) ) "type mismatch" diff --git a/test/core/table_size.wast b/test/core/table_size.wast index 5817104a..ad293b5e 100644 --- a/test/core/table_size.wast +++ b/test/core/table_size.wast @@ -1,8 +1,8 @@ (module - (table $t0 0 anyref) - (table $t1 1 anyref) - (table $t2 0 2 anyref) - (table $t3 3 8 anyref) + (table $t0 0 externref) + (table $t1 1 externref) + (table $t2 0 2 externref) + (table $t3 3 8 externref) (func (export "size-t0") (result i32) (table.size $t0)) (func (export "size-t1") (result i32) (table.size $t1)) @@ -10,16 +10,16 @@ (func (export "size-t3") (result i32) (table.size $t3)) (func (export "grow-t0") (param $sz i32) - (drop (table.grow $t0 (ref.null) (local.get $sz))) + (drop (table.grow $t0 (ref.null extern) (local.get $sz))) ) (func (export "grow-t1") (param $sz i32) - (drop (table.grow $t1 (ref.null) (local.get $sz))) + (drop (table.grow $t1 (ref.null extern) (local.get $sz))) ) (func (export "grow-t2") (param $sz i32) - (drop (table.grow $t2 (ref.null) (local.get $sz))) + (drop (table.grow $t2 (ref.null extern) (local.get $sz))) ) (func (export "grow-t3") (param $sz i32) - (drop (table.grow $t3 (ref.null) (local.get $sz))) + (drop (table.grow $t3 (ref.null extern) (local.get $sz))) ) ) @@ -68,7 +68,7 @@ (assert_invalid (module - (table $t 1 anyref) + (table $t 1 externref) (func $type-result-i32-vs-empty (table.size $t) ) @@ -77,7 +77,7 @@ ) (assert_invalid (module - (table $t 1 anyref) + (table $t 1 externref) (func $type-result-i32-vs-f32 (result f32) (table.size $t) )