Commit 1777fb25bc

Luuk de Gram <luuk@degram.dev>
2021-11-30 20:12:34
wasm: Implement WrapErrorUnionErr(payload)
1 parent e81fda9
Changed files (2)
src
arch
link
src/arch/wasm/CodeGen.zig
@@ -1148,6 +1148,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
         .unwrap_errunion_payload => self.airUnwrapErrUnionPayload(inst),
         .unwrap_errunion_err => self.airUnwrapErrUnionError(inst),
         .wrap_errunion_payload => self.airWrapErrUnionPayload(inst),
+        .wrap_errunion_err => self.airWrapErrUnionErr(inst),
 
         .optional_payload => self.airOptionalPayload(inst),
         .optional_payload_ptr => self.airOptionalPayload(inst),
@@ -1328,16 +1329,15 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro
                     return;
                 },
                 .local => {
-                    // Load values from `rhs` stack position and store in `lhs` instead
-                    const tag_local = try self.load(rhs, tag_ty, 0);
-                    const payload_local = try self.load(rhs, payload_ty, payload_offset);
-
-                    try self.store(lhs, tag_local, tag_ty, 0);
-                    return try self.store(lhs, payload_local, payload_ty, payload_offset);
+                    if (payload_ty.hasCodeGenBits()) {
+                        try self.store(lhs, rhs, payload_ty, payload_offset);
+                    }
+                    return try self.store(lhs, rhs, tag_ty, 0);
                 },
                 .local_with_offset => |with_offset| {
                     const tag_local = try self.allocLocal(tag_ty);
                     try self.addImm32(0);
+                    try self.addLabel(.local_set, tag_local.local);
                     try self.store(lhs, tag_local, tag_ty, 0);
 
                     return try self.store(
@@ -1415,7 +1415,10 @@ fn load(self: *Self, operand: WValue, ty: Type, offset: u32) InnerError!WValue {
     // load local's value from memory by its stack position
     try self.emitWValue(operand);
     // Build the opcode with the right bitsize
-    const signedness: std.builtin.Signedness = if (ty.isUnsignedInt()) .unsigned else .signed;
+    const signedness: std.builtin.Signedness = if (ty.isUnsignedInt() or ty.zigTypeTag() == .ErrorSet)
+        .unsigned
+    else
+        .signed;
     // check if we should pass by pointer or value based on ABI size
     // TODO: Implement a way to get ABI values from a given type,
     // that is portable across the backend, rather than copying logic.
@@ -2081,9 +2084,25 @@ fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
 }
 
 fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
+    if (self.liveness.isUnused(inst)) return WValue.none;
+    const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+    const operand = self.resolveInst(ty_op.operand);
+
+    const op_ty = self.air.typeOf(ty_op.operand);
+    if (!op_ty.hasCodeGenBits()) return WValue.none;
+    const err_ty = self.air.getRefType(ty_op.ty);
+    const offset = err_ty.errorUnionSet().abiSize(self.target);
+
+    return WValue{ .local_with_offset = .{
+        .local = operand.local,
+        .offset = @intCast(u32, offset),
+    } };
+}
+
+fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
+    if (self.liveness.isUnused(inst)) return WValue.none;
     const ty_op = self.air.instructions.items(.data)[inst].ty_op;
-    _ = ty_op;
-    return self.fail("TODO: wasm airWrapErrUnionPayload", .{});
+    return self.resolveInst(ty_op.operand);
 }
 
 fn airIntcast(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
src/link/Wasm.zig
@@ -162,9 +162,8 @@ pub fn deinit(self: *Wasm) void {
         decl.link.wasm.deinit(self.base.allocator);
     }
 
-    for (self.func_types.items) |func_type| {
-        self.base.allocator.free(func_type.params);
-        self.base.allocator.free(func_type.returns);
+    for (self.func_types.items) |*func_type| {
+        func_type.deinit(self.base.allocator);
     }
     for (self.segment_info.items) |segment_info| {
         self.base.allocator.free(segment_info.name);
@@ -574,7 +573,6 @@ fn resetState(self: *Wasm) void {
     self.segments.clearRetainingCapacity();
     self.segment_info.clearRetainingCapacity();
     self.data_segments.clearRetainingCapacity();
-    self.function_table.clearRetainingCapacity();
     self.atoms.clearRetainingCapacity();
     self.code_section_index = null;
 }
@@ -684,12 +682,16 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void {
         );
     }
 
+    // Table section
     if (self.function_table.count() > 0) {
         const header_offset = try reserveVecSectionHeader(file);
         const writer = file.writer();
 
         try leb.writeULEB128(writer, wasm.reftype(.funcref));
-        try emitLimits(writer, .{ .min = 1, .max = null });
+        try emitLimits(writer, .{
+            .min = @intCast(u32, self.function_table.count()),
+            .max = null,
+        });
 
         try writeVecSectionHeader(
             file,