WebAssembly Specification

1. Introduction

1.1. Introduction

WebAssembly (abbreviated Wasm [1]) is a safe, portable, low-level code format designed for efficient execution and compact representation. Its main goal is to enable high performance applications on the Web, but it does not make any Web-specific assumptions or provide Web-specific features, so it can be employed in other environments as well.

WebAssembly is an open standard developed by a W3C Community Group.

This document describes version 1.0 of the core WebAssembly standard. It is intended that it will be superseded by new incremental releases with additional features in the future.

1.1.1. Design Goals

The design goals of WebAssembly are the following:

  • Fast, safe, and portable semantics:
    • Fast: executes with near native code performance, taking advantage of capabilities common to all contemporary hardware.
    • Safe: code is validated and executes in a memory-safe [2], sandboxed environment preventing data corruption or security breaches.
    • Well-defined: fully and precisely defines valid programs and their behavior in a way that is easy to reason about informally and formally.
    • Hardware-independent: can be compiled on all modern architectures, desktop or mobile devices and embedded systems alike.
    • Language-independent: does not privilege any particular language, programming model, or object model.
    • Platform-independent: can be embedded in browsers, run as a stand-alone VM, or integrated in other environments.
    • Open: programs can interoperate with their environment in a simple and universal manner.
  • Efficient and portable representation:
    • Compact: has a binary format that is fast to transmit by being smaller than typical text or native code formats.
    • Modular: programs can be split up in smaller parts that can be transmitted, cached, and consumed separately.
    • Efficient: can be decoded, validated, and compiled in a fast single pass, equally with either just-in-time (JIT) or ahead-of-time (AOT) compilation.
    • Streamable: allows decoding, validation, and compilation to begin as soon as possible, before all data has been seen.
    • Parallelizable: allows decoding, validation, and compilation to be split into many independent parallel tasks.
    • Portable: makes no architectural assumptions that are not broadly supported across modern hardware.

WebAssembly code is also intended to be easy to inspect and debug, especially in environments like web browsers, but such features are beyond the scope of this specification.

[1] A contraction of “WebAssembly”, not an acronym, hence not using all-caps.
[2] No program can break WebAssembly’s memory model. Of course, it cannot guarantee that an unsafe language compiling to WebAssembly does not corrupt its own memory layout, e.g. inside WebAssembly’s linear memory.

1.1.2. Scope

At its core, WebAssembly is a virtual instruction set architecture (virtual ISA). As such, it has many use cases and can be embedded in many different environments. To encompass their variety and enable maximum reuse, the WebAssembly specification is split and layered into several documents.

This document is concerned with the core ISA layer of WebAssembly. It defines the instruction set, binary encoding, validation, and execution semantics, as well as a textual representation. It does not, however, define how WebAssembly programs can interact with a specific environment they execute in, nor how they are invoked from such an environment.

Instead, this specification is complemented by additional documents defining interfaces to specific embedding environments such as the Web. These will each define a WebAssembly application programming interface (API) suitable for a given environment.

1.2. Security Considerations

WebAssembly provides no ambient access to the computing environment in which code is executed. Any interaction with the environment, such as I/O, access to resources, or operating system calls, can only be performed by invoking functions provided by the embedder and imported into a WebAssembly module. An embedder can establish security policies suitable for a respective environment by controlling or limiting which functional capabilities it makes available for import. Such considerations are an embedder’s responsibility and the subject of API definitions for a specific environment.

Because WebAssembly is designed to be translated into machine code running directly on the host’s hardware, it is potentially vulnerable to side channel attacks on the hardware level. In environments where this is a concern, an embedder may have to put suitable mitigations into place to isolate WebAssembly computations.

1.2.1. Dependencies

WebAssembly depends on two existing standards:

However, to make this specification self-contained, relevant aspects of the aforementioned standards are defined and formalized as part of this specification, such as the binary representation and rounding of floating-point values, and the value range and UTF-8 encoding of Unicode characters.

Note

The aforementioned standards are the authoritative source of all respective definitions. Formalizations given in this specification are intended to match these definitions. Any discrepancy in the syntax or semantics described is to be considered an error.

1.3. Overview

1.3.1. Concepts

WebAssembly encodes a low-level, assembly-like programming language. This language is structured around the following concepts.

Values
WebAssembly provides only four basic value types. These are integers and [IEEE-754-2019] numbers, each in 32 and 64 bit width. 32 bit integers also serve as Booleans and as memory addresses. The usual operations on these types are available, including the full matrix of conversions between them. There is no distinction between signed and unsigned integer types. Instead, integers are interpreted by respective operations as either unsigned or signed in two’s complement representation.
Instructions
The computational model of WebAssembly is based on a stack machine. Code consists of sequences of instructions that are executed in order. Instructions manipulate values on an implicit operand stack [1] and fall into two main categories. Simple instructions perform basic operations on data. They pop arguments from the operand stack and push results back to it. Control instructions alter control flow. Control flow is structured, meaning it is expressed with well-nested constructs such as blocks, loops, and conditionals. Branches can only target such constructs.
Traps
Under some conditions, certain instructions may produce a trap, which immediately aborts execution. Traps cannot be handled by WebAssembly code, but are reported to the outside environment, where they typically can be caught.
Functions
Code is organized into separate functions. Each function takes a sequence of values as parameters and returns a sequence of values as results. [2] Functions can call each other, including recursively, resulting in an implicit call stack that cannot be accessed directly. Functions may also declare mutable local variables that are usable as virtual registers.
Tables
A table is an array of opaque values of a particular element type. It allows programs to select such values indirectly through a dynamic index operand. Currently, the only available element type is an untyped function reference. Thereby, a program can call functions indirectly through a dynamic index into a table. For example, this allows emulating function pointers by way of table indices.
Linear Memory
A linear memory is a contiguous, mutable array of raw bytes. Such a memory is created with an initial size but can be grown dynamically. A program can load and store values from/to a linear memory at any byte address (including unaligned). Integer loads and stores can specify a storage size which is smaller than the size of the respective value type. A trap occurs if an access is not within the bounds of the current memory size.
Modules
A WebAssembly binary takes the form of a module that contains definitions for functions, tables, and linear memories, as well as mutable or immutable global variables. Definitions can also be imported, specifying a module/name pair and a suitable type. Each definition can optionally be exported under one or more names. In addition to definitions, modules can define initialization data for their memories or tables that takes the form of segments copied to given offsets. They can also define a start function that is automatically executed.
Embedder
A WebAssembly implementation will typically be embedded into a host environment. This environment defines how loading of modules is initiated, how imports are provided (including host-side definitions), and how exports can be accessed. However, the details of any particular embedding are beyond the scope of this specification, and will instead be provided by complementary, environment-specific API definitions.
[1] In practice, implementations need not maintain an actual operand stack. Instead, the stack can be viewed as a set of anonymous registers that are implicitly referenced by instructions. The type system ensures that the stack height, and thus any referenced register, is always known statically.
[2] In the current version of WebAssembly, there may be at most one result value.

1.3.2. Semantic Phases

Conceptually, the semantics of WebAssembly is divided into three phases. For each part of the language, the specification specifies each of them.

Decoding
WebAssembly modules are distributed in a binary format. Decoding processes that format and converts it into an internal representation of a module. In this specification, this representation is modelled by abstract syntax, but a real implementation could compile directly to machine code instead.
Validation
A decoded module has to be valid. Validation checks a number of well-formedness conditions to guarantee that the module is meaningful and safe. In particular, it performs type checking of functions and the instruction sequences in their bodies, ensuring for example that the operand stack is used consistently.
Execution

Finally, a valid module can be executed. Execution can be further divided into two phases:

Instantiation. A module instance is the dynamic representation of a module, complete with its own state and execution stack. Instantiation executes the module body itself, given definitions for all its imports. It initializes globals, memories and tables and invokes the module’s start function if defined. It returns the instances of the module’s exports.

Invocation. Once instantiated, further WebAssembly computations can be initiated by invoking an exported function on a module instance. Given the required arguments, that executes the respective function and returns its results.

Instantiation and invocation are operations within the embedding environment.

2. Structure

2.1. Conventions

WebAssembly is a programming language that has multiple concrete representations (its binary format and the text format). Both map to a common structure. For conciseness, this structure is described in the form of an abstract syntax. All parts of this specification are defined in terms of this abstract syntax.

2.1.1. Grammar Notation

The following conventions are adopted in defining grammar rules for abstract syntax.

  • Terminal symbols (atoms) are written in sans-serif font:
  • Nonterminal symbols are written in italic font:
  • Productions are written
  • Large productions may be split into multiple definitions, indicated by ending the first one with explicit ellipses,
  • Some productions are augmented with side conditions in parentheses, “

2.1.2. Auxiliary Notation

When dealing with syntactic constructs the following notation is also used:

Moreover, the following conventions are employed:

  • The notation
  • When given a sequence

Productions of the following form are interpreted as records that map a fixed set of fields

The following notation is adopted for manipulating such records:

The update notation for sequences and records generalizes recursively to nested components accessed by “paths”

where

2.1.3. Vectors

Vectors are bounded sequences of the form

2.2. Values

WebAssembly programs operate on primitive numeric values. Moreover, in the definition of programs, immutable sequences of values occur to represent more complex data, such as text strings or other vectors.

2.2.1. Bytes

The simplest form of value are raw uninterpreted bytes. In the abstract syntax they are represented as hexadecimal literals.

2.2.1.1. Conventions
  • The meta variable
  • Bytes are sometimes interpreted as natural numbers

2.2.2. Integers

Different classes of integers with different value ranges are distinguished by their bit width

The latter class defines uninterpreted integers, whose signedness interpretation can vary depending on context. In the abstract syntax, they are represented as unsigned values. However, some operations convert them to signed based on a two’s complement interpretation.

Note

The main integer types occurring in this specification are

2.2.2.1. Conventions
  • The meta variables
  • Numbers may be denoted by simple arithmetics, as in the grammar above. In order to distinguish arithmetics like

2.2.3. Floating-Point

Floating-point data represents 32 or 64 bit values that correspond to the respective binary formats of the [IEEE-754-2019] standard (Section 3.3).

Every value has a sign and a magnitude. Magnitudes can either be expressed as normal numbers of the form

Possible magnitudes also include the special values

where

A canonical NaN is a floating-point value

An arithmetic NaN is a floating-point value

Note

In the abstract syntax, subnormals are distinguished by the leading 0 of the significand. The exponent of subnormals has the same value as the smallest possible exponent of a normal number. Only in the binary representation the exponent of a subnormal is encoded differently than the exponent of any normal number.

2.2.3.1. Conventions
  • The meta variable

2.2.4. Names

Names are sequences of characters, which are scalar values as defined by [UNICODE] (Section 2.4).

Due to the limitations of the binary format, the length of a name is bounded by the length of its UTF-8 encoding.

2.2.4.1. Convention
  • Characters (Unicode scalar values) are sometimes used interchangeably with natural numbers

2.3. Types

Various entities in WebAssembly are classified by types. Types are checked during validation, instantiation, and possibly execution.

2.3.1. Value Types

Value types classify the individual values that WebAssembly code can compute with and the values that a variable accepts.

The types

The types

2.3.1.1. Conventions
  • The meta variable
  • The notation

2.3.2. Result Types

Result types classify the result of executing instructions or blocks, which is a sequence of values written with brackets.

Note

In the current version of WebAssembly, at most one value is allowed as a result. However, this may be generalized to sequences of values in future versions.

2.3.3. Function Types

Function types classify the signature of functions, mapping a vector of parameters to a vector of results, written as follows.

Note

In the current version of WebAssembly, the length of the result type vector of a valid function type may be at most

2.3.4. Limits

Limits classify the size range of resizeable storage associated with memory types and table types.

If no maximum is given, the respective storage can grow to any size.

2.3.5. Memory Types

Memory types classify linear memories and their size range.

The limits constrain the minimum and optionally the maximum size of a memory. The limits are given in units of page size.

2.3.6. Table Types

