diff --git a/document/core/Makefile b/document/core/Makefile index 74c9daeea6..3ac2f1c814 100644 --- a/document/core/Makefile +++ b/document/core/Makefile @@ -80,7 +80,7 @@ publish-main: clean main bikeshed-keep deploy all: pdf html bikeshed .PHONY: main -main: pdf html +main: macrosok pdf html # Dirty hack to avoid rebuilding the Bikeshed version for every push. .PHONY: bikeshed-keep @@ -97,6 +97,10 @@ GENERATED = appendix/index-instructions.rst %.rst: %.py (cd `dirname $@`; ./`basename $^`) +.PHONY: macrosok +macrosok: $(GENERATED) + sh util/check_macros.sh + .PHONY: pdf pdf: $(GENERATED) latexpdf mkdir -p $(BUILDDIR)/html/$(DOWNLOADDIR) diff --git a/document/core/appendix/embedding.rst b/document/core/appendix/embedding.rst index 2afc574e80..e58f8966cd 100644 --- a/document/core/appendix/embedding.rst +++ b/document/core/appendix/embedding.rst @@ -652,11 +652,12 @@ Globals \end{array} -.. index:: reference, reference type +.. index:: reference, reference type, value type, value .. _embed-ref-type: +.. _embed-val-default: -References -~~~~~~~~~~ +Values +~~~~~~ :math:`\F{ref\_type}(\store, \reff) : \reftype` ............................................... @@ -678,6 +679,20 @@ References In such cases, this function may return a less precise supertype. +:math:`\F{val\_default}(\valtype) : \val` +............................................... + +1. If :math:`\default_{valtype}` is not defined, then return :math:`\ERROR`. + +1. Else, return the :ref:`value ` :math:`\default_{valtype}`. + +.. math:: + \begin{array}{lclll} + \F{val\_default}(t) &=& v && (\iff \default_t = v) \\ + \F{val\_default}(t) &=& \ERROR && (\iff \default_t = \epsilon) \\ + \end{array} + + .. index:: value type, external type, subtyping .. _embed-match-valtype: .. _embed-match-externtype: diff --git a/document/core/appendix/index-instructions.py b/document/core/appendix/index-instructions.py index e63d78fafc..267bf433af 100755 --- a/document/core/appendix/index-instructions.py +++ b/document/core/appendix/index-instructions.py @@ -356,7 +356,7 @@ def Instruction(name, opcode, type=None, validation=None, execution=None, operat Instruction(r'\BRONCASTFAIL~t_1~t_2', r'\hex{FB}~\hex{19}', r'[t_1] \to [t_2]', r'valid-br_on_cast_fail', r'exec-br_on_cast_fail'), Instruction(r'\ANYCONVERTEXTERN', r'\hex{FB}~\hex{1A}', r'[(\REF~\NULL~\EXTERN)] \to [(\REF~\NULL~\ANY)]', r'valid-any.convert_extern', r'exec-any.convert_extern'), Instruction(r'\EXTERNCONVERTANY', r'\hex{FB}~\hex{1B}', r'[(\REF~\NULL~\ANY)] \to [(\REF~\NULL~\EXTERN)]', r'valid-extern.convert_any', r'exec-extern.convert_any'), - Instruction(r'\REFI31', r'\hex{FB}~\hex{1C}', r'[\I32] \to [\I31REF]', r'valid-ref.i31', r'exec-ref.i31'), + Instruction(r'\REFI31', r'\hex{FB}~\hex{1C}', r'[\I32] \to [(\REF~\I31)]', r'valid-ref.i31', r'exec-ref.i31'), Instruction(r'\I31GETS', r'\hex{FB}~\hex{1D}', r'[\I31REF] \to [\I32]', r'valid-i31.get_sx', r'exec-i31.get_sx'), Instruction(r'\I31GETU', r'\hex{FB}~\hex{1E}', r'[\I31REF] \to [\I32]', r'valid-i31.get_sx', r'exec-i31.get_sx'), Instruction(None, r'\hex{FB}~\hex{1E} \dots'), diff --git a/document/core/appendix/properties.rst b/document/core/appendix/properties.rst index 7ec5853574..b4c15c8f31 100644 --- a/document/core/appendix/properties.rst +++ b/document/core/appendix/properties.rst @@ -21,7 +21,7 @@ In order to state and prove soundness precisely, the typing rules must be extend .. index:: context, recursive type, recursive type index -.. context-rec: +.. _context-ext: Contexts ~~~~~~~~ @@ -832,7 +832,7 @@ where :math:`\val_1 \gg^+_S \val_2` denotes the transitive closure of the follow * Let :math:`x^\ast` be the sequence of :ref:`function indices ` from :math:`0` to :math:`m-1`. * Then the module instance is valid with :ref:`context ` - :math:`\{\CTYPES~\deftype^\ast,` :math:`\CFUNCS~\functype^\ast,` :math:`\CTABLES~\tabletype^\ast,` :math:`\CMEMS~\memtype^\ast,` :math:`\CGLOBALS~\globaltype^\ast,` \CTAGS~\tagtype^\ast, :math:`\CELEMS~\reftype^\ast,` :math:`\CDATAS~{\ok}^n\}`. + :math:`\{\CTYPES~\deftype^\ast,` :math:`\CFUNCS~\functype^\ast,` :math:`\CTABLES~\tabletype^\ast,` :math:`\CMEMS~\memtype^\ast,` :math:`\CGLOBALS~\globaltype^\ast,` \CTAGS~\tagtype^\ast, :math:`\CELEMS~\reftype^\ast,` :math:`\CDATAS~{\ok}^n,` :math:`\CREFS~x^\ast\}`. .. math:: ~\\[-1ex] diff --git a/document/core/binary/modules.rst b/document/core/binary/modules.rst index bb2b732d48..105b834dfb 100644 --- a/document/core/binary/modules.rst +++ b/document/core/binary/modules.rst @@ -350,7 +350,7 @@ It decodes into a vector of :ref:`element segments ` that represent \production{element segment} & \Belem &::=& 0{:}\Bu32~~e{:}\Bexpr~~y^\ast{:}\Bvec(\Bfuncidx) &\Rightarrow& \\&&&\quad - \{ \ETYPE~(\REF~\NULL~\FUNC), \EINIT~((\REFFUNC~y)~\END)^\ast, \EMODE~\EACTIVE~\{ \ETABLE~0, \EOFFSET~e \} \} \\ &&|& + \{ \ETYPE~(\REF~\FUNC), \EINIT~((\REFFUNC~y)~\END)^\ast, \EMODE~\EACTIVE~\{ \ETABLE~0, \EOFFSET~e \} \} \\ &&|& 1{:}\Bu32~~\X{et}:\Belemkind~~y^\ast{:}\Bvec(\Bfuncidx) &\Rightarrow& \\&&&\quad \{ \ETYPE~\X{et}, \EINIT~((\REFFUNC~y)~\END)^\ast, \EMODE~\EPASSIVE \} \\ &&|& @@ -362,7 +362,7 @@ It decodes into a vector of :ref:`element segments ` that represent \{ \ETYPE~\X{et}, \EINIT~((\REFFUNC~y)~\END)^\ast, \EMODE~\EDECLARATIVE \} \\ &&|& 4{:}\Bu32~~e{:}\Bexpr~~\X{el}^\ast{:}\Bvec(\Bexpr) &\Rightarrow& \\&&&\quad - \{ \ETYPE~(\REF~\NULL~\FUNC), \EINIT~\X{el}^\ast, \EMODE~\EACTIVE~\{ \ETABLE~0, \EOFFSET~e \} \} \\ &&|& + \{ \ETYPE~(\REF~\FUNC), \EINIT~\X{el}^\ast, \EMODE~\EACTIVE~\{ \ETABLE~0, \EOFFSET~e \} \} \\ &&|& 5{:}\Bu32~~\X{et}:\Breftype~~\X{el}^\ast{:}\Bvec(\Bexpr) &\Rightarrow& \\&&&\quad \{ \ETYPE~et, \EINIT~\X{el}^\ast, \EMODE~\EPASSIVE \} \\ &&|& @@ -373,7 +373,7 @@ It decodes into a vector of :ref:`element segments ` that represent &\Rightarrow& \\&&&\quad \{ \ETYPE~et, \EINIT~\X{el}^\ast, \EMODE~\EDECLARATIVE \} \\ \production{element kind} & \Belemkind &::=& - \hex{00} &\Rightarrow& \FUNCREF \\ + \hex{00} &\Rightarrow& (\REF~\FUNC) \\ \end{array} .. note:: diff --git a/document/core/exec/instructions.rst b/document/core/exec/instructions.rst index 497de98266..13cb52da75 100644 --- a/document/core/exec/instructions.rst +++ b/document/core/exec/instructions.rst @@ -819,14 +819,14 @@ Reference Instructions S; F; (\I32.\CONST~s)~(\I32.\CONST~n)~(\ARRAYNEWDATA~x~y) &\stepto& \TRAP \\&& \begin{array}[t]{@{}r@{~}l@{}} - (\iff & \expanddt(F.\AMODULE.\MITYPES[x]) = \TARRAY~\X{ft}^n \\ + (\iff & \expanddt(F.\AMODULE.\MITYPES[x]) = \TARRAY~\X{ft} \\ \land & s + n\cdot|\X{ft}|/8 > |S.\SDATAS[F.\AMODULE.\MIDATAS[y]].\DIDATA|) \end{array} \\ \\[1ex] S; F; (\I32.\CONST~s)~(\I32.\CONST~n)~(\ARRAYNEWDATA~x~y) &\stepto& (t.\CONST~c)^n~(\ARRAYNEWFIXED~x~n) \\&& \begin{array}[t]{@{}r@{~}l@{}} - (\iff & \expanddt(F.\AMODULE.\MITYPES[x]) = \TARRAY~\X{ft}^n \\ + (\iff & \expanddt(F.\AMODULE.\MITYPES[x]) = \TARRAY~\X{ft} \\ \land & t = \unpacktype(\X{ft}) \\ \land & \concat((\bytes_{\X{ft}}(c))^n) = S.\SDATAS[F.\AMODULE.\MIDATAS[y]].\DIDATA[s \slice n\cdot|\X{ft}|/8] \\ \end{array} \\ @@ -1065,7 +1065,7 @@ Reference Instructions 12. Assert: due to :ref:`validation `, the :ref:`array instance ` :math:`S.\SARRAYS[a]` exists. -13. If :math:`d + n` is larger than or equal to the length of :math:`S.\SARRAYS[a].\AIFIELDS`, then: +13. If :math:`d + n` is larger than the length of :math:`S.\SARRAYS[a].\AIFIELDS`, then: a. Trap. @@ -1102,13 +1102,13 @@ Reference Instructions (\iff d + n > |S.\SARRAYS[a].\AIFIELDS|) \\[1ex] S; (\REFARRAYADDR~a)~(\I32.\CONST~d)~\val~(\I32.\CONST~0)~(\ARRAYFILL~x) - \quad\stepto\quad S; \epsilon + \quad\stepto\quad \epsilon \\ \qquad (\otherwise) \\[1ex] S; (\REFARRAYADDR~a)~(\I32.\CONST~d)~\val~(\I32.\CONST~n+1)~(\ARRAYFILL~x) \quad\stepto - \\ \quad S; + \\ \quad \begin{array}[t]{@{}l@{}} (\REFARRAYADDR~a)~(\I32.\CONST~d)~\val~(\ARRAYSET~x) \\ (\REFARRAYADDR~a)~(\I32.\CONST~d+1)~\val~(\I32.\CONST~n)~(\ARRAYFILL~x) \\ @@ -1175,11 +1175,11 @@ Reference Instructions 23. Assert: due to :ref:`validation `, the :ref:`array instance ` :math:`S.\SARRAYS[a_2]` exists. -24. If :math:`d + n` is larger than or equal to the length of :math:`S.\SARRAYS[a_1].\AIFIELDS`, then: +24. If :math:`d + n` is larger than the length of :math:`S.\SARRAYS[a_1].\AIFIELDS`, then: a. Trap. -25. If :math:`s + n` is larger than or equal to the length of :math:`S.\SARRAYS[a_2].\AIFIELDS`, then: +25. If :math:`s + n` is larger than the length of :math:`S.\SARRAYS[a_2].\AIFIELDS`, then: a. Trap. @@ -1252,7 +1252,7 @@ Reference Instructions (\iff d + n > |S.\SARRAYS[a_1].\AIFIELDS| \vee s + n > |S.\SARRAYS[a_2].\AIFIELDS|) \\[1ex] S; F; (\REFARRAYADDR~a_1)~(\I32.\CONST~d)~(\REFARRAYADDR~a_2)~(\I32.\CONST~s)~(\I32.\CONST~0)~(\ARRAYCOPY~x~y) - \quad\stepto\quad S; \epsilon + \quad\stepto\quad \epsilon \\ \qquad (\otherwise) \\[1ex] @@ -1391,13 +1391,13 @@ Where: \end{array} \\[1ex] S; F; (\REFARRAYADDR~a)~(\I32.\CONST~d)~(\I32.\CONST~s)~(\I32.\CONST~0)~(\ARRAYINITDATA~x~y) - \quad\stepto\quad S; F; \epsilon + \quad\stepto\quad \epsilon \\ \qquad (\otherwise) \\[1ex] S; F; (\REFARRAYADDR~a)~(\I32.\CONST~d)~(\I32.\CONST~s)~(\I32.\CONST~n+1)~(\ARRAYINITDATA~x~y) \quad\stepto - \\ \quad S; F; + \\ \quad \begin{array}[t]{@{}l@{}} (\REFARRAYADDR~a)~(\I32.\CONST~d)~(t.\CONST~c)~(\ARRAYSET~x) \\ (\REFARRAYADDR~a)~(\I32.\CONST~d+1)~(\I32.\CONST~s+|\X{ft}|/8)~(\I32.\CONST~n)~(\ARRAYINITDATA~x~y) \\ @@ -1497,13 +1497,13 @@ Where: \end{array} \\[1ex] S; F; (\REFARRAYADDR~a)~(\I32.\CONST~d)~(\I32.\CONST~s)~(\I32.\CONST~0)~(\ARRAYINITELEM~x~y) - \quad\stepto\quad S; F; \epsilon + \quad\stepto\quad \epsilon \\ \qquad (\otherwise) \\[1ex] S; F; (\REFARRAYADDR~a)~(\I32.\CONST~d)~(\I32.\CONST~s)~(\I32.\CONST~n+1)~(\ARRAYINITELEM~x~y) \quad\stepto - \\ \quad S; F; + \\ \quad \begin{array}[t]{@{}l@{}} (\REFARRAYADDR~a)~(\I32.\CONST~d)~\REF~(\ARRAYSET~x) \\ (\REFARRAYADDR~a)~(\I32.\CONST~d+1)~(\I32.\CONST~s+1)~(\I32.\CONST~n)~(\ARRAYINITELEM~x~y) \\ @@ -1538,7 +1538,7 @@ Where: .. math:: \begin{array}{lcl@{\qquad}l} - (\REFNULL \X{ht})~\ANYCONVERTEXTERN &\stepto& (\REFNULL~\ANY) \\ + (\REFNULL~\X{ht})~\ANYCONVERTEXTERN &\stepto& (\REFNULL~\ANY) \\ (\REFEXTERN~\reff)~\ANYCONVERTEXTERN &\stepto& \reff \\ \end{array} @@ -1564,8 +1564,8 @@ Where: .. math:: \begin{array}{lcl@{\qquad}l} - (\REFNULL \X{ht})~\EXTERNCONVERTANY &\stepto& (\REFNULL~\EXTERN) \\ - \reff~\EXTERNCONVERTANY &\stepto& (\REFEXTERN~\reff) & (\iff \reff \neq (\REFNULL \X{ht})) \\ + (\REFNULL~\X{ht})~\EXTERNCONVERTANY &\stepto& (\REFNULL~\EXTERN) \\ + \reff~\EXTERNCONVERTANY &\stepto& (\REFEXTERN~\reff) & (\iff \reff \neq (\REFNULL~\X{ht})) \\ \end{array} @@ -1776,7 +1776,7 @@ Most other vector instructions are defined in terms of numeric operators that ar :math:`\shape\K{.}\SPLAT` ......................... -1. Let :math:`t` be the type :math:`\unpacked(\shape)`. +1. Let :math:`t` be the type :math:`\unpackshape(\shape)`. 2. Assert: due to :ref:`validation `, a value of :ref:`value type ` :math:`t` is on the top of the stack. @@ -1791,7 +1791,7 @@ Most other vector instructions are defined in terms of numeric operators that ar .. math:: \begin{array}{lcl@{\qquad}l} (t\K{.}\CONST~c_1)~\shape\K{.}\SPLAT &\stepto& (\V128\K{.}\VCONST~c) - & (\iff t = \unpacked(\shape) + & (\iff t = \unpackshape(\shape) \wedge c = \lanes^{-1}_{\shape}(c_1^{\dim(\shape)})) \\ \end{array} @@ -1810,7 +1810,7 @@ Most other vector instructions are defined in terms of numeric operators that ar 4. Let :math:`i^\ast` be the result of computing :math:`\lanes_{t_1\K{x}N}(c_1)`. -5. Let :math:`t_2` be the type :math:`\unpacked(t_1\K{x}N)`. +5. Let :math:`t_2` be the type :math:`\unpackshape(t_1\K{x}N)`. 6. Let :math:`c_2` be the result of computing :math:`\extend^{sx^?}_{t_1,t_2}(i^\ast[x])`. @@ -1823,7 +1823,7 @@ Most other vector instructions are defined in terms of numeric operators that ar \end{array} \\ \qquad \begin{array}[t]{@{}r@{~}l@{}} - (\iff & t_2 = \unpacked(t_1\K{x}N) \\ + (\iff & t_2 = \unpackshape(t_1\K{x}N) \\ \wedge & c_2 = \extend^{sx^?}_{t_1,t_2}(\lanes_{t_1\K{x}N}(c_1)[x])) \end{array} \end{array} @@ -1836,7 +1836,7 @@ Most other vector instructions are defined in terms of numeric operators that ar 1. Assert: due to :ref:`validation `, :math:`x < \dim(\shape)`. -2. Let :math:`t_2` be the type :math:`\unpacked(\shape)`. +2. Let :math:`t_2` be the type :math:`\unpackshape(\shape)`. 3. Assert: due to :ref:`validation `, a value of :ref:`value type ` :math:`t_1` is on the top of the stack. @@ -4377,7 +4377,7 @@ Control Instructions \begin{array}{lcl@{\qquad}l} S; F; \reff~(\BRONCAST~l~\X{rt}_1~\X{rt}_2) &\stepto& \reff~(\BR~l) & (\iff S \vdashval \reff : \X{rt} - \land \vdashreftypematch \X{rt} \matchesreftype \insttype_{F.\AMODULE}(\X{rt}_2)) \\ + \land {} \vdashreftypematch \X{rt} \matchesreftype \insttype_{F.\AMODULE}(\X{rt}_2)) \\ S; F; \reff~(\BRONCAST~l~\X{rt}_1~\X{rt}_2) &\stepto& \reff & (\otherwise) \\ \end{array} @@ -4412,7 +4412,7 @@ Control Instructions \begin{array}{lcl@{\qquad}l} S; F; \reff~(\BRONCASTFAIL~l~\X{rt}_1~\X{rt}_2) &\stepto& \reff & (\iff S \vdashval \reff : \X{rt} - \land \vdashreftypematch \X{rt} \matchesreftype \insttype_{F.\AMODULE}(\X{rt}_2)) \\ + \land {} \vdashreftypematch \X{rt} \matchesreftype \insttype_{F.\AMODULE}(\X{rt}_2)) \\ S; F; \reff~(\BRONCASTFAIL~l~\X{rt}_1~\X{rt}_2) &\stepto& \reff~(\BR~l) & (\otherwise) \\ \end{array} diff --git a/document/core/exec/runtime.rst b/document/core/exec/runtime.rst index 6fd25c304c..8a91a1f766 100644 --- a/document/core/exec/runtime.rst +++ b/document/core/exec/runtime.rst @@ -572,7 +572,7 @@ Conventions .. math:: \begin{array}{@{}lcl} \packval_{\valtype}(\val) &=& \val \\ - \packval_{\packedtype}(\I32.\CONST~i) &=& \packedtype.\PACK~(\wrap_{32,|\packtype|}(i)) + \packval_{\packedtype}(\I32.\CONST~i) &=& \packedtype.\PACK~(\wrap_{32,|\packedtype|}(i)) \end{array} * The inverse conversion of a :ref:`field value ` to a regular :ref:`value ` is defined as follows: @@ -726,6 +726,7 @@ Conventions pair:: abstract syntax; administrative instruction .. _syntax-trap: .. _syntax-invoke: +.. _syntax-return_invoke: .. _syntax-instr-admin: Administrative Instructions diff --git a/document/core/exec/values.rst b/document/core/exec/values.rst index 684e0da4aa..5902929a61 100644 --- a/document/core/exec/values.rst +++ b/document/core/exec/values.rst @@ -48,7 +48,7 @@ The following auxiliary typing rules specify this typing relation relative to a * The :ref:`heap type ` must be :ref:`valid ` under the empty :ref:`context `. -* Then value is valid with :ref:`reference type ` :math:`(\REF~\NULL~t')`, where the :ref:`heap type ` :math:`t'` that is the least type that :ref:`matches ` :math:`t`. +* Then the value is valid with :ref:`reference type ` :math:`(\REF~\NULL~t')`, where the :ref:`heap type ` :math:`t'` is the least type that :ref:`matches ` :math:`t`. .. math:: \frac{ diff --git a/document/core/syntax/types.rst b/document/core/syntax/types.rst index bbbfd3033e..883dfa330d 100644 --- a/document/core/syntax/types.rst +++ b/document/core/syntax/types.rst @@ -81,6 +81,7 @@ Conventions .. _type-concrete: .. _syntax-i31: .. _syntax-heaptype: +.. _syntax-absheaptype: Heap Types ~~~~~~~~~~ @@ -298,12 +299,21 @@ Structures are heterogeneous, but require static indexing, while arrays need to \end{array} .. _bitwidth-fieldtype: +.. _aux-unpacktype: Conventions ........... * The notation :math:`|t|` for :ref:`bit width ` extends to packed types as well, that is, :math:`|\I8| = 8` and :math:`|\I16| = 16`. +* The auxiliary function :math:`\unpacktype` maps a storage type to the :ref:`value type ` obtained when accessing a field: + + .. math:: + \begin{array}{lll} + \unpacktype(\valtype) &=& \valtype \\ + \unpacktype(\packedtype) &=& \I32 \\ + \end{array} + .. index:: ! composite type, function type, aggreagate type, structure type, array type pair: abstract syntax; composite type diff --git a/document/core/text/lexical.rst b/document/core/text/lexical.rst index 4584b0c424..684688d49a 100644 --- a/document/core/text/lexical.rst +++ b/document/core/text/lexical.rst @@ -71,8 +71,9 @@ Any token that does not fall into any of the other categories is considered *res .. index:: ! white space, character, ASCII single: text format; white space -.. _text-format: .. _text-space: +.. _text-format: +.. _text-newline: White Space ~~~~~~~~~~~ diff --git a/document/core/text/modules.rst b/document/core/text/modules.rst index 0cb0568af4..1f35b89dc5 100644 --- a/document/core/text/modules.rst +++ b/document/core/text/modules.rst @@ -641,7 +641,7 @@ As another abbreviation, element segments may also be specified inline with :ref single: data; segment .. _text-datastring: .. _text-data: -.. _test-memuse: +.. _text-memuse: Data Segments ~~~~~~~~~~~~~ diff --git a/document/core/util/check_macros.sh b/document/core/util/check_macros.sh new file mode 100644 index 0000000000..2ac6101291 --- /dev/null +++ b/document/core/util/check_macros.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +cd `dirname $0`/.. + +FILES=`ls */*.rst` +ERRORS=0 + +for XREF in `grep "[\\]xref" util/macros.def`; do + if echo $XREF | grep -q "[|]"; then + MACRO=`echo $XREF | sed 's/^[^|]*[|]//g' | sed 's/[|].*$//g'` + elif echo $XREF | grep -q xref; then + FILE=`echo $XREF | sed 's/^.*xref{//g' | sed 's/}.*$//g'`.rst + LABEL=`echo $XREF | sed 's/^[^}]*}{//g' | sed 's/}.*$//g'` + TARGET=".. _$LABEL:" + if ! [ -f $FILE ] || ! grep -q "$TARGET" $FILE; then + ERRORS=1 + echo Undefined cross-reference $FILE:$LABEL in macro "|$MACRO|" + if ! [ -f $FILE ]; then + echo ...non-existent file $FILE + fi + if grep -q "$TARGET" $FILES; then + echo ...defined in `grep -l "$TARGET" $FILES` + fi + fi + fi +done + +if [ $ERRORS -eq 0 ]; then + echo All cross-references okay. +else + exit 1; +fi diff --git a/document/core/util/macros.def b/document/core/util/macros.def index dccb861690..a256d0b7aa 100644 --- a/document/core/util/macros.def +++ b/document/core/util/macros.def @@ -101,7 +101,7 @@ .. Notation for Sequences & Records -.. |subst| mathdef:: \xref{syntax/conventions}{notation-subst}{\mathrel{\mathbf{:=}}} +.. |subst| mathdef:: \xref{valid/conventions}{notation-subst}{\mathrel{\mathbf{:=}}} .. |slice| mathdef:: \xref{syntax/conventions}{notation-slice}{\mathrel{\mathbf{:}}} .. |with| mathdef:: \xref{syntax/conventions}{notation-replace}{\mathrel{\mbox{with}}} .. |concat| mathdef:: \xref{syntax/conventions}{notation-concat}{\F{concat}} @@ -178,13 +178,13 @@ .. Types, terminals .. |toF| mathdef:: \xref{syntax/types}{syntax-functype}{\rightarrow} -.. |to| mathdef:: \mathrel{\xref{syntax/types}{syntax-instrtype}{\rightarrow}} +.. |to| mathdef:: \mathrel{\xref{valid/conventions}{syntax-instrtype}{\rightarrow}} .. |BOTH| mathdef:: \xref{valid/conventions}{syntax-heaptype-ext}{\K{bot}} .. |BOT| mathdef:: \xref{valid/conventions}{syntax-valtype-ext}{\K{bot}} -.. |I8| mathdef:: \xref{syntax/runtime}{syntax-storagetype}{\K{i8}} -.. |I16| mathdef:: \xref{syntax/runtime}{syntax-storagetype}{\K{i16}} +.. |I8| mathdef:: \xref{syntax/types}{syntax-storagetype}{\K{i8}} +.. |I16| mathdef:: \xref{syntax/types}{syntax-storagetype}{\K{i16}} .. |I32| mathdef:: \xref{syntax/types}{syntax-valtype}{\K{i32}} .. |I64| mathdef:: \xref{syntax/types}{syntax-valtype}{\K{i64}} .. |F32| mathdef:: \xref{syntax/types}{syntax-valtype}{\K{f32}} @@ -239,8 +239,8 @@ .. |MVAR| mathdef:: \xref{syntax/types}{syntax-mut}{\K{var}} .. |MCONST| mathdef:: \xref{syntax/types}{syntax-mut}{\K{const}} -.. |SET| mathdef:: \xref{syntax/types}{syntax-init}{\K{set}} -.. |UNSET| mathdef:: \xref{syntax/types}{syntax-init}{\K{unset}} +.. |SET| mathdef:: \xref{valid/conventions}{syntax-init}{\K{set}} +.. |UNSET| mathdef:: \xref{valid/conventions}{syntax-init}{\K{unset}} .. |LMIN| mathdef:: \xref{syntax/types}{syntax-limits}{\K{min}} .. |LMAX| mathdef:: \xref{syntax/types}{syntax-limits}{\K{max}} @@ -279,7 +279,7 @@ .. |limits| mathdef:: \xref{syntax/types}{syntax-limits}{\X{limits}} .. |mut| mathdef:: \xref{syntax/types}{syntax-mut}{\X{mut}} -.. |init| mathdef:: \xref{syntax/types}{syntax-init}{\X{init}} +.. |init| mathdef:: \xref{valid/conventions}{syntax-init}{\X{init}} .. |instrtype| mathdef:: \xref{valid/conventions}{syntax-instrtype}{\X{instrtype}} .. |localtype| mathdef:: \xref{valid/conventions}{syntax-localtype}{\X{localtype}} @@ -297,7 +297,6 @@ .. |expanddt| mathdef:: \xref{valid/conventions}{aux-expand-deftype}{\F{expand}} .. |unrollht| mathdef:: \xref{appendix/properties}{aux-unroll-heaptype}{\F{unroll}} -.. |packtype| mathdef:: \xref{syntax/types}{aux-packtype}{\F{pack}} .. |unpacktype| mathdef:: \xref{syntax/types}{aux-unpacktype}{\F{unpack}} .. |etfuncs| mathdef:: \xref{syntax/types}{syntax-externtype}{\F{funcs}} @@ -519,10 +518,10 @@ .. |ARRAYGETU| mathdef:: \xref{syntax/instructions}{syntax-instr-array}{\K{array.get\_u}} .. |ARRAYSET| mathdef:: \xref{syntax/instructions}{syntax-instr-array}{\K{array.set}} .. |ARRAYLEN| mathdef:: \xref{syntax/instructions}{syntax-instr-array}{\K{array.len}} -.. |ARRAYFILL| mathdef:: \xref{syntax/instructions}{syntax-instr-aray}{\K{array.fill}} -.. |ARRAYCOPY| mathdef:: \xref{syntax/instructions}{syntax-instr-aray}{\K{array.copy}} -.. |ARRAYINITDATA| mathdef:: \xref{syntax/instructions}{syntax-instr-aray}{\K{array.init\_data}} -.. |ARRAYINITELEM| mathdef:: \xref{syntax/instructions}{syntax-instr-aray}{\K{array.init\_elem}} +.. |ARRAYFILL| mathdef:: \xref{syntax/instructions}{syntax-instr-array}{\K{array.fill}} +.. |ARRAYCOPY| mathdef:: \xref{syntax/instructions}{syntax-instr-array}{\K{array.copy}} +.. |ARRAYINITDATA| mathdef:: \xref{syntax/instructions}{syntax-instr-array}{\K{array.init\_data}} +.. |ARRAYINITELEM| mathdef:: \xref{syntax/instructions}{syntax-instr-array}{\K{array.init\_elem}} .. |REFI31| mathdef:: \xref{syntax/instructions}{syntax-instr-i31}{\K{ref.i31}} .. |I31GET| mathdef:: \xref{syntax/instructions}{syntax-instr-i31}{\K{i31.get}} @@ -655,9 +654,7 @@ .. |vunop| mathdef:: \xref{syntax/instructions}{syntax-vunop}{\X{vunop}} .. |vbinop| mathdef:: \xref{syntax/instructions}{syntax-vbinop}{\X{vbinop}} .. |vrelop| mathdef:: \xref{syntax/instructions}{syntax-vrelop}{\X{vrelop}} -.. |vternop| mathdef:: \xref{syntax/instructions}{syntax-vternop}{\X{vternop}} .. |vcvtop| mathdef:: \xref{syntax/instructions}{syntax-vcvtop}{\X{vcvtop}} -.. |vextmul| mathdef:: \xref{syntax/instructions}{syntax-vextmul}{\X{vextmul}} .. |laneidx| mathdef:: \xref{syntax/instructions}{syntax-laneidx}{\X{laneidx}} .. |vvunop| mathdef:: \xref{syntax/instructions}{syntax-vvunop}{\X{vvunop}} @@ -934,7 +931,7 @@ .. |Tfunctype| mathdef:: \xref{text/types}{text-functype}{\T{functype}} .. |Tstructtype| mathdef:: \xref{text/types}{text-structtype}{\T{structtype}} .. |Tarraytype| mathdef:: \xref{text/types}{text-arraytype}{\T{arraytype}} -.. |Taggrtype| mathdef:: \xref{text/types}{text-aggrype}{\T{aggrtype}} +.. |Taggrtype| mathdef:: \xref{text/types}{text-aggrtype}{\T{aggrtype}} .. |Tfieldtype| mathdef:: \xref{text/types}{text-fieldtype}{\T{fieldtype}} .. |Tstoragetype| mathdef:: \xref{text/types}{text-storagetype}{\T{storagetype}} .. |Tpackedtype| mathdef:: \xref{text/types}{text-packedtype}{\T{packedtype}} @@ -971,9 +968,8 @@ .. Modules, non-terminals .. |Tmodule| mathdef:: \xref{text/modules}{text-module}{\T{module}} -.. |Tmodulebody| mathdef:: \xref{text/modules}{text-modulebody}{\T{modulebody}} .. |Tmodulefield| mathdef:: \xref{text/modules}{text-modulefield}{\T{modulefield}} -.. |Ttype| mathdef:: \xref{text/modules}{text-typedef}{\T{type}} +.. |Ttype| mathdef:: \xref{text/types}{text-typedef}{\T{type}} .. |Ttypeuse| mathdef:: \xref{text/modules}{text-typeuse}{\T{typeuse}} .. |Tfunc| mathdef:: \xref{text/modules}{text-func}{\T{func}} .. |Ttable| mathdef:: \xref{text/modules}{text-table}{\T{table}} @@ -988,7 +984,6 @@ .. |Telemlist| mathdef:: \xref{text/modules}{text-elemlist}{\T{elemlist}} .. |Telemexpr| mathdef:: \xref{text/modules}{text-elemexpr}{\T{elemexpr}} .. |Ttableuse| mathdef:: \xref{text/modules}{text-tableuse}{\T{tableuse}} -.. |Tcode| mathdef:: \xref{text/modules}{text-code}{\T{code}} .. |Tlocal| mathdef:: \xref{text/modules}{text-local}{\T{local}} .. |Tlocals| mathdef:: \xref{text/modules}{text-local}{\T{locals}} .. |Tdata| mathdef:: \xref{text/modules}{text-data}{\T{data}} @@ -1077,7 +1072,7 @@ .. Meta functions -.. |clostype| mathdef:: \xref{valid/conventions}{closure}{\K{clos}} +.. |clostype| mathdef:: \xref{valid/conventions}{aux-clostype}{\K{clos}} .. Contexts @@ -1094,7 +1089,7 @@ .. |CLABELS| mathdef:: \xref{valid/conventions}{context}{\K{labels}} .. |CRETURN| mathdef:: \xref{valid/conventions}{context}{\K{return}} .. |CREFS| mathdef:: \xref{valid/conventions}{context}{\K{refs}} -.. |CRECS| mathdef:: \xref{valid/matching}{context-rec}{\K{recs}} +.. |CRECS| mathdef:: \xref{appendix/properties}{context-ext}{\K{recs}} .. Judgments @@ -1175,7 +1170,7 @@ .. |vdashimportdesc| mathdef:: \xref{valid/modules}{valid-importdesc}{\vdash} .. |vdashmodule| mathdef:: \xref{valid/modules}{valid-module}{\vdash} -.. |unpacked| mathdef:: \xref{valid/instructions}{aux-unpacked}{\F{unpacked}} +.. |unpackshape| mathdef:: \xref{valid/instructions}{aux-unpackshape}{\F{unpack}} .. |dim| mathdef:: \xref{valid/instructions}{aux-dim}{\F{dim}} @@ -1184,7 +1179,7 @@ .. Notation -.. |stepto| mathdef:: \xref{exec/conventions}{formal-notation}{\hookrightarrow} +.. |stepto| mathdef:: \xref{exec/conventions}{exec-notation}{\hookrightarrow} .. |extendsto| mathdef:: \xref{appendix/properties}{extend}{\preceq} @@ -1225,13 +1220,13 @@ .. Address, meta functions -.. |freefuncaddr| mathdef:: \xref{syntax/modules}{syntax-funcaddr}{\F{funcaddr}} -.. |freetableaddr| mathdef:: \xref{syntax/modules}{syntax-tableaddr}{\F{tableaddr}} -.. |freememaddr| mathdef:: \xref{syntax/modules}{syntax-memaddr}{\F{memaddr}} -.. |freeglobaladdr| mathdef:: \xref{syntax/modules}{syntax-globaladdr}{\F{globaladdr}} -.. |freetagaddr| mathdef:: \xref{syntax/modules}{syntax-globaladdr}{\F{tagaddr}} -.. |freeelemaddr| mathdef:: \xref{syntax/modules}{syntax-elemaddr}{\F{elemaddr}} -.. |freedataaddr| mathdef:: \xref{syntax/modules}{syntax-dataaddr}{\F{dataaddr}} +.. |freefuncaddr| mathdef:: \xref{exec/runtime}{syntax-funcaddr}{\F{funcaddr}} +.. |freetableaddr| mathdef:: \xref{exec/runtime}{syntax-tableaddr}{\F{tableaddr}} +.. |freememaddr| mathdef:: \xref{exec/runtime}{syntax-memaddr}{\F{memaddr}} +.. |freeglobaladdr| mathdef:: \xref{exec/runtime}{syntax-globaladdr}{\F{globaladdr}} +.. |freetagaddr| mathdef:: \xref{exec/runtime}{syntax-globaladdr}{\F{tagaddr}} +.. |freeelemaddr| mathdef:: \xref{exec/runtime}{syntax-elemaddr}{\F{elemaddr}} +.. |freedataaddr| mathdef:: \xref{exec/runtime}{syntax-dataaddr}{\F{dataaddr}} .. Instances, terminals @@ -1286,8 +1281,8 @@ .. |EIFIELDS| mathdef:: \xref{exec/runtime}{syntax-exninst}{\K{fields}} .. |PACK| mathdef:: \xref{exec/runtime}{syntax-packedval}{\K{pack}} -.. |I8PACK| mathdef:: \xref{exec/runtime}{syntax-packval}{\K{i8.pack}} -.. |I16PACK| mathdef:: \xref{exec/runtime}{syntax-packval}{\K{i16.pack}} +.. |I8PACK| mathdef:: \xref{exec/runtime}{syntax-packedval}{\K{i8.pack}} +.. |I16PACK| mathdef:: \xref{exec/runtime}{syntax-packedval}{\K{i16.pack}} .. Instances, non-terminals @@ -1380,7 +1375,7 @@ .. Values & Results, non-terminals .. |num| mathdef:: \xref{exec/runtime}{syntax-num}{\X{num}} -.. |vecc| mathdef:: \xref{exec/runtime}{syntax-vec}{\X{vec}} +.. |vecc| mathdef:: \xref{exec/runtime}{syntax-vecc}{\X{vec}} .. |reff| mathdef:: \xref{exec/runtime}{syntax-ref}{\X{ref}} .. |val| mathdef:: \xref{exec/runtime}{syntax-val}{\X{val}} .. |result| mathdef:: \xref{exec/runtime}{syntax-result}{\X{result}} @@ -1451,10 +1446,10 @@ .. |imins| mathdef:: \xref{exec/numerics}{op-imin_s}{\F{imin\_s}} .. |imaxu| mathdef:: \xref{exec/numerics}{op-imax_u}{\F{imax\_u}} .. |imaxs| mathdef:: \xref{exec/numerics}{op-imax_s}{\F{imax\_s}} -.. |iaddsatu| mathdef:: \xref{exec/numerics}{op-iaddsat_u}{\F{iaddsat\_u}} -.. |iaddsats| mathdef:: \xref{exec/numerics}{op-iaddsat_s}{\F{iaddsat\_s}} -.. |isubsatu| mathdef:: \xref{exec/numerics}{op-isubsat_u}{\F{isubsat\_u}} -.. |isubsats| mathdef:: \xref{exec/numerics}{op-isubsat_s}{\F{isubsat\_s}} +.. |iaddsatu| mathdef:: \xref{exec/numerics}{op-iadd_sat_u}{\F{iadd\_sat\_u}} +.. |iaddsats| mathdef:: \xref{exec/numerics}{op-iadd_sat_s}{\F{iadd\_sat\_s}} +.. |isubsatu| mathdef:: \xref{exec/numerics}{op-isub_sat_u}{\F{isub\_sat\_u}} +.. |isubsats| mathdef:: \xref{exec/numerics}{op-isub_sat_s}{\F{isub\_sat\_s}} .. |iavgru| mathdef:: \xref{exec/numerics}{op-iavgr_u}{\F{iavgr\_u}} .. |iq15mulrsats| mathdef:: \xref{exec/numerics}{op-iq15mulrsat_s}{\F{iq15mulrsat\_s}} diff --git a/document/core/valid/conventions.rst b/document/core/valid/conventions.rst index bc6a02f400..6dc6950147 100644 --- a/document/core/valid/conventions.rst +++ b/document/core/valid/conventions.rst @@ -303,6 +303,7 @@ In addition to field access written :math:`C.\K{field}` the following notation i .. index:: ! type closure .. _type-closure: +.. _aux-clostype: Convention .......... diff --git a/document/core/valid/instructions.rst b/document/core/valid/instructions.rst index 83e74e96b4..8088049e4f 100644 --- a/document/core/valid/instructions.rst +++ b/document/core/valid/instructions.rst @@ -379,7 +379,7 @@ Aggregate Reference Instructions \qquad \X{ft}^\ast[y] = \mut~\X{st} \qquad - \sx = \epsilon \Leftrightarrow \X{st} = \unpacktype(\X{st}) + \sx^? = \epsilon \Leftrightarrow \X{st} = \unpacktype(\X{st}) }{ C \vdashinstr \STRUCTGET\K{\_}\sx^?~x~y : [(\REF~\NULL~x)] \to [\unpacktype(\X{st})] } @@ -508,7 +508,7 @@ Aggregate Reference Instructions \qquad C \vdashreftypematch C.\CELEMS[y] \matchesreftype \X{rt} }{ - C \vdashinstr \ARRAYNEWELEM~x~n : [\I32~\I32] \to [(\REF~x)] + C \vdashinstr \ARRAYNEWELEM~x~y : [\I32~\I32] \to [(\REF~x)] } @@ -539,7 +539,7 @@ Aggregate Reference Instructions \qquad C.\CDATAS[y] = {\ok} }{ - C \vdashinstr \ARRAYNEWDATA~x~n : [\I32~\I32] \to [(\REF~x)] + C \vdashinstr \ARRAYNEWDATA~x~y : [\I32~\I32] \to [(\REF~x)] } @@ -566,7 +566,7 @@ Aggregate Reference Instructions \frac{ \expanddt(C.\CTYPES[x]) = \TARRAY~(\mut~\X{st}) \qquad - \sx = \epsilon \Leftrightarrow \X{st} = \unpacktype(\X{st}) + \sx^? = \epsilon \Leftrightarrow \X{st} = \unpacktype(\X{st}) }{ C \vdashinstr \ARRAYGET\K{\_}\sx^?~x : [(\REF~\NULL~x)~\I32] \to [\unpacktype(\X{st})] } @@ -806,7 +806,7 @@ External Reference Instructions single: abstract syntax; instruction .. _valid-instr-vec: -.. _aux-unpacked: +.. _aux-unpackshape: Vector Instructions ~~~~~~~~~~~~~~~~~~~ @@ -815,9 +815,7 @@ Vector instructions can have a prefix to describe the :ref:`shape ` classifying a module may contain f * For each :math:`\tag_i` in :math:`\module.\MTAGS`, the definition :math:`\tag_i` must be :ref:`valid ` with a :ref:`tag type ` :math:`\X{ht}_i`. - * For each :math:`\table_i` in :math:`\module.\MTABLES`, - the definition :math:`\table_i` must be :ref:`valid ` with a :ref:`table type ` :math:`\X{tt}_i`. - - * For each :math:`\mem_i` in :math:`\module.\MMEMS`, - the definition :math:`\mem_i` must be :ref:`valid ` with a :ref:`memory type ` :math:`\X{mt}_i`. - - * For each :math:`\global_i` in :math:`\module.\MGLOBALS`, - the definition :math:`\global_i` must be :ref:`valid ` with a :ref:`global type ` :math:`\X{gt}_i`. - * For each :math:`\elem_i` in :math:`\module.\MELEMS`, the segment :math:`\elem_i` must be :ref:`valid ` with :ref:`reference type ` :math:`\X{rt}_i`. * For each :math:`\data_i` in :math:`\module.\MDATAS`, the segment :math:`\data_i` must be :ref:`valid `. -* Under the context :math:`C`: - - * For each :math:`\func_i` in :math:`\module.\MFUNCS`, - the definition :math:`\func_i` must be :ref:`valid ` with a :ref:`function type ` :math:`\X{ft}_i`. - * If :math:`\module.\MSTART` is non-empty, then :math:`\module.\MSTART` must be :ref:`valid `. @@ -839,11 +825,7 @@ The :ref:`external types ` classifying a module may contain f * For each :math:`\export_i` in :math:`\module.\MEXPORTS`, the segment :math:`\export_i` must be :ref:`valid ` with :ref:`external type ` :math:`\X{et}_i`. -* The length of :math:`C.\CMEMS` must not be larger than :math:`1`. - -* All export names :math:`\export_i.\ENAME` must be different. - -* Let :math:`\X{ft}^\ast` be the concatenation of the internal :ref:`function types ` :math:`\X{ft}_i`, in index order. +* Let :math:`\X{dt}^\ast` be the concatenation of the internal :ref:`function types ` :math:`\X{dt}_i`, in index order. * Let :math:`\X{tt}^\ast` be the concatenation of the internal :ref:`table types ` :math:`\X{tt}_i`, in index order. @@ -912,9 +894,6 @@ The :ref:`external types ` classifying a module may contain f \CREFS~x^\ast \} \\ C' = \{ \CTYPES~C_0.\CTYPES, \CGLOBALS~\X{igt}^\ast, \CFUNCS~(C.\CFUNCS), \CTABLES~(C.\CTABLES), \CMEMS~(C.\CMEMS), \CREFS~(C.\CREFS) \} - %C' = C \with \CGLOBALS = \X{igt}^\ast - %\qquad - %|C.\CMEMS| \leq 1 \qquad (\export.\ENAME)^\ast ~\F{disjoint} \\ diff --git a/document/js-api/index.bs b/document/js-api/index.bs index 99e162d21f..fb60d30b2a 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -118,6 +118,7 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df text: global_read; url: appendix/embedding.html#embed-global-read text: global_write; url: appendix/embedding.html#embed-global-write text: ref_type; url: appendix/embedding.html#embed-ref-type + text: val_default; url: appendix/embedding.html#embed-val-default text: match_valtype; url: appendix/embedding.html#embed-match-valtype text: error; url: appendix/embedding.html#embed-error text: store; url: exec/runtime.html#syntax-store @@ -391,7 +392,7 @@ A {{Module}} object represents a single WebAssembly module. Each {{Module}} obje 1. Throw a {{LinkError}} exception. 1. If |valtype| is [=v128=], 1. Throw a {{LinkError}} exception. - 1. Let |value| be [=ToWebAssemblyValue=](|v|, |valtype|). + 1. Let |value| be [=ToWebAssemblyValue=](|v|, |valtype|). If this operation throws a {{TypeError}}, catch it, and throw a {{LinkError}} exception. 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. 1. Let (|store|, |globaladdr|) be [=global_alloc=](|store|, [=const=] |valtype|, |value|). 1. Set the [=surrounding agent=]'s [=associated store=] to |store|. @@ -878,6 +879,7 @@ Each {{Table}} object has a \[[Table]] internal slot, which is a [=table address 1. If |maximum| is not empty and |maximum| < |initial|, throw a {{RangeError}} exception. 1. If |value| is missing, 1. Let |ref| be [=DefaultValue=](|elementType|). + 1. Assert: |ref| is not [=error=]. 1. Otherwise, 1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementType|). 1. Let |type| be the [=table type=] {[=table type|min=] |initial|, [=table type|max=] |maximum|} |elementType|. @@ -895,6 +897,7 @@ Each {{Table}} object has a \[[Table]] internal slot, which is a [=table address 1. Let (limits, |elementType|) be [=table_type=](|tableaddr|). 1. If |value| is missing, 1. Let |ref| be [=DefaultValue=](|elementType|). + 1. If |ref| is [=error=], throw a {{TypeError}} exception. 1. Otherwise, 1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementType|). 1. Let |result| be [=table_grow=](|store|, |tableaddr|, |delta|, |ref|). @@ -934,6 +937,7 @@ Each {{Table}} object has a \[[Table]] internal slot, which is a [=table address 1. [=Throw=] a {{TypeError}} exception. 1. If |value| is missing, 1. Let |ref| be [=DefaultValue=](|elementType|). + 1. If |ref| is [=error=], throw a {{TypeError}} exception. 1. Otherwise, 1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementType|). 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. @@ -1010,13 +1014,8 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each
The algorithm DefaultValue(|valuetype|) performs the following steps: - 1. If |valuetype| equals [=i32=], return [=i32.const=] 0. - 1. If |valuetype| equals [=i64=], return [=i64.const=] 0. - 1. If |valuetype| equals [=f32=], return [=f32.const=] 0. - 1. If |valuetype| equals [=f64=], return [=f64.const=] 0. - 1. If |valuetype| equals [=funcref=], return [=ref.null=] [=funcref=]. 1. If |valuetype| equals [=externref=], return [=ToWebAssemblyValue=](undefined, |valuetype|). - 1. Assert: This step is not reached. + 1. Return [=val_default=](|valuetype|).
@@ -1027,6 +1026,7 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each 1. Throw a {{TypeError}} exception. 1. If |v| is missing, 1. Let |value| be [=DefaultValue=](|valuetype|). + 1. Assert: |value| is not [=error=]. 1. Otherwise, 1. Let |value| be [=ToWebAssemblyValue=](|v|, |valuetype|). 1. If |mutable| is true, let |globaltype| be [=var=] |valuetype|; otherwise, let |globaltype| be [=const=] |valuetype|. diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml index f9858f4461..4cfa822ff1 100644 --- a/interpreter/binary/decode.ml +++ b/interpreter/binary/decode.ml @@ -1248,7 +1248,7 @@ let elem s = | 0x04l -> let emode = at active_zero s in let einit = vec const s in - {etype = (NoNull, FuncHT); einit; emode} + {etype = (Null, FuncHT); einit; emode} | 0x05l -> let emode = at passive s in let etype = ref_type s in diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml index 04492bf1a5..3392165fd9 100644 --- a/interpreter/binary/encode.ml +++ b/interpreter/binary/encode.ml @@ -1067,7 +1067,7 @@ struct match emode.it with | Passive -> u32 0x01l; elem_kind etype; vec elem_index einit - | Active {index; offset} when index.it = 0l && is_elem_kind etype -> + | Active {index; offset} when index.it = 0l -> u32 0x00l; const offset; vec elem_index einit | Active {index; offset} -> u32 0x02l; @@ -1078,7 +1078,7 @@ struct match emode.it with | Passive -> u32 0x05l; ref_type etype; vec const einit - | Active {index; offset} when index.it = 0l && is_elem_kind etype -> + | Active {index; offset} when index.it = 0l && etype = (Null, FuncHT) -> u32 0x04l; const offset; vec const einit | Active {index; offset} -> u32 0x06l; var index; const offset; ref_type etype; vec const einit diff --git a/interpreter/runtime/value.ml b/interpreter/runtime/value.ml index a3762725e5..dec2597229 100644 --- a/interpreter/runtime/value.ml +++ b/interpreter/runtime/value.ml @@ -95,23 +95,17 @@ let is_null_ref = function (* Typing *) let type_of_op = function - | I32 _ -> Types.I32T - | I64 _ -> Types.I64T - | F32 _ -> Types.F32T - | F64 _ -> Types.F64T - -let type_of_vecop = function - | V128 _ -> Types.V128T - -let type_of_num = function | I32 _ -> I32T | I64 _ -> I64T | F32 _ -> F32T | F64 _ -> F64T -let type_of_vec = function +let type_of_vecop = function | V128 _ -> V128T +let type_of_num = type_of_op +let type_of_vec = type_of_vecop + let type_of_ref' = ref (function _ -> assert false) let type_of_ref = function | NullRef t -> (Null, Match.bot_of_heap_type [] t) diff --git a/interpreter/script/js.ml b/interpreter/script/js.ml index 9c28daa216..6a029f9817 100644 --- a/interpreter/script/js.ml +++ b/interpreter/script/js.ml @@ -302,8 +302,29 @@ let nan_bitmask_of = function | CanonicalNan -> abs_mask_of (* differ from canonical NaN in sign bit *) | ArithmeticNan -> canonical_nan_of (* 1 everywhere canonical NaN is *) +let type_of_num_pat = function + | NumPat num -> Value.type_of_num num.it + | NanPat op -> Value.type_of_op op.it + +let type_of_vec_pat = function + | VecPat vec -> Value.type_of_vec vec + +let type_of_ref_pat = function + | RefPat ref -> type_of_ref ref.it + | RefTypePat ht -> (NoNull, ht) + | NullPat -> (Null, BotHT) + +let type_of_result res = + match res.it with + | NumResult pat -> NumT (type_of_num_pat pat) + | VecResult pat -> VecT (type_of_vec_pat pat) + | RefResult pat -> RefT (type_of_ref_pat pat) + let assert_return ress ts at = let test (res, t) = + if not (Match.match_val_type [] t (type_of_result res)) then + [ Br (0l @@ at) @@ at ] + else match res.it with | NumResult (NumPat {it = num; at = at'}) -> let t', reinterpret = reinterpret_of (Value.type_of_op num) in @@ -370,7 +391,7 @@ let assert_return ress ts at = VecTest (V128 (V128.I8x16 V128Op.AllTrue)) @@ at; Test (I32 I32Op.Eqz) @@ at; BrIf (0l @@ at) @@ at ] - | RefResult (RefPat {it = NullRef t; _}) -> + | RefResult (RefPat {it = NullRef _; _}) -> [ RefIsNull @@ at; Test (Value.I32 I32Op.Eqz) @@ at; BrIf (0l @@ at) @@ at ] @@ -382,17 +403,16 @@ let assert_return ress ts at = BrIf (0l @@ at) @@ at ] | RefResult (RefPat _) -> assert false + | RefResult (RefTypePat (ExnHT | ExternHT)) -> + [ BrOnNull (0l @@ at) @@ at ] | RefResult (RefTypePat t) -> [ RefTest (NoNull, t) @@ at; Test (I32 I32Op.Eqz) @@ at; BrIf (0l @@ at) @@ at ] | RefResult NullPat -> - (match t with - | RefT _ -> - [ BrOnNull (0l @@ at) @@ at ] - | _ -> - [ Br (0l @@ at) @@ at ] - ) + [ RefIsNull @@ at; + Test (I32 I32Op.Eqz) @@ at; + BrIf (0l @@ at) @@ at ] in [], List.flatten (List.rev_map test (List.combine ress ts)) let i32 = NumT I32T @@ -439,10 +459,17 @@ let is_js_num_type = function | I32T -> true | I64T | F32T | F64T -> false +let is_js_vec_type = function + | _ -> false + +let is_js_ref_type = function + | (_, ExnHT) -> false + | _ -> true + let is_js_val_type = function | NumT t -> is_js_num_type t - | VecT _ -> false - | RefT _ -> true + | VecT t -> is_js_vec_type t + | RefT t -> is_js_ref_type t | BotT -> assert false let is_js_global_type = function diff --git a/interpreter/script/run.ml b/interpreter/script/run.ml index 4d8a5f44aa..ac42defc6f 100644 --- a/interpreter/script/run.ml +++ b/interpreter/script/run.ml @@ -394,6 +394,7 @@ let assert_ref_pat r p = | RefTypePat Types.StructHT, Aggr.StructRef _ | RefTypePat Types.ArrayHT, Aggr.ArrayRef _ -> true | RefTypePat Types.FuncHT, Instance.FuncRef _ + | RefTypePat Types.ExnHT, Value.ExnRef _ | RefTypePat Types.ExternHT, _ -> true | NullPat, Value.NullRef _ -> true | _ -> false diff --git a/interpreter/text/lexer.mll b/interpreter/text/lexer.mll index 24a7ac3f12..3b16de0362 100644 --- a/interpreter/text/lexer.mll +++ b/interpreter/text/lexer.mll @@ -336,6 +336,7 @@ rule token = parse | "ref.func" -> REF_FUNC | "ref.struct" -> REF_STRUCT | "ref.array" -> REF_ARRAY + | "ref.exn" -> REF_EXN | "ref.extern" -> REF_EXTERN | "ref.host" -> REF_HOST diff --git a/interpreter/text/parser.mly b/interpreter/text/parser.mly index d169703578..93142b24c8 100644 --- a/interpreter/text/parser.mly +++ b/interpreter/text/parser.mly @@ -283,7 +283,7 @@ let inline_tag_type (c : context) (TagT ht) at = %token OFFSET_EQ_NAT ALIGN_EQ_NAT %token Ast.instr' * Value.num> CONST %token UNARY BINARY TEST COMPARE CONVERT -%token REF_NULL REF_FUNC REF_I31 REF_STRUCT REF_ARRAY REF_EXTERN REF_HOST +%token REF_NULL REF_FUNC REF_I31 REF_STRUCT REF_ARRAY REF_EXN REF_EXTERN REF_HOST %token REF_EQ REF_IS_NULL REF_AS_NON_NULL REF_TEST REF_CAST %token I31_GET %token Ast.instr'> STRUCT_NEW ARRAY_NEW ARRAY_GET @@ -1514,6 +1514,7 @@ result : | LPAR REF_STRUCT RPAR { RefResult (RefTypePat StructHT) @@ $sloc } | LPAR REF_ARRAY RPAR { RefResult (RefTypePat ArrayHT) @@ $sloc } | LPAR REF_FUNC RPAR { RefResult (RefTypePat FuncHT) @@ $sloc } + | LPAR REF_EXN RPAR { RefResult (RefTypePat ExnHT) @@ $sloc } | LPAR REF_EXTERN RPAR { RefResult (RefTypePat ExternHT) @@ $sloc } | LPAR REF_NULL RPAR { RefResult NullPat @@ $sloc } | LPAR VEC_CONST VEC_SHAPE list(numpat) RPAR diff --git a/proposals/gc/MVP.md b/proposals/gc/MVP.md index 081dfc539e..cec9ee12b7 100644 --- a/proposals/gc/MVP.md +++ b/proposals/gc/MVP.md @@ -466,7 +466,7 @@ Then, `$rttA` would carry supertype vector `[$rttA]`, `$rttB` has `[$rttA, $rttB Now consider a function that casts a `$B` to a `$C`: ``` (func $castBtoC (param $x (ref $B)) (result (ref $C)) - (ref.cast $C (local.get $x)) + (ref.cast (ref $C) (local.get $x)) ) ``` This can compile to machine code that (1) reads the RTT from `$x`, (2) checks that the length of its supertype table is >= 3, and (3) pointer-compares table[2] against `$rttC`. diff --git a/test/core/elem.wast b/test/core/elem.wast index 7084e7901e..1722a30b81 100644 --- a/test/core/elem.wast +++ b/test/core/elem.wast @@ -242,6 +242,352 @@ ) +;; Binary format variations + +(module + (func) + (table 1 funcref) + (elem (i32.const 0) func 0) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\07\01" ;; Elem section: 1 element segment + "\00\41\00\0b\01\00" ;; Segment 0: (i32.const 0) func 0 + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 funcref) + (elem func 0) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\05\01" ;; Elem section: 1 element segment + "\01\00\01\00" ;; Segment 0: func 0 + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 funcref) + (elem (table 0) (i32.const 0) func 0) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\09\01" ;; Elem section: 1 element segment + "\02\00\41\00\0b\00\01\00" ;; Segment 0: (table 0) (i32.const 0) func 0 + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 funcref) + (elem declare func 0) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\05\01" ;; Elem section: 1 element segment + "\03\00\01\00" ;; Segment 0: declare func 0 + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 funcref) + (elem (i32.const 0) (;;)(ref func) (ref.func 0)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\09\01" ;; Elem section: 1 element segment + "\04\41\00\0b\01\d2\00\0b" ;; Segment 0: (i32.const 0) (ref.func 0) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) +(module + (func) + (table 1 funcref) + (elem (i32.const 0) funcref (ref.null func)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\09\01" ;; Elem section: 1 element segment + "\04\41\00\0b\01\d0\70\0b" ;; Segment 0: (i32.const 0) (ref.null func) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 funcref) + (elem (i32.const 0) funcref (ref.func 0)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\07\01" ;; Elem section: 1 element segment + "\05\70\01\d2\00\0b" ;; Segment 0: funcref (ref.func 0) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) +(module + (func) + (table 1 funcref) + (elem (i32.const 0) funcref (ref.null func)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\07\01" ;; Elem section: 1 element segment + "\05\70\01\d0\70\0b" ;; Segment 0: funcref (ref.null func) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 funcref) + (elem (table 0) (i32.const 0) funcref (ref.func 0)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\0b\01" ;; Elem section: 1 element segment + "\06\00\41\00\0b\70\01\d2\00\0b" ;; Segment 0: (table 0) (i32.const 0) funcref (ref.func 0) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) +(module + (func) + (table 1 funcref) + (elem (table 0) (i32.const 0) funcref (ref.null func)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\0b\01" ;; Elem section: 1 element segment + "\06\00\41\00\0b\70\01\d0\70\0b" ;; Segment 0: (table 0) (i32.const 0) funcref (ref.null func) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 funcref) + (elem declare funcref (ref.func 0)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\07\01" ;; Elem section: 1 element segment + "\07\70\01\d2\00\0b" ;; Segment 0: declare funcref (ref.func 0) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) +(module + (func) + (table 1 funcref) + (elem declare funcref (ref.null func)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\07\01" ;; Elem section: 1 element segment + "\07\70\01\d0\70\0b" ;; Segment 0: declare funcref (ref.null func) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + + +(module + (func) + (table 1 (ref func) (ref.func 0)) + (elem (i32.const 0) func 0) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\0a\01" ;; Table section: 1 table + "\40\00\64\70\00\01\d2\00\0b" ;; Table 0: [1..] (ref func) (ref.func 0) + "\09\07\01" ;; Elem section: 1 element segment + "\00\41\00\0b\01\00" ;; Segment 0: (i32.const 0) func 0 + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 (ref func) (ref.func 0)) + (elem func 0) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\0a\01" ;; Table section: 1 table + "\40\00\64\70\00\01\d2\00\0b" ;; Table 0: [1..] (ref func) (ref.func 0) + "\09\05\01" ;; Elem section: 1 element segment + "\01\00\01\00" ;; Segment 0: func 0 + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 (ref func) (ref.func 0)) + (elem (table 0) (i32.const 0) func 0) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\0a\01" ;; Table section: 1 table + "\40\00\64\70\00\01\d2\00\0b" ;; Table 0: [1..] (ref func) (ref.func 0) + "\09\09\01" ;; Elem section: 1 element segment + "\02\00\41\00\0b\00\01\00" ;; Segment 0: (table 0) (i32.const 0) func 0 + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 (ref func) (ref.func 0)) + (elem declare func 0) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\0a\01" ;; Table section: 1 table + "\40\00\64\70\00\01\d2\00\0b" ;; Table 0: [1..] (ref func) (ref.func 0) + "\09\05\01" ;; Elem section: 1 element segment + "\03\00\01\00" ;; Segment 0: declare func 0 + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(assert_invalid + (module + (func) + (table 1 (ref func) (ref.func 0)) + (elem (i32.const 0) funcref (ref.func 0)) + ) + "type mismatch" +) +(assert_invalid + (module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\0a\01" ;; Table section: 1 table + "\40\00\64\70\00\01\d2\00\0b" ;; Table 0: [1..] (ref func) (ref.func 0) + "\09\09\01" ;; Elem section: 1 element segment + "\04\41\00\0b\01\d2\00\0b" ;; Segment 0: (i32.const 0) (ref.func 0) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty + ) + "type mismatch" +) + +(module + (func) + (table 1 (ref func) (ref.func 0)) + (elem (ref func) (ref.func 0)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\0a\01" ;; Table section: 1 table + "\40\00\64\70\00\01\d2\00\0b" ;; Table 0: [1..] (ref func) (ref.func 0) + "\09\08\01" ;; Elem section: 1 element segment + "\05\64\70\01\d2\00\0b" ;; Segment 0: (ref func) (ref.func 0) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 (ref func) (ref.func 0)) + (elem (table 0) (i32.const 0) (ref func) (ref.func 0)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\0a\01" ;; Table section: 1 table + "\40\00\64\70\00\01\d2\00\0b" ;; Table 0: [1..] (ref func) (ref.func 0) + "\09\0c\01" ;; Elem section: 1 element segment + "\06\00\41\00\0b\64\70\01\d2\00\0b" ;; Segment 0: (table 0) (i32.const 0) (ref func) (ref.func 0) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 (ref func) (ref.func 0)) + (elem declare (ref func) (ref.func 0)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\0a\01" ;; Table section: 1 table + "\40\00\64\70\00\01\d2\00\0b" ;; Table 0: [1..] (ref func) (ref.func 0) + "\09\08\01" ;; Elem section: 1 element segment + "\07\64\70\01\d2\00\0b" ;; Segment 0: declare (ref func) (ref.func 0) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + + ;; Invalid bounds for elements (assert_trap @@ -659,11 +1005,11 @@ ;; Initializing a table with an externref-type element segment (module $m - (table $t (export "table") 2 externref) - (func (export "get") (param $i i32) (result externref) - (table.get $t (local.get $i))) - (func (export "set") (param $i i32) (param $x externref) - (table.set $t (local.get $i) (local.get $x)))) + (table $t (export "table") 2 externref) + (func (export "get") (param $i i32) (result externref) + (table.get $t (local.get $i))) + (func (export "set") (param $i i32) (param $x externref) + (table.set $t (local.get $i) (local.get $x)))) (register "exporter" $m) diff --git a/test/core/gc/i31.wast b/test/core/gc/i31.wast index 3b6c32fbad..7485650454 100644 --- a/test/core/gc/i31.wast +++ b/test/core/gc/i31.wast @@ -19,10 +19,15 @@ (global $i (ref i31) (ref.i31 (i32.const 2))) (global $m (mut (ref i31)) (ref.i31 (i32.const 3))) + (func (export "get_globals") (result i32 i32) (i31.get_u (global.get $i)) (i31.get_u (global.get $m)) ) + + (func (export "set_global") (param i32) + (global.set $m (ref.i31 (local.get 0))) + ) ) (assert_return (invoke "new" (i32.const 1)) (ref.i31)) @@ -49,3 +54,175 @@ (assert_trap (invoke "get_s-null") "null i31 reference") (assert_return (invoke "get_globals") (i32.const 2) (i32.const 3)) + +(invoke "set_global" (i32.const 1234)) +(assert_return (invoke "get_globals") (i32.const 2) (i32.const 1234)) + +(module $tables_of_i31ref + (table $table 3 10 i31ref) + (elem (table $table) (i32.const 0) i31ref (item (ref.i31 (i32.const 999))) + (item (ref.i31 (i32.const 888))) + (item (ref.i31 (i32.const 777)))) + + (func (export "size") (result i32) + table.size $table + ) + + (func (export "get") (param i32) (result i32) + (i31.get_u (table.get $table (local.get 0))) + ) + + (func (export "grow") (param i32 i32) (result i32) + (table.grow $table (ref.i31 (local.get 1)) (local.get 0)) + ) + + (func (export "fill") (param i32 i32 i32) + (table.fill $table (local.get 0) (ref.i31 (local.get 1)) (local.get 2)) + ) + + (func (export "copy") (param i32 i32 i32) + (table.copy $table $table (local.get 0) (local.get 1) (local.get 2)) + ) + + (elem $elem i31ref (item (ref.i31 (i32.const 123))) + (item (ref.i31 (i32.const 456))) + (item (ref.i31 (i32.const 789)))) + (func (export "init") (param i32 i32 i32) + (table.init $table $elem (local.get 0) (local.get 1) (local.get 2)) + ) +) + +;; Initial state. +(assert_return (invoke "size") (i32.const 3)) +(assert_return (invoke "get" (i32.const 0)) (i32.const 999)) +(assert_return (invoke "get" (i32.const 1)) (i32.const 888)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 777)) + +;; Grow from size 3 to size 5. +(assert_return (invoke "grow" (i32.const 2) (i32.const 333)) (i32.const 3)) +(assert_return (invoke "size") (i32.const 5)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 333)) +(assert_return (invoke "get" (i32.const 4)) (i32.const 333)) + +;; Fill table[2..4] = 111. +(invoke "fill" (i32.const 2) (i32.const 111) (i32.const 2)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 111)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 111)) + +;; Copy from table[0..2] to table[3..5]. +(invoke "copy" (i32.const 3) (i32.const 0) (i32.const 2)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 999)) +(assert_return (invoke "get" (i32.const 4)) (i32.const 888)) + +;; Initialize the passive element at table[1..4]. +(invoke "init" (i32.const 1) (i32.const 0) (i32.const 3)) +(assert_return (invoke "get" (i32.const 1)) (i32.const 123)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 456)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 789)) + +(module $env + (global (export "g") i32 (i32.const 42)) +) +(register "env") + +(module $i31ref_of_global_table_initializer + (global $g (import "env" "g") i32) + (table $t 3 3 (ref i31) (ref.i31 (global.get $g))) + (func (export "get") (param i32) (result i32) + (i31.get_u (local.get 0) (table.get $t)) + ) +) + +(assert_return (invoke "get" (i32.const 0)) (i32.const 42)) +(assert_return (invoke "get" (i32.const 1)) (i32.const 42)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 42)) + +(module $i31ref_of_global_global_initializer + (global $g0 (import "env" "g") i32) + (global $g1 i31ref (ref.i31 (global.get $g0))) + (func (export "get") (result i32) + (i31.get_u (global.get $g1)) + ) +) + +(assert_return (invoke "get") (i32.const 42)) + +(module $anyref_global_of_i31ref + (global $c anyref (ref.i31 (i32.const 1234))) + (global $m (mut anyref) (ref.i31 (i32.const 5678))) + + (func (export "get_globals") (result i32 i32) + (i31.get_u (ref.cast i31ref (global.get $c))) + (i31.get_u (ref.cast i31ref (global.get $m))) + ) + + (func (export "set_global") (param i32) + (global.set $m (ref.i31 (local.get 0))) + ) +) + +(assert_return (invoke "get_globals") (i32.const 1234) (i32.const 5678)) +(invoke "set_global" (i32.const 0)) +(assert_return (invoke "get_globals") (i32.const 1234) (i32.const 0)) + +(module $anyref_table_of_i31ref + (table $table 3 10 anyref) + (elem (table $table) (i32.const 0) i31ref (item (ref.i31 (i32.const 999))) + (item (ref.i31 (i32.const 888))) + (item (ref.i31 (i32.const 777)))) + + (func (export "size") (result i32) + table.size $table + ) + + (func (export "get") (param i32) (result i32) + (i31.get_u (ref.cast i31ref (table.get $table (local.get 0)))) + ) + + (func (export "grow") (param i32 i32) (result i32) + (table.grow $table (ref.i31 (local.get 1)) (local.get 0)) + ) + + (func (export "fill") (param i32 i32 i32) + (table.fill $table (local.get 0) (ref.i31 (local.get 1)) (local.get 2)) + ) + + (func (export "copy") (param i32 i32 i32) + (table.copy $table $table (local.get 0) (local.get 1) (local.get 2)) + ) + + (elem $elem i31ref (item (ref.i31 (i32.const 123))) + (item (ref.i31 (i32.const 456))) + (item (ref.i31 (i32.const 789)))) + (func (export "init") (param i32 i32 i32) + (table.init $table $elem (local.get 0) (local.get 1) (local.get 2)) + ) +) + +;; Initial state. +(assert_return (invoke "size") (i32.const 3)) +(assert_return (invoke "get" (i32.const 0)) (i32.const 999)) +(assert_return (invoke "get" (i32.const 1)) (i32.const 888)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 777)) + +;; Grow from size 3 to size 5. +(assert_return (invoke "grow" (i32.const 2) (i32.const 333)) (i32.const 3)) +(assert_return (invoke "size") (i32.const 5)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 333)) +(assert_return (invoke "get" (i32.const 4)) (i32.const 333)) + +;; Fill table[2..4] = 111. +(invoke "fill" (i32.const 2) (i32.const 111) (i32.const 2)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 111)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 111)) + +;; Copy from table[0..2] to table[3..5]. +(invoke "copy" (i32.const 3) (i32.const 0) (i32.const 2)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 999)) +(assert_return (invoke "get" (i32.const 4)) (i32.const 888)) + +;; Initialize the passive element at table[1..4]. +(invoke "init" (i32.const 1) (i32.const 0) (i32.const 3)) +(assert_return (invoke "get" (i32.const 1)) (i32.const 123)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 456)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 789)) diff --git a/test/core/gc/type-subtyping.wast b/test/core/gc/type-subtyping.wast index a9022fc334..f2b33d7c49 100644 --- a/test/core/gc/type-subtyping.wast +++ b/test/core/gc/type-subtyping.wast @@ -316,6 +316,34 @@ (assert_trap (invoke "fail3") "cast") (assert_trap (invoke "fail4") "cast") +(module + (type $t1 (sub (func))) + (type $t2 (sub $t1 (func))) + (type $t3 (sub $t2 (func))) + (type $t4 (sub final (func))) + + (func $f2 (type $t2)) + (func $f3 (type $t3)) + (table (ref null $t2) (elem $f2 $f3)) + + (func (export "run") + (call_indirect (type $t1) (i32.const 0)) + (call_indirect (type $t1) (i32.const 1)) + (call_indirect (type $t2) (i32.const 0)) + (call_indirect (type $t2) (i32.const 1)) + (call_indirect (type $t3) (i32.const 1)) + ) + + (func (export "fail1") + (call_indirect (type $t3) (i32.const 0)) + ) + (func (export "fail2") + (call_indirect (type $t4) (i32.const 0)) + ) +) +(assert_return (invoke "run")) +(assert_trap (invoke "fail1") "indirect call") +(assert_trap (invoke "fail2") "indirect call") (module (rec (type $f1 (sub (func))) (type (struct (field (ref $f1))))) @@ -740,7 +768,7 @@ "sub type" ) -(assert_invalid +(assert_invalid (module (type $f0 (sub (func (param i32) (result i32)))) (type $s0 (sub $f0 (struct))) @@ -764,7 +792,7 @@ "sub type" ) -(assert_invalid +(assert_invalid (module (type $s0 (sub (struct))) (type $f0 (sub $s0 (func (param i32) (result i32)))) @@ -772,7 +800,7 @@ "sub type" ) -(assert_invalid +(assert_invalid (module (type $a0 (sub (array i32))) (type $f0 (sub $a0 (func (param i32) (result i32)))) @@ -803,4 +831,3 @@ ) "sub type" ) - diff --git a/test/core/memory.wast b/test/core/memory.wast index 56ffd6b52d..c8d75f9470 100644 --- a/test/core/memory.wast +++ b/test/core/memory.wast @@ -133,44 +133,44 @@ ;; Sign and zero extending memory loads (func (export "i32_load8_s") (param $i i32) (result i32) - (i32.store8 (i32.const 8) (local.get $i)) - (i32.load8_s (i32.const 8)) + (i32.store8 (i32.const 8) (local.get $i)) + (i32.load8_s (i32.const 8)) ) (func (export "i32_load8_u") (param $i i32) (result i32) - (i32.store8 (i32.const 8) (local.get $i)) - (i32.load8_u (i32.const 8)) + (i32.store8 (i32.const 8) (local.get $i)) + (i32.load8_u (i32.const 8)) ) (func (export "i32_load16_s") (param $i i32) (result i32) - (i32.store16 (i32.const 8) (local.get $i)) - (i32.load16_s (i32.const 8)) + (i32.store16 (i32.const 8) (local.get $i)) + (i32.load16_s (i32.const 8)) ) (func (export "i32_load16_u") (param $i i32) (result i32) - (i32.store16 (i32.const 8) (local.get $i)) - (i32.load16_u (i32.const 8)) + (i32.store16 (i32.const 8) (local.get $i)) + (i32.load16_u (i32.const 8)) ) (func (export "i64_load8_s") (param $i i64) (result i64) - (i64.store8 (i32.const 8) (local.get $i)) - (i64.load8_s (i32.const 8)) + (i64.store8 (i32.const 8) (local.get $i)) + (i64.load8_s (i32.const 8)) ) (func (export "i64_load8_u") (param $i i64) (result i64) - (i64.store8 (i32.const 8) (local.get $i)) - (i64.load8_u (i32.const 8)) + (i64.store8 (i32.const 8) (local.get $i)) + (i64.load8_u (i32.const 8)) ) (func (export "i64_load16_s") (param $i i64) (result i64) - (i64.store16 (i32.const 8) (local.get $i)) - (i64.load16_s (i32.const 8)) + (i64.store16 (i32.const 8) (local.get $i)) + (i64.load16_s (i32.const 8)) ) (func (export "i64_load16_u") (param $i i64) (result i64) - (i64.store16 (i32.const 8) (local.get $i)) - (i64.load16_u (i32.const 8)) + (i64.store16 (i32.const 8) (local.get $i)) + (i64.load16_u (i32.const 8)) ) (func (export "i64_load32_s") (param $i i64) (result i64) - (i64.store32 (i32.const 8) (local.get $i)) - (i64.load32_s (i32.const 8)) + (i64.store32 (i32.const 8) (local.get $i)) + (i64.load32_s (i32.const 8)) ) (func (export "i64_load32_u") (param $i i64) (result i64) - (i64.store32 (i32.const 8) (local.get $i)) - (i64.load32_u (i32.const 8)) + (i64.store32 (i32.const 8) (local.get $i)) + (i64.load32_u (i32.const 8)) ) ) diff --git a/test/js-api/gc/default-value.tentative.any.js b/test/js-api/gc/default-value.tentative.any.js new file mode 100644 index 0000000000..d828b4d87f --- /dev/null +++ b/test/js-api/gc/default-value.tentative.any.js @@ -0,0 +1,43 @@ +// META: global=window,dedicatedworker,jsshell +// META: script=/wasm/jsapi/wasm-module-builder.js + +let exports = {}; +setup(() => { + const builder = new WasmModuleBuilder(); + + builder.addTable(wasmRefType(kWasmAnyRef), 10, 20, [...wasmI32Const(42), ...GCInstr(kExprRefI31)]) + .exportAs("tableAnyNonNullable"); + builder.addTable(wasmRefNullType(kWasmAnyRef), 10, 20) + .exportAs("tableAnyNullable"); + + const buffer = builder.toBuffer(); + const module = new WebAssembly.Module(buffer); + const instance = new WebAssembly.Instance(module, {}); + exports = instance.exports; +}); + +test(() => { + exports.tableAnyNullable.grow(5); + for (let i = 0; i < 5; i++) + assert_equals(exports.tableAnyNullable.get(10 + i), null); +}, "grow (nullable anyref)"); + +test(() => { + assert_throws_js(TypeError, () => { exports.tableAnyNonNullable.grow(5); }); + exports.tableAnyNonNullable.grow(5, "foo"); + for (let i = 0; i < 5; i++) + assert_equals(exports.tableAnyNonNullable.get(10 + i), "foo"); +}, "grow (non-nullable anyref)"); + +test(() => { + for (let i = 0; i < exports.tableAnyNullable.length; i++) { + exports.tableAnyNullable.set(i); + assert_equals(exports.tableAnyNullable.get(i), null); + } +}, "set (nullable anyref)"); + +test(() => { + for (let i = 0; i < exports.tableAnyNonNullable.length; i++) { + assert_throws_js(TypeError, () => { exports.tableAnyNonNullable.set(i); }); + } +}, "set (non-nullable anyref)"); diff --git a/test/js-api/gc/i31.tentative.any.js b/test/js-api/gc/i31.tentative.any.js index 17fd82440c..d8cfe424e8 100644 --- a/test/js-api/gc/i31.tentative.any.js +++ b/test/js-api/gc/i31.tentative.any.js @@ -11,7 +11,7 @@ setup(() => { builder .addFunction("makeI31", makeSig_r_x(i31Ref, kWasmI32)) .addBody([kExprLocalGet, 0, - ...GCInstr(kExprI31New)]) + ...GCInstr(kExprRefI31)]) .exportFunc(); builder @@ -33,7 +33,7 @@ setup(() => { .exportFunc(); builder - .addGlobal(i31NullableRef, true, [...wasmI32Const(0), ...GCInstr(kExprI31New)]) + .addGlobal(i31NullableRef, true, [...wasmI32Const(0), ...GCInstr(kExprRefI31)]) builder .addExportOfKind("i31Global", kExternalGlobal, 0); diff --git a/test/js-api/wasm-module-builder.js b/test/js-api/wasm-module-builder.js index 8c6519239b..104c730c7c 100644 --- a/test/js-api/wasm-module-builder.js +++ b/test/js-api/wasm-module-builder.js @@ -456,7 +456,7 @@ let kExprBrOnCast = 0x18; let kExprBrOnCastFail = 0x19; let kExprExternInternalize = 0x1a; let kExprExternExternalize = 0x1b; -let kExprI31New = 0x1c; +let kExprRefI31 = 0x1c; let kExprI31GetS = 0x1d; let kExprI31GetU = 0x1e; @@ -1199,6 +1199,10 @@ class WasmModuleBuilder { binary.emit_section(kTableSectionCode, section => { section.emit_u32v(wasm.tables.length); for (let table of wasm.tables) { + if (table.has_init) { + section.emit_u8(0x40); // "has initializer" + section.emit_u8(0x00); // Reserved byte. + } section.emit_type(table.type); section.emit_u8(table.has_max); section.emit_u32v(table.initial_size);