blob: a7c93c418f8ed402d136fba5297976aeebe5728e [file] [log] [blame]
Modules
-------
:ref:`Modules <syntax-module>` are valid when all the components they contain are valid.
Furthermore, most definitions are themselves classified with a suitable type.
.. index:: function, local, function index, local index, type index, function type, value type, expression, import
pair: abstract syntax; function
single: abstract syntax; function
.. _valid-local:
.. _valid-func:
Functions
~~~~~~~~~
Functions :math:`\func` are classified by :ref:`function types <syntax-functype>` of the form :math:`[t_1^\ast] \to [t_2^?]`.
:math:`\{ \FTYPE~x, \FLOCALS~t^\ast, \FBODY~\expr \}`
.....................................................
* The type :math:`C.\CTYPES[x]` must be defined in the context.
* Let :math:`[t_1^\ast] \to [t_2^?]` be the :ref:`function type <syntax-functype>` :math:`C.\CTYPES[x]`.
* Let :math:`C'` be the same :ref:`context <context>` as :math:`C`,
but with:
* |CLOCALS| set to the sequence of :ref:`value types <syntax-valtype>` :math:`t_1^\ast~t^\ast`, concatenating parameters and locals,
* |CLABELS| set to the singular sequence containing only :ref:`result type <syntax-valtype>` :math:`[t_2^?]`.
* |CRETURN| set to the :ref:`result type <syntax-valtype>` :math:`[t_2^?]`.
* Under the context :math:`C'`,
the expression :math:`\expr` must be valid with type :math:`t_2^?`.
* Then the function definition is valid with type :math:`[t_1^\ast] \to [t_2^?]`.
.. math::
\frac{
C.\CTYPES[x] = [t_1^\ast] \to [t_2^?]
\qquad
C,\CLOCALS\,t_1^\ast~t^\ast,\CLABELS~[t_2^?],\CRETURN~[t_2^?] \vdashexpr \expr : [t_2^?]
}{
C \vdashfunc \{ \FTYPE~x, \FLOCALS~t^\ast, \FBODY~\expr \} : [t_1^\ast] \to [t_2^?]
}
.. note::
The restriction on the length of the result types :math:`t_2^\ast` may be lifted in future versions of WebAssembly.
.. index:: table, table type
pair: validation; table
single: abstract syntax; table
.. _valid-table:
Tables
~~~~~~
Tables :math:`\table` are classified by :ref:`table types <syntax-tabletype>`.
:math:`\{ \TTYPE~\tabletype \}`
...............................
* The :ref:`table type <syntax-tabletype>` :math:`\tabletype` must be :ref:`valid <valid-tabletype>`.
* Then the table definition is valid with type :math:`\tabletype`.
.. math::
\frac{
\vdashtabletype \tabletype \ok
}{
C \vdashtable \{ \TTYPE~\tabletype \} : \tabletype
}
.. index:: memory, memory type
pair: validation; memory
single: abstract syntax; memory
.. _valid-mem:
Memories
~~~~~~~~
Memories :math:`\mem` are classified by :ref:`memory types <syntax-memtype>`.
:math:`\{ \MTYPE~\memtype \}`
.............................
* The :ref:`memory type <syntax-memtype>` :math:`\memtype` must be :ref:`valid <valid-memtype>`.
* Then the memory definition is valid with type :math:`\memtype`.
.. math::
\frac{
\vdashmemtype \memtype \ok
}{
C \vdashmem \{ \MTYPE~\memtype \} : \memtype
}
.. index:: global, global type, expression
pair: validation; global
single: abstract syntax; global
.. _valid-global:
Globals
~~~~~~~
Globals :math:`\global` are classified by :ref:`global types <syntax-globaltype>` of the form :math:`\mut~t`.
:math:`\{ \GTYPE~\mut~t, \GINIT~\expr \}`
.........................................
* The :ref:`global type <syntax-globaltype>` :math:`\mut~t` must be :ref:`valid <valid-globaltype>`.
* The expression :math:`\expr` must be :ref:`valid <valid-expr>` with :ref:`result type <syntax-resulttype>` :math:`[t]`.
* The expression :math:`\expr` must be :ref:`constant <valid-constant>`.
* Then the global definition is valid with type :math:`\mut~t`.
.. math::
\frac{
\vdashglobaltype \mut~t \ok
\qquad
C \vdashexpr \expr : [t]
\qquad
C \vdashexprconst \expr \const
}{
C \vdashglobal \{ \GTYPE~\mut~t, \GINIT~\expr \} : \mut~t
}
.. index:: element, table, table index, expression, function index
pair: validation; element
single: abstract syntax; element
single: table; element
single: element; segment
.. _valid-elem:
Element Segments
~~~~~~~~~~~~~~~~
Element segments :math:`\elem` are not classified by a type.
:math:`\{ \ETABLE~x, \EOFFSET~\expr, \EINIT~y^\ast \}`
......................................................
* The table :math:`C.\CTABLES[x]` must be defined in the context.
* Let :math:`\limits~\elemtype` be the :ref:`table type <syntax-tabletype>` :math:`C.\CTABLES[x]`.
* The :ref:`element type <syntax-elemtype>` :math:`\elemtype` must be |FUNCREF|.
* The expression :math:`\expr` must be :ref:`valid <valid-expr>` with :ref:`result type <syntax-resulttype>` :math:`[\I32]`.
* The expression :math:`\expr` must be :ref:`constant <valid-constant>`.
* For each :math:`y_i` in :math:`y^\ast`,
the function :math:`C.\CFUNCS[y]` must be defined in the context.
* Then the element segment is valid.
.. math::
\frac{
C.\CTABLES[x] = \limits~\FUNCREF
\qquad
C \vdashexpr \expr : [\I32]
\qquad
C \vdashexprconst \expr \const
\qquad
(C.\CFUNCS[y] = \functype)^\ast
}{
C \vdashelem \{ \ETABLE~x, \EOFFSET~\expr, \EINIT~y^\ast \} \ok
}
.. index:: data, memory, memory index, expression, byte
pair: validation; data
single: abstract syntax; data
single: memory; data
single: data; segment
.. _valid-data:
Data Segments
~~~~~~~~~~~~~
Data segments :math:`\data` are not classified by any type.
:math:`\{ \DMEM~x, \DOFFSET~\expr, \DINIT~b^\ast \}`
....................................................
* The memory :math:`C.\CMEMS[x]` must be defined in the context.
* The expression :math:`\expr` must be :ref:`valid <valid-expr>` with :ref:`result type <syntax-resulttype>` :math:`[\I32]`.
* The expression :math:`\expr` must be :ref:`constant <valid-constant>`.
* Then the data segment is valid.
.. math::
\frac{
C.\CMEMS[x] = \limits
\qquad
C \vdashexpr \expr : [\I32]
\qquad
C \vdashexprconst \expr \const
}{
C \vdashdata \{ \DMEM~x, \DOFFSET~\expr, \DINIT~b^\ast \} \ok
}
.. index:: start function, function index
pair: validation; start function
single: abstract syntax; start function
.. _valid-start:
Start Function
~~~~~~~~~~~~~~
Start function declarations :math:`\start` are not classified by any type.
:math:`\{ \SFUNC~x \}`
......................
* The function :math:`C.\CFUNCS[x]` must be defined in the context.
* The type of :math:`C.\CFUNCS[x]` must be :math:`[] \to []`.
* Then the start function is valid.
.. math::
\frac{
C.\CFUNCS[x] = [] \to []
}{
C \vdashstart \{ \SFUNC~x \} \ok
}
.. index:: export, name, index, function index, table index, memory index, global index
pair: validation; export
single: abstract syntax; export
.. _valid-exportdesc:
.. _valid-export:
Exports
~~~~~~~
Exports :math:`\export` and export descriptions :math:`\exportdesc` are classified by their :ref:`external type <syntax-externtype>`.
:math:`\{ \ENAME~\name, \EDESC~\exportdesc \}`
..............................................
* The export description :math:`\exportdesc` must be valid with :ref:`external type <syntax-externtype>` :math:`\externtype`.
* Then the export is valid with :ref:`external type <syntax-externtype>` :math:`\externtype`.
.. math::
\frac{
C \vdashexportdesc \exportdesc : \externtype
}{
C \vdashexport \{ \ENAME~\name, \EDESC~\exportdesc \} : \externtype
}
:math:`\EDFUNC~x`
.................
* The function :math:`C.\CFUNCS[x]` must be defined in the context.
* Then the export description is valid with :ref:`external type <syntax-externtype>` :math:`\ETFUNC~C.\CFUNCS[x]`.
.. math::
\frac{
C.\CFUNCS[x] = \functype
}{
C \vdashexportdesc \EDFUNC~x : \ETFUNC~\functype
}
:math:`\EDTABLE~x`
..................
* The table :math:`C.\CTABLES[x]` must be defined in the context.
* Then the export description is valid with :ref:`external type <syntax-externtype>` :math:`\ETTABLE~C.\CTABLES[x]`.
.. math::
\frac{
C.\CTABLES[x] = \tabletype
}{
C \vdashexportdesc \EDTABLE~x : \ETTABLE~\tabletype
}
:math:`\EDMEM~x`
................
* The memory :math:`C.\CMEMS[x]` must be defined in the context.
* Then the export description is valid with :ref:`external type <syntax-externtype>` :math:`\ETMEM~C.\CMEMS[x]`.
.. math::
\frac{
C.\CMEMS[x] = \memtype
}{
C \vdashexportdesc \EDMEM~x : \ETMEM~\memtype
}
:math:`\EDGLOBAL~x`
...................
* The global :math:`C.\CGLOBALS[x]` must be defined in the context.
* Then the export description is valid with :ref:`external type <syntax-externtype>` :math:`\ETGLOBAL~C.\CGLOBALS[x]`.
.. math::
\frac{
C.\CGLOBALS[x] = \globaltype
}{
C \vdashexportdesc \EDGLOBAL~x : \ETGLOBAL~\globaltype
}
.. index:: import, name, function type, table type, memory type, global type
pair: validation; import
single: abstract syntax; import
.. _valid-importdesc:
.. _valid-import:
Imports
~~~~~~~
Imports :math:`\import` and import descriptions :math:`\importdesc` are classified by :ref:`external types <syntax-externtype>`.
:math:`\{ \IMODULE~\name_1, \INAME~\name_2, \IDESC~\importdesc \}`
..................................................................
* The import description :math:`\importdesc` must be valid with type :math:`\externtype`.
* Then the import is valid with type :math:`\externtype`.
.. math::
\frac{
C \vdashimportdesc \importdesc : \externtype
}{
C \vdashimport \{ \IMODULE~\name_1, \INAME~\name_2, \IDESC~\importdesc \} : \externtype
}
:math:`\IDFUNC~x`
.................
* The function :math:`C.\CTYPES[x]` must be defined in the context.
* Let :math:`[t_1^\ast] \to [t_2^\ast]` be the :ref:`function type <syntax-functype>` :math:`C.\CTYPES[x]`.
* Then the import description is valid with type :math:`\ETFUNC~[t_1^\ast] \to [t_2^\ast]`.
.. math::
\frac{
C.\CTYPES[x] = [t_1^\ast] \to [t_2^\ast]
}{
C \vdashimportdesc \IDFUNC~x : \ETFUNC~[t_1^\ast] \to [t_2^\ast]
}
:math:`\IDTABLE~\tabletype`
...........................
* The table type :math:`\tabletype` must be :ref:`valid <valid-tabletype>`.
* Then the import description is valid with type :math:`\ETTABLE~\tabletype`.
.. math::
\frac{
\vdashtable \tabletype \ok
}{
C \vdashimportdesc \IDTABLE~\tabletype : \ETTABLE~\tabletype
}
:math:`\IDMEM~\memtype`
.......................
* The memory type :math:`\memtype` must be :ref:`valid <valid-memtype>`.
* Then the import description is valid with type :math:`\ETMEM~\memtype`.
.. math::
\frac{
\vdashmemtype \memtype \ok
}{
C \vdashimportdesc \IDMEM~\memtype : \ETMEM~\memtype
}
:math:`\IDGLOBAL~\globaltype`
.............................
* The global type :math:`\globaltype` must be :ref:`valid <valid-globaltype>`.
* Then the import description is valid with type :math:`\ETGLOBAL~\globaltype`.
.. math::
\frac{
\vdashglobaltype \globaltype \ok
}{
C \vdashimportdesc \IDGLOBAL~\globaltype : \ETGLOBAL~\globaltype
}
.. index:: module, type definition, function type, function, table, memory, global, element, data, start function, import, export, context
pair: validation; module
single: abstract syntax; module
.. _valid-module:
Modules
~~~~~~~
Modules are classified by their mapping from the :ref:`external types <syntax-externtype>` of their :ref:`imports <syntax-import>` to those of their :ref:`exports <syntax-export>`.
A module is entirely *closed*,
that is, its components can only refer to definitions that appear in the module itself.
Consequently, no initial :ref:`context <context>` is required.
Instead, the context :math:`C` for validation of the module's content is constructed from the definitions in the module.
* Let :math:`\module` be the module to validate.
* Let :math:`C` be a :ref:`context <context>` where:
* :math:`C.\CTYPES` is :math:`\module.\MTYPES`,
* :math:`C.\CFUNCS` is :math:`\etfuncs(\X{it}^\ast)` concatenated with :math:`\X{ft}^\ast`,
with the import's :ref:`external types <syntax-externtype>` :math:`\X{it}^\ast` and the internal :ref:`function types <syntax-functype>` :math:`\X{ft}^\ast` as determined below,
* :math:`C.\CTABLES` is :math:`\ettables(\X{it}^\ast)` concatenated with :math:`\X{tt}^\ast`,
with the import's :ref:`external types <syntax-externtype>` :math:`\X{it}^\ast` and the internal :ref:`table types <syntax-tabletype>` :math:`\X{tt}^\ast` as determined below,
* :math:`C.\CMEMS` is :math:`\etmems(\X{it}^\ast)` concatenated with :math:`\X{mt}^\ast`,
with the import's :ref:`external types <syntax-externtype>` :math:`\X{it}^\ast` and the internal :ref:`memory types <syntax-memtype>` :math:`\X{mt}^\ast` as determined below,
* :math:`C.\CGLOBALS` is :math:`\etglobals(\X{it}^\ast)` concatenated with :math:`\X{gt}^\ast`,
with the import's :ref:`external types <syntax-externtype>` :math:`\X{it}^\ast` and the internal :ref:`global types <syntax-globaltype>` :math:`\X{gt}^\ast` as determined below,
* :math:`C.\CLOCALS` is empty,
* :math:`C.\CLABELS` is empty,
* :math:`C.\CRETURN` is empty.
* Let :math:`C'` be the :ref:`context <context>` where :math:`C'.\CGLOBALS` is the sequence :math:`\etglobals(\X{it}^\ast)` and all other fields are empty.
* Under the context :math:`C`:
* For each :math:`\functype_i` in :math:`\module.\MTYPES`,
the :ref:`function type <syntax-functype>` :math:`\functype_i` must be :ref:`valid <valid-functype>`.
* For each :math:`\func_i` in :math:`\module.\MFUNCS`,
the definition :math:`\func_i` must be :ref:`valid <valid-func>` with a :ref:`function type <syntax-functype>` :math:`\X{ft}_i`.
* For each :math:`\table_i` in :math:`\module.\MTABLES`,
the definition :math:`\table_i` must be :ref:`valid <valid-table>` with a :ref:`table type <syntax-tabletype>` :math:`\X{tt}_i`.
* For each :math:`\mem_i` in :math:`\module.\MMEMS`,
the definition :math:`\mem_i` must be :ref:`valid <valid-mem>` with a :ref:`memory type <syntax-memtype>` :math:`\X{mt}_i`.
* For each :math:`\global_i` in :math:`\module.\MGLOBALS`:
* Under the context :math:`C'`,
the definition :math:`\global_i` must be :ref:`valid <valid-global>` with a :ref:`global type <syntax-globaltype>` :math:`\X{gt}_i`.
* For each :math:`\elem_i` in :math:`\module.\MELEM`,
the segment :math:`\elem_i` must be :ref:`valid <valid-elem>`.
* For each :math:`\data_i` in :math:`\module.\MDATA`,
the segment :math:`\data_i` must be :ref:`valid <valid-data>`.
* If :math:`\module.\MSTART` is non-empty,
then :math:`\module.\MSTART` must be :ref:`valid <valid-start>`.
* For each :math:`\import_i` in :math:`\module.\MIMPORTS`,
the segment :math:`\import_i` must be :ref:`valid <valid-import>` with an :ref:`external type <syntax-externtype>` :math:`\X{it}_i`.
* For each :math:`\export_i` in :math:`\module.\MEXPORTS`,
the segment :math:`\export_i` must be :ref:`valid <valid-export>` with :ref:`external type <syntax-externtype>` :math:`\X{et}_i`.
* The length of :math:`C.\CTABLES` must not be larger than :math:`1`.
* 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 <syntax-functype>` :math:`\X{ft}_i`, in index order.
* Let :math:`\X{tt}^\ast` be the concatenation of the internal :ref:`table types <syntax-tabletype>` :math:`\X{tt}_i`, in index order.
* Let :math:`\X{mt}^\ast` be the concatenation of the internal :ref:`memory types <syntax-memtype>` :math:`\X{mt}_i`, in index order.
* Let :math:`\X{gt}^\ast` be the concatenation of the internal :ref:`global types <syntax-globaltype>` :math:`\X{gt}_i`, in index order.
* Let :math:`\X{it}^\ast` be the concatenation of :ref:`external types <syntax-externtype>` :math:`\X{it}_i` of the imports, in index order.
* Let :math:`\X{et}^\ast` be the concatenation of :ref:`external types <syntax-externtype>` :math:`\X{et}_i` of the exports, in index order.
* Then the module is valid with :ref:`external types <syntax-externtype>` :math:`\X{it}^\ast \to \X{et}^\ast`.
.. math::
\frac{
\begin{array}{@{}c@{}}
(\vdashfunctype \functype \ok)^\ast
\quad
(C \vdashfunc \func : \X{ft})^\ast
\quad
(C \vdashtable \table : \X{tt})^\ast
\quad
(C \vdashmem \mem : \X{mt})^\ast
\quad
(C' \vdashglobal \global : \X{gt})^\ast
\\
(C \vdashelem \elem \ok)^\ast
\quad
(C \vdashdata \data \ok)^\ast
\quad
(C \vdashstart \start \ok)^?
\quad
(C \vdashimport \import : \X{it})^\ast
\quad
(C \vdashexport \export : \X{et})^\ast
\\
\X{ift}^\ast = \etfuncs(\X{it}^\ast)
\qquad
\X{itt}^\ast = \ettables(\X{it}^\ast)
\qquad
\X{imt}^\ast = \etmems(\X{it}^\ast)
\qquad
\X{igt}^\ast = \etglobals(\X{it}^\ast)
\\
C = \{ \CTYPES~\functype^\ast, \CFUNCS~\X{ift}^\ast~\X{ft}^\ast, \CTABLES~\X{itt}^\ast~\X{tt}^\ast, \CMEMS~\X{imt}^\ast~\X{mt}^\ast, \CGLOBALS~\X{igt}^\ast~\X{gt}^\ast \}
\\
C' = \{ \CGLOBALS~\X{igt}^\ast \}
\qquad
|C.\CTABLES| \leq 1
\qquad
|C.\CMEMS| \leq 1
\qquad
(\export.\ENAME)^\ast ~\F{disjoint}
\end{array}
}{
\vdashmodule \{
\begin{array}[t]{@{}l@{}}
\MTYPES~\functype^\ast,
\MFUNCS~\func^\ast,
\MTABLES~\table^\ast,
\MMEMS~\mem^\ast,
\MGLOBALS~\global^\ast, \\
\MELEM~\elem^\ast,
\MDATA~\data^\ast,
\MSTART~\start^?,
\MIMPORTS~\import^\ast,
\MEXPORTS~\export^\ast \} : \X{it}^\ast \to \X{et}^\ast \\
\end{array}
}
.. note::
Most definitions in a module -- particularly functions -- are mutually recursive.
Consequently, the definition of the :ref:`context <context>` :math:`C` in this rule is recursive:
it depends on the outcome of validation of the function, table, memory, and global definitions contained in the module,
which itself depends on :math:`C`.
However, this recursion is just a specification device.
All types needed to construct :math:`C` can easily be determined from a simple pre-pass over the module that does not perform any actual validation.
Globals, however, are not recursive.
The effect of defining the limited context :math:`C'` for validating the module's globals is that their initialization expressions can only access imported globals and nothing else.
.. note::
The restriction on the number of tables and memories may be lifted in future versions of WebAssembly.