Table types classify tables over elements of element types within a size range.

Like memories, tables are constrained by limits for their minimum and optionally maximum size. The limits are given in numbers of entries.

The element type

Note

In future versions of WebAssembly, additional element types may be introduced.

2.3.7. Global Types

Global types classify global variables, which hold a value and can either be mutable or immutable.

2.3.8. External Types

External types classify imports and external values with their respective types.

2.3.8.1. Conventions

The following auxiliary notation is defined for sequences of external types. It filters out entries of a specific kind in an order-preserving fashion:

2.4. Instructions

WebAssembly code consists of sequences of instructions. Its computational model is based on a stack machine in that instructions manipulate values on an implicit operand stack, consuming (popping) argument values and producing or returning (pushing) result values.

Note

In the current version of WebAssembly, at most one result value can be pushed by a single instruction. This restriction may be lifted in future versions.

In addition to dynamic operands from the stack, some instructions also have static immediate arguments, typically indices or type annotations, which are part of the instruction itself.

Some instructions are structured in that they bracket nested sequences of instructions.

The following sections group instructions into a number of different categories.

2.4.1. Numeric Instructions

Numeric instructions provide basic operations over numeric values of specific type. These operations closely match respective operations available in hardware.

Numeric instructions are divided by value type. For each type, several subcategories can be distinguished:

  • Constants: return a static constant.
  • Unary Operators: consume one operand and produce one result of the respective type.
  • Binary Operators: consume two operands and produce one result of the respective type.
  • Tests: consume one operand of the respective type and produce a Boolean integer result.
  • Comparisons: consume two operands of the respective type and produce a Boolean integer result.
  • Conversions: consume a value of one type and produce a result of another (the source type of the conversion is the one after the “

Some integer instructions come in two flavors, where a signedness annotation

2.4.1.1. Conventions

Occasionally, it is convenient to group operators together according to the following grammar shorthands:

2.4.2. Parametric Instructions

Instructions in this group can operate on operands of any value type.

The

The

2.4.3. Variable Instructions

Variable instructions are concerned with access to local or global variables.

These instructions get or set the values of variables, respectively. The

2.4.4. Memory Instructions

Instructions in this group are concerned with linear memory.

Memory is accessed with

The static address offset is added to the dynamic address operand, yielding a 33 bit effective address that is the zero-based index at which the memory is accessed. All values are read and written in little endian byte order. A trap results if any of the accessed memory bytes lies outside the address range implied by the memory’s current size.

Note

Future version of WebAssembly might provide memory instructions with 64 bit address ranges.

The

Note

In the current version of WebAssembly, all memory instructions implicitly operate on memory index

2.4.5. Control Instructions

Instructions in this group affect the flow of control.

The

The

The

Each structured control instruction introduces an implicit label. Labels are targets for branch instructions that reference them with label indices. Unlike with other index spaces, indexing of labels is relative by nesting depth, that is, label

Note

This enforces structured control flow. Intuitively, a branch targeting a

Branch instructions come in several flavors:

The

Note

In the current version of WebAssembly,

2.4.6. Expressions

Function bodies, initialization values for globals, and offsets of element or data segments are given as expressions, which are sequences of instructions terminated by an

In some places, validation restricts expressions to be constant, which limits the set of allowable instructions.

2.5. Modules

WebAssembly programs are organized into modules, which are the unit of deployment, loading, and compilation. A module collects definitions for types, functions, tables, memories, and globals. In addition, it can declare imports and exports and provide initialization logic in the form of data and element segments or a start function.

Each of the vectors – and thus the entire module – may be empty.

2.5.1. Indices

Definitions are referenced with zero-based indices. Each class of definition has its own index space, as distinguished by the following classes.

The index space for functions, tables, memories and globals includes respective imports declared in the same module. The indices of these imports precede the indices of other definitions in the same index space.

The index space for locals is only accessible inside a function and includes the parameters of that function, which precede the local variables.

Label indices reference structured control instructions inside an instruction sequence.

2.5.1.1. Conventions
  • The meta variable
  • The meta variables

2.5.2. Types

The

All function types used in a module must be defined in this component. They are referenced by type indices.

Note

Future versions of WebAssembly may add additional forms of type definitions.

2.5.3. Functions

The

The

The

The

Functions are referenced through function indices, starting with the smallest index not referencing a function import.

2.5.4. Tables

The

A table is a vector of opaque values of a particular table element type. The

Tables can be initialized through element segments.

Tables are referenced through table indices, starting with the smallest index not referencing a table import. Most constructs implicitly reference table index

Note

In the current version of WebAssembly, at most one table may be defined or imported in a single module, and all constructs implicitly reference this table

2.5.5. Memories

The

A memory is a vector of raw uninterpreted bytes. The

Memories can be initialized through data segments.

Memories are referenced through memory indices, starting with the smallest index not referencing a memory import. Most constructs implicitly reference memory index

Note

In the current version of WebAssembly, at most one memory may be defined or imported in a single module, and all constructs implicitly reference this memory

2.5.6. Globals

The

Each global stores a single value of the given global type. Its

Globals are referenced through global indices, starting with the smallest index not referencing a global import.

2.5.7. Element Segments

The initial contents of a table is uninitialized. The

The

Note

In the current version of WebAssembly, at most one table is allowed in a module. Consequently, the only valid

2.5.8. Data Segments

The initial contents of a memory are zero-valued bytes. The

The

Note

In the current version of WebAssembly, at most one memory is allowed in a module. Consequently, the only valid

2.5.9. Start Function

The

Note

The start function is intended for initializing the state of a module. The module and its exports are not accessible before this initialization has completed.

2.5.10. Exports

The

Each export is labeled by a unique name. Exportable definitions are functions, tables, memories, and globals, which are referenced through a respective descriptor.

2.5.10.1. Conventions

The following auxiliary notation is defined for sequences of exports, filtering out indices of a specific kind in an order-preserving fashion:

2.5.11. Imports

The

Each import is labeled by a two-level name space, consisting of a

Every import defines an index in the respective index space. In each index space, the indices of imports go before the first index of any definition contained in the module itself.

Note

Unlike export names, import names are not necessarily unique. It is possible to import the same

3. Validation

3.1. Conventions

Validation checks that a WebAssembly module is well-formed. Only valid modules can be instantiated.

Validity is defined by a type system over the abstract syntax of a module and its contents. For each piece of abstract syntax, there is a typing rule that specifies the constraints that apply to it. All rules are given in two equivalent forms:

  1. In prose, describing the meaning in intuitive form.
  2. In formal notation, describing the rule in mathematical form. [1]

Note

The prose and formal rules are equivalent, so that understanding of the formal notation is not required to read this specification. The formalism offers a more concise description in notation that is used widely in programming languages semantics and is readily amenable to mathematical proof.

In both cases, the rules are formulated in a declarative manner. That is, they only formulate the constraints, they do not define an algorithm. The skeleton of a sound and complete algorithm for type-checking instruction sequences according to this specification is provided in the appendix.

3.1.1. Contexts

Validity of an individual definition is specified relative to a context, which collects relevant information about the surrounding module and the definitions in scope:

  • Types: the list of types defined in the current module.
  • Functions: the list of functions declared in the current module, represented by their function type.
  • Tables: the list of tables declared in the current module, represented by their table type.
  • Memories: the list of memories declared in the current module, represented by their memory type.
  • Globals: the list of globals declared in the current module, represented by their global type.
  • Locals: the list of locals declared in the current function (including parameters), represented by their value type.
  • Labels: the stack of labels accessible from the current position, represented by their result type.
  • Return: the return type of the current function, represented as an optional result type that is absent when no return is allowed, as in free-standing expressions.

In other words, a context contains a sequence of suitable types for each index space, describing each defined entry in that space. Locals, labels and return type are only used for validating instructions in function bodies, and are left empty elsewhere. The label stack is the only part of the context that changes as validation of an instruction sequence proceeds.

More concretely, contexts are defined as records

In addition to field access written

  • When spelling out a context, empty fields are omitted.

Note

We use indexing notation like

3.1.2. Prose Notation

Validation is specified by stylised rules for each relevant part of the abstract syntax. The rules not only state constraints defining when a phrase is valid, they also classify it with a type. The following conventions are adopted in stating these rules.

  • A phrase

    Note

    For example, if

  • The rules implicitly assume a given context

  • In some places, this context is locally extended to a context

3.1.3. Formal Notation

Note

This section gives a brief explanation of the notation for specifying typing rules formally. For the interested reader, a more thorough introduction can be found in respective text books. [2]

The proposition that a phrase

The formal typing rules use a standard approach for specifying type systems, rendering them into deduction rules. Every rule has the following general form:

Such a rule is read as a big implication: if all premises hold, then the conclusion holds. Some rules have no premises; they are axioms whose conclusion holds unconditionally. The conclusion always is a judgment

Note

For example, the typing rule for the

The instruction is always valid with type

An instruction like

Here, the premise enforces that the immediate local index

Finally, a structured instruction requires a recursive rule, where the premise is itself a typing judgement:

A

[1] The semantics is derived from the following article: Andreas Haas, Andreas Rossberg, Derek Schuff, Ben Titzer, Dan Gohman, Luke Wagner, Alon Zakai, JF Bastien, Michael Holman. Bringing the Web up to Speed with WebAssembly. Proceedings of the 38th ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI 2017). ACM 2017.
[2] For example: Benjamin Pierce. Types and Programming Languages. The MIT Press 2002

3.2. Types

Most types are universally valid. However, restrictions apply to function types as well as the limits of table types and memory types, which must be checked during validation.

3.2.1. Limits

Limits must have meaningful bounds that are within a given range.

3.2.1.1.
  • The value of
  • If the maximum
  • Then the limit is valid within range

3.2.2. Function Types

Function types may not specify more than one result.

3.2.2.1.
  • The arity
  • Then the function type is valid.

Note

The restriction to at most one result may be removed in future versions of WebAssembly.

3.2.3. Table Types

3.2.3.1.
  • The limits
  • Then the table type is valid.

3.2.4. Memory Types

3.2.4.1.
  • The limits
  • Then the memory type is valid.

3.2.5. Global Types

3.2.5.1.
  • The global type is valid.

3.2.6. External Types

3.2.6.1.
3.2.6.2.
3.2.6.3.
3.2.6.4.

3.3. Instructions

Instructions are classified by function types

Note

For example, the instruction

Typing extends to instruction sequences

For some instructions, the typing rules do not fully constrain the type, and therefore allow for multiple types. Such instructions are called polymorphic. Two degrees of polymorphism can be distinguished:

In both cases, the unconstrained types or type sequences can be chosen arbitrarily, as long as they meet the constraints imposed for the surrounding parts of the program.

Note

For example, the

and

are valid, with

The

is valid by assuming type

is invalid, because there is no possible type to pick for the

3.3.1. Numeric Instructions

3.3.1.1.
  • The instruction is valid with type
3.3.1.2.
  • The instruction is valid with type
3.3.1.3.
  • The instruction is valid with type
3.3.1.4.
  • The instruction is valid with type
3.3.1.5.
  • The instruction is valid with type
3.3.1.6.
  • The instruction is valid with type

3.3.2. Parametric Instructions

3.3.2.1.
  • The instruction is valid with type
3.3.2.2.

Note

Both

3.3.3. Variable Instructions

3.3.3.1.
  • The local
  • Let
  • Then the instruction is valid with type
3.3.3.2.
  • The local
  • Let
  • Then the instruction is valid with type
3.3.3.3.
  • The local
  • Let
  • Then the instruction is valid with type
3.3.3.4.
3.3.3.5.

3.3.4. Memory Instructions

3.3.4.1.
  • The memory
  • The alignment
  • Then the instruction is valid with type
3.3.4.2.
  • The memory
  • The alignment
  • Then the instruction is valid with type
3.3.4.3.
  • The memory
  • The alignment
  • Then the instruction is valid with type
3.3.4.4.
  • The memory
  • The alignment
  • Then the instruction is valid with type
3.3.4.5.
  • The memory
  • Then the instruction is valid with type
