Instructions

Instructions are syntactically distinguished into plain and structured instructions.

instrI::=in:plaininstrIin|in:blockinstrIin

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

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.

labelI::=v:id{labels v}I(ifvI.labels)|v:id{labels v}(Iwithlabels[i]=ϵ)(ifI.labels[i]=v)|ϵ{labels (ϵ)}I

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.

If a label with the same name already exists, then it is shadowed and the earlier label becomes inaccessible.

Control Instructions

Structured control instructions can bind an optional symbolic label identifier. The same label identifier may optionally be repeated after the corresponding end and else pseudo instructions, to indicate the matching delimiters.

Their block type is given as a type use, analogous to the type of functions. However, the special case of a type use that is syntactically empty or consists of only a single result is not regarded as an abbreviation for an inline function type, but is parsed directly into an optional value type.

blocktypeI::=|(t:result)?t?x,I:typeuseIx(ifI={locals (ϵ)})blockinstrI::=block  I:labelI  bt:blocktypeI  (in:instrI)  end  id?block bt in end  (ifid?=ϵid?=label)|loop  I:labelI  bt:blocktypeI  (in:instrI)  end  id?loop bt in end(ifid?=ϵid?=label)|if  I:labelI  bt:blocktypeI  (in1:instrI)  else  id1?  (in2:instrI)  end  id2?if bt in1 else in2 end(ifid1?=ϵid1?=label,id2?=ϵid2?=label)

Note

The side condition stating that the identifier context I must only contain unnamed entries in the rule for typeuse block types enforces that no identifier can be bound in any param declaration for a block type.

All other control instruction are represented verbatim.

plaininstrI::=unreachableunreachable|nopnop|br  l:labelidxIbr l|br_if  l:labelidxIbr_if l|br_table  l:vec(labelidxI)  lN:labelidxIbr_table l lN|returnreturn|call  x:funcidxIcall x|call_indirect  x:tableidx  y,I:typeuseIcall_indirect x y(ifI={locals (ϵ)})

Note

The side condition stating that the identifier context I must only contain unnamed entries in the rule for call_indirect enforces that no identifier can be bound in any param declaration appearing in the type annotation.

Abbreviations

The else keyword of an if instruction can be omitted if the following instruction sequence is empty.

if  label  blocktype  instr  endif  label  blocktype  instr  else  end

Also, for backwards compatibility, the table index to call_indirect can be omitted, defaulting to 0.

call_indirect  typeusecall_indirect  0  typeuse

Reference Instructions

plaininstrI::=|ref.null  t:heaptyperef.null t|ref.is_nullref.is_null|ref.func  x:funcidxref.func x

Parametric Instructions

plaininstrI::=|dropdrop|select ((t:result))?select (t)?

Variable Instructions

plaininstrI::=|local.get  x:localidxIlocal.get x|local.set  x:localidxIlocal.set x|local.tee  x:localidxIlocal.tee x|global.get  x:globalidxIglobal.get x|global.set  x:globalidxIglobal.set x

Table Instructions

plaininstrI::=|table.get  x:tableidxItable.get x|table.set  x:tableidxItable.set x|table.size  x:tableidxItable.size x|table.grow  x:tableidxItable.grow x|table.fill  x:tableidxItable.fill x|table.copy  x:tableidxI  y:tableidxItable.copy x y|table.init  x:tableidxI  y:elemidxItable.init x y|elem.drop  x:elemidxIelem.drop x

Abbreviations

For backwards compatibility, all table indices may be omitted from table instructions, defaulting to 0.

table.gettable.get  0table.settable.set  0table.sizetable.size  0table.growtable.grow  0table.filltable.fill  0table.copytable.copy  0  0table.init  x:elemidxItable.init  0  x:elemidxI

Memory Instructions

The offset and alignment immediates to memory instructions are optional. The offset defaults to 0, the alignment to the storage size of the respective memory access, which is its natural alignment. Lexically, an offset or align phrase is considered a single keyword token, so no white space is allowed around the =.

