diff --git a/lib/std/wasm.zig b/lib/std/wasm.zig index 0e61b3fb3007b42b9d3e2a948b78cd7ea9c02941..2d519ace8b20860666be14bedbed9adb4678e531 100644 --- a/lib/std/wasm.zig +++ b/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, diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index ed7f0303deea60ddbc09454b98f43d61dd56a208..21d792697899d2fdf6f579aa46f362ffabe2184f 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/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 { diff --git a/src/arch/wasm/Emit.zig b/src/arch/wasm/Emit.zig index 45e02e0986668f5dadf3e04462c77e33f06ff63a..71d21d2797e7341c0d2cfe98f8d0513c717dc7c9 100644 --- a/src/arch/wasm/Emit.zig +++ b/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)}), } } diff --git a/src/arch/wasm/Mir.zig b/src/arch/wasm/Mir.zig index 66969a9c218acc258d25b5baa8247ad41f12e284..2d59c09e186b5b3fb78999c85b442cc1e5dfb624 100644 --- a/src/arch/wasm/Mir.zig +++ b/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.