3.3.4.6.
  • The memory
  • Then the instruction is valid with type

3.3.5. Control Instructions

3.3.5.1.
  • The instruction is valid with type
3.3.5.2.
  • The instruction is valid with type

Note

The

3.3.5.3.
  • Let
  • Under context
  • Then the compound instruction is valid with type

Note

The notation

The fact that the nested instruction sequence

3.3.5.4.
  • Let
  • Under context
  • Then the compound instruction is valid with type

Note

The notation

The fact that the nested instruction sequence

3.3.5.5.
  • Let
  • Under context
  • Under context
  • Then the compound instruction is valid with type

Note

The notation

The fact that the nested instruction sequence

3.3.5.6.
  • The label
  • Let
  • Then the instruction is valid with type

Note

The label index space in the context

The

3.3.5.7.
  • The label
  • Let
  • Then the instruction is valid with type

Note

The label index space in the context

3.3.5.8.
  • The label
  • Let
  • For all
  • For all
  • Then the instruction is valid with type

Note

The label index space in the context

The

3.3.5.9.
  • The return type
  • Let
  • Then the instruction is valid with type

Note

The

3.3.5.10.
  • The function
  • Then the instruction is valid with type
3.3.5.11.

3.3.6. Instruction Sequences

Typing of instruction sequences is defined recursively.

3.3.6.1. Empty Instruction Sequence:
  • The empty instruction sequence is valid with type
3.3.6.2. Non-empty Instruction Sequence:
  • The instruction sequence
  • The instruction
  • There must be a sequence of value types
  • Then the combined instruction sequence is valid with type

3.3.7. Expressions

Expressions

3.3.7.1.
3.3.7.2. Constant Expressions

Note

Currently, constant expressions occurring as initializers of globals are further constrained in that contained

The definition of constant expression may be extended in future versions of WebAssembly.

3.4. Modules

Modules are valid when all the components they contain are valid. Furthermore, most definitions are themselves classified with a suitable type.

3.4.1. Functions

Functions

3.4.1.1.
  • The type
  • Let
  • Let
  • Under the context
  • Then the function definition is valid with type

Note

The restriction on the length of the result types

3.4.2. Tables

Tables

3.4.2.1.

3.4.3. Memories

Memories

3.4.3.1.

3.4.4. Globals

Globals

3.4.4.1.

3.4.5. Element Segments

Element segments

3.4.5.1.

3.4.6. Data Segments

Data segments

3.4.6.1.

3.4.7. Start Function

Start function declarations

3.4.7.1.
  • The function
  • The type of
  • Then the start function is valid.

3.4.8. Exports

Exports

3.4.8.1.
3.4.8.2.
3.4.8.3.
3.4.8.4.
  • The memory
  • Then the export description is valid with external type
3.4.8.5.

3.4.9. Imports

Imports

3.4.9.1.
3.4.9.2.
  • The function
  • Let
  • Then the import description is valid with type
3.4.9.3.
3.4.9.4.
3.4.9.5.

3.4.10. Modules

Modules are classified by their mapping from the external types of their imports to those of their exports.

A module is entirely closed, that is, its components can only refer to definitions that appear in the module itself. Consequently, no initial context is required. Instead, the context

Note

Most definitions in a module – particularly functions – are mutually recursive. Consequently, the definition of the context

Globals, however, are not recursive. The effect of defining the limited context

Note

The restriction on the number of tables and memories may be lifted in future versions of WebAssembly.

4. Execution

4.1. Conventions

WebAssembly code is executed when instantiating a module or invoking an exported function on the resulting module instance.

Execution behavior is defined in terms of an abstract machine that models the program state. It includes a stack, which records operand values and control constructs, and an abstract store containing global state.

For each instruction, there is a rule that specifies the effect of its execution on the program state. Furthermore, there are rules describing the instantiation of a module. As with validation, all rules are given in two equivalent forms:

  1. In prose, describing the execution in intuitive form.
  2. In formal notation, describing the rule in mathematical form. [1]

Note

As with validation, the prose and formal rules are equivalent, so that understanding of the formal notation is not required to read this specification. The formalism offers a more concise description in notation that is used widely in programming languages semantics and is readily amenable to mathematical proof.

4.1.1. Prose Notation

Execution is specified by stylised, step-wise rules for each instruction of the abstract syntax. The following conventions are adopted in stating these rules.

  • The execution rules implicitly assume a given store
  • The execution rules also assume the presence of an implicit stack that is modified by pushing or popping values, labels, and frames.
  • Certain rules require the stack to contain at least one frame. The most recent frame is referred to as the current frame.
  • Both the store and the current frame are mutated by replacing some of their components. Such replacement is assumed to apply globally.
  • The execution of an instruction may trap, in which case the entire computation is aborted and no further modifications to the store are performed by it. (Other computations can still be initiated afterwards.)
  • The execution of an instruction may also end in a jump to a designated target, which defines the next instruction to execute.
  • Execution can enter and exit instruction sequences that form blocks.
  • Instruction sequences are implicitly executed in order, unless a trap or jump occurs.
  • In various places the rules contain assertions expressing crucial invariants about the program state.

4.1.2. Formal Notation

Note

This section gives a brief explanation of the notation for specifying execution formally. For the interested reader, a more thorough introduction can be found in respective text books. [2]

The formal execution rules use a standard approach for specifying operational semantics, rendering them into reduction rules. Every rule has the following general form:

A configuration is a syntactic description of a program state. Each rule specifies one step of execution. As long as there is at most one reduction rule applicable to a given configuration, reduction – and thereby execution – is deterministic. WebAssembly has only very few exceptions to this, which are noted explicitly in this specification.

For WebAssembly, a configuration typically is a tuple

To avoid unnecessary clutter, the store

There is no separate representation of the stack. Instead, it is conveniently represented as part of the configuration’s instruction sequence. In particular, values are defined to coincide with

Note

For example, the reduction rule for the

Per this rule, two

When no result is produced, an instruction reduces to the empty sequence:

Labels and frames are similarly defined to be part of an instruction sequence.

The order of reduction is determined by the definition of an appropriate evaluation context.

Reduction terminates when no more reduction rules are applicable. Soundness of the WebAssembly type system guarantees that this is only the case when the original instruction sequence has either been reduced to a sequence of

Note

For example, the following instruction sequence,

terminates after three steps:

where

[1] The semantics is derived from the following article: Andreas Haas, Andreas Rossberg, Derek Schuff, Ben Titzer, Dan Gohman, Luke Wagner, Alon Zakai, JF Bastien, Michael Holman. Bringing the Web up to Speed with WebAssembly. Proceedings of the 38th ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI 2017). ACM 2017.
[2] For example: Benjamin Pierce. Types and Programming Languages. The MIT Press 2002

4.2. Runtime Structure

Store, stack, and other runtime structure forming the WebAssembly abstract machine, such as values or module instances, are made precise in terms of additional auxiliary syntax.

4.2.1. Values

WebAssembly computations manipulate values of the four basic value types: integers and floating-point data of 32 or 64 bit width each, respectively.

In most places of the semantics, values of different types can occur. In order to avoid ambiguities, values are therefore represented with an abstract syntax that makes their type explicit. It is convenient to reuse the same notation as for the

4.2.2. Results

A result is the outcome of a computation. It is either a sequence of values or a trap.

Note

In the current version of WebAssembly, a result can consist of at most one value.

4.2.3. Store

The store represents all global state that can be manipulated by WebAssembly programs. It consists of the runtime representation of all instances of functions, tables, memories, and globals that have been allocated during the life time of the abstract machine. [1]

Syntactically, the store is defined as a record listing the existing instances of each category:

[1] In practice, implementations may apply techniques like garbage collection to remove objects from the store that are no longer referenced. However, such techniques are not semantically observable, and hence outside the scope of this specification.
4.2.3.1. Convention
  • The meta variable

4.2.4. Addresses

Function instances, table instances, memory instances, and global instances in the store are referenced with abstract addresses. These are simply indices into the respective store component.

An embedder may assign identity to exported store objects corresponding to their addresses, even where this identity is not observable from within WebAssembly code itself (such as for function instances or immutable globals).

Note

Addresses are dynamic, globally unique references to runtime objects, in contrast to indices, which are static, module-local references to their original definitions. A memory address

There is no specific limit on the number of allocations of store objects, hence logical addresses can be arbitrarily large natural numbers.

4.2.5. Module Instances

A module instance is the runtime representation of a module. It is created by instantiating a module, and collects runtime representations of all entities that are imported, defined, or exported by the module.

Each component references runtime instances corresponding to respective declarations from the original module – whether imported or defined – in the order of their static indices. Function instances, table instances, memory instances, and global instances are referenced with an indirection through their respective addresses in the store.

It is an invariant of the semantics that all export instances in a given module instance have different names.

4.2.6. Function Instances

A function instance is the runtime representation of a function. It effectively is a closure of the original function over the runtime module instance of its originating module. The module instance is used to resolve references to other definitions during execution of the function.

A host function is a function expressed outside WebAssembly but passed to a module as an import. The definition and behavior of host functions are outside the scope of this specification. For the purpose of this specification, it is assumed that when invoked, a host function behaves non-deterministically, but within certain constraints that ensure the integrity of the runtime.

Note

Function instances are immutable, and their identity is not observable by WebAssembly code. However, the embedder might provide implicit or explicit means for distinguishing their addresses.

4.2.7. Table Instances

A table instance is the runtime representation of a table. It holds a vector of function elements and an optional maximum size, if one was specified in the table type at the table’s definition site.

Each function element is either empty, representing an uninitialized table entry, or a function address. Function elements can be mutated through the execution of an element segment or by external means provided by the embedder.

It is an invariant of the semantics that the length of the element vector never exceeds the maximum size, if present.

Note

Other table elements may be added in future versions of WebAssembly.

4.2.8. Memory Instances

A memory instance is the runtime representation of a linear memory. It holds a vector of bytes and an optional maximum size, if one was specified at the definition site of the memory.

The length of the vector always is a multiple of the WebAssembly page size, which is defined to be the constant

The bytes can be mutated through memory instructions, the execution of a data segment, or by external means provided by the embedder.

It is an invariant of the semantics that the length of the byte vector, divided by page size, never exceeds the maximum size, if present.

4.2.9. Global Instances

A global instance is the runtime representation of a global variable. It holds an individual value and a flag indicating whether it is mutable.

The value of mutable globals can be mutated through variable instructions or by external means provided by the embedder.

4.2.10. Export Instances

An export instance is the runtime representation of an export. It defines the export’s name and the associated external value.

4.2.11. External Values

An external value is the runtime representation of an entity that can be imported or exported. It is an address denoting either a function instance, table instance, memory instance, or global instances in the shared store.

4.2.11.1. Conventions

The following auxiliary notation is defined for sequences of external values. It filters out entries of a specific kind in an order-preserving fashion:

4.2.12. Stack

Besides the store, most instructions interact with an implicit stack. The stack contains three kinds of entries:

These entries can occur on the stack in any order during the execution of a program. Stack entries are described by abstract syntax as follows.

Note

It is possible to model the WebAssembly semantics using separate stacks for operands, control constructs, and calls. However, because the stacks are interdependent, additional book keeping about associated stack heights would be required. For the purpose of this specification, an interleaved representation is simpler.

4.2.12.1. Values

Values are represented by themselves.

4.2.12.2. Labels

Labels carry an argument arity

Intuitively,

Note

For example, a loop label has the form

When performing a branch to this label, this executes the loop, effectively restarting it from the beginning. Conversely, a simple block label has the form

When branching, the empty continuation ends the targeted block, such that execution can proceed with consecutive instructions.

4.2.12.3. Activations and Frames

Activation frames carry the return arity

The values of the locals are mutated by respective variable instructions.

4.2.12.4. Conventions
  • The meta variable
  • The meta variable

Note

In the current version of WebAssembly, the arities of labels and frames cannot be larger than

4.2.13. Administrative Instructions

Note

This section is only relevant for the formal notation.