memargN::=o:offset  a:alignN{align n, offset o}(ifa=2n)offset::=offset=o:u32o|ϵ0alignN::=align=a:u32a|ϵNplaininstrI::=|i32.load  m:memarg4i32.load m|i64.load  m:memarg8i64.load m|f32.load  m:memarg4f32.load m|f64.load  m:memarg8f64.load m|i32.load8_s  m:memarg1i32.load8_s m|i32.load8_u  m:memarg1i32.load8_u m|i32.load16_s  m:memarg2i32.load16_s m|i32.load16_u  m:memarg2i32.load16_u m|i64.load8_s  m:memarg1i64.load8_s m|i64.load8_u  m:memarg1i64.load8_u m|i64.load16_s  m:memarg2i64.load16_s m|i64.load16_u  m:memarg2i64.load16_u m|i64.load32_s  m:memarg4i64.load32_s m|i64.load32_u  m:memarg4i64.load32_u m|i32.store  m:memarg4i32.store m|i64.store  m:memarg8i64.store m|f32.store  m:memarg4f32.store m|f64.store  m:memarg8f64.store m|i32.store8  m:memarg1i32.store8 m|i32.store16  m:memarg2i32.store16 m|i64.store8  m:memarg1i64.store8 m|i64.store16  m:memarg2i64.store16 m|i64.store32  m:memarg4i64.store32 m|memory.sizememory.size|memory.growmemory.grow|memory.fillmemory.fill|memory.copymemory.copy|memory.init  x:dataidxImemory.init x|data.drop  x:dataidxIdata.drop x

Numeric Instructions

plaininstrI::=|i32.const  n:i32i32.const n|i64.const  n:i64i64.const n|f32.const  z:f32f32.const z|f64.const  z:f64f64.const z
plaininstrI::=thisisenoughthisshouldbeenough|i32.clzi32.clz|i32.ctzi32.ctz|i32.popcnti32.popcnt|i32.addi32.add|i32.subi32.sub|i32.muli32.mul|i32.div_si32.div_s|i32.div_ui32.div_u|i32.rem_si32.rem_s|i32.rem_ui32.rem_u|i32.andi32.and|i32.ori32.or|i32.xori32.xor|i32.shli32.shl|i32.shr_si32.shr_s|i32.shr_ui32.shr_u|i32.rotli32.rotl|i32.rotri32.rotr
plaininstrI::=thisisenoughthisshouldbeenough|i64.clzi64.clz|i64.ctzi64.ctz|i64.popcnti64.popcnt|i64.addi64.add|i64.subi64.sub|i64.muli64.mul|i64.div_si64.div_s|i64.div_ui64.div_u|i64.rem_si64.rem_s|i64.rem_ui64.rem_u|i64.andi64.and|i64.ori64.or|i64.xori64.xor|i64.shli64.shl|i64.shr_si64.shr_s|i64.shr_ui64.shr_u|i64.rotli64.rotl|i64.rotri64.rotr
plaininstrI::=thisisenoughthisshouldbeenough|f32.absf32.abs|f32.negf32.neg|f32.ceilf32.ceil|f32.floorf32.floor|f32.truncf32.trunc|f32.nearestf32.nearest|f32.sqrtf32.sqrt|f32.addf32.add|f32.subf32.sub|f32.mulf32.mul|f32.divf32.div|f32.minf32.min|f32.maxf32.max|f32.copysignf32.copysign
plaininstrI::=thisisenoughthisshouldbeenough|f64.absf64.abs|f64.negf64.neg|f64.ceilf64.ceil|f64.floorf64.floor|f64.truncf64.trunc|f64.nearestf64.nearest|f64.sqrtf64.sqrt|f64.addf64.add|f64.subf64.sub|f64.mulf64.mul|f64.divf64.div|f64.minf64.min|f64.maxf64.max|f64.copysignf64.copysign
plaininstrI::=thisisenoughthisshouldbeenough|i32.eqzi32.eqz|i32.eqi32.eq|i32.nei32.ne|i32.lt_si32.lt_s|i32.lt_ui32.lt_u|i32.gt_si32.gt_s|i32.gt_ui32.gt_u|i32.le_si32.le_s|i32.le_ui32.le_u|i32.ge_si32.ge_s|i32.ge_ui32.ge_u
plaininstrI::=thisisenoughthisshouldbeenough|i64.eqzi64.eqz|i64.eqi64.eq|i64.nei64.ne|i64.lt_si64.lt_s|i64.lt_ui64.lt_u|i64.gt_si64.gt_s|i64.gt_ui64.gt_u|i64.le_si64.le_s|i64.le_ui64.le_u|i64.ge_si64.ge_s|i64.ge_ui64.ge_u
plaininstrI::=thisisenoughthisshouldbeenough|f32.eqf32.eq|f32.nef32.ne|f32.ltf32.lt|f32.gtf32.gt|f32.lef32.le|f32.gef32.ge
plaininstrI::=thisisenoughthisshouldbeenough|f64.eqf64.eq|f64.nef64.ne|f64.ltf64.lt|f64.gtf64.gt|f64.lef64.le|f64.gef64.ge
plaininstrI::=thisisenoughthisshouldbeenough|i32.wrap_i64i32.wrap_i64|i32.trunc_f32_si32.trunc_f32_s|i32.trunc_f32_ui32.trunc_f32_u|i32.trunc_f64_si32.trunc_f64_s|i32.trunc_f64_ui32.trunc_f64_u|i32.trunc_sat_f32_si32.trunc_sat_f32_s|i32.trunc_sat_f32_ui32.trunc_sat_f32_u|i32.trunc_sat_f64_si32.trunc_sat_f64_s|i32.trunc_sat_f64_ui32.trunc_sat_f64_u|i64.extend_i32_si64.extend_i32_s|i64.extend_i32_ui64.extend_i32_u|i64.trunc_f32_si64.trunc_f32_s|i64.trunc_f32_ui64.trunc_f32_u|i64.trunc_f64_si64.trunc_f64_s|i64.trunc_f64_ui64.trunc_f64_u|i64.trunc_sat_f32_si64.trunc_sat_f32_s|i64.trunc_sat_f32_ui64.trunc_sat_f32_u|i64.trunc_sat_f64_si64.trunc_sat_f64_s|i64.trunc_sat_f64_ui64.trunc_sat_f64_u|f32.convert_i32_sf32.convert_i32_s|f32.convert_i32_uf32.convert_i32_u|f32.convert_i64_sf32.convert_i64_s|f32.convert_i64_uf32.convert_i64_u|f32.demote_f64f32.demote_f64|f64.convert_i32_sf64.convert_i32_s|f64.convert_i32_uf64.convert_i32_u|f64.convert_i64_sf64.convert_i64_s|f64.convert_i64_uf64.convert_i64_u|f64.promote_f32f64.promote_f32|i32.reinterpret_f32i32.reinterpret_f32|i64.reinterpret_f64i64.reinterpret_f64|f32.reinterpret_i32f32.reinterpret_i32|f64.reinterpret_i64f64.reinterpret_i64
plaininstrI::=thisisenoughthisshouldbeenough|i32.extend8_si32.extend8_s|i32.extend16_si32.extend16_s|i64.extend8_si64.extend8_s|i64.extend16_si64.extend16_s|i64.extend32_si64.extend32_s

