zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 8a81dfc9997c4ae8a109071be9754d3bb52a78f0 (tree)
parent 967a299c346937316158f58f3d3ae1be7ee0f551
Author: Luuk de Gram <Luukdegram@users.noreply.github.com>
Date:   Fri, 28 May 2021 10:50:16 +0200

wasm: Reverse the order of error and payload

This will set us up to correctly retrieve the error local index and payload index
depending on that of the multi_value's index. As from now, the error will always use
the multi_value's index, and the payload will use the following locals.

Diffstat:
Msrc/codegen/wasm.zig | 37+++++++++++++++++++++----------------
1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/src/codegen/wasm.zig b/src/codegen/wasm.zig @@ -623,7 +623,8 @@ pub const Context = struct { .Struct => { // for each struct field, generate a local const struct_data: *Module.Struct = ty.castTag(.@"struct").?.data; - try self.locals.ensureCapacity(self.gpa, self.locals.items.len + struct_data.fields.count()); + const fields_len = @intCast(u32, struct_data.fields.count()); + try self.locals.ensureCapacity(self.gpa, self.locals.items.len + fields_len); for (struct_data.fields.items()) |entry| { const val_type = try self.genValtype( .{ .node_offset = struct_data.node_offset }, @@ -634,19 +635,20 @@ pub const Context = struct { } return WValue{ .multi_value = .{ .index = initial_index, - .count = @intCast(u32, struct_data.fields.count()), + .count = fields_len, } }; }, .ErrorUnion => { - // generate a local for both the error and the payload. const payload_type = ty.errorUnionChild(); + const val_type = try self.genValtype(.{ .node_offset = 0 }, payload_type); - // we emit the payload value as the first local, and the error as the second - // The first local is also used to find the index of the error. + // we emit the error value as the first local, and the payload as the following. + // The first local is also used to find the index of the error and payload. + // + // TODO: Add support where the payload is a type that contains multiple locals such as a struct. try self.locals.ensureCapacity(self.gpa, self.locals.items.len + 2); - const val_type = try self.genValtype(.{ .node_offset = 0 }, payload_type); - self.locals.appendAssumeCapacity(val_type); self.locals.appendAssumeCapacity(wasm.valtype(.i32)); // error values are always i32 + self.locals.appendAssumeCapacity(val_type); self.local_index += 2; return WValue{ .multi_value = .{ @@ -1039,6 +1041,9 @@ pub const Context = struct { const error_type = ty.errorUnionSet(); const payload_type = ty.errorUnionChild(); if (value.getError()) |_| { + // write the error value + try self.emitConstant(src, data, error_type); + // no payload, so write a '0' const const opcode: wasm.Opcode = buildOpcode(.{ .op = .@"const", @@ -1046,15 +1051,12 @@ pub const Context = struct { }); try writer.writeByte(wasm.opcode(opcode)); try leb.writeULEB128(writer, @as(u32, 0)); - - // write the error value - try self.emitConstant(src, data, error_type); } else { - // payload first - try self.emitConstant(src, data, payload_type); // no error, so write a '0' const try writer.writeByte(wasm.opcode(.i32_const)); try leb.writeULEB128(writer, @as(u32, 0)); + // after the error code, we emit the payload + try self.emitConstant(src, data, payload_type); } }, else => |zig_type| return self.fail(src, "Wasm TODO: emitConstant for zigTypeTag {s}", .{zig_type}), @@ -1278,8 +1280,8 @@ pub const Context = struct { const offset = self.code.items.len; const writer = self.code.writer(); - // load the error value which is the payload's multi_value index + 1 - try self.emitWValue(.{ .local = operand.multi_value.index + 1 }); + // load the error value which is positioned at multi_value's index + try self.emitWValue(.{ .local = operand.multi_value.index }); // Compare the error value with '0' try writer.writeByte(wasm.opcode(.i32_const)); try leb.writeILEB128(writer, @as(i32, 0)); @@ -1293,8 +1295,11 @@ pub const Context = struct { fn genUnwrapErrUnionPayload(self: *Context, inst: *Inst.UnOp) InnerError!WValue { const operand = self.resolveInst(inst.operand); - // payload's local index is that of its multi_value index, so convert it to a `WValue.local` - return WValue{ .local = operand.multi_value.index }; + // The index of multi_value contains the error code. To get the initial index of the payload we get + // the following index. Next, convert it to a `WValue.local` + // + // TODO: Check if payload is a type that requires a multi_value as well and emit that instead. i.e. a struct. + return WValue{ .local = operand.multi_value.index + 1 }; } fn genWrapErrUnionPayload(self: *Context, inst: *Inst.UnOp) InnerError!WValue {