In order to express the reduction of traps, calls, and control instructions, the syntax of instructions is extended to include the following administrative instructions:

The

The

The

Note

The reason for splitting instantiation into individual reduction steps is to provide a semantics that is compatible with future extensions like threads.

The

Note

For example, the reduction rule for

This replaces the block with a label instruction, which can be interpreted as “pushing” the label on the stack. When

This can be interpreted as removing the label from the stack and only leaving the locally accumulated operand values.

4.2.13.1. Block Contexts

In order to specify the reduction of branches, the following syntax of block contexts is defined, indexed by the count

This definition allows to index active labels surrounding a branch or return instruction.

Note

For example, the reduction of a simple branch can be defined as follows:

Here, the hole

4.2.13.2. Configurations

A configuration consists of the current store and an executing thread.

A thread is a computation over instructions that operates relative to a current frame referring to the module instance in which the computation runs, i.e., where the current function originates from.

Note

The current version of WebAssembly is single-threaded, but configurations with multiple threads may be supported in the future.

4.2.13.3. Evaluation Contexts

Finally, the following definition of evaluation context and associated structural rules enable reduction inside instruction sequences and administrative forms as well as the propagation of traps:

Reduction terminates when a thread’s instruction sequence has been reduced to a result, that is, either a sequence of values or to a

Note

The restriction on evaluation contexts rules out contexts like

For an example of reduction under evaluation contexts, consider the following instruction sequence.

This can be decomposed into

Moreover, this is the only possible choice of evaluation context where the contents of the hole matches the left-hand side of a reduction rule.

4.3. Numerics

Numeric primitives are defined in a generic manner, by operators indexed over a bit width

Some operators are non-deterministic, because they can return one of several possible results (such as different NaN values). Technically, each operator thus returns a set of allowed values. For convenience, deterministic results are expressed as plain values, which are assumed to be identified with a respective singleton set.

Some operators are partial, because they are not defined on certain inputs. Technically, an empty set of results is returned for these inputs.

In formal notation, each operator is defined by equational clauses that apply in decreasing order of precedence. That is, the first clause that is applicable to the given arguments defines the result. In some cases, similar clauses are combined into one by using the notation

Note

For example, the

This definition is to be read as a shorthand for the following expansion of each clause into two separate ones:

Conventions:

  • The meta variable

  • The meta variable

  • The meta variable

  • The notation

  • Truncation of rational values is written

4.3.1. Representations

Numbers have an underlying binary representation as a sequence of bits:

Each of these functions is a bijection, hence they are invertible.

4.3.1.1. Integers

Integers are represented as base two unsigned numbers:

Boolean operators like

4.3.1.2. Floating-Point

Floating-point values are represented in the respective binary format defined by [IEEE-754-2019] (Section 3.4):

where

4.3.1.3. Storage

When a number is stored into memory, it is converted into a sequence of bytes in little endian byte order:

Again these functions are invertable bijections.

4.3.2. Integer Operations

4.3.2.1. Sign Interpretation

Integer operators are defined on

This function is bijective, and hence invertible.

4.3.2.2. Boolean Interpretation

The integer result of predicates – i.e., tests and relational operators – is defined with the help of the following auxiliary function producing the value

4.3.2.3.
  • Return the result of adding
4.3.2.4.
  • Return the result of subtracting
4.3.2.5.
  • Return the result of multiplying
4.3.2.6.
  • If
  • Else, return the result of dividing

Note

This operator is partial.

4.3.2.7.
  • Let
  • Let
  • If
  • Else if
  • Else, return the result of dividing

Note

This operator is partial. Besides division by

4.3.2.8.
  • If
  • Else, return the remainder of dividing

Note

This operator is partial.

As long as both operators are defined, it holds that

4.3.2.9.
  • Let
  • Let
  • If
  • Else, return the remainder of dividing

Note

This operator is partial.

As long as both operators are defined, it holds that

4.3.2.10.
  • Return the bitwise conjunction of
4.3.2.11.
  • Return the bitwise disjunction of
4.3.2.12.
  • Return the bitwise exclusive disjunction of
4.3.2.13.
  • Let
  • Return the result of shifting
4.3.2.14.
  • Let
  • Return the result of shifting
4.3.2.15.
  • Let
  • Return the result of shifting
4.3.2.16.
  • Let
  • Return the result of rotating
4.3.2.17.
  • Let
  • Return the result of rotating
4.3.2.18.
  • Return the count of leading zero bits in
4.3.2.19.
  • Return the count of trailing zero bits in
4.3.2.20.
  • Return the count of non-zero bits in
4.3.2.21.
  • Return
4.3.2.22.
  • Return
4.3.2.23.
  • Return
4.3.2.24.
  • Return
4.3.2.25.
4.3.2.26.
  • Return
4.3.2.27.
4.3.2.28.
  • Return
4.3.2.29.
4.3.2.30.
  • Return
4.3.2.31.

4.3.3. Floating-Point Operations

Floating-point arithmetic follows the [IEEE-754-2019] standard, with the following qualifications:

  • All operators use round-to-nearest ties-to-even, except where otherwise specified. Non-default directed rounding attributes are not supported.
  • Following the recommendation that operators propagate NaN payloads from their operands is permitted but not required.
  • All operators use “non-stop” mode, and floating-point exceptions are not otherwise observable. In particular, neither alternate floating-point exception handling attributes nor operators on status flags are supported. There is no observable difference between quiet and signalling NaNs.

Note

Some of these limitations may be lifted in future versions of WebAssembly.

4.3.3.1. Rounding

Rounding always is round-to-nearest ties-to-even, in correspondence with [IEEE-754-2019] (Section 4.3.1).

An exact floating-point number is a rational number that is exactly representable as a floating-point number of given bit width

A limit number for a given floating-point bit width

A candidate number is either an exact floating-point number or a positive or negative limit number for the given bit width

A candidate pair is a pair

A real number

  • If
  • Else if
  • Else if
  • Else if
  • Else if
  • If
  • Else if
  • Else, return

where:

4.3.3.2. NaN Propagation

When the result of a floating-point operator other than

  • If the payload of all NaN inputs to the operator is canonical (including the case that there are no NaN inputs), then the payload of the output is canonical as well.
  • Otherwise the payload is picked non-determinsitically among all arithmetic NaNs; that is, its most significant bit is

This non-deterministic result is expressed by the following auxiliary function producing a set of allowed outputs from a set of inputs:

4.3.3.3.
  • If either
  • Else if both
  • Else if both
  • Else if one of
  • Else if both
  • Else if both
  • Else if one of
  • Else if both
  • Else return the result of adding
4.3.3.4.
  • If either
  • Else if both
  • Else if both
  • Else if
  • Else if
  • Else if both
  • Else if both
  • Else if
  • Else if
  • Else if both
  • Else return the result of subtracting

Note

Up to the non-determinism regarding NaNs, it always holds that

4.3.3.5.
  • If either
  • Else if one of
  • Else if both
  • Else if both
  • Else if one of
  • Else if one of
  • Else if both
  • Else if both
  • Else return the result of multiplying
4.3.3.6.
  • If either
  • Else if both
  • Else if both
  • Else if
  • Else if
  • Else if
  • Else if
  • Else if
  • Else if
  • Else if
  • Else if
  • Else return the result of dividing
4.3.3.7.
  • If either
  • Else if one of
  • Else if one of
  • Else if both
  • Else return the smaller value of
4.3.3.8.
  • If either
  • Else if one of
  • Else if one of
  • Else if both
  • Else return the larger value of
4.3.3.9.
  • If
  • Else return
4.3.3.10.
  • If
  • Else if
  • Else if
  • Else if
  • Else return
4.3.3.11.
  • If
  • Else if
  • Else if
  • Else return
4.3.3.12.
  • If
  • Else if
  • Else if
  • Else if
  • Else return the square root of
4.3.3.13.
  • If
  • Else if
  • Else if
  • Else if
  • Else return the smallest integral value that is not smaller than
4.3.3.14.
  • If
  • Else if
  • Else if
  • Else if
  • Else return the largest integral value that is not larger than
4.3.3.15.
  • If
  • Else if
  • Else if
  • Else if
  • Else if
  • Else return the integral value with the same sign as
4.3.3.16.
  • If
  • Else if
  • Else if
  • Else if
  • Else if
  • Else return the integral value that is nearest to
4.3.3.17.
  • If either
  • Else if both
  • Else if both
  • Else return
4.3.3.18.
  • If either
  • Else if both
  • Else if both
  • Else return
4.3.3.19.
  • If either
  • Else if
  • Else if
  • Else if
  • Else if
  • Else if
  • Else if both
  • Else if
  • Else return
4.3.3.20.
  • If either
  • Else if
  • Else if
  • Else if
  • Else if
  • Else if
  • Else if both
  • Else if
  • Else return
4.3.3.21.
  • If either
  • Else if
  • Else if
  • Else if
  • Else if
  • Else if
  • Else if both
  • Else if
  • Else return
4.3.3.22.
  • If either
  • Else if
  • Else if
  • Else if
  • Else if
  • Else if
  • Else if both
  • Else if
  • Else return

4.3.4. Conversions

4.3.4.1.
  • Return

Note

In the abstract syntax, unsigned extension just reinterprets the same value.

4.3.4.2.
  • Let
  • Return the two’s complement of
4.3.4.3.
  • Return
4.3.4.4.
  • If
  • Else if
  • Else if
  • Else the result is undefined.

Note

This operator is partial. It is not defined for NaNs, infinities, or values for which the result is out of range.

4.3.4.5.
  • If
  • Else if
  • If
  • Else the result is undefined.

Note

This operator is partial. It is not defined for NaNs, infinities, or values for which the result is out of range.

4.3.4.6.
  • If
  • Else if
  • Else, return
4.3.4.7.
  • If
  • Else if
  • Else if
  • Else if
  • Else, return
4.3.4.8.
4.3.4.9.
4.3.4.10.
  • Let
  • Return the constant

4.4. Instructions

WebAssembly computation is performed by executing individual instructions.

4.4.1. Numeric Instructions

Numeric instructions are defined in terms of the generic numeric operators. The mapping of numeric instructions to their underlying operators is expressed by the following definition:

And for conversion operators:

Where the underlying operators are partial, the corresponding instruction will trap when the result is not defined. Where the underlying operators are non-deterministic, because they may return one of multiple possible NaN values, so are the corresponding instructions.

Note

For example, the result of instruction

4.4.1.1.
  1. Push the value

Note

No formal reduction rule is required for this instruction, since

4.4.1.2.
  1. Assert: due to validation, a value of value type
  2. Pop the value
  3. If
  4. Else:
    1. Trap.
4.4.1.3.
  1. Assert: due to validation, two values of value type
  2. Pop the value
  3. Pop the value
  4. If
  5. Else:
    1. Trap.
4.4.1.4.
  1. Assert: due to validation, a value of value type
  2. Pop the value
  3. Let
  4. Push the value
4.4.1.5.
  1. Assert: due to validation, two values of value type
  2. Pop the value
  3. Pop the value
  4. Let
  5. Push the value
4.4.1.6.
  1. Assert: due to validation, a value of value type
  2. Pop the value
  3. If
  4. Else:
    1. Trap.

4.4.2. Parametric Instructions

4.4.2.1.
  1. Assert: due to validation, a value is on the top of the stack.
  2. Pop the value
4.4.2.2.
  1. Assert: due to validation, a value of value type
  2. Pop the value
  3. Assert: due to validation, two more values (of the same value type) are on the top of the stack.
  4. Pop the value
  5. Pop the value
  6. If
  7. Else:
    1. Push the value

4.4.3. Variable Instructions

4.4.3.1.
  1. Let
  2. Assert: due to validation,
  3. Let
  4. Push the value
4.4.3.2.
  1. Let
  2. Assert: due to validation,
  3. Assert: due to validation, a value is on the top of the stack.
  4. Pop the value
  5. Replace
4.4.3.3.
  1. Assert: due to validation, a value is on the top of the stack.
  2. Pop the value
  3. Push the value
  4. Push the value
  5. Execute the instruction