Vector Instructions

Vector memory instructions have optional offset and alignment immediates, like the memory instructions.

plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|v128.load  m:memarg16v128.load m|v128.load8x8_s  m:memarg8v128.load8x8_s m|v128.load8x8_u  m:memarg8v128.load8x8_u m|v128.load16x4_s  m:memarg8v128.load16x4_s m|v128.load16x4_u  m:memarg8v128.load16x4_u m|v128.load32x2_s  m:memarg8v128.load32x2_s m|v128.load32x2_u  m:memarg8v128.load32x2_u m|v128.load8_splat  m:memarg1v128.load8_splat m|v128.load16_splat  m:memarg2v128.load16_splat m|v128.load32_splat  m:memarg4v128.load32_splat m|v128.load64_splat  m:memarg8v128.load64_splat m|v128.load32_zero  m:memarg4v128.load32_zero m|v128.load64_zero  m:memarg8v128.load64_zero m|v128.store  m:memarg16v128.store m|v128.load8_lane  m:memarg1  laneidx:u8v128.load8_lane m laneidx|v128.load16_lane  m:memarg2  laneidx:u8v128.load16_lane m laneidx|v128.load32_lane  m:memarg4  laneidx:u8v128.load32_lane m laneidx|v128.load64_lane  m:memarg8  laneidx:u8v128.load64_lane m laneidx|v128.store8_lane  m:memarg1  laneidx:u8v128.store8_lane m laneidx|v128.store16_lane  m:memarg2  laneidx:u8v128.store16_lane m laneidx|v128.store32_lane  m:memarg4  laneidx:u8v128.store32_lane m laneidx|v128.store64_lane  m:memarg8  laneidx:u8v128.store64_lane m laneidx

