约定

WebAssembly 的二进制格式 模块 是它们 抽象语法 的密集线性编码[1]

该格式由属性语法定义,该语法的唯一终结符是 字节。字节序列是模块的良好编码,当且仅当它是通过语法生成的。

此语法的每个产生式恰好有一个综合属性:相应的字节序列编码的抽象语法。因此,属性语法隐式地定义了一个解码函数(即二进制格式的解析函数)。

除了少数例外,二进制语法与抽象语法的语法非常相似。

注意

抽象语法的某些短语在二进制格式中可能有多种可能的编码。例如,数字可以像具有可选前导零一样进行编码。解码器的实现必须支持所有可能的替代方案;编码器的实现可以选择任何允许的编码。

包含二进制格式的 WebAssembly 模块的文件的推荐扩展名为“\(\mathtt{.wasm}\)”,推荐的 媒体类型 为“\(\mathtt{application/wasm}\)”。

语法

在定义二进制格式的语法规则时,采用以下约定。它们反映了用于 抽象语法 的约定。为了区分二进制语法的符号和抽象语法的符号,对前者采用\(\mathtt{typewriter}\)字体。

  • 终结符是 字节,以十六进制表示:\(\def\mathdef1315#1{\mathtt{0x#1}}\mathdef1315{0F}\)

  • 非终结符以打字机字体书写:\(\mathtt{valtype}, \mathtt{instr}\)

  • \(B^n\)\(n\geq 0\)\(B\) 的序列。

  • \(B^\ast\) 是可能为空的 \(B\) 的序列。(这是在 \(n\) 不相关的情况下使用的 \(B^n\) 的简写。)

  • \(B^?\)\(B\) 的可选出现。(这是 \(B^n\) 的简写,其中 \(n \leq 1\)。)

  • \(x{:}B\) 表示与非终结符 \(B\) 相同的语言,但也将变量 \(x\) 绑定到为 \(B\) 合成的属性。模式也可以用作变量,例如,\(7{:}B\)

  • 产生式写成 \(\mathtt{sym} ::= B_1 \Rightarrow A_1 ~|~ \dots ~|~ B_n \Rightarrow A_n\),其中每个 \(A_i\) 是在给定情况下为 \(\mathtt{sym}\) 合成的属性,通常来自 \(B_i\) 中绑定的属性变量。

  • 一些产生式通过括号中的边条件进行增强,这些条件限制了产生式的适用性。它们为将产生式组合扩展为许多单独的情况提供了一种简写。

  • 如果相同的元变量或非终结符在产生式中出现多次(在语法中或在属性中),则所有这些出现必须具有相同的实例化。(这是对需要多个不同变量相等的边条件的简写。)

注意

例如,二进制语法 用于 数字类型 如下所示

\[\begin{split}\begin{array}{llcll@{\qquad\qquad}l} \def\mathdef1276#1{{}}\mathdef1276{数字类型} & \href{../binary/types.html#binary-numtype}{\mathtt{numtype}} &::=& \def\mathdef1316#1{\mathtt{0x#1}}\mathdef1316{7F} &\Rightarrow& \href{../syntax/types.html#syntax-valtype}{\mathsf{i32}} \\ &&|& \def\mathdef1317#1{\mathtt{0x#1}}\mathdef1317{7E} &\Rightarrow& \href{../syntax/types.html#syntax-valtype}{\mathsf{i64}} \\ &&|& \def\mathdef1318#1{\mathtt{0x#1}}\mathdef1318{7D} &\Rightarrow& \href{../syntax/types.html#syntax-valtype}{\mathsf{f32}} \\ &&|& \def\mathdef1319#1{\mathtt{0x#1}}\mathdef1319{7C} &\Rightarrow& \href{../syntax/types.html#syntax-valtype}{\mathsf{f64}} \\ \end{array}\end{split}\]

因此,字节 \(\def\mathdef1320#1{\mathtt{0x#1}}\mathdef1320{7F}\) 编码类型 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{i32}}\)\(\def\mathdef1321#1{\mathtt{0x#1}}\mathdef1321{7E}\) 编码类型 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{i64}}\),依此类推。没有其他字节值可以作为数字类型的编码。

用于 限制二进制语法 定义如下

\[\begin{split}\begin{array}{llclll} \def\mathdef1276#1{{}}\mathdef1276{限制} & \href{../binary/types.html#binary-limits}{\mathtt{limits}} &::=& \def\mathdef1322#1{\mathtt{0x#1}}\mathdef1322{00}~~n{:}\href{../binary/values.html#binary-int}{\def\mathdef1281#1{{\mathtt{u}#1}}\mathdef1281{\mathtt{32}}} &\Rightarrow& \{ \href{../syntax/types.html#syntax-limits}{\mathsf{min}}~n, \href{../syntax/types.html#syntax-limits}{\mathsf{max}}~\epsilon \} \\ &&|& \def\mathdef1323#1{\mathtt{0x#1}}\mathdef1323{01}~~n{:}\href{../binary/values.html#binary-int}{\def\mathdef1281#1{{\mathtt{u}#1}}\mathdef1281{\mathtt{32}}}~~m{:}\href{../binary/values.html#binary-int}{\def\mathdef1281#1{{\mathtt{u}#1}}\mathdef1281{\mathtt{32}}} &\Rightarrow& \{ \href{../syntax/types.html#syntax-limits}{\mathsf{min}}~n, \href{../syntax/types.html#syntax-limits}{\mathsf{max}}~m \} \\ \end{array}\end{split}\]

也就是说,限制对编码为字节 \(\def\mathdef1324#1{\mathtt{0x#1}}\mathdef1324{00}\) 后跟 \(\href{../syntax/values.html#syntax-int}{\mathit{u32}}\) 值的编码,或者字节 \(\def\mathdef1325#1{\mathtt{0x#1}}\mathdef1325{01}\) 后跟两个这样的编码。变量 \(n\)\(m\) 命名各自 \(\href{../binary/values.html#binary-int}{\def\mathdef1281#1{{\mathtt{u}#1}}\mathdef1281{\mathtt{32}}}\) 非终结符的属性,在本例中,它们是解码成它们的实际 无符号整数。然后完整产生式的属性是限制的抽象语法,用前一个值表示。

辅助符号

处理二进制编码时,还使用以下符号

  • \(\epsilon\) 表示空字节序列。

  • \(||B||\) 是从产生式 \(B\) 在推导中生成的字节序列的长度。

向量

向量 编码为它们的 \(\href{../binary/values.html#binary-int}{\def\mathdef1281#1{{\mathtt{u}#1}}\mathdef1281{\mathtt{32}}}\) 长度,后跟其元素序列的编码。

\[\begin{split}\begin{array}{llclll@{\qquad\qquad}l} \def\mathdef1276#1{{}}\mathdef1276{向量} & \href{../binary/conventions.html#binary-vec}{\mathtt{vec}}(\mathtt{B}) &::=& n{:}\href{../binary/values.html#binary-int}{\def\mathdef1281#1{{\mathtt{u}#1}}\mathdef1281{\mathtt{32}}}~~(x{:}\mathtt{B})^n &\Rightarrow& x^n \\ \end{array}\end{split}\]