4.4.3.4.
  1. Let
  2. Assert: due to validation,
  3. Let
  4. Assert: due to validation,
  5. Let
  6. Let
  7. Push the value
4.4.3.5.
  1. Let
  2. Assert: due to validation,
  3. Let
  4. Assert: due to validation,
  5. Let
  6. Assert: due to validation, a value is on the top of the stack.
  7. Pop the value
  8. Replace

Note

Validation ensures that the global is, in fact, marked as mutable.

4.4.4. Memory Instructions

Note

The alignment

4.4.4.1.
  1. Let
  2. Assert: due to validation,
  3. Let
  4. Assert: due to validation,
  5. Let
  6. Assert: due to validation, a value of value type
  7. Pop the value
  8. Let
  9. If
  10. If
  11. Let
  12. If
  13. Else:
    1. Let
  14. Push the value
4.4.4.2.
  1. Let
  2. Assert: due to validation,
  3. Let
  4. Assert: due to validation,
  5. Let
  6. Assert: due to validation, a value of value type
  7. Pop the value
  8. Assert: due to validation, a value of value type
  9. Pop the value
  10. Let
  11. If
  12. If
  13. If
  14. Else:
    1. Let
  15. Replace the bytes
4.4.4.3.
  1. Let
  2. Assert: due to validation,
  3. Let
  4. Assert: due to validation,
  5. Let
  6. Let
  7. Push the value
4.4.4.4.
  1. Let
  2. Assert: due to validation,
  3. Let
  4. Assert: due to validation,
  5. Let
  6. Let
  7. Assert: due to validation, a value of value type
  8. Pop the value
  9. Either, try growing
  10. Or, push the value

Note

The

4.4.5. Control Instructions

4.4.5.1.
  1. Do nothing.
4.4.5.2.
  1. Trap.
4.4.5.3.
  1. Let
  2. Let
  3. Enter the block
4.4.5.4.
  1. Let
  2. Enter the block
4.4.5.5.
  1. Assert: due to validation, a value of value type
  2. Pop the value
  3. Let
  4. Let
  5. If
  6. Else:
    1. Enter the block
4.4.5.6.
  1. Assert: due to validation, the stack contains at least
  2. Let
  3. Let
  4. Assert: due to validation, there are at least
  5. Pop the values
  6. Repeat
  7. Push the values
  8. Jump to the continuation of
4.4.5.7.
  1. Assert: due to validation, a value of value type
  2. Pop the value
  3. If
  4. Else:
    1. Do nothing.
4.4.5.8.
  1. Assert: due to validation, a value of value type
  2. Pop the value
  3. If
  4. Else:
    1. Execute the instruction
4.4.5.9.
  1. Let
  2. Let
  3. Assert: due to validation, there are at least
  4. Pop the results
  5. Assert: due to validation, the stack contains at least one frame.
  6. While the top of the stack is not a frame, do:
    1. Pop the top element from the stack.
  7. Assert: the top of the stack is the frame
  8. Pop the frame from the stack.
  9. Push
  10. Jump to the instruction after the original call that pushed the frame.
4.4.5.10.
  1. Let
  2. Assert: due to validation,
  3. Let
  4. Invoke the function instance at address
4.4.5.11.
  1. Let
  2. Assert: due to validation,
  3. Let
  4. Assert: due to validation,
  5. Let
  6. Assert: due to validation,
  7. Let
  8. Assert: due to validation, a value with value type
  9. Pop the value
  10. If
  11. If
  12. Let
  13. Assert: due to validation,
  14. Let
  15. Let
  16. If
  17. Invoke the function instance at address

4.4.6. Blocks

The following auxiliary rules define the semantics of executing an instruction sequence that forms a block.

4.4.6.1. Entering
  1. Push
  2. Jump to the start of the instruction sequence

Note

No formal reduction rule is needed for entering an instruction sequence, because the label

4.4.6.2. Exiting

When the end of a block is reached without a jump or trap aborting it, then the following steps are performed.

  1. Let
  2. Pop the values
  3. Assert: due to validation, the label
  4. Pop the label from the stack.
  5. Push
  6. Jump to the position after the

Note

This semantics also applies to the instruction sequence contained in a

4.4.7. Function Calls

The following auxiliary rules define the semantics of invoking a function instance through one of the call instructions and returning from it.

4.4.7.1. Invocation of function address
  1. Assert: due to validation,
  2. Let
  3. Let
  4. Assert: due to validation,
  5. Let
  6. Let
  7. Assert: due to validation,
  8. Pop the values
  9. Let
  10. Let
  11. Push the activation of
  12. Execute the instruction
4.4.7.2. Returning from a function