Vector constant instructions have a mandatory shape descriptor, which determines how the following values are parsed.

plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|v128.const  i8x16  (n:i8)16v128.const bytesi1281(bytesi8(n)16)|v128.const  i16x8  (n:i16)8v128.const bytesi1281(bytesi16(n)8)|v128.const  i32x4  (n:i32)4v128.const bytesi1281(bytesi32(n)4)|v128.const  i64x2  (n:i64)2v128.const bytesi1281(bytesi64(n)2)|v128.const  f32x4  (z:f32)4v128.const bytesi1281(bytesf32(z)4)|v128.const  f64x2  (z:f64)2v128.const bytesi1281(bytesf64(z)2)
plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|i8x16.shuffle  (laneidx:u8)16i8x16.shuffle laneidx16|i8x16.swizzlei8x16.swizzle
plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|i8x16.splati8x16.splat|i16x8.splati16x8.splat|i32x4.splati32x4.splat|i64x2.splati64x2.splat|f32x4.splatf32x4.splat|f64x2.splatf64x2.splat
plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|i8x16.extract_lane_s  laneidx:u8i8x16.extract_lane_s laneidx|i8x16.extract_lane_u  laneidx:u8i8x16.extract_lane_u laneidx|i8x16.replace_lane  laneidx:u8i8x16.replace_lane laneidx|i16x8.extract_lane_s  laneidx:u8i16x8.extract_lane_s laneidx|i16x8.extract_lane_u  laneidx:u8i16x8.extract_lane_u laneidx|i16x8.replace_lane  laneidx:u8i16x8.replace_lane laneidx|i32x4.extract_lane  laneidx:u8i32x4.extract_lane laneidx|i32x4.replace_lane  laneidx:u8i32x4.replace_lane laneidx|i64x2.extract_lane  laneidx:u8i64x2.extract_lane laneidx|i64x2.replace_lane  laneidx:u8i64x2.replace_lane laneidx|f32x4.extract_lane  laneidx:u8f32x4.extract_lane laneidx|f32x4.replace_lane  laneidx:u8f32x4.replace_lane laneidx|f64x2.extract_lane  laneidx:u8f64x2.extract_lane laneidx|f64x2.replace_lane  laneidx:u8f64x2.replace_lane laneidx
plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|i8x16.eqi8x16.eq|i8x16.nei8x16.ne|i8x16.lt_si8x16.lt_s|i8x16.lt_ui8x16.lt_u|i8x16.gt_si8x16.gt_s|i8x16.gt_ui8x16.gt_u|i8x16.le_si8x16.le_s|i8x16.le_ui8x16.le_u|i8x16.ge_si8x16.ge_s|i8x16.ge_ui8x16.ge_u
plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|i16x8.eqi16x8.eq|i16x8.nei16x8.ne|i16x8.lt_si16x8.lt_s|i16x8.lt_ui16x8.lt_u|i16x8.gt_si16x8.gt_s|i16x8.gt_ui16x8.gt_u|i16x8.le_si16x8.le_s|i16x8.le_ui16x8.le_u|i16x8.ge_si16x8.ge_s|i16x8.ge_ui16x8.ge_u
plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|i32x4.eqi32x4.eq|i32x4.nei32x4.ne|i32x4.lt_si32x4.lt_s|i32x4.lt_ui32x4.lt_u|i32x4.gt_si32x4.gt_s|i32x4.gt_ui32x4.gt_u|i32x4.le_si32x4.le_s|i32x4.le_ui32x4.le_u|i32x4.ge_si32x4.ge_s|i32x4.ge_ui32x4.ge_u
plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|i64x2.eqi64x2.eq|i64x2.nei64x2.ne|i64x2.lt_si64x2.lt_s|i64x2.gt_si64x2.gt_s|i64x2.le_si64x2.le_s|i64x2.ge_si64x2.ge_s|
plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|f32x4.eqf32x4.eq|f32x4.nef32x4.ne|f32x4.ltf32x4.lt|f32x4.gtf32x4.gt|f32x4.lef32x4.le|f32x4.gef32x4.ge
plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|f64x2.eqf64x2.eq|f64x2.nef64x2.ne|f64x2.ltf64x2.lt|f64x2.gtf64x2.gt|f64x2.lef64x2.le|f64x2.gef64x2.ge
plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|v128.notv128.not|v128.andv128.and|v128.andnotv128.andnot|v128.orv128.or|v128.xorv128.xor|v128.bitselectv128.bitselect|v128.any_truev128.any_true
plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|i8x16.absi8x16.abs|i8x16.negi8x16.neg|i8x16.all_truei8x16.all_true|i8x16.bitmaski8x16.bitmask|i8x16.narrow_i16x8_si8x16.narrow_i16x8_s|i8x16.narrow_i16x8_ui8x16.narrow_i16x8_u|i8x16.shli8x16.shl|i8x16.shr_si8x16.shr_s|i8x16.shr_ui8x16.shr_u|i8x16.addi8x16.add|i8x16.add_sat_si8x16.add_sat_s|i8x16.add_sat_ui8x16.add_sat_u|i8x16.subi8x16.sub|i8x16.sub_sat_si8x16.sub_sat_s|i8x16.sub_sat_ui8x16.sub_sat_u|i8x16.min_si8x16.min_s|i8x16.min_ui8x16.min_u|i8x16.max_si8x16.max_s|i8x16.max_ui8x16.max_u|i8x16.avgr_ui8x16.avgr_u|i8x16.popcnti8x16.popcnt
plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|i16x8.absi16x8.abs|i16x8.negi16x8.neg|i16x8.all_truei16x8.all_true|i16x8.bitmaski16x8.bitmask|i16x8.narrow_i32x4_si16x8.narrow_i32x4_s|i16x8.narrow_i32x4_ui16x8.narrow_i32x4_u|i16x8.extend_low_i8x16_si16x8.extend_low_i8x16_s|i16x8.extend_high_i8x16_si16x8.extend_high_i8x16_s|i16x8.extend_low_i8x16_ui16x8.extend_low_i8x16_u|i16x8.extend_high_i8x16_ui16x8.extend_high_i8x16_u|i16x8.shli16x8.shl|i16x8.shr_si16x8.shr_s|i16x8.shr_ui16x8.shr_u|i16x8.addi16x8.add|i16x8.add_sat_si16x8.add_sat_s|i16x8.add_sat_ui16x8.add_sat_u|i16x8.subi16x8.sub|i16x8.sub_sat_si16x8.sub_sat_s|i16x8.sub_sat_ui16x8.sub_sat_u|i16x8.muli16x8.mul|i16x8.min_si16x8.min_s|i16x8.min_ui16x8.min_u|i16x8.max_si16x8.max_s|i16x8.max_ui16x8.max_u|i16x8.avgr_ui16x8.avgr_u|i16x8.q15mulr_sat_si16x8.q15mulr_sat_s|i16x8.extmul_low_i8x16_si16x8.extmul_low_i8x16_s|i16x8.extmul_high_i8x16_si16x8.extmul_high_i8x16_s|i16x8.extmul_low_i8x16_ui16x8.extmul_low_i8x16_u|i16x8.extmul_high_i8x16_ui16x8.extmul_high_i8x16_u|i16x8.extadd_pairwise_i8x16_si16x8.extadd_pairwise_i8x16_s|i16x8.extadd_pairwise_i8x16_ui16x8.extadd_pairwise_i8x16_u
plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|i32x4.absi32x4.abs|i32x4.negi32x4.neg|i32x4.all_truei32x4.all_true|i32x4.bitmaski32x4.bitmask|i32x4.extadd_pairwise_i16x8_si32x4.extadd_pairwise_i16x8_s|i32x4.extend_low_i16x8_si32x4.extend_low_i16x8_s|i32x4.extend_high_i16x8_si32x4.extend_high_i16x8_s|i32x4.extend_low_i16x8_ui32x4.extend_low_i16x8_u|i32x4.extend_high_i16x8_ui32x4.extend_high_i16x8_u|i32x4.shli32x4.shl|i32x4.shr_si32x4.shr_s|i32x4.shr_ui32x4.shr_u|i32x4.addi32x4.add|i32x4.subi32x4.sub|i32x4.muli32x4.mul|i32x4.min_si32x4.min_s|i32x4.min_ui32x4.min_u|i32x4.max_si32x4.max_s|i32x4.max_ui32x4.max_u|i32x4.dot_i16x8_si32x4.dot_i16x8_s|i32x4.extmul_low_i16x8_si32x4.extmul_low_i16x8_s|i32x4.extmul_high_i16x8_si32x4.extmul_high_i16x8_s|i32x4.extmul_low_i16x8_ui32x4.extmul_low_i16x8_u|i32x4.extmul_high_i16x8_ui32x4.extmul_high_i16x8_u
plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|i64x2.absi64x2.abs|i64x2.negi64x2.neg|i64x2.all_truei64x2.all_true|i64x2.bitmaski64x2.bitmask|i64x2.extend_low_i32x4_si64x2.extend_low_i32x4_s|i64x2.extend_high_i32x4_si64x2.extend_high_i32x4_s|i64x2.extend_low_i32x4_ui64x2.extend_low_i32x4_u|i64x2.extend_high_i32x4_ui64x2.extend_high_i32x4_u|i64x2.shli64x2.shl|i64x2.shr_si64x2.shr_s|i64x2.shr_ui64x2.shr_u|i64x2.addi64x2.add|i64x2.subi64x2.sub|i64x2.muli64x2.mul|i64x2.extmul_low_i32x4_si64x2.extmul_low_i32x4_s|i64x2.extmul_high_i32x4_si64x2.extmul_high_i32x4_s|i64x2.extmul_low_i32x4_ui64x2.extmul_low_i32x4_u|i64x2.extmul_high_i32x4_ui64x2.extmul_high_i32x4_u
plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|f32x4.absf32x4.abs|f32x4.negf32x4.neg|f32x4.sqrtf32x4.sqrt|f32x4.ceilf32x4.ceil|f32x4.floorf32x4.floor|f32x4.truncf32x4.trunc|f32x4.nearestf32x4.nearest|f32x4.addf32x4.add|f32x4.subf32x4.sub|f32x4.mulf32x4.mul|f32x4.divf32x4.div|f32x4.minf32x4.min|f32x4.maxf32x4.max|f32x4.pminf32x4.pmin|f32x4.pmaxf32x4.pmax
plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|f64x2.absf64x2.abs|f64x2.negf64x2.neg|f64x2.sqrtf64x2.sqrt|f64x2.ceilf64x2.ceil|f64x2.floorf64x2.floor|f64x2.truncf64x2.trunc|f64x2.nearestf64x2.nearest|f64x2.addf64x2.add|f64x2.subf64x2.sub|f64x2.mulf64x2.mul|f64x2.divf64x2.div|f64x2.minf64x2.min|f64x2.maxf64x2.max|f64x2.pminf64x2.pmin|f64x2.pmaxf64x2.pmax
plaininstrI::=averylonginstructionnameforvectextvechasreallylonginstructionnames|i32x4.trunc_sat_f32x4_si32x4.trunc_sat_f32x4_s|i32x4.trunc_sat_f32x4_ui32x4.trunc_sat_f32x4_u|i32x4.trunc_sat_f64x2_s_zeroi32x4.trunc_sat_f64x2_s_zero|i32x4.trunc_sat_f64x2_u_zeroi32x4.trunc_sat_f64x2_u_zero|f32x4.convert_i32x4_sf32x4.convert_i32x4_s|f32x4.convert_i32x4_uf32x4.convert_i32x4_u|f64x2.convert_low_i32x4_sf64x2.convert_low_i32x4_s|f64x2.convert_low_i32x4_uf64x2.convert_low_i32x4_u|f32x4.demote_f64x2_zerof32x4.demote_f64x2_zero|f64x2.promote_low_f32x4f64x2.promote_low_f32x4

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 end delimiter. For if instructions, both branches have to be wrapped into nested S-expressions, headed by the keywords then and else.

The set of all phrases defined by the following abbreviations recursively forms the auxiliary syntactic class foldedinstr. Such a folded instruction can appear anywhere a regular instruction can.

( plaininstr  foldedinstr )foldedinstr  plaininstr( block  label  blocktype  instr )block  label  blocktype  instr  end( loop  label  blocktype  instr )loop  label  blocktype  instr  end( if  label  blocktype  foldedinstr( then  instr1 )  (( else  instr2 ))?  )foldedinstr  if  label  blocktypeinstr1  else  (instr2)? end

Note

For example, the instruction sequence

(local.get $x) (i32.const 2) i32.add (i32.const 3) i32.mul

can be folded into

(i32.mul (i32.add (local.get $x) (i32.const 2)) (i32.const 3))

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

Expressions

Expressions are written as instruction sequences. No explicit end keyword is included, since they only occur in bracketed positions.

exprI::=(in:instrI)in end