kwasm.format.binary.instruction

Kwasm.format.binary.instruction

package kwasm.format.binary.instruction

Methods

readControlInstruction

fun BinaryParser.readControlInstruction(opcode: Int): ControlInstruction

From the docs:

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

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.


blocktype   ::= 0x40                                => ϵ
t:valtype                           => t
x:s33                               => x (if x >= 0)
instr       ::= 0x00                                => unreachable
0x01                                => nop
0x02 bt:blocktype (in:instr)* 0x0B  => block bt in* end
0x03 bt:blocktype (in:instr)* 0x0B  => loop bt in* end
0x04 bt:blocktype (in:instr)* 0x0B  => if bt in* else ϵ end
0x04 bt:blocktype (in1:instr)* 0x05 (in2:instr)* 0x0B
=> if bt in1 else in2 end
0x0C l:labelidx                     => br l
0x0D l:labelidx                     => br_if l
0x0E l*:vec(labelidx) l_N:labelidx  => br_table l* l_N
0x0F                                => return
0x10 x:funcidx                      => call x
0x11 x:typeidx 0x00                 => call_indirect x

Note The else opcode 0x05 in the encoding of an if 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.

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