When the end of a function is reached without a jump (i.e.,

  1. Let
  2. Let
  3. Assert: due to validation, there are
  4. Pop the results
  5. Assert: due to validation, the frame
  6. Pop the frame from the stack.
  7. Push
  8. Jump to the instruction after the original call.
4.4.7.3. Host Functions

Invoking a host function has non-deterministic behavior. It may either terminate with a trap or return regularly. However, in the latter case, it must consume and produce the right number and types of WebAssembly values on the stack, according to its function type.

A host function may also modify the store. However, all store modifications must result in an extension of the original store, i.e., they must only modify mutable contents and must not have instances removed. Furthermore, the resulting store must be valid, i.e., all data and code in it is well-typed.

Here,

For a WebAssembly implementation to be sound in the presence of host functions, every host function instance must be valid, which means that it adheres to suitable pre- and post-conditions: under a valid store

Note

A host function can call back into WebAssembly by invoking a function exported from a module. However, the effects of any such call are subsumed by the non-deterministic behavior allowed for the host function.

4.4.8. Expressions

An expression is evaluated relative to a current frame pointing to its containing module instance.

  1. Jump to the start of the instruction sequence
  2. Execute the instruction sequence.
  3. Assert: due to validation, the top of the stack contains a value.
  4. Pop the value

The value

Note

Evaluation iterates this reduction rule until reaching a value. Expressions constituting function bodies are executed during function invocation.

4.5. Modules

For modules, the execution semantics primarily defines instantiation, which allocates instances for a module and its contained definitions, inititializes tables and memories from contained element and data segments, and invokes the start function if present. It also includes invocation of exported functions.

Instantiation depends on a number of auxiliary notions for type-checking imports and allocating instances.

4.5.1. External Typing

For the purpose of checking external values against imports, such values are classified by external types. The following auxiliary typing rules specify this typing relation relative to a store

4.5.1.1.
4.5.1.2.
4.5.1.3.
4.5.1.4.

4.5.2. Import Matching

When instantiating a module, external values must be provided whose types are matched against the respective external types classifying each import. In some cases, this allows for a simple form of subtyping, as defined below.

4.5.2.1. Limits

Limits

  • Either:
  • Or:
    • Both
4.5.2.2. Functions

An external type

4.5.2.3. Tables

An external type

4.5.2.4. Memories

An external type

4.5.2.5. Globals

An external type

4.5.3. Allocation

New instances of functions, tables, memories, and globals are allocated in a store

4.5.3.1. Functions
  1. Let
  2. Let
  3. Let
  4. Let
  5. Append
  6. Return
4.5.3.2. Host Functions
  1. Let
  2. Let
  3. Let
  4. Append
  5. Return

Note

Host functions are never allocated by the WebAssembly semantics itself, but may be allocated by the embedder.

4.5.3.3. Tables
  1. Let
  2. Let
  3. Let
  4. Let
  5. Append
  6. Return
4.5.3.4. Memories
  1. Let
  2. Let
  3. Let
  4. Let
  5. Append
  6. Return
4.5.3.5. Globals
  1. Let
  2. Let
  3. Let
  4. Let
  5. Append
  6. Return
4.5.3.6. Growing tables
  1. Let
  2. Let
  3. If
  4. If
  5. Append
4.5.3.7. Growing memories
  1. Let
  2. Assert: The length of
  3. Let
  4. If
  5. If
  6. Append
4.5.3.8. Modules

The allocation function for modules requires a suitable list of external values that are assumed to match the import vector of the module, and a list of initialization values for the module’s globals.

1. Let

  1. For each function
  2. For each table
  3. For each memory
  4. For each global
  5. Let
  6. Let
  7. Let
  8. Let
  9. Let
  10. Let
  11. Let
  12. Let
  13. For each export
  14. Let
  15. Let
  16. Return

where:

Here, the notation

Moreover, if the dots

Note

The definition of module allocation is mutually recursive with the allocation of its associated functions, because the resulting module instance

4.5.4. Instantiation

Given a store

Instantiation checks that the module is valid and the provided imports match the declared types, and may fail with an error otherwise. Instantiation can also result in a trap from executing the start function. It is up to the embedder to define how such conditions are reported.

  1. If
  2. Assert:
  3. If the number
  4. For each external value
  1. Let

    1. Let
    2. Let
    3. Push the frame
    4. For each global
    5. Assert: due to validation, the frame
    6. Pop the frame
  2. Let

  3. Let

  4. Push the frame

  5. For each element segment

    1. Let
    2. Assert: due to validation,
    3. Let
    4. Assert: due to validation,
    5. Let
    6. Assert: due to validation,
    7. Let
    8. Let
    9. If
  6. For each data segment

    1. Let
    2. Assert: due to validation,
    3. Let
    4. Assert: due to validation,
    5. Let
    6. Assert: due to validation,
    7. Let
    8. Let
    9. If
  7. Assert: due to validation, the frame

  8. Pop the frame from the stack.

  9. For each element segment

    1. For each function index
  10. For each data segment

    1. For each byte
  11. If the start function

    1. Assert: due to validation,
    2. Let
    3. Invoke the function instance at

Note

Module allocation and the evaluation of global initializers are mutually recursive because the global initialization values

All failure conditions are checked before any observable mutation of the store takes place. Store mutation is not atomic; it happens in individual steps that may be interleaved with other threads.

Evaluation of constant expressions does not affect the store.

4.5.5. Invocation

Once a module has been instantiated, any exported function can be invoked externally via its function address

Invocation may fail with an error if the arguments do not fit the function type. Invocation can also result in a trap. It is up to the embedder to define how such conditions are reported.

Note

If the embedder API performs type checks itself, either statically or dynamically, before performing an invocation, then no failure other than traps can occur.

The following steps are performed:

  1. Assert:
  2. Let
  3. Let
  4. If the length
  5. For each value type
  6. Let
  7. Push the frame
  8. Push the values
  9. Invoke the function instance at address

Once the function has returned, the following steps are executed:

  1. Assert: due to validation,
  2. Pop

The values

5. Binary Format

5.1. Conventions

The binary format for WebAssembly modules is a dense linear encoding of their abstract syntax. [1]

The format is defined by an attribute grammar whose only terminal symbols are bytes. A byte sequence is a well-formed encoding of a module if and only if it is generated by the grammar.

Each production of this grammar has exactly one synthesized attribute: the abstract syntax that the respective byte sequence encodes. Thus, the attribute grammar implicitly defines a decoding function (i.e., a parsing function for the binary format).

Except for a few exceptions, the binary grammar closely mirrors the grammar of the abstract syntax.

Note

Some phrases of abstract syntax have multiple possible encodings in the binary format. For example, numbers may be encoded as if they had optional leading zeros. Implementations of decoders must support all possible alternatives; implementations of encoders can pick any allowed encoding.

The recommended extension for files containing WebAssembly modules in binary format is “

[1] Additional encoding layers – for example, introducing compression – may be defined on top of the basic representation defined here. However, such layers are outside the scope of the current specification.

5.1.1. Grammar

The following conventions are adopted in defining grammar rules for the binary format. They mirror the conventions used for abstract syntax. In order to distinguish symbols of the binary syntax from symbols of the abstract syntax,

  • Terminal symbols are bytes expressed in hexadecimal notation:
  • Nonterminal symbols are written in typewriter font:
  • Productions are written
  • Some productions are augmented by side conditions in parentheses, which restrict the applicability of the production. They provide a shorthand for a combinatorial expansion of the production into many separate cases.

Note

For example, the binary grammar for value types is given as follows:

Consequently, the byte

The binary grammar for limits is defined as follows:

That is, a limits pair is encoded as either the byte

5.1.2. Auxiliary Notation

When dealing with binary encodings the following notation is also used:

5.1.3. Vectors

Vectors are encoded with their

5.2. Values

5.2.1. Bytes

Bytes encode themselves.

5.2.2. Integers

All integers are encoded using the LEB128 variable-length integer encoding, in either unsigned or signed variant.

Unsigned integers are encoded in unsigned LEB128 format. As an additional constraint, the total number of bytes encoding a value of type

Signed integers are encoded in signed LEB128 format, which uses a two’s complement representation. As an additional constraint, the total number of bytes encoding a value of type

Uninterpreted integers are encoded as signed integers.

Note

The side conditions

The side conditions on the value

5.2.3. Floating-Point

Floating-point values are encoded directly by their [IEEE-754-2019] (Section 3.4) bit pattern in little endian byte order:

5.2.4. Names

Names are encoded as a vector of bytes containing the [UNICODE] (Section 3.9) UTF-8 encoding of the name’s character sequence.

The auxiliary

Note

Unlike in some other formats, name strings are not 0-terminated.

5.3. Types

5.3.1. Value Types

Value types are encoded by a single byte.

Note

In future versions of WebAssembly, value types may include types denoted by type indices. Thus, the binary format for types corresponds to the signed LEB128 encoding of small negative

5.3.2. Result Types

The only result types occurring in the binary format are the types of blocks. These are encoded in special compressed form, by either the byte

Note

In future versions of WebAssembly, this scheme may be extended to support multiple results or more general block types.

5.3.3. Function Types

Function types are encoded by the byte

5.3.4. Limits

Limits are encoded with a preceding flag indicating whether a maximum is present.

5.3.5. Memory Types

Memory types are encoded with their limits.

5.3.6. Table Types

Table types are encoded with their limits and a constant byte indicating their element type.

5.3.7. Global Types

Global types are encoded by their value type and a flag for their mutability.

5.4. Instructions

Instructions are encoded by opcodes. Each opcode is represented by a single byte, and is followed by the instruction’s immediate arguments, where present. The only exception are structured control instructions, which consist of several opcodes bracketing their nested instruction sequences.

Note

Gaps in the byte code ranges for encoding instructions are reserved for future extensions.

5.4.1. Control Instructions

Control instructions have varying encodings. For structured instructions, the instruction sequences forming nested blocks are terminated with explicit opcodes for

Note

The

Note

In future versions of WebAssembly, the zero byte occurring in the encoding of the

5.4.2. Parametric Instructions

Parametric instructions are represented by single byte codes.

5.4.3. Variable Instructions

Variable instructions are represented by byte codes followed by the encoding of the respective index.

5.4.4. Memory Instructions

Each variant of memory instruction is encoded with a different byte code. Loads and stores are followed by the encoding of their

Note

In future versions of WebAssembly, the additional zero bytes occurring in the encoding of the

5.4.5. Numeric Instructions

All variants of numeric instructions are represented by separate byte codes.

The

All other numeric instructions are plain opcodes without any immediates.

5.4.6. Expressions

Expressions are encoded by their instruction sequence terminated with an explicit

5.5. Modules

The binary encoding of modules is organized into sections. Most sections correspond to one component of a module record, except that function definitions are split into two sections, separating their type declarations in the function section from their bodies in the code section.

Note

This separation enables parallel and streaming compilation of the functions in a module.

5.5.1. Indices

All indices are encoded with their respective value.

5.5.2. Sections

Each section consists of

  • a one-byte section id,
  • the
  • the actual contents, whose structure is depended on the section id.

Every section is optional; an omitted section is equivalent to the section being present with empty contents.

The following parameterized grammar rule defines the generic structure of a section with id

For most sections, the contents

Note

Other than for unknown custom sections, the

The following section ids are used:

Id Section
0 custom section
1 type section
2 import section
3 function section
4 table section
5 memory section
6 global section
7 export section
8 start section
9 element section
10 code section
11 data section

5.5.3. Custom Section

Custom sections have the id 0. They are intended to be used for debugging information or third-party extensions, and are ignored by the WebAssembly semantics. Their contents consist of a name further identifying the custom section, followed by an uninterpreted sequence of bytes for custom use.

Note

If an implementation interprets the contents of a custom section, then errors in that contents, or the placement of the section, must not invalidate the module.

5.5.4. Type Section

The type section has the id 1. It decodes into a vector of function types that represent the

5.5.5. Import Section

The import section has the id 2. It decodes into a vector of imports that represent the

5.5.6. Function Section

The function section has the id 3. It decodes into a vector of type indices that represent the

5.5.7. Table Section

The table section has the id 4. It decodes into a vector of tables that represent the

5.5.8. Memory Section

The memory section has the id 5. It decodes into a vector of memories that represent the

5.5.9. Global Section

The global section has the id 6. It decodes into a vector of globals that represent the

5.5.10. Export Section

The export section has the id 7. It decodes into a vector of exports that represent the

5.5.11. Start Section

The start section has the id 8. It decodes into an optional start function that represents the

5.5.12. Element Section

The element section has the id 9. It decodes into a vector of element segments that represent the

5.5.13. Code Section

The code section has the id 10. It decodes into a vector of code entries that are pairs of value type vectors and expressions. They represent the

The encoding of each code entry consists of

  • the
  • the actual function code, which in turn consists of
    • the declaration of locals,
    • the function body as an expression.

Local declarations are compressed into a vector whose entries consist of

denoting count locals of the same value type.

Here,

Note

Like with sections, the code

5.5.14. Data Section

The data section has the id 11. It decodes into a vector of data segments that represent the

5.5.15. Modules

The encoding of a module starts with a preamble containing a 4-byte magic number (the string

The preamble is followed by a sequence of sections. Custom sections may be inserted at any place in this sequence, while other sections must occur at most once and in the prescribed order. All sections can be empty.

The lengths of vectors produced by the (possibly empty) function and code section must match up.

where for each

Note

The version of the WebAssembly binary format may increase in the future if backward-incompatible changes have to be made to the format. However, such changes are expected to occur very infrequently, if ever. The binary format is intended to be forward-compatible, such that future extensions can be made without incrementing its version.

6. Text Format

6.1. Conventions

The textual format for WebAssembly modules is a rendering of their abstract syntax into S-expressions.

Like the binary format, the text format is defined by an attribute grammar. A text string is a well-formed description of a module if and only if it is generated by the grammar. Each production of this grammar has at most one synthesized attribute: the abstract syntax that the respective character sequence expresses. Thus, the attribute grammar implicitly defines a parsing function. Some productions also take a context as an inherited attribute that records bound identifers.

Except for a few exceptions, the core of the text grammar closely mirrors the grammar of the abstract syntax. However, it also defines a number of abbreviations that are “syntactic sugar” over the core syntax.

The recommended extension for files containing WebAssembly modules in text format is “

6.1.1. Grammar

The following conventions are adopted in defining grammar rules of the text format. They mirror the conventions used for abstract syntax and for the binary format. In order to distinguish symbols of the textual syntax from symbols of the abstract syntax,

  • Terminal symbols are either literal strings of characters enclosed in quotes or expressed as [UNICODE] scalar values:
  • Nonterminal symbols are written in typewriter font:
  • Productions are written
  • Some productions are augmented by side conditions in parentheses, which restrict the applicability of the production. They provide a shorthand for a combinatorial expansion of the production into many separate cases.
  • A distinction is made between lexical and syntactic productions. For the latter, arbitrary white space is allowed in any place where the grammar contains spaces. The productions defining lexical syntax and the syntax of values are considered lexical, all others are syntactic.

Note

For example, the textual grammar for value types is given as follows:

The textual grammar for limits is defined as follows:

The variables

6.1.2. Abbreviations

In addition to the core grammar, which corresponds directly to the abstract syntax, the textual syntax also defines a number of abbreviations that can be used for convenience and readability.

Abbreviations are defined by rewrite rules specifying their expansion into the core syntax:

These expansions are assumed to be applied, recursively and in order of appearance, before applying the core grammar rules to construct the abstract syntax.

6.1.3. Contexts

The text format allows the use of symbolic identifiers in place of indices. To resolve these identifiers into concrete indices, some grammar production are indexed by an identifier context

It is convenient to define identifier contexts as records

For each index space, such a context contains the list of identifiers assigned to the defined indices. Unnamed indices are associated with empty (

An identifier context is well-formed if no index space contains duplicate identifiers.

6.1.3.1. Conventions

To avoid unnecessary clutter, empty components are omitted when writing out identifier contexts. For example, the record

6.1.4. Vectors

Vectors are written as plain sequences, but with a restriction on the length of these sequence.

6.2. Lexical Format

6.2.1. Characters

The text format assigns meaning to source text, which consists of a sequence of characters. Characters are assumed to be represented as valid [UNICODE] (Section 2.4) scalar values.

Note

While source text may contain any Unicode character in comments or string literals, the rest of the grammar is formed exclusively from the characters supported by the 7-bit ASCII subset of Unicode.

6.2.2. Tokens

The character stream in the source text is divided, from left to right, into a sequence of tokens, as defined by the following grammar.

Tokens are formed from the input character stream according to the longest match rule. That is, the next token always consists of the longest possible sequence of characters that is recognized by the above lexical grammar. Tokens can be separated by white space, but except for strings, they cannot themselves contain whitespace.

The set of keyword tokens is defined implicitly, by all occurrences of a terminal symbol in literal form, such as

Any token that does not fall into any of the other categories is considered reserved, and cannot occur in source text.

Note

The effect of defining the set of reserved tokens is that all tokens must be separated by either parentheses or white space. For example,

6.2.3. White Space

White space is any sequence of literal space characters, formatting characters, or comments. The allowed formatting characters correspond to a subset of the ASCII format effectors, namely, horizontal tabulation (

The only relevance of white space is to separate tokens. It is otherwise ignored.

6.2.4. Comments

A comment can either be a line comment, started with a double semicolon

Here, the pseudo token

Note

Any formatting and control characters are allowed inside comments.

6.3. Values

The grammar productions in this section define lexical syntax, hence no white space is allowed.

6.3.1. Integers

All integers can be written in either decimal or hexadecimal notation. In both cases, digits can optionally be separated by underscores.

The allowed syntax for integer literals depends on size and signedness. Moreover, their value must lie within the range of the respective type.

Uninterpreted integers can be written as either signed or unsigned, and are normalized to unsigned in the abstract syntax.

6.3.2. Floating-Point

Floating-point values can be represented in either decimal or hexadecimal notation.

The value of a literal must not lie outside the representable range of the corresponding [IEEE-754-2019] type (that is, a numeric value must not overflow to

Note

Rounding can be prevented by using hexadecimal notation with no more significant bits than supported by the required type.

Floating-point values may also be written as constants for infinity or canonical NaN (not a number). Furthermore, arbitrary NaN values may be expressed by providing an explicit payload value.

6.3.3. Strings

Strings denote sequences of bytes that can represent both textual and binary data. They are enclosed in quotation marks and may contain any character other than ASCII control characters, quotation marks (

Each character in a string literal represents the byte sequence corresponding to its UTF-8 [UNICODE] (Section 2.5) encoding, except for hexadecimal escape sequences

6.3.4. Names

Names are strings denoting a literal character sequence. A name string must form a valid UTF-8 encoding as defined by [UNICODE] (Section 2.5) and is interpreted as a string of Unicode scalar values.

Note

Presuming the source text is itself encoded correctly, strings that do not contain any uses of hexadecimal byte escapes are always valid names.

6.3.5. Identifiers

Indices can be given in both numeric and symbolic form. Symbolic identifiers that stand in lieu of indices start with

6.3.5.1. Conventions

The expansion rules of some abbreviations require insertion of a fresh identifier. That may be any syntactically valid identifier that does not already occur in the given source text.

6.4. Types

6.4.1. Value Types

6.4.2. Result Types

Note

In future versions of WebAssembly, this scheme may be extended to support multiple results or more general result types.

6.4.3. Function Types

6.4.3.1. Abbreviations

Multiple anonymous parameters or results may be combined into a single declaration:

6.4.4. Limits

6.4.5. Memory Types

6.4.6. Table Types

Note

Additional element types may be introduced in future versions of WebAssembly.

6.4.7. Global Types

6.5. Instructions

Instructions are syntactically distinguished into plain and structured instructions.

In addition, as a syntactic abbreviation, instructions can be written as S-expressions in folded form, to group them visually.

6.5.1. Labels

Structured control instructions can be annotated with a symbolic label identifier. They are the only symbolic identifiers that can be bound locally in an instruction sequence. The following grammar handles the corresponding update to the identifier context by composing the context with an additional label entry.

Note

The new label entry is inserted at the beginning of the label list in the identifier context. This effectively shifts all existing labels up by one, mirroring the fact that control instructions are indexed relatively not absolutely.

6.5.2. Control Instructions

Structured control instructions can bind an optional symbolic label identifier. The same label identifier may optionally be repeated after the corresponding

All other control instruction are represented verbatim.

Note

The side condition stating that the identifier context

6.5.2.1. Abbreviations

The

6.5.3. Parametric Instructions

6.5.4. Variable Instructions

6.5.5. Memory Instructions

The offset and alignment immediates to memory instructions are optional. The offset defaults to

6.5.6. Numeric Instructions

6.5.7. Folded Instructions

Instructions can be written as S-expressions by grouping them into folded form. In that notation, an instruction is wrapped in parentheses and optionally includes nested folded instructions to indicate its operands.

In the case of block instructions, the folded form omits the

The set of all phrases defined by the following abbreviations recursively forms the auxiliary syntactic class

Note

For example, the instruction sequence

can be folded into

Folded instructions are solely syntactic sugar, no additional syntactic or type-based checking is implied.

6.5.8. Expressions

Expressions are written as instruction sequences. No explicit

6.6. Modules

6.6.1. Indices

Indices can be given either in raw numeric form or as symbolic identifiers when bound by a respective construct. Such identifiers are looked up in the suitable space of the identifier context

6.6.2. Types

Type definitions can bind a symbolic type identifier.

6.6.3. Type Uses

A type use is a reference to a type definition. It may optionally be augmented by explicit inlined parameter and result declarations. That allows binding symbolic identifiers to name the local indices of parameters. If inline declarations are given, then their types must match the referenced function type.

The synthesized attribute of a

Note

Both productions overlap for the case that the function type is

The well-formedness condition on

6.6.3.1. Abbreviations

A

where

is inserted at the end of the module.

Abbreviations are expanded in the order they appear, such that previously inserted type definitions are reused by consecutive expansions.

6.6.4. Imports

The descriptors in imports can bind a symbolic function, table, memory, or global identifier.

6.6.4.1. Abbreviations

As an abbreviation, imports may also be specified inline with function, table, memory, or global definitions; see the respective sections.

6.6.5. Functions

Function definitions can bind a symbolic function identifier, and local identifiers for its parameters and locals.

The definition of the local identifier context

Note

The well-formedness condition on

6.6.5.1. Abbreviations

Multiple anonymous locals may be combined into a single declaration:

Functions can be defined as imports or exports inline:

The latter abbreviation can be applied repeatedly, with “

6.6.6. Tables

Table definitions can bind a symbolic table identifier.

6.6.6.1. Abbreviations

An element segment can be given inline with a table definition, in which case its offset is

Tables can be defined as imports or exports inline:

The latter abbreviation can be applied repeatedly, with “

6.6.7. Memories

Memory definitions can bind a symbolic memory identifier.

6.6.7.1. Abbreviations

A data segment can be given inline with a memory definition, in which case its offset is

Memories can be defined as imports or exports inline:

The latter abbreviation can be applied repeatedly, with “

6.6.8. Globals

Global definitions can bind a symbolic global identifier.

6.6.8.1. Abbreviations

Globals can be defined as imports or exports inline:

The latter abbreviation can be applied repeatedly, with “

6.6.9. Exports

The syntax for exports mirrors their abstract syntax directly.

6.6.9.1. Abbreviations

As an abbreviation, exports may also be specified inline with function, table, memory, or global definitions; see the respective sections.

6.6.10. Start Function

A start function is defined in terms of its index.

Note

At most one start function may occur in a module, which is ensured by a suitable side condition on the

6.6.11. Element Segments

Element segments allow for an optional table index to identify the table to initialize.

Note

In the current version of WebAssembly, the only valid table index is 0 or a symbolic table identifier resolving to the same value.

6.6.11.1. Abbreviations

As an abbreviation, a single instruction may occur in place of the offset:

Also, the table index can be omitted, defaulting to

As another abbreviation, element segments may also be specified inline with table definitions; see the respective section.

6.6.12. Data Segments

Data segments allow for an optional memory index to identify the memory to initialize. The data is written as a string, which may be split up into a possibly empty sequence of individual string literals.

Note

In the current version of WebAssembly, the only valid memory index is 0 or a symbolic memory identifier resolving to the same value.

6.6.12.1. Abbreviations

As an abbreviation, a single instruction may occur in place of the offset:

Also, the memory index can be omitted, defaulting to

As another abbreviation, data segments may also be specified inline with memory definitions; see the respective section.

6.6.13. Modules

A module consists of a sequence of fields that can occur in any order. All definitions and their respective bound identifiers scope over the entire module, including the text preceding them.

A module may optionally bind an identifier that names the module. The name serves a documentary role only.

Note

Tools may include the module name in the name section of the binary format.

The following restrictions are imposed on the composition of modules:

Note

The first condition ensures that there is at most one start function. The second condition enforces that all imports must occur before any regular definition of a function, table, memory, or global, thereby maintaining the ordering of the respective index spaces.

The well-formedness condition on

The definition of the initial identifier context

6.6.13.1. Abbreviations

In a source file, the toplevel

A Appendix

A.1 Embedding

A WebAssembly implementation will typically be embedded into a host environment. An embedder implements the connection between such a host environment and the WebAssembly semantics as defined in the main body of this specification. An embedder is expected to interact with the semantics in well-defined ways.

This section defines a suitable interface to the WebAssembly semantics in the form of entry points through which an embedder can access it. The interface is intended to be complete, in the sense that an embedder does not need to reference other functional parts of the WebAssembly specification directly.

Note

On the other hand, an embedder does not need to provide the host environment with access to all functionality defined in this interface. For example, an implementation may not support parsing of the text format.

Types

In the description of the embedder interface, syntactic classes from the abstract syntax and the runtime’s abstract machine are used as names for variables that range over the possible objects from that class. Hence, these syntactic classes can also be interpreted as types.

For numeric parameters, notation like

Errors

Failure of an interface operation is indicated by an auxiliary syntactic class:

In addition to the error conditions specified explicitly in this section, implementations may also return errors when specific implementation limitations are reached.

Note

Errors are abstract and unspecific with this definition. Implementations can refine it to carry suitable classifications and diagnostic messages.

Pre- and Post-Conditions

Some operations state pre-conditions about their arguments or post-conditions about their results. It is the embedder’s responsibility to meet the pre-conditions. If it does, the post conditions are guaranteed by the semantics.

In addition to pre- and post-conditions explicitly stated with each operation, the specification adopts the following conventions for runtime objects (

  • Every runtime object passed as a parameter must be valid per an implicit pre-condition.
  • Every runtime object returned as a result is valid per an implicit post-condition.

Note

As long as an embedder treats runtime objects as abstract and only creates and manipulates them through the interface defined here, all implicit pre-conditions are automatically met.

Store

  1. Return the empty store.

Modules

  1. If there exists a derivation for the byte sequence
  2. Else, return
  1. If there exists a derivation for the source
  2. Else, return
  1. If
  2. Else, return
  1. Try instantiating
  1. If it succeeds with a module instance
  2. Else, let
  1. Return the new store paired with

Note

The store may be modified even in case of an error.

  1. Pre-condition:
  2. Let
  3. Assert: the length of
  4. For each
  1. Let
  1. Return the concatenation of all
  2. Post-condition: each
  1. Pre-condition:
  2. Let
  3. Assert: the length of
  4. For each
  1. Let
  1. Return the concatenation of all
  2. Post-condition: each

Module Instances

  1. Assert: due to validity of the module instance
  2. If there exists an
  3. Else, return

Functions

  1. Pre-condition:
  2. Let
  3. Return the new store paired with

Note

This operation assumes that

Regular (non-host) function instances can only be created indirectly through module instantiation.

  1. Assert: the external value
  2. Return
  3. Post-condition:
  1. Try invoking the function
  1. If it succeeds with values
  2. Else it has trapped, hence let
  1. Return the new store paired with

Note

The store may be modified even in case of an error.

Tables

  1. Pre-condition:
  2. Let
  3. Return the new store paired with
  1. Assert: the external value
  2. Return
  3. Post-condition:
  1. Let
  2. If
  3. Else, return
  1. Let
  2. If
  3. Replace
  4. Return the updated store.
  1. Return the length of
  1. Try growing the table instance

Memories

  1. Pre-condition:
  2. Let
  3. Return the new store paired with
  1. Assert: the external value
  2. Return
  3. Post-condition:
  1. Let
  2. If
  3. Else, return the byte
  1. Let
  2. If
  3. Replace
  4. Return the updated store.
  1. Return the length of
  1. Try growing the memory instance

Globals

  1. Pre-condition:
  2. Let
  3. Return the new store paired with
  1. Assert: the external value
  2. Return
  3. Post-condition:
  1. Let
  2. Return the value
  1. Let
  2. If
  3. Replace
  4. Return the updated store.

A.2 Implementation Limitations

Implementations typically impose additional restrictions on a number of aspects of a WebAssembly module or execution. These may stem from:

  • physical resource limits,
  • constraints imposed by the embedder or its environment,
  • limitations of selected implementation strategies.

This section lists allowed limitations. Where restrictions take the form of numeric limits, no minimum requirements are given, nor are the limits assumed to be concrete, fixed numbers. However, it is expected that all implementations have “reasonably” large limits to enable common applications.

Note

A conforming implementation is not allowed to leave out individual features. However, designated subsets of WebAssembly may be specified in the future.

Syntactic Limits

Structure

An implementation may impose restrictions on the following dimensions of a module:

If the limits of an implementation are exceeded for a given module, then the implementation may reject the validation, compilation, or instantiation of that module with an embedder-specific error.

Note

The last item allows embedders that operate in limited environments without support for [UNICODE] to limit the names of imports and exports to common subsets like ASCII.

Binary Format

For a module given in binary format, additional limitations may be imposed on the following dimensions:

Text Format

For a module given in text format, additional limitations may be imposed on the following dimensions:

Validation

An implementation may defer validation of individual functions until they are first invoked.

If a function turns out to be invalid, then the invocation, and every consecutive call to the same function, results in a trap.

Note

This is to allow implementations to use interpretation or just-in-time compilation for functions. The function must still be fully validated before execution of its body begins.

Execution

Restrictions on the following dimensions may be imposed during execution of a WebAssembly program:

If the runtime limits of an implementation are exceeded during execution of a computation, then it may terminate that computation and report an embedder-specific error to the invoking code.

Some of the above limits may already be verified during instantiation, in which case an implementation may report exceedance in the same manner as for syntactic limits.

Note

Concrete limits are usually not fixed but may be dependent on specifics, interdependent, vary over time, or depend on other implementation- or embedder-specific situations or events.

A.3 Validation Algorithm

The specification of WebAssembly validation is purely declarative. It describes the constraints that must be met by a module or instruction sequence to be valid.

This section sketches the skeleton of a sound and complete algorithm for effectively validating code, i.e., sequences of instructions. (Other aspects of validation are straightforward to implement.)

In fact, the algorithm is expressed over the flat sequence of opcodes as occurring in the binary format, and performs only a single pass over it. Consequently, it can be integrated directly into a decoder.

The algorithm is expressed in typed pseudo code whose semantics is intended to be self-explanatory.

Data Structures

The algorithm uses two separate stacks: the operand stack and the control stack. The former tracks the types of operand values on the stack, the latter surrounding structured control instructions and their associated blocks.

type val_type = I32 | I64 | F32 | F64

type opd_stack = stack(val_type | Unknown)

type ctrl_stack = stack(ctrl_frame)
type ctrl_frame = {
  label_types : list(val_type)
  end_types : list(val_type)
  height : nat
  unreachable : bool
}

For each value, the operand stack records its value type, or Unknown when the type is not known.

For each entered block, the control stack records a control frame with the type of the associated 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 stack-polymorphic typing after branches).

Note

In the presentation of this algorithm, multiple values are supported for the result types classifying blocks and labels. With the current version of WebAssembly, the list could be simplified to an optional value.

For the purpose of presenting the algorithm, the operand and control stacks are simply maintained as global variables:

var opds : opd_stack
var ctrls : ctrl_stack

However, these variables are not manipulated directly by the main checking function, but through a set of auxiliary functions:

func push_opd(type : val_type | Unknown) =
  opds.push(type)

func pop_opd() : val_type | Unknown =
  if (opds.size() = ctrls[0].height && ctrls[0].unreachable) return Unknown
  error_if(opds.size() = ctrls[0].height)
  return opds.pop()

func pop_opd(expect : val_type | Unknown) : val_type | Unknown =
  let actual = pop_opd()
  if (actual = Unknown) return expect
  if (expect = Unknown) return actual
  error_if(actual =/= expect)
  return actual

func push_opds(types : list(val_type)) = foreach (t in types) push_opd(t)
func pop_opds(types : list(val_type)) = foreach (t in reverse(types)) pop_opd(t)

Pushing an operand simply pushes the respective type to the operand stack.

Popping an operand checks that the operand 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 operands, but has been marked as unreachable. That can occur after an unconditional branch, when the stack is typed polymorphically. In that case, an unknown type is returned.

A second function for popping an operand takes an expected type, which the actual operand type is checked against. The types may differ in case one of them is Unknown. The more specific type is returned.

Finally, there are accumulative functions for pushing or popping multiple operand types.

Note

The notation stack[i] is meant to index the stack from the top, so that ctrls[0] accesses the element pushed last.

The control stack is likewise manipulated through auxiliary functions:

func push_ctrl(label : list(val_type), out : list(val_type)) =
  let frame = ctrl_frame(label, out, opds.size(), false)
  ctrls.push(frame)

func pop_ctrl() : list(val_type) =
  error_if(ctrls.is_empty())
  let frame = ctrls[0]
  pop_opds(frame.end_types)
  error_if(opds.size() =/= frame.height)
  ctrls.pop()
  return frame.end_types

func unreachable() =
  opds.resize(ctrls[0].height)
  ctrls[0].unreachable := true

Pushing a control frame takes the types of the label and result values. It allocates a new frame record recording them along with the current height of the operand stack and marks the block as reachable.

Popping a frame first checks that the control stack is not empty. It then verifies that the operand stack contains the right types of values expected at the end of the exited block and pops them off the operand stack. Afterwards, it checks that the stack has shrunk back to its initial height.

Finally, the current frame can be marked as unreachable. In that case, all existing operand types are purged from the operand stack, in order to allow for the stack-polymorphism logic in pop_opd to take effect.

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 examples like

Validation of Opcode Sequences

The following function shows the validation of a number of representative instructions that manipulate the stack. Other instructions are checked in a similar manner.

Note

Various instructions not shown here will additionally require the presence of a validation context for checking uses of indices. That is an easy addition and therefore omitted from this presentation.

func validate(opcode) =
  switch (opcode)
    case (i32.add)
      pop_opd(I32)
      pop_opd(I32)
      push_opd(I32)

   case (drop)
      pop_opd()

   case (select)
      pop_opd(I32)
      let t1 = pop_opd()
      let t2 = pop_opd(t1)
      push_opd(t2)

   case (unreachable)
      unreachable()

   case (block t*)
      push_ctrl([t*], [t*])

   case (loop t*)
      push_ctrl([], [t*])

   case (if t*)
      pop_opd(I32)
      push_ctrl([t*], [t*])

   case (end)
      let results = pop_ctrl()
      push_opds(results)

   case (else)
      let results = pop_ctrl()
      push_ctrl(results, results)

   case (br n)
      error_if(ctrls.size() < n)
      pop_opds(ctrls[n].label_types)
      unreachable()

   case (br_if n)
      error_if(ctrls.size() < n)
      pop_opd(I32)
      pop_opds(ctrls[n].label_types)
      push_opds(ctrls[n].label_types)

   case (br_table n* m)
      error_if(ctrls.size() < m)
      foreach (n in n*)
        error_if(ctrls.size() < n || ctrls[n].label_types =/= ctrls[m].label_types)
      pop_opd(I32)
      pop_opds(ctrls[m].label_types)
      unreachable()

Note

It is an invariant under the current WebAssembly instruction set that an operand of Unknown type is never duplicated on the stack. This would change if the language were extended with stack operators like dup. Under such an extension, the above algorithm would need to be refined by replacing the Unknown type with proper type variables to ensure that all uses are consistent.

A.4 Custom Sections

This appendix defines dedicated custom sections for WebAssembly’s binary format. Such sections do not contribute to, or otherwise affect, the WebAssembly semantics, and like any custom section they may be ignored by an implementation. However, they provide useful meta data that implementations can make use of to improve user experience or take compilation hints.

Currently, only one dedicated custom section is defined, the name section.

Name Section

The name section is a custom section whose name string is itself

The purpose of this section is to attach printable names to definitions in a module, which e.g. can be used by a debugger or when parts of the module are to be rendered in text form.

Note

All names are represented in [UNICODE] encoded in UTF-8. Names need not be unique.

Subsections

The data of a name section consists of a sequence of subsections. Each subsection consists of a

  • a one-byte subsection id,
  • the
  • the actual contents, whose structure is depended on the subsection id.

The following subsection ids are used:

Id Subsection
0 module name
1 function names
2 local names

Each subsection may occur at most once, and in order of increasing id.

Name Maps

A name map assigns names to indices in a given index space. It consists of a vector of index/name pairs in order of increasing index value. Each index must be unique, but the assigned names need not be.

An indirect name map assigns names to a two-dimensional index space, where secondary indices are grouped by primary indices. It consists of a vector of primary index/name map pairs in order of increasing index value, where each name map in turn maps secondary indices to names. Each primary index must be unique, and likewise each secondary index per individual name map.

Module Names

The module name subsection has the id 0. It simply consists of a single name that is assigned to the module itself.

Function Names

The function name subsection has the id 1. It consists of a name map assigning function names to function indices.

Local Names

The local name subsection has the id 2. It consists of an indirect name map assigning local names to local indices grouped by function indices.

A.5 Soundness

The type system of WebAssembly is sound, implying both type safety and memory safety with respect to the WebAssembly semantics. For example:

  • All types declared and derived during validation are respected at run time; e.g., every local or global variable will only contain type-correct values, every instruction will only be applied to operands of the expected type, and every function invocation always evaluates to a result of the right type (if it does not trap or diverge).
  • No memory location will be read or written except those explicitly defined by the program, i.e., as a local, a global, an element in a table, or a location within a linear memory.
  • There is no undefined behavior, i.e., the execution rules cover all possible cases that can occur in a valid program, and the rules are mutually consistent.

Soundness also is instrumental in ensuring additional properties, most notably, encapsulation of function and module scopes: no locals can be accessed outside their own function and no module components can be accessed outside their own module unless they are explicitly exported or imported.

The typing rules defining WebAssembly validation only cover the static components of a WebAssembly program. In order to state and prove soundness precisely, the typing rules must be extended to the dynamic components of the abstract runtime, that is, the store, configurations, and administrative instructions. [1]

Values and Results

Values and results can be classified by value types and result types as follows.

Values
Results
Results

Store Validity

The following typing rules specify when a runtime store

To that end, each kind of instance is classified by a respective function, table, memory, or global type. Module instances are classified by module contexts, which are regular contexts repurposed as module types describing the index spaces defined by a module.

Store
Host Function Instances

Note

This rule states that, if appropriate pre-conditions about store and arguments are satisfied, then executing the host function must satisfy appropriate post-conditions about store and results. The post-conditions match the ones in the execution rule for invoking host functions.

Any store under which the function is invoked is assumed to be an extension of the current store. That way, the function itself is able to make sufficient assumptions about future stores.

Table Instances
Memory Instances
Global Instances
Module Instances

Configuration Validity

To relate the WebAssembly type system to its execution semantics, the typing rules for instructions must be extended to configurations

Configurations and threads are classified by their result type. In addition to the store

Finally, frames are classified with frame contexts, which extend the module contexts of a frame’s associated module instance with the locals that the frame contains.

Configurations
Threads
Frames

Administrative Instructions

Typing rules for administrative instructions are specified as follows. In addition to the context

  • The instruction is valid with type
  • The instruction sequence
  • Let
  • Under context
  • Then the compound instruction is valid with type

Store Extension

Programs can mutate the store and its contained instances. Any such modification must respect certain invariants, such as not removing allocated instances or changing immutable definitions. While these invariants are inherent to the execution semantics of WebAssembly instructions and modules, host functions do not automatically adhere to them. Consequently, the required invariants must be stated as explicit constraints on the invocation of host functions. Soundness only holds when the embedder ensures these constraints.

The necessary constraints are codified by the notion of store extension: a store state

Note

Extension does not imply that the new store is valid, which is defined separately above.

Store
Function Instance
  • A function instance must remain unchanged.
Table Instance
Memory Instance
Global Instance

Theorems

Given the definition of valid configurations, the standard soundness theorems hold. [2]

Theorem (Preservation). If a configuration

A terminal thread is one whose sequence of instructions is a result. A terminal configuration is a configuration whose thread is terminal.

Theorem (Progress). If a configuration

From Preservation and Progress the soundness of the WebAssembly type system follows directly.

Corollary (Soundness). If a configuration

In other words, every thread in a valid configuration either runs forever, traps, or terminates with a result that has the expected type. Consequently, given a valid store, no computation defined by instantiation or invocation of a valid module can “crash” or otherwise (mis)behave in ways not covered by the execution semantics given in this specification.

[1] The formalization and theorems are derived from the following article: Andreas Haas, Andreas Rossberg, Derek Schuff, Ben Titzer, Dan Gohman, Luke Wagner, Alon Zakai, JF Bastien, Michael Holman. Bringing the Web up to Speed with WebAssembly. Proceedings of the 38th ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI 2017). ACM 2017.
[2] A machine-verified version of the formalization and soundness proof is described in the following article: Conrad Watt. Mechanising and Verifying the WebAssembly Specification. Proceedings of the 7th ACM SIGPLAN Conference on Certified Programs and Proofs (CPP 2018). ACM 2018.

A.6 Index of Types

Category Constructor Binary Opcode
Type index (positive number as
Value type
Value type
Value type
Value type
(reserved)
Element type
(reserved)
Function type
(reserved)
Result type
Table type (none)
Memory type (none)
Global type (none)

A.7 Index of Instructions

Instruction Binary Opcode Type Validation Execution
validation execution
validation execution
validation execution
validation execution
validation execution
(reserved)
(reserved)
(reserved)
(reserved)
(reserved)
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
(reserved)
(reserved)
(reserved)
(reserved)
(reserved)
(reserved)
(reserved)
(reserved)
validation execution
validation execution
(reserved)
(reserved)
(reserved)
(reserved)
validation execution
validation execution
validation execution
validation execution
validation execution
(reserved)
(reserved)
(reserved)
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator
validation execution, operator

A.8 Index of Semantic Rules

Import Matching

Construct Judgement
Limits
External type

Execution

Construct Judgement
Instruction
Expression