Commit 0d66112643
Changed files (4)
lib
std
src
arch
lib/std/wasm.zig
@@ -215,7 +215,9 @@ test "Wasm - opcodes" {
}
/// Opcodes that require a prefix `0xFC`
-pub const PrefixedOpcode = enum(u8) {
+/// Each opcode represents a varuint32, meaning
+/// they are encoded as leb128 in binary.
+pub const PrefixedOpcode = enum(u32) {
i32_trunc_sat_f32_s = 0x00,
i32_trunc_sat_f32_u = 0x01,
i32_trunc_sat_f64_s = 0x02,
src/arch/wasm/CodeGen.zig
@@ -905,7 +905,9 @@ fn addTag(func: *CodeGen, tag: Mir.Inst.Tag) error{OutOfMemory}!void {
}
fn addExtended(func: *CodeGen, opcode: wasm.PrefixedOpcode) error{OutOfMemory}!void {
- try func.addInst(.{ .tag = .extended, .secondary = @enumToInt(opcode), .data = .{ .tag = {} } });
+ const extra_index = @intCast(u32, func.mir_extra.items.len);
+ try func.mir_extra.append(func.gpa, @enumToInt(opcode));
+ try func.addInst(.{ .tag = .extended, .data = .{ .payload = extra_index } });
}
fn addLabel(func: *CodeGen, tag: Mir.Inst.Tag, label: u32) error{OutOfMemory}!void {
src/arch/wasm/Emit.zig
@@ -423,9 +423,40 @@ fn emitMemAddress(emit: *Emit, inst: Mir.Inst.Index) !void {
}
fn emitExtended(emit: *Emit, inst: Mir.Inst.Index) !void {
- const opcode = emit.mir.instructions.items(.secondary)[inst];
+ const extra_index = emit.mir.instructions.items(.data)[inst].payload;
+ const opcode = emit.mir.extra[extra_index];
+ const writer = emit.code.writer();
+ try emit.code.append(0xFC);
+ try leb128.writeULEB128(writer, opcode);
switch (@intToEnum(std.wasm.PrefixedOpcode, opcode)) {
- .memory_fill => try emit.emitMemFill(),
+ // bulk-memory opcodes
+ .data_drop => {
+ const segment = emit.mir.extra[extra_index + 1];
+ try leb128.writeULEB128(writer, segment);
+ },
+ .memory_init => {
+ const segment = emit.mir.extra[extra_index + 1];
+ try leb128.writeULEB128(writer, segment);
+ try leb128.writeULEB128(writer, @as(u32, 0)); // memory index
+ },
+ .memory_fill => {
+ try leb128.writeULEB128(writer, @as(u32, 0)); // memory index
+ },
+ .memory_copy => {
+ try leb128.writeULEB128(writer, @as(u32, 0)); // dst memory index
+ try leb128.writeULEB128(writer, @as(u32, 0)); // src memory index
+ },
+
+ // nontrapping-float-to-int-conversion opcodes
+ .i32_trunc_sat_f32_s,
+ .i32_trunc_sat_f32_u,
+ .i32_trunc_sat_f64_s,
+ .i32_trunc_sat_f64_u,
+ .i64_trunc_sat_f32_s,
+ .i64_trunc_sat_f32_u,
+ .i64_trunc_sat_f64_s,
+ .i64_trunc_sat_f64_u,
+ => {}, // opcode already written
else => |tag| return emit.fail("TODO: Implement extension instruction: {s}\n", .{@tagName(tag)}),
}
}
src/arch/wasm/Mir.zig
@@ -19,9 +19,6 @@ extra: []const u32,
pub const Inst = struct {
/// The opcode that represents this instruction
tag: Tag,
- /// This opcode will be set when `tag` represents an extended
- /// instruction with prefix 0xFC, or a simd instruction with prefix 0xFD.
- secondary: u8 = 0,
/// Data is determined by the set `tag`.
/// For example, `data` will be an i32 for when `tag` is 'i32_const'.
data: Data,
@@ -513,10 +510,11 @@ pub const Inst = struct {
i64_extend16_s = 0xC3,
/// Uses `tag`
i64_extend32_s = 0xC4,
- /// The instruction consists of an extension opcode
- /// set in `secondary`
+ /// The instruction consists of an extension opcode.
+ /// The prefixed opcode can be found at payload's index.
///
- /// The `data` field depends on the extension instruction
+ /// The `data` field depends on the extension instruction and
+ /// may contain additional data.
extended = 0xFC,
/// The instruction consists of a simd opcode.
/// The actual simd-opcode is found at payload's index.