指令
WebAssembly 代码由一系列指令组成。它的计算模型基于堆栈机,其中指令操作隐式操作数堆栈上的值,消耗(弹出)参数值并生成或返回(压入)结果值。
除了来自堆栈的动态操作数外,某些指令还具有静态立即参数,通常是索引或类型注释,它们是指令本身的一部分。
某些指令是结构化的,因为它们括号嵌套的指令序列。
以下部分将指令分组到不同的类别中。
数值指令
数值指令提供针对特定类型的数值值的基本操作。这些操作与硬件中可用的相应操作密切匹配。
\[\begin{split}\begin{array}{llcl} \def\mathdef2519#1{{}}\mathdef2519{width} & \mathit{nn}, \mathit{mm} &::=& \mathsf{32} ~|~ \mathsf{64} \\ \def\mathdef2519#1{{}}\mathdef2519{signedness} & \href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} &::=& \mathsf{u} ~|~ \mathsf{s} \\ \def\mathdef2519#1{{}}\mathdef2519{instruction} & \href{../syntax/instructions.html#syntax-instr}{\mathit{instr}} &::=& \mathsf{i}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{const}}~\href{../syntax/values.html#syntax-int}{\def\mathdef2558#1{{\mathit{u#1}}}\mathdef2558{\mathit{nn}}} ~|~ \mathsf{f}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{const}}~\href{../syntax/values.html#syntax-float}{\def\mathdef2559#1{{\mathit{f#1}}}\mathdef2559{\mathit{nn}}} \\&&|& \mathsf{i}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-iunop}{\mathit{iunop}} ~|~ \mathsf{f}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-funop}{\mathit{funop}} \\&&|& \mathsf{i}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-ibinop}{\mathit{ibinop}} ~|~ \mathsf{f}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-fbinop}{\mathit{fbinop}} \\&&|& \mathsf{i}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-itestop}{\mathit{itestop}} \\&&|& \mathsf{i}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-irelop}{\mathit{irelop}} ~|~ \mathsf{f}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-frelop}{\mathit{frelop}} \\&&|& \mathsf{i}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{extend}}\mathsf{8\_s} ~|~ \mathsf{i}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{extend}}\mathsf{16\_s} ~|~ \mathsf{i64.}\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{extend}}\mathsf{32\_s} \\&&|& \mathsf{i32.}\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{wrap}}\mathsf{\_i64} ~|~ \mathsf{i64.}\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{extend}}\mathsf{\_i32}\mathsf{\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{i}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{trunc}}\mathsf{\_f}\mathit{mm}\mathsf{\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} \\&&|& \mathsf{i}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{trunc}}\mathsf{\_sat\_f}\mathit{mm}\mathsf{\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} \\&&|& \mathsf{f32.}\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{demote}}\mathsf{\_f64} ~|~ \mathsf{f64.}\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{promote}}\mathsf{\_f32} ~|~ \mathsf{f}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{convert}}\mathsf{\_i}\mathit{mm}\mathsf{\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} \\&&|& \mathsf{i}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{reinterpret}}\mathsf{\_f}\mathit{nn} ~|~ \mathsf{f}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{reinterpret}}\mathsf{\_i}\mathit{nn} \\&&|& \dots \\ \def\mathdef2519#1{{}}\mathdef2519{integer unary operator} & \href{../syntax/instructions.html#syntax-iunop}{\mathit{iunop}} &::=& \mathsf{clz} ~|~ \mathsf{ctz} ~|~ \mathsf{popcnt} \\ \def\mathdef2519#1{{}}\mathdef2519{integer binary operator} & \href{../syntax/instructions.html#syntax-ibinop}{\mathit{ibinop}} &::=& \mathsf{add} ~|~ \mathsf{sub} ~|~ \mathsf{mul} ~|~ \mathsf{div\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{rem\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} \\&&|& \mathsf{and} ~|~ \mathsf{or} ~|~ \mathsf{xor} ~|~ \mathsf{shl} ~|~ \mathsf{shr\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{rotl} ~|~ \mathsf{rotr} \\ \def\mathdef2519#1{{}}\mathdef2519{floating-point unary operator} & \href{../syntax/instructions.html#syntax-funop}{\mathit{funop}} &::=& \mathsf{abs} ~|~ \mathsf{neg} ~|~ \mathsf{sqrt} ~|~ \mathsf{ceil} ~|~ \mathsf{floor} ~|~ \mathsf{trunc} ~|~ \mathsf{nearest} \\ \def\mathdef2519#1{{}}\mathdef2519{floating-point binary operator} & \href{../syntax/instructions.html#syntax-fbinop}{\mathit{fbinop}} &::=& \mathsf{add} ~|~ \mathsf{sub} ~|~ \mathsf{mul} ~|~ \mathsf{div} ~|~ \mathsf{min} ~|~ \mathsf{max} ~|~ \mathsf{copysign} \\ \def\mathdef2519#1{{}}\mathdef2519{integer test operator} & \href{../syntax/instructions.html#syntax-itestop}{\mathit{itestop}} &::=& \mathsf{eqz} \\ \def\mathdef2519#1{{}}\mathdef2519{integer relational operator} & \href{../syntax/instructions.html#syntax-irelop}{\mathit{irelop}} &::=& \mathsf{eq} ~|~ \mathsf{ne} ~|~ \mathsf{lt\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{gt\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{le\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{ge\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} \\ \def\mathdef2519#1{{}}\mathdef2519{floating-point relational operator} & \href{../syntax/instructions.html#syntax-frelop}{\mathit{frelop}} &::=& \mathsf{eq} ~|~ \mathsf{ne} ~|~ \mathsf{lt} ~|~ \mathsf{gt} ~|~ \mathsf{le} ~|~ \mathsf{ge} \\ \end{array}\end{split}\]
数值指令按数字类型划分。对于每种类型,可以区分几个子类别
常量:返回一个静态常量。
一元运算:消耗一个操作数并生成一个相应类型的结果。
二元运算:消耗两个操作数并生成一个相应类型的结果。
测试:消耗一个相应类型的操作数并生成一个布尔整型结果。
比较:消耗两个相应类型的操作数并生成一个布尔整型结果。
转换:消耗一个类型的值并生成另一个类型的结果(转换的源类型是“\(\mathsf{\_}\)”后面的那个)。
一些整型指令有两种形式,其中有符号注释 \(\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}}\)区分操作数是应该解释为无符号还是有符号整数。对于其他整型指令,使用二进制补码进行有符号解释意味着它们的行为无论有符号还是无符号都是相同的。
约定
有时,根据以下语法缩写将运算符分组在一起会很方便
\[\begin{split}\begin{array}{llll} \def\mathdef2519#1{{}}\mathdef2519{unary operator} & \href{../syntax/instructions.html#syntax-unop}{\mathit{unop}} &::=& \href{../syntax/instructions.html#syntax-iunop}{\mathit{iunop}} ~|~ \href{../syntax/instructions.html#syntax-funop}{\mathit{funop}} ~|~ \href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{extend}}{N}\mathsf{\_s} \\ \def\mathdef2519#1{{}}\mathdef2519{binary operator} & \href{../syntax/instructions.html#syntax-binop}{\mathit{binop}} &::=& \href{../syntax/instructions.html#syntax-ibinop}{\mathit{ibinop}} ~|~ \href{../syntax/instructions.html#syntax-fbinop}{\mathit{fbinop}} \\ \def\mathdef2519#1{{}}\mathdef2519{test operator} & \href{../syntax/instructions.html#syntax-testop}{\mathit{testop}} &::=& \href{../syntax/instructions.html#syntax-itestop}{\mathit{itestop}} \\ \def\mathdef2519#1{{}}\mathdef2519{relational operator} & \href{../syntax/instructions.html#syntax-relop}{\mathit{relop}} &::=& \href{../syntax/instructions.html#syntax-irelop}{\mathit{irelop}} ~|~ \href{../syntax/instructions.html#syntax-frelop}{\mathit{frelop}} \\ \def\mathdef2519#1{{}}\mathdef2519{conversion operator} & \href{../syntax/instructions.html#syntax-cvtop}{\mathit{cvtop}} &::=& \href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{wrap}} ~|~ \href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{extend}} ~|~ \href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{trunc}} ~|~ \href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{trunc}}\mathsf{\_sat} ~|~ \href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{convert}} ~|~ \href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{demote}} ~|~ \href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{promote}} ~|~ \href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{reinterpret}} \\ \end{array}\end{split}\]
向量指令
向量指令(也称为SIMD指令,单指令多数据)提供针对向量类型的值的基本操作。
\[\begin{split}\begin{array}{llcl} \def\mathdef2519#1{{}}\mathdef2519{ishape} & \href{../syntax/instructions.html#syntax-shape}{\mathit{ishape}} &::=& \mathsf{i8x16} ~|~ \mathsf{i16x8} ~|~ \mathsf{i32x4} ~|~ \mathsf{i64x2} \\ \def\mathdef2519#1{{}}\mathdef2519{fshape} & \href{../syntax/instructions.html#syntax-shape}{\mathit{fshape}} &::=& \mathsf{f32x4} ~|~ \mathsf{f64x2} \\ \def\mathdef2519#1{{}}\mathdef2519{shape} & \href{../syntax/instructions.html#syntax-shape}{\mathit{shape}} &::=& \href{../syntax/instructions.html#syntax-shape}{\mathit{ishape}} ~|~ \href{../syntax/instructions.html#syntax-shape}{\mathit{fshape}} \\ \def\mathdef2519#1{{}}\mathdef2519{half} & \href{../syntax/instructions.html#syntax-half}{\mathit{half}} &::=& \mathsf{low} ~|~ \mathsf{high} \\ \def\mathdef2519#1{{}}\mathdef2519{lane index} & \href{../syntax/instructions.html#syntax-laneidx}{\mathit{laneidx}} &::=& \href{../syntax/values.html#syntax-int}{\mathit{u8}} \\ \end{array}\end{split}\]
\[\begin{split}\begin{array}{llcl} \def\mathdef2519#1{{}}\mathdef2519{指令} & \href{../syntax/instructions.html#syntax-instr}{\mathit{instr}} &::=& \dots \\&&|& \mathsf{v128.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{const}}~\href{../syntax/values.html#syntax-int}{\mathit{i128}} \\&&|& \mathsf{v128.}\href{../syntax/instructions.html#syntax-vvunop}{\mathit{vvunop}} \\&&|& \mathsf{v128.}\href{../syntax/instructions.html#syntax-vvbinop}{\mathit{vvbinop}} \\&&|& \mathsf{v128.}\href{../syntax/instructions.html#syntax-vvternop}{\mathit{vvternop}} \\&&|& \mathsf{v128.}\href{../syntax/instructions.html#syntax-vvtestop}{\mathit{vvtestop}} \\&&|& \mathsf{i8x16.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{shuffle}}~\href{../syntax/instructions.html#syntax-laneidx}{\mathit{laneidx}}^{16} \\&&|& \mathsf{i8x16.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{swizzle}} \\&&|& \href{../syntax/instructions.html#syntax-shape}{\mathit{shape}}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{splat}} \\&&|& \mathsf{i8x16.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{extract\_lane}}\mathsf{\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}}~\href{../syntax/instructions.html#syntax-laneidx}{\mathit{laneidx}} ~|~ \mathsf{i16x8.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{extract\_lane}}\mathsf{\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}}~\href{../syntax/instructions.html#syntax-laneidx}{\mathit{laneidx}} \\&&|& \mathsf{i32x4.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{extract\_lane}}~\href{../syntax/instructions.html#syntax-laneidx}{\mathit{laneidx}} ~|~ \mathsf{i64x2.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{extract\_lane}}~\href{../syntax/instructions.html#syntax-laneidx}{\mathit{laneidx}} \\&&|& \href{../syntax/instructions.html#syntax-shape}{\mathit{fshape}}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{extract\_lane}}~\href{../syntax/instructions.html#syntax-laneidx}{\mathit{laneidx}} \\&&|& \href{../syntax/instructions.html#syntax-shape}{\mathit{shape}}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{replace\_lane}}~\href{../syntax/instructions.html#syntax-laneidx}{\mathit{laneidx}} \\&&|& \mathsf{i8x16}\mathsf{.}\href{../syntax/instructions.html#syntax-virelop}{\mathit{virelop}} ~|~ \mathsf{i16x8}\mathsf{.}\href{../syntax/instructions.html#syntax-virelop}{\mathit{virelop}} ~|~ \mathsf{i32x4}\mathsf{.}\href{../syntax/instructions.html#syntax-virelop}{\mathit{virelop}} \\&&|& \mathsf{i64x2.}\mathsf{eq} ~|~ \mathsf{i64x2.}\mathsf{ne} ~|~ \mathsf{i64x2.}\mathsf{lt\_s} ~|~ \mathsf{i64x2.}\mathsf{gt\_s} ~|~ \mathsf{i64x2.}\mathsf{le\_s} ~|~ \mathsf{i64x2.}\mathsf{ge\_s} \\&&|& \href{../syntax/instructions.html#syntax-shape}{\mathit{fshape}}\mathsf{.}\href{../syntax/instructions.html#syntax-vfrelop}{\mathit{vfrelop}} \\&&|& \href{../syntax/instructions.html#syntax-shape}{\mathit{ishape}}\mathsf{.}\href{../syntax/instructions.html#syntax-viunop}{\mathit{viunop}} ~|~ \mathsf{i8x16.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{popcnt}} \\&&|& \mathsf{i16x8.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{q15mulr\_sat}}\mathsf{\_s} \\ &&|& \mathsf{i32x4.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{dot}}\mathsf{\_i16x8\_s} \\ &&|& \href{../syntax/instructions.html#syntax-shape}{\mathit{fshape}}\mathsf{.}\href{../syntax/instructions.html#syntax-vfunop}{\mathit{vfunop}} \\&&|& \href{../syntax/instructions.html#syntax-shape}{\mathit{ishape}}\mathsf{.}\href{../syntax/instructions.html#syntax-vitestop}{\mathit{vitestop}} \\ &&|& \href{../syntax/instructions.html#syntax-shape}{\mathit{ishape}}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{bitmask}} \\ &&|& \mathsf{i8x16.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{narrow}}\mathsf{\_i16x8\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{i16x8.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{narrow}}\mathsf{\_i32x4\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} \\&&|& \mathsf{i16x8.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{extend}}\mathsf{\_}\href{../syntax/instructions.html#syntax-half}{\mathit{half}}\mathsf{\_i8x16\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{i32x4.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{extend}}\mathsf{\_}\href{../syntax/instructions.html#syntax-half}{\mathit{half}}\mathsf{\_i16x8\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} \\&&|& \mathsf{i64x2.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{extend}}\mathsf{\_}\href{../syntax/instructions.html#syntax-half}{\mathit{half}}\mathsf{\_i32x4\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} \\&&|& \href{../syntax/instructions.html#syntax-shape}{\mathit{ishape}}\mathsf{.}\href{../syntax/instructions.html#syntax-vishiftop}{\mathit{vishiftop}} \\&&|& \href{../syntax/instructions.html#syntax-shape}{\mathit{ishape}}\mathsf{.}\href{../syntax/instructions.html#syntax-vibinop}{\mathit{vibinop}} \\&&|& \mathsf{i8x16.}\href{../syntax/instructions.html#syntax-viminmaxop}{\mathit{viminmaxop}} ~|~ \mathsf{i16x8.}\href{../syntax/instructions.html#syntax-viminmaxop}{\mathit{viminmaxop}} ~|~ \mathsf{i32x4.}\href{../syntax/instructions.html#syntax-viminmaxop}{\mathit{viminmaxop}} \\&&|& \mathsf{i8x16.}\href{../syntax/instructions.html#syntax-visatbinop}{\mathit{visatbinop}} ~|~ \mathsf{i16x8.}\href{../syntax/instructions.html#syntax-visatbinop}{\mathit{visatbinop}} \\&&|& \mathsf{i16x8.}\mathsf{mul} ~|~ \mathsf{i32x4.}\mathsf{mul} ~|~ \mathsf{i64x2.}\mathsf{mul} \\&&|& \mathsf{i8x16.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{avgr}}\mathsf{\_u} ~|~ \mathsf{i16x8.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{avgr}}\mathsf{\_u} \\&&|& \mathsf{i16x8.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{extmul}}\mathsf{\_}\href{../syntax/instructions.html#syntax-half}{\mathit{half}}\mathsf{\_i8x16\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{i32x4.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{extmul}}\mathsf{\_}\href{../syntax/instructions.html#syntax-half}{\mathit{half}}\mathsf{\_i16x8\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{i64x2.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{extmul}}\mathsf{\_}\href{../syntax/instructions.html#syntax-half}{\mathit{half}}\mathsf{\_i32x4\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} \\ &&|& \mathsf{i16x8.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{extadd\_pairwise}}\mathsf{\_i8x16\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{i32x4.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{extadd\_pairwise}}\mathsf{\_i16x8\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} \\ &&|& \href{../syntax/instructions.html#syntax-shape}{\mathit{fshape}}\mathsf{.}\href{../syntax/instructions.html#syntax-vfbinop}{\mathit{vfbinop}} \\&&|& \mathsf{i32x4.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{trunc}}\mathsf{\_sat\_f32x4\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{i32x4.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{trunc}}\mathsf{\_sat\_f64x2\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}}\mathsf{\_zero} \\&&|& \mathsf{f32x4.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{convert}}\mathsf{\_i32x4\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{f32x4.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{demote}}\mathsf{\_f64x2\_zero} \\&&|& \mathsf{f64x2.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{convert}}\mathsf{\_low\_i32x4\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{f64x2.}\href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{promote}}\mathsf{\_low\_f32x4} \\&&|& \dots \\ \end{array}\end{split}\]
\[\begin{split}\begin{array}{llcl} \def\mathdef2519#1{{}}\mathdef2519{向量位运算一元运算符} & \href{../syntax/instructions.html#syntax-vvunop}{\mathit{vvunop}} &::=& \mathsf{not} \\ \def\mathdef2519#1{{}}\mathdef2519{向量位运算二元运算符} & \href{../syntax/instructions.html#syntax-vvbinop}{\mathit{vvbinop}} &::=& \mathsf{and} ~|~ \mathsf{andnot} ~|~ \mathsf{or} ~|~ \mathsf{xor} \\ \def\mathdef2519#1{{}}\mathdef2519{向量位运算三元运算符} & \href{../syntax/instructions.html#syntax-vvternop}{\mathit{vvternop}} &::=& \mathsf{bitselect} \\ \def\mathdef2519#1{{}}\mathdef2519{向量位运算测试运算符} & \href{../syntax/instructions.html#syntax-vvtestop}{\mathit{vvtestop}} &::=& \mathsf{any\_true} \\ \def\mathdef2519#1{{}}\mathdef2519{向量整数测试运算符} & \href{../syntax/instructions.html#syntax-vitestop}{\mathit{vitestop}} &::=& \mathsf{all\_true} \\ \def\mathdef2519#1{{}}\mathdef2519{向量整数关系运算符} & \href{../syntax/instructions.html#syntax-virelop}{\mathit{virelop}} &::=& \mathsf{eq} ~|~ \mathsf{ne} ~|~ \mathsf{lt\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{gt\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{le\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{ge\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} \\ \def\mathdef2519#1{{}}\mathdef2519{向量浮点数关系运算符} & \href{../syntax/instructions.html#syntax-vfrelop}{\mathit{vfrelop}} &::=& \mathsf{eq} ~|~ \mathsf{ne} ~|~ \mathsf{lt} ~|~ \mathsf{gt} ~|~ \mathsf{le} ~|~ \mathsf{ge} \\ \def\mathdef2519#1{{}}\mathdef2519{向量整数一元运算符} & \href{../syntax/instructions.html#syntax-viunop}{\mathit{viunop}} &::=& \mathsf{abs} ~|~ \mathsf{neg} \\ \def\mathdef2519#1{{}}\mathdef2519{向量整数二元运算符} & \href{../syntax/instructions.html#syntax-vibinop}{\mathit{vibinop}} &::=& \mathsf{add} ~|~ \mathsf{sub} \\ \def\mathdef2519#1{{}}\mathdef2519{向量整数二元最小/最大运算符} & \href{../syntax/instructions.html#syntax-viminmaxop}{\mathit{viminmaxop}} &::=& \mathsf{min\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{max\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} \\ \def\mathdef2519#1{{}}\mathdef2519{向量整数饱和二元运算符} & \href{../syntax/instructions.html#syntax-visatbinop}{\mathit{visatbinop}} &::=& \mathsf{add\_sat\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} ~|~ \mathsf{sub\_sat\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} \\ \def\mathdef2519#1{{}}\mathdef2519{向量整数移位运算符} & \href{../syntax/instructions.html#syntax-vishiftop}{\mathit{vishiftop}} &::=& \mathsf{shl} ~|~ \mathsf{shr\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}} \\ \def\mathdef2519#1{{}}\mathdef2519{向量浮点数一元运算符} & \href{../syntax/instructions.html#syntax-vfunop}{\mathit{vfunop}} &::=& \mathsf{abs} ~|~ \mathsf{neg} ~|~ \mathsf{sqrt} ~|~ \mathsf{ceil} ~|~ \mathsf{floor} ~|~ \mathsf{trunc} ~|~ \mathsf{nearest} \\ \def\mathdef2519#1{{}}\mathdef2519{向量浮点数二元运算符} & \href{../syntax/instructions.html#syntax-vfbinop}{\mathit{vfbinop}} &::=& \mathsf{add} ~|~ \mathsf{sub} ~|~ \mathsf{mul} ~|~ \mathsf{div} ~|~ \mathsf{min} ~|~ \mathsf{max} ~|~ \mathsf{pmin} ~|~ \mathsf{pmax} \\ \end{array}\end{split}\]
向量指令的命名约定包含一个前缀,该前缀决定了操作数的解释方式。该前缀描述了操作数的形状,写成 \(t\mathsf{x}N\),由一个打包的数值类型 \(t\) 和该类型的通道数量 \(N\) 组成。对每个通道的值执行逐点运算。
注意
例如,形状 \(\mathsf{i32x4}\) 将操作数解释为四个 \(\href{../syntax/values.html#syntax-int}{\mathit{i32}}\) 值,打包成一个 \(\href{../syntax/values.html#syntax-int}{\mathit{i128}}\)。数值类型 \(t\) 的位宽乘以 \(N\) 始终为 128。
以 \(\mathsf{v128}\) 为前缀的指令不涉及特定解释,并将 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{v128}}\) 视为一个 \(\href{../syntax/values.html#syntax-int}{\mathit{i128}}\) 值或一个包含 128 个独立位的向量。
向量指令可以分为几个子类别
常量:返回一个静态常量。
一元运算:接收一个 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{v128}}\) 操作数并生成一个 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{v128}}\) 结果。
二元运算:接收两个 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{v128}}\) 操作数并生成一个 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{v128}}\) 结果。
三元运算:接收三个 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{v128}}\) 操作数并生成一个 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{v128}}\) 结果。
测试:接收一个 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{v128}}\) 操作数并生成一个布尔整数结果。
移位:接收一个 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{v128}}\) 操作数和一个 \(\href{../syntax/values.html#syntax-int}{\mathit{i32}}\) 操作数,生成一个 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{v128}}\) 结果。
splat:接收一个数值类型的值,生成一个指定形状的 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{v128}}\) 结果。
提取通道:接收一个 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{v128}}\) 操作数并返回给定通道中的数值。
替换通道:接收一个 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{v128}}\) 操作数和给定通道的数值,生成一个 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{v128}}\) 结果。
一些向量指令具有符号性注释 \(\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}}\),用于区分操作数中的元素是作为解释 无符号 还是有符号 整数。对于其他向量指令,使用二进制补码进行有符号解释意味着无论符号性如何,它们的行为都相同。
约定
有时,根据以下语法缩写将运算符分组在一起会很方便
\[\begin{split}\begin{array}{llll} \def\mathdef2519#1{{}}\mathdef2519{一元运算符} & \href{../syntax/instructions.html#syntax-vunop}{\mathit{vunop}} &::=& \href{../syntax/instructions.html#syntax-viunop}{\mathit{viunop}} ~|~ \href{../syntax/instructions.html#syntax-vfunop}{\mathit{vfunop}} ~|~ \href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{popcnt}} \\ \def\mathdef2519#1{{}}\mathdef2519{二元运算符} & \href{../syntax/instructions.html#syntax-vbinop}{\mathit{vbinop}} &::=& \href{../syntax/instructions.html#syntax-vibinop}{\mathit{vibinop}} ~|~ \href{../syntax/instructions.html#syntax-vfbinop}{\mathit{vfbinop}} \\&&|& \href{../syntax/instructions.html#syntax-viminmaxop}{\mathit{viminmaxop}} ~|~ \href{../syntax/instructions.html#syntax-visatbinop}{\mathit{visatbinop}} \\&&|& \href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{mul}} ~|~ \href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{avgr}}\mathsf{\_u} ~|~ \href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{q15mulr\_sat}}\mathsf{\_s} \\ \def\mathdef2519#1{{}}\mathdef2519{测试运算符} & \href{../syntax/instructions.html#syntax-vtestop}{\mathit{vtestop}} &::=& \href{../syntax/instructions.html#syntax-vitestop}{\mathit{vitestop}} \\ \def\mathdef2519#1{{}}\mathdef2519{关系运算符} & \href{../syntax/instructions.html#syntax-vrelop}{\mathit{vrelop}} &::=& \href{../syntax/instructions.html#syntax-virelop}{\mathit{virelop}} ~|~ \href{../syntax/instructions.html#syntax-vfrelop}{\mathit{vfrelop}} \\ \def\mathdef2519#1{{}}\mathdef2519{转换运算符} & \href{../syntax/instructions.html#syntax-vcvtop}{\mathit{vcvtop}} &::=& \href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{extend}} ~|~ \href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{trunc}}\mathsf{\_sat} ~|~ \href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{convert}} ~|~ \href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{demote}} ~|~ \href{../syntax/instructions.html#syntax-instr-vec}{\mathsf{promote}} \\ \end{array}\end{split}\]
参考指令
本组中的指令与访问 引用 相关。
\[\begin{split}\begin{array}{llcl} \def\mathdef2519#1{{}}\mathdef2519{instruction} & \href{../syntax/instructions.html#syntax-instr}{\mathit{instr}} &::=& \dots \\&&|& \href{../syntax/instructions.html#syntax-instr-ref}{\mathsf{ref{.}null}}~\href{../syntax/types.html#syntax-reftype}{\mathit{reftype}} \\&&|& \href{../syntax/instructions.html#syntax-instr-ref}{\mathsf{ref{.}is\_null}} \\&&|& \href{../syntax/instructions.html#syntax-instr-ref}{\mathsf{ref{.}func}}~\href{../syntax/modules.html#syntax-funcidx}{\mathit{funcidx}} \\ \end{array}\end{split}\]
这些指令分别产生一个空值、检查是否为空值或生成指向给定函数的引用。
参数化指令
本组中的指令可以操作任何 值类型 的操作数。
\[\begin{split}\begin{array}{llcl} \def\mathdef2519#1{{}}\mathdef2519{instruction} & \href{../syntax/instructions.html#syntax-instr}{\mathit{instr}} &::=& \dots \\&&|& \href{../syntax/instructions.html#syntax-instr-parametric}{\mathsf{drop}} \\&&|& \href{../syntax/instructions.html#syntax-instr-parametric}{\mathsf{select}}~(\href{../syntax/types.html#syntax-valtype}{\mathit{valtype}}^\ast)^? \\ \end{array}\end{split}\]
\(\href{../syntax/instructions.html#syntax-instr-parametric}{\mathsf{drop}}\) 指令简单地丢弃一个操作数。
\(\href{../syntax/instructions.html#syntax-instr-parametric}{\mathsf{select}}\) 指令根据其第三个操作数是否为零来选择其前两个操作数之一。它可能包含一个 值类型 来确定这些操作数的类型。如果缺少,则操作数必须为 数值类型。
注意
在 WebAssembly 的未来版本中,\(\href{../syntax/instructions.html#syntax-instr-parametric}{\mathsf{select}}\) 上的类型注释可能允许同时选择多个值。
变量指令
变量指令与访问 局部变量 或 全局变量 相关。
\[\begin{split}\begin{array}{llcl} \def\mathdef2519#1{{}}\mathdef2519{instruction} & \href{../syntax/instructions.html#syntax-instr}{\mathit{instr}} &::=& \dots \\&&|& \href{../syntax/instructions.html#syntax-instr-variable}{\mathsf{local.get}}~\href{../syntax/modules.html#syntax-localidx}{\mathit{localidx}} \\&&|& \href{../syntax/instructions.html#syntax-instr-variable}{\mathsf{local.set}}~\href{../syntax/modules.html#syntax-localidx}{\mathit{localidx}} \\&&|& \href{../syntax/instructions.html#syntax-instr-variable}{\mathsf{local.tee}}~\href{../syntax/modules.html#syntax-localidx}{\mathit{localidx}} \\&&|& \href{../syntax/instructions.html#syntax-instr-variable}{\mathsf{global.get}}~\href{../syntax/modules.html#syntax-globalidx}{\mathit{globalidx}} \\&&|& \href{../syntax/instructions.html#syntax-instr-variable}{\mathsf{global.set}}~\href{../syntax/modules.html#syntax-globalidx}{\mathit{globalidx}} \\ \end{array}\end{split}\]
这些指令分别获取或设置变量的值。\(\href{../syntax/instructions.html#syntax-instr-variable}{\mathsf{local.tee}}\) 指令类似于 \(\href{../syntax/instructions.html#syntax-instr-variable}{\mathsf{local.set}}\),但也会返回其参数。
表指令
本组中的指令与 表 相关。
\[\begin{split}\begin{array}{llcl} \def\mathdef2519#1{{}}\mathdef2519{instruction} & \href{../syntax/instructions.html#syntax-instr}{\mathit{instr}} &::=& \dots \\&&|& \href{../syntax/instructions.html#syntax-instr-table}{\mathsf{table.get}}~\href{../syntax/modules.html#syntax-tableidx}{\mathit{tableidx}} \\&&|& \href{../syntax/instructions.html#syntax-instr-table}{\mathsf{table.set}}~\href{../syntax/modules.html#syntax-tableidx}{\mathit{tableidx}} \\&&|& \href{../syntax/instructions.html#syntax-instr-table}{\mathsf{table.size}}~\href{../syntax/modules.html#syntax-tableidx}{\mathit{tableidx}} \\&&|& \href{../syntax/instructions.html#syntax-instr-table}{\mathsf{table.grow}}~\href{../syntax/modules.html#syntax-tableidx}{\mathit{tableidx}} \\&&|& \href{../syntax/instructions.html#syntax-instr-table}{\mathsf{table.fill}}~\href{../syntax/modules.html#syntax-tableidx}{\mathit{tableidx}} \\&&|& \href{../syntax/instructions.html#syntax-instr-table}{\mathsf{table.copy}}~\href{../syntax/modules.html#syntax-tableidx}{\mathit{tableidx}}~\href{../syntax/modules.html#syntax-tableidx}{\mathit{tableidx}} \\&&|& \href{../syntax/instructions.html#syntax-instr-table}{\mathsf{table.init}}~\href{../syntax/modules.html#syntax-tableidx}{\mathit{tableidx}}~\href{../syntax/modules.html#syntax-elemidx}{\mathit{elemidx}} \\&&|& \href{../syntax/instructions.html#syntax-instr-table}{\mathsf{elem.drop}}~\href{../syntax/modules.html#syntax-elemidx}{\mathit{elemidx}} \\ \end{array}\end{split}\]
\(\href{../syntax/instructions.html#syntax-instr-table}{\mathsf{table.get}}\) 和 \(\href{../syntax/instructions.html#syntax-instr-table}{\mathsf{table.set}}\) 指令分别在表中加载或存储一个元素。
\(\href{../syntax/instructions.html#syntax-instr-table}{\mathsf{table.size}}\) 指令返回表的当前大小。\(\href{../syntax/instructions.html#syntax-instr-table}{\mathsf{table.grow}}\) 指令按给定的增量扩展表,并返回以前的大小,如果无法分配足够的存储空间,则返回 \(-1\)。它还接受为新分配的条目提供的初始化值。
\(\href{../syntax/instructions.html#syntax-instr-table}{\mathsf{table.fill}}\) 指令将范围内所有条目设置为给定值。
\(\href{../syntax/instructions.html#syntax-instr-table}{\mathsf{table.copy}}\) 指令将元素从源表区域复制到可能重叠的目标区域;第一个索引表示目标。\(\href{../syntax/instructions.html#syntax-instr-table}{\mathsf{table.init}}\) 指令将元素从 被动元素段 复制到表中。\(\href{../syntax/instructions.html#syntax-instr-table}{\mathsf{elem.drop}}\) 指令防止进一步使用被动元素段。此指令旨在用作优化提示。在删除元素段后,不再能够检索其元素,因此可释放该段使用的内存。
访问表的另一个指令是 控制指令 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{call\_indirect}}\)。
内存指令
本组中的指令与线性 内存 相关。
\[\begin{split}\begin{array}{llcl} \def\mathdef2519#1{{}}\mathdef2519{memory immediate} & \href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} &::=& \{ \href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{offset}}~\href{../syntax/values.html#syntax-int}{\mathit{u32}}, \href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{align}}~\href{../syntax/values.html#syntax-int}{\mathit{u32}} \} \\ \def\mathdef2519#1{{}}\mathdef2519{lane width} & \mathit{ww} &::=& 8 ~|~ 16 ~|~ 32 ~|~ 64 \\ \def\mathdef2519#1{{}}\mathdef2519{instruction} & \href{../syntax/instructions.html#syntax-instr}{\mathit{instr}} &::=& \dots \\&&|& \mathsf{i}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{load}}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} ~|~ \mathsf{f}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{load}}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} ~|~ \mathsf{v128.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{load}}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} \\&&|& \mathsf{i}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{store}}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} ~|~ \mathsf{f}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{store}}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} ~|~ \mathsf{v128.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{store}}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} \\&&|& \mathsf{i}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{load}}\mathsf{8\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} ~|~ \mathsf{i}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{load}}\mathsf{16\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} ~|~ \mathsf{i64.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{load}}\mathsf{32\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} \\&&|& \mathsf{i}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{store}}\mathsf{8}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} ~|~ \mathsf{i}\mathit{nn}\mathsf{.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{store}}\mathsf{16}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} ~|~ \mathsf{i64.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{store}}\mathsf{32}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} \\&&|& \mathsf{v128.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{load}}\mathsf{8x8\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} ~|~ \mathsf{v128.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{load}}\mathsf{16x4\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} ~|~ \mathsf{v128.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{load}}\mathsf{32x2\_}\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} \\&&|& \mathsf{v128.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{load}}\mathsf{32\_zero}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} ~|~ \mathsf{v128.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{load}}\mathsf{64\_zero}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} \\&&|& \mathsf{v128.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{load}}\mathit{ww}\mathsf{\_splat}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}} \\&&|& \mathsf{v128.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{load}}\mathit{ww}\mathsf{\_lane}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}}~\href{../syntax/instructions.html#syntax-laneidx}{\mathit{laneidx}} ~|~ \mathsf{v128.}\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{store}}\mathit{ww}\mathsf{\_lane}~\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}}~\href{../syntax/instructions.html#syntax-laneidx}{\mathit{laneidx}} \\&&|& \href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{memory.size}} \\&&|& \href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{memory.grow}} \\&&|& \href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{memory.fill}} \\&&|& \href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{memory.copy}} \\&&|& \href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{memory.init}}~\href{../syntax/modules.html#syntax-dataidx}{\mathit{dataidx}} \\&&|& \href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{data.drop}}~\href{../syntax/modules.html#syntax-dataidx}{\mathit{dataidx}} \\ \end{array}\end{split}\]
使用 \(\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{load}}\) 和 \(\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{store}}\) 指令访问内存,以支持不同的 数字类型。它们都采用一个 内存立即数 \(\href{../syntax/instructions.html#syntax-memarg}{\mathit{memarg}}\),其中包含一个地址 偏移量 和预期 对齐方式(表示为 2 的幂的指数)。整数加载和存储可以选择指定一个 存储大小,该大小小于相应值类型的 位宽。在加载的情况下,需要一个符号扩展模式 \(\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}}\) 来选择适当的行为。
向量加载可以指定一个形状,该形状是 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{v128}}\) 的 位宽 的一半。每条车道都是其通常大小的一半,符号扩展模式 \(\href{../syntax/instructions.html#syntax-sx}{\mathit{sx}}\) 然后指定如何将较小的车道扩展到较大的车道。或者,向量加载可以执行一个 散布,使得只加载指定存储大小的单个车道,并将结果复制到所有车道。
静态地址偏移量添加到动态地址操作数,生成一个 33 位的 有效地址,该地址是访问内存的从零开始的索引。所有值都以 小端 字节顺序读取和写入。如果任何被访问的内存字节位于内存当前大小所暗示的地址范围之外,则会产生 陷阱。
注意
WebAssembly 的未来版本可能会提供具有 64 位地址范围的内存指令。
指令 \(\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{memory.size}}\) 返回当前内存的大小。指令 \(\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{memory.grow}}\) 按给定的增量增长内存,并返回之前的内存大小,如果无法分配足够的内存,则返回 \(-1\)。这两个指令的操作单位都是 页面大小。
指令 \(\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{memory.fill}}\) 将区域中的所有值设置为给定的字节。指令 \(\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{memory.copy}}\) 将数据从源内存区域复制到可能重叠的目标区域。指令 \(\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{memory.init}}\) 将数据从 被动数据段 复制到内存中。指令 \(\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{data.drop}}\) 阻止进一步使用被动数据段。该指令旨在用作优化提示。数据段被丢弃后,其数据将无法再被检索,因此该段使用的内存可以被释放。
注意
在当前版本的 WebAssembly 中,所有内存指令都隐式地对 内存 索引 \(0\) 进行操作。此限制可能会在未来的版本中解除。
控制指令
该组中的指令会影响控制流。
\[\begin{split}\begin{array}{llcl} \def\mathdef2519#1{{}}\mathdef2519{块类型} & \href{../syntax/instructions.html#syntax-blocktype}{\mathit{blocktype}} &::=& \href{../syntax/modules.html#syntax-typeidx}{\mathit{typeidx}} ~|~ \href{../syntax/types.html#syntax-valtype}{\mathit{valtype}}^? \\ \def\mathdef2519#1{{}}\mathdef2519{指令} & \href{../syntax/instructions.html#syntax-instr}{\mathit{instr}} &::=& \dots \\&&|& \href{../syntax/instructions.html#syntax-instr-control}{\mathsf{nop}} \\&&|& \href{../syntax/instructions.html#syntax-instr-control}{\mathsf{unreachable}} \\&&|& \href{../syntax/instructions.html#syntax-instr-control}{\mathsf{block}}~\href{../syntax/instructions.html#syntax-blocktype}{\mathit{blocktype}}~\href{../syntax/instructions.html#syntax-instr}{\mathit{instr}}^\ast~\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{end}} \\&&|& \href{../syntax/instructions.html#syntax-instr-control}{\mathsf{loop}}~\href{../syntax/instructions.html#syntax-blocktype}{\mathit{blocktype}}~\href{../syntax/instructions.html#syntax-instr}{\mathit{instr}}^\ast~\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{end}} \\&&|& \href{../syntax/instructions.html#syntax-instr-control}{\mathsf{if}}~\href{../syntax/instructions.html#syntax-blocktype}{\mathit{blocktype}}~\href{../syntax/instructions.html#syntax-instr}{\mathit{instr}}^\ast~\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{else}}~\href{../syntax/instructions.html#syntax-instr}{\mathit{instr}}^\ast~\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{end}} \\&&|& \href{../syntax/instructions.html#syntax-instr-control}{\mathsf{br}}~\href{../syntax/modules.html#syntax-labelidx}{\mathit{labelidx}} \\&&|& \href{../syntax/instructions.html#syntax-instr-control}{\mathsf{br\_if}}~\href{../syntax/modules.html#syntax-labelidx}{\mathit{labelidx}} \\&&|& \href{../syntax/instructions.html#syntax-instr-control}{\mathsf{br\_table}}~\href{../syntax/conventions.html#syntax-vec}{\mathit{vec}}(\href{../syntax/modules.html#syntax-labelidx}{\mathit{labelidx}})~\href{../syntax/modules.html#syntax-labelidx}{\mathit{labelidx}} \\&&|& \href{../syntax/instructions.html#syntax-instr-control}{\mathsf{return}} \\&&|& \href{../syntax/instructions.html#syntax-instr-control}{\mathsf{call}}~\href{../syntax/modules.html#syntax-funcidx}{\mathit{funcidx}} \\&&|& \href{../syntax/instructions.html#syntax-instr-control}{\mathsf{call\_indirect}}~\href{../syntax/modules.html#syntax-tableidx}{\mathit{tableidx}}~\href{../syntax/modules.html#syntax-typeidx}{\mathit{typeidx}} \\ \end{array}\end{split}\]
指令 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{nop}}\) 不执行任何操作。
指令 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{unreachable}}\) 会导致无条件的 陷阱。
指令 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{block}}\)、\(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{loop}}\) 和 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{if}}\) 是结构化指令。它们将嵌套的指令序列(称为块)括起来,并以 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{end}}\) 或 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{else}}\) 伪指令结束或分隔。正如语法规定,它们必须是嵌套良好的。
结构化指令可以根据其注释的块类型在操作数栈上消耗输入并产生输出。它要么以 类型索引 形式给出,该索引引用合适的 函数类型,要么以可选的 值类型 形式给出,它是函数类型 \([] \href{../syntax/types.html#syntax-functype}{\rightarrow} [\href{../syntax/types.html#syntax-valtype}{\mathit{valtype}}^?]\) 的简写。
每个结构化控制指令都会引入一个隐式的标签。标签是分支指令的目标,这些指令使用 标签索引 来引用它们。与其他 索引空间 不同,标签的索引是相对于嵌套深度的,也就是说,标签 \(0\) 指的是包含引用分支指令的最内层结构化控制指令,而递增的索引指的是那些更外层的指令。因此,标签只能从关联的结构化控制指令内部引用。这也意味着分支只能指向外部,即从它们的目标控制结构的块中“跳出”。确切的效果取决于该控制结构。如果是 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{block}}\) 或 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{if}}\),则它是向前跳转,在匹配的 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{end}}\) 后继续执行。如果是 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{loop}}\),则它是向后跳转到循环的开头。
注意
这强制执行结构化控制流。直观地说,指向 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{block}}\) 或 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{if}}\) 的分支在大多数类似 C 的语言中就像一个 \(\mathsf{break}\) 语句,而指向 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{loop}}\) 的分支就像一个 \(\mathsf{continue}\) 语句。
分支指令有几种形式:\(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{br}}\) 执行无条件分支,\(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{br\_if}}\) 执行条件分支,\(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{br\_table}}\) 通过操作数索引到指令的立即数的标签向量中执行间接分支,或者如果操作数超出范围,则执行到默认目标。指令 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{return}}\) 是对指向最外层块(隐式地是当前函数的主体)的无条件分支的简写。执行分支会展开操作数栈,直到目标结构化控制指令进入时的堆栈高度。但是,分支本身可能还会消耗操作数,它们在展开后会将这些操作数重新压入操作数栈。向前分支根据目标块类型的输出要求操作数,即代表已终止块产生的值。向后分支根据目标块类型的输入要求操作数,即代表已重启块消耗的值。
指令 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{call}}\) 调用另一个 函数,从栈中消耗必要的参数,并返回调用的结果值。指令 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{call\_indirect}}\) 通过操作数索引到一个 表 间接调用函数,该表由一个 表索引 表示,并且必须具有类型 \(\href{../syntax/types.html#syntax-reftype}{\mathsf{funcref}}\)。由于它可能包含异构类型的函数,因此被调用者的类型会动态地与指令第二个立即数索引的 函数类型 进行检查,如果类型不匹配,则调用会中止并产生一个 陷阱。
表达式
函数 主体、全局变量 的初始化值、元素 段的元素和偏移量以及 数据 段的偏移量都是以表达式形式给出的,表达式是由 指令 序列组成的,并以一个 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{end}}\) 标记结束。
\[\begin{split}\begin{array}{llll} \def\mathdef2519#1{{}}\mathdef2519{表达式} & \href{../syntax/instructions.html#syntax-expr}{\mathit{expr}} &::=& \href{../syntax/instructions.html#syntax-instr}{\mathit{instr}}^\ast~\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{end}} \\ \end{array}\end{split}\]
在某些情况下,验证 限制 表达式为常量,这限制了允许指令的集合。