Kwasm.format.binary.instruction
package kwasm.format.binary.instruction
Methods
readControlInstruction
fun BinaryParser.readControlInstruction(opcode: Int): ControlInstruction
Receiver
Name | Description |
---|---|
BinaryParser
|
Parameters
Name | Description |
---|---|
opcode: Int
|
ReturnValue
Name | Description |
---|---|
ControlInstruction
|
readExpression
fun BinaryParser.readExpression(): Expression
From the docs:
Expressions are encoded by their instruction sequence terminated with an explicit 0x0B
opcode for end.
expr ::= (in:instr)* 0x0B => in* end
Receiver
Name | Description |
---|---|
BinaryParser
|
ReturnValue
Name | Description |
---|---|
Expression
|
readInstruction
fun BinaryParser.readInstruction(): Instruction?
Parses an instruction given the opcode byte provided, or throws a ParseException if no
instruction can be found for the provided opcode. Returns null if end
was read.
From the docs:
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.
Receiver
Name | Description |
---|---|
BinaryParser
|
ReturnValue
Name | Description |
---|---|
Instruction?
|
readMemoryInstruction
fun BinaryParser.readMemoryInstruction(opcode: Int): Instruction
From the docs:
Each variant of memory instruction is encoded with a different byte code. Loads and stores are
followed by the encoding of their memarg
immediate.
memarg ::= a:u32 o:u32 => {align a, offset o}
instr ::= 0x28 m:memarg => i32.load m
0x29 m:memarg => i64.load m
0x2A m:memarg => f32.load m
0x2B m:memarg => f64.load m
0x2C m:memarg => i32.load8_s m
0x2D m:memarg => i32.load8_u m
0x2E m:memarg => i32.load16_s m
0x2F m:memarg => i32.load16_u m
0x30 m:memarg => i64.load8_s m
0x31 m:memarg => i64.load8_u m
0x32 m:memarg => i64.load16_s m
0x33 m:memarg => i64.load16_u m
0x34 m:memarg => i64.load32_s m
0x35 m:memarg => i64.load32_u m
0x36 m:memarg => i32.store m
0x37 m:memarg => i64.store m
0x38 m:memarg => f32.store m
0x39 m:memarg => f64.store m
0x3A m:memarg => i32.store8 m
0x3B m:memarg => i32.store16 m
0x3C m:memarg => i64.store8 m
0x3D m:memarg => i64.store16 m
0x3E m:memarg => i64.store32 m
0x3F 0x00 => memory.size
0x40 0x00 => memory.grow
Note
In future versions of WebAssembly, the additional zero bytes occurring in the encoding of the
memory.size
and memory.grow
instructions may be used to index additional memories.
Receiver
Name | Description |
---|---|
BinaryParser
|
Parameters
Name | Description |
---|---|
opcode: Int
|
ReturnValue
Name | Description |
---|---|
Instruction
|
readMemoryArg
fun BinaryParser.readMemoryArg(): MemArg
Reads a MemArg node from the binary stream.
Receiver
Name | Description |
---|---|
BinaryParser
|
ReturnValue
Name | Description |
---|---|
MemArg
|
readNumericInstruction
fun BinaryParser.readNumericInstruction(opcode: Int): Instruction
From the docs :
All variants of numeric instructions are represented by separate byte codes.
The const
instructions are followed by the respective literal.
instr ::= 0x41 n:i32 => i32.const n
0x42 n:i64 => i64.const n
0x43 z:f32 => f32.const z
0x44 z:f64 => f64.const z
All other numeric instructions are plain opcodes without any immediates.
instr ::= 0x45 => i32.eqz
0x46 => i32.eq
0x47 => i32.ne
0x48 => i32.lt_s
0x49 => i32.lt_u
0x4A => i32.gt_s
0x4B => i32.gt_u
0x4C => i32.le_s
0x4D => i32.le_u
0x4E => i32.ge_s
0x4F => i32.ge_u
0x50 => i64.eqz
0x51 => i64.eq
0x52 => i64.ne
0x53 => i64.lt_s
0x54 => i64.lt_u
0x55 => i64.gt_s
0x56 => i64.gt_u
0x57 => i64.le_s
0x58 => i64.le_u
0x59 => i64.ge_s
0x5A => i64.ge_u
0x5B => f32.eq
0x5C => f32.ne
0x5D => f32.lt
0x5E => f32.gt
0x5F => f32.le
0x60 => f32.ge
0x61 => f64.eq
0x62 => f64.ne
0x63 => f64.lt
0x64 => f64.gt
0x65 => f64.le
0x66 => f64.ge
0x67 => i32.clz
0x68 => i32.ctz
0x69 => i32.popcnt
0x6A => i32.add
0x6B => i32.sub
0x6C => i32.mul
0x6D => i32.div_s
0x6E => i32.div_u
0x6F => i32.rem_s
0x70 => i32.rem_u
0x71 => i32.and
0x72 => i32.or
0x73 => i32.xor
0x74 => i32.shl
0x75 => i32.shr_s
0x76 => i32.shr_u
0x77 => i32.rotl
0x78 => i32.rotr
0x79 => i64.clz
0x7A => i64.ctz
0x7B => i64.popcnt
0x7C => i64.add
0x7D => i64.sub
0x7E => i64.mul
0x7F => i64.div_s
0x80 => i64.div_u
0x81 => i64.rem_s
0x82 => i64.rem_u
0x83 => i64.and
0x84 => i64.or
0x85 => i64.xor
0x86 => i64.shl
0x87 => i64.shr_s
0x88 => i64.shr_u
0x89 => i64.rotl
0x8A => i64.rotr
0x8B => f32.abs
0x8C => f32.neg
0x8D => f32.ceil
0x8E => f32.floor
0x8F => f32.trunc
0x90 => f32.nearest
0x91 => f32.sqrt
0x92 => f32.add
0x93 => f32.sub
0x94 => f32.mul
0x95 => f32.div
0x96 => f32.min
0x97 => f32.max
0x98 => f32.copysign
0x99 => f64.abs
0x9A => f64.neg
0x9B => f64.ceil
0x9C => f64.floor
0x9D => f64.trunc
0x9E => f64.nearest
0x9F => f64.sqrt
0xA0 => f64.add
0xA1 => f64.sub
0xA2 => f64.mul
0xA3 => f64.div
0xA4 => f64.min
0xA5 => f64.max
0xA6 => f64.copysign
0xA7 => i32.wrap_i64
0xA8 => i32.trunc_f32_s
0xA9 => i32.trunc_f32_u
0xAA => i32.trunc_f64_s
0xAB => i32.trunc_f64_u
0xAC => i64.extend_i32_s
0xAD => i64.extend_i32_u
0xAE => i64.trunc_f32_s
0xAF => i64.trunc_f32_u
0xB0 => i64.trunc_f64_s
0xB1 => i64.trunc_f64_u
0xB2 => f32.convert_i32_s
0xB3 => f32.convert_i32_u
0xB4 => f32.convert_i64_s
0xB5 => f32.convert_i64_u
0xB6 => f32.demote_f64
0xB7 => f64.convert_i32_s
0xB8 => f64.convert_i32_u
0xB9 => f64.convert_i64_s
0xBA => f64.convert_i64_u
0xBB => f64.promote_f32
0xBC => i32.reinterpret_f32
0xBD => i64.reinterpret_f64
0xBE => f32.reinterpret_i32
0xBF => f64.reinterpret_i64
0xC0 => i32.extend8_s
0xC1 => i32.extend16_s
0xC2 => i64.extend8_s
0xC3 => i64.extend16_s
0xC4 => i64.extend32_s
The saturating truncation instructions all have a one byte prefix, whereas the actual opcode is encoded by a variable-length unsigned integer.
instr ::= 0xFC 0:u32 => i32.trunc_sat_f32_s
0xFC 1:u32 => i32.trunc_sat_f32_u
0xFC 2:u32 => i32.trunc_sat_f64_s
0xFC 3:u32 => i32.trunc_sat_f64_u
0xFC 4:u32 => i64.trunc_sat_f32_s
0xFC 5:u32 => i64.trunc_sat_f32_u
0xFC 6:u32 => i64.trunc_sat_f64_s
0xFC 7:u32 => i64.trunc_sat_f64_u
Receiver
Name | Description |
---|---|
BinaryParser
|
Parameters
Name | Description |
---|---|
opcode: Int
|
ReturnValue
Name | Description |
---|---|
Instruction
|
readParametricInstruction
fun BinaryParser.readParametricInstruction(opcode: Int): ParametricInstruction
From the docs:
Parametric instructions are represented by single byte codes.
instr ::= 0x1A => drop
0x1B => select
Receiver
Name | Description |
---|---|
BinaryParser
|
Parameters
Name | Description |
---|---|
opcode: Int
|
ReturnValue
Name | Description |
---|---|
ParametricInstruction
|
readVariableInstruction
fun BinaryParser.readVariableInstruction(opcode: Int): VariableInstruction
From the docs:
Variable instructions are represented by byte codes followed by the encoding of the respective index.
instr ::= 0x20 x:localidx => local.get x
0x21 x:localidx => local.set x
0x22 x:localidx => local.tee x
0x23 x:globalidx => global.get x
0x24 x:globalidx => global.set x
Receiver
Name | Description |
---|---|
BinaryParser
|
Parameters
Name | Description |
---|---|
opcode: Int
|
ReturnValue
Name | Description |
---|---|
VariableInstruction
|
From the docs:
Control instructions have varying encodings. For structured instructions, the instruction sequences forming nested blocks are terminated with explicit opcodes for
end
andelse
.Block types are encoded in special compressed form, by either the byte
0x40
indicating the empty type, as a single value type, or as a type index encoded as a positive signed integer.Note The
else
opcode0x05
in the encoding of anif
instruction can be omitted if the following instruction sequence is empty.Unlike any other occurrence, the type index in a block type is encoded as a positive signed integer, so that its signed LEB128 bit pattern cannot collide with the encoding of value types or the special code
0x40
, which correspond to the LEB128 encoding of negative integers. To avoid any loss in the range of allowed indices, it is treated as a 33 bit signed integer.In future versions of WebAssembly, the zero byte occurring in the encoding of the
call_indirect
instruction may be used to index additional tables.