authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-05-23 22:06:27+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-24 15:34:52-07:00
log3a059ebe4c84a1e541bb3b2ccee2e7cc25686a4d
tree5b1db05ab7e4b261ffa9372b536ca39cbf577f39
parentc90a97f9be9ffef858b0e450de5006f61a12fafd

wasm: Fixes for error union semantics


3 files changed, 110 insertions(+), 51 deletions(-)

src/arch/wasm/CodeGen.zig+107-47
...@@ -636,7 +636,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!WValue {...@@ -636,7 +636,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!WValue {
636 // means we must generate it from a constant.636 // means we must generate it from a constant.
637 const val = self.air.value(ref).?;637 const val = self.air.value(ref).?;
638 const ty = self.air.typeOf(ref);638 const ty = self.air.typeOf(ref);
639 if (!ty.hasRuntimeBitsIgnoreComptime() and !ty.isInt()) {639 if (!ty.hasRuntimeBitsIgnoreComptime() and !ty.isInt() and !ty.isError()) {
640 gop.value_ptr.* = WValue{ .none = {} };640 gop.value_ptr.* = WValue{ .none = {} };
641 return gop.value_ptr.*;641 return gop.value_ptr.*;
642 }642 }
...@@ -804,6 +804,8 @@ fn genFunctype(gpa: Allocator, fn_info: Type.Payload.Function.Data, target: std....@@ -804,6 +804,8 @@ fn genFunctype(gpa: Allocator, fn_info: Type.Payload.Function.Data, target: std.
804 } else {804 } else {
805 try returns.append(typeToValtype(fn_info.return_type, target));805 try returns.append(typeToValtype(fn_info.return_type, target));
806 }806 }
807 } else if (fn_info.return_type.isError()) {
808 try returns.append(.i32);
807 }809 }
808810
809 // param types811 // param types
...@@ -1373,10 +1375,15 @@ fn isByRef(ty: Type, target: std.Target) bool {...@@ -1373,10 +1375,15 @@ fn isByRef(ty: Type, target: std.Target) bool {
1373 .Int => return ty.intInfo(target).bits > 64,1375 .Int => return ty.intInfo(target).bits > 64,
1374 .Float => return ty.floatBits(target) > 64,1376 .Float => return ty.floatBits(target) > 64,
1375 .ErrorUnion => {1377 .ErrorUnion => {
1376 const has_tag = ty.errorUnionSet().hasRuntimeBitsIgnoreComptime();1378 const err_ty = ty.errorUnionSet();
1377 const has_pl = ty.errorUnionPayload().hasRuntimeBitsIgnoreComptime();1379 const pl_ty = ty.errorUnionPayload();
1378 if (!has_tag or !has_pl) return false;1380 if (err_ty.errorSetCardinality() == .zero) {
1379 return ty.hasRuntimeBitsIgnoreComptime();1381 return isByRef(pl_ty, target);
1382 }
1383 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {
1384 return false;
1385 }
1386 return true;
1380 },1387 },
1381 .Optional => {1388 .Optional => {
1382 if (ty.isPtrLikeOptional()) return false;1389 if (ty.isPtrLikeOptional()) return false;
...@@ -1624,13 +1631,14 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -1624,13 +1631,14 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1624fn airRet(self: *Self, inst: Air.Inst.Index) InnerError!WValue {1631fn airRet(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
1625 const un_op = self.air.instructions.items(.data)[inst].un_op;1632 const un_op = self.air.instructions.items(.data)[inst].un_op;
1626 const operand = try self.resolveInst(un_op);1633 const operand = try self.resolveInst(un_op);
1627 const ret_ty = self.decl.ty.fnReturnType();1634 const fn_info = self.decl.ty.fnInfo();
1635 const ret_ty = fn_info.return_type;
16281636
1629 // result must be stored in the stack and we return a pointer1637 // result must be stored in the stack and we return a pointer
1630 // to the stack instead1638 // to the stack instead
1631 if (self.return_value != .none) {1639 if (self.return_value != .none) {
1632 try self.store(self.return_value, operand, self.decl.ty.fnReturnType(), 0);1640 try self.store(self.return_value, operand, ret_ty, 0);
1633 } else if (self.decl.ty.fnInfo().cc == .C and ret_ty.hasRuntimeBitsIgnoreComptime()) {1641 } else if (fn_info.cc == .C and ret_ty.hasRuntimeBitsIgnoreComptime()) {
1634 switch (ret_ty.zigTypeTag()) {1642 switch (ret_ty.zigTypeTag()) {
1635 // Aggregate types can be lowered as a singular value1643 // Aggregate types can be lowered as a singular value
1636 .Struct, .Union => {1644 .Struct, .Union => {
...@@ -1650,7 +1658,11 @@ fn airRet(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -1650,7 +1658,11 @@ fn airRet(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
1650 else => try self.emitWValue(operand),1658 else => try self.emitWValue(operand),
1651 }1659 }
1652 } else {1660 } else {
1653 try self.emitWValue(operand);1661 if (!ret_ty.hasRuntimeBitsIgnoreComptime() and ret_ty.isError()) {
1662 try self.addImm32(0);
1663 } else {
1664 try self.emitWValue(operand);
1665 }
1654 }1666 }
1655 try self.restoreStackPointer();1667 try self.restoreStackPointer();
1656 try self.addTag(.@"return");1668 try self.addTag(.@"return");
...@@ -1675,7 +1687,13 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -1675,7 +1687,13 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
1675 const un_op = self.air.instructions.items(.data)[inst].un_op;1687 const un_op = self.air.instructions.items(.data)[inst].un_op;
1676 const operand = try self.resolveInst(un_op);1688 const operand = try self.resolveInst(un_op);
1677 const ret_ty = self.air.typeOf(un_op).childType();1689 const ret_ty = self.air.typeOf(un_op).childType();
1678 if (!ret_ty.hasRuntimeBitsIgnoreComptime()) return WValue.none;1690 if (!ret_ty.hasRuntimeBitsIgnoreComptime()) {
1691 if (ret_ty.isError()) {
1692 try self.addImm32(0);
1693 } else {
1694 return WValue.none;
1695 }
1696 }
16791697
1680 if (!firstParamSRet(self.decl.ty.fnInfo(), self.target)) {1698 if (!firstParamSRet(self.decl.ty.fnInfo(), self.target)) {
1681 const result = try self.load(operand, ret_ty, 0);1699 const result = try self.load(operand, ret_ty, 0);
...@@ -1723,8 +1741,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -1723,8 +1741,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
17231741
1724 const sret = if (first_param_sret) blk: {1742 const sret = if (first_param_sret) blk: {
1725 const sret_local = try self.allocStack(ret_ty);1743 const sret_local = try self.allocStack(ret_ty);
1726 const ptr_offset = try self.buildPointerOffset(sret_local, 0, .new);1744 try self.lowerToStack(sret_local);
1727 try self.emitWValue(ptr_offset);
1728 break :blk sret_local;1745 break :blk sret_local;
1729 } else WValue{ .none = {} };1746 } else WValue{ .none = {} };
17301747
...@@ -1754,7 +1771,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -1754,7 +1771,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
1754 try self.addLabel(.call_indirect, fn_type_index);1771 try self.addLabel(.call_indirect, fn_type_index);
1755 }1772 }
17561773
1757 if (self.liveness.isUnused(inst) or !ret_ty.hasRuntimeBitsIgnoreComptime()) {1774 if (self.liveness.isUnused(inst) or (!ret_ty.hasRuntimeBitsIgnoreComptime() and !ret_ty.isError())) {
1758 return WValue.none;1775 return WValue.none;
1759 } else if (ret_ty.isNoReturn()) {1776 } else if (ret_ty.isNoReturn()) {
1760 try self.addTag(.@"unreachable");1777 try self.addTag(.@"unreachable");
...@@ -1796,8 +1813,11 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro...@@ -1796,8 +1813,11 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro
1796 .ErrorUnion => {1813 .ErrorUnion => {
1797 const err_ty = ty.errorUnionSet();1814 const err_ty = ty.errorUnionSet();
1798 const pl_ty = ty.errorUnionPayload();1815 const pl_ty = ty.errorUnionPayload();
1816 if (err_ty.errorSetCardinality() == .zero) {
1817 return self.store(lhs, rhs, pl_ty, 0);
1818 }
1799 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {1819 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {
1800 return self.store(lhs, rhs, err_ty, 0);1820 return self.store(lhs, rhs, Type.anyerror, 0);
1801 }1821 }
18021822
1803 const len = @intCast(u32, ty.abiSize(self.target));1823 const len = @intCast(u32, ty.abiSize(self.target));
...@@ -2256,6 +2276,7 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {...@@ -2256,6 +2276,7 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
2256 const target = self.target;2276 const target = self.target;
22572277
2258 switch (ty.zigTypeTag()) {2278 switch (ty.zigTypeTag()) {
2279 .Void => return WValue{ .none = {} },
2259 .Int => {2280 .Int => {
2260 const int_info = ty.intInfo(self.target);2281 const int_info = ty.intInfo(self.target);
2261 switch (int_info.signedness) {2282 switch (int_info.signedness) {
...@@ -2324,6 +2345,10 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {...@@ -2324,6 +2345,10 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
2324 },2345 },
2325 .ErrorUnion => {2346 .ErrorUnion => {
2326 const error_type = ty.errorUnionSet();2347 const error_type = ty.errorUnionSet();
2348 if (error_type.errorSetCardinality() == .zero) {
2349 const pl_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef);
2350 return self.lowerConstant(pl_val, ty.errorUnionPayload());
2351 }
2327 const is_pl = val.errorUnionIsPayload();2352 const is_pl = val.errorUnionIsPayload();
2328 const err_val = if (!is_pl) val else Value.initTag(.zero);2353 const err_val = if (!is_pl) val else Value.initTag(.zero);
2329 return self.lowerConstant(err_val, error_type);2354 return self.lowerConstant(err_val, error_type);
...@@ -2892,12 +2917,19 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!W...@@ -2892,12 +2917,19 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!W
2892 const err_ty = self.air.typeOf(un_op);2917 const err_ty = self.air.typeOf(un_op);
2893 const pl_ty = err_ty.errorUnionPayload();2918 const pl_ty = err_ty.errorUnionPayload();
28942919
2895 // load the error tag value2920 if (err_ty.errorUnionSet().errorSetCardinality() == .zero) {
2921 switch (opcode) {
2922 .i32_ne => return WValue{ .imm32 = 0 },
2923 .i32_eq => return WValue{ .imm32 = 1 },
2924 else => unreachable,
2925 }
2926 }
2927
2896 try self.emitWValue(operand);2928 try self.emitWValue(operand);
2897 if (pl_ty.hasRuntimeBitsIgnoreComptime()) {2929 if (pl_ty.hasRuntimeBitsIgnoreComptime()) {
2898 try self.addMemArg(.i32_load16_u, .{2930 try self.addMemArg(.i32_load16_u, .{
2899 .offset = operand.offset(),2931 .offset = operand.offset() + errUnionErrorOffset(pl_ty, self.target),
2900 .alignment = err_ty.errorUnionSet().abiAlignment(self.target),2932 .alignment = Type.anyerror.abiAlignment(self.target),
2901 });2933 });
2902 }2934 }
29032935
...@@ -2905,7 +2937,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!W...@@ -2905,7 +2937,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!W
2905 try self.addImm32(0);2937 try self.addImm32(0);
2906 try self.addTag(Mir.Inst.Tag.fromOpcode(opcode));2938 try self.addTag(Mir.Inst.Tag.fromOpcode(opcode));
29072939
2908 const is_err_tmp = try self.allocLocal(Type.initTag(.i32)); // result is always an i322940 const is_err_tmp = try self.allocLocal(Type.i32);
2909 try self.addLabel(.local_set, is_err_tmp.local);2941 try self.addLabel(.local_set, is_err_tmp.local);
2910 return is_err_tmp;2942 return is_err_tmp;
2911}2943}
...@@ -2917,14 +2949,18 @@ fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index, op_is_ptr: bool)...@@ -2917,14 +2949,18 @@ fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index, op_is_ptr: bool)
2917 const op_ty = self.air.typeOf(ty_op.operand);2949 const op_ty = self.air.typeOf(ty_op.operand);
2918 const err_ty = if (op_is_ptr) op_ty.childType() else op_ty;2950 const err_ty = if (op_is_ptr) op_ty.childType() else op_ty;
2919 const payload_ty = err_ty.errorUnionPayload();2951 const payload_ty = err_ty.errorUnionPayload();
2952
2953 if (err_ty.errorUnionSet().errorSetCardinality() == .zero) {
2954 return operand;
2955 }
2956
2920 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return WValue{ .none = {} };2957 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return WValue{ .none = {} };
2921 const err_align = err_ty.abiAlignment(self.target);2958
2922 const set_size = err_ty.errorUnionSet().abiSize(self.target);2959 const pl_offset = errUnionPayloadOffset(payload_ty, self.target);
2923 const offset = mem.alignForwardGeneric(u64, set_size, err_align);
2924 if (op_is_ptr or isByRef(payload_ty, self.target)) {2960 if (op_is_ptr or isByRef(payload_ty, self.target)) {
2925 return self.buildPointerOffset(operand, offset, .new);2961 return self.buildPointerOffset(operand, pl_offset, .new);
2926 }2962 }
2927 return self.load(operand, payload_ty, @intCast(u32, offset));2963 return self.load(operand, payload_ty, pl_offset);
2928}2964}
29292965
2930fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!WValue {2966fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!WValue {
...@@ -2935,11 +2971,16 @@ fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index, op_is_ptr: bool) In...@@ -2935,11 +2971,16 @@ fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index, op_is_ptr: bool) In
2935 const op_ty = self.air.typeOf(ty_op.operand);2971 const op_ty = self.air.typeOf(ty_op.operand);
2936 const err_ty = if (op_is_ptr) op_ty.childType() else op_ty;2972 const err_ty = if (op_is_ptr) op_ty.childType() else op_ty;
2937 const payload_ty = err_ty.errorUnionPayload();2973 const payload_ty = err_ty.errorUnionPayload();
2974
2975 if (err_ty.errorUnionSet().errorSetCardinality() == .zero) {
2976 return WValue{ .imm32 = 0 };
2977 }
2978
2938 if (op_is_ptr or !payload_ty.hasRuntimeBitsIgnoreComptime()) {2979 if (op_is_ptr or !payload_ty.hasRuntimeBitsIgnoreComptime()) {
2939 return operand;2980 return operand;
2940 }2981 }
29412982
2942 return self.load(operand, err_ty.errorUnionSet(), 0);2983 return self.load(operand, Type.anyerror, errUnionErrorOffset(payload_ty, self.target));
2943}2984}
29442985
2945fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {2986fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
...@@ -2947,22 +2988,26 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -2947,22 +2988,26 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
29472988
2948 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2989 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2949 const operand = try self.resolveInst(ty_op.operand);2990 const operand = try self.resolveInst(ty_op.operand);
2991 const err_ty = self.air.typeOfIndex(inst);
29502992
2951 const op_ty = self.air.typeOf(ty_op.operand);2993 if (err_ty.errorUnionSet().errorSetCardinality() == .zero) {
2952 if (!op_ty.hasRuntimeBitsIgnoreComptime()) return operand;2994 return operand;
2953 const err_union_ty = self.air.getRefType(ty_op.ty);2995 }
2954 const err_align = err_union_ty.abiAlignment(self.target);2996
2955 const set_size = err_union_ty.errorUnionSet().abiSize(self.target);2997 const pl_ty = self.air.typeOf(ty_op.operand);
2956 const offset = mem.alignForwardGeneric(u64, set_size, err_align);2998 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {
2999 return operand;
3000 }
29573001
2958 const err_union = try self.allocStack(err_union_ty);3002 const err_union = try self.allocStack(err_ty);
2959 const payload_ptr = try self.buildPointerOffset(err_union, offset, .new);3003 const payload_ptr = try self.buildPointerOffset(err_union, errUnionPayloadOffset(pl_ty, self.target), .new);
2960 try self.store(payload_ptr, operand, op_ty, 0);3004 try self.store(payload_ptr, operand, pl_ty, 0);
29613005
2962 // ensure we also write '0' to the error part, so any present stack value gets overwritten by it.3006 // ensure we also write '0' to the error part, so any present stack value gets overwritten by it.
2963 try self.emitWValue(err_union);3007 try self.emitWValue(err_union);
2964 try self.addImm32(0);3008 try self.addImm32(0);
2965 try self.addMemArg(.i32_store16, .{ .offset = err_union.offset(), .alignment = 2 });3009 const err_val_offset = errUnionErrorOffset(pl_ty, self.target);
3010 try self.addMemArg(.i32_store16, .{ .offset = err_union.offset() + err_val_offset, .alignment = 2 });
29663011
2967 return err_union;3012 return err_union;
2968}3013}
...@@ -2973,17 +3018,18 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -2973,17 +3018,18 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
2973 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3018 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2974 const operand = try self.resolveInst(ty_op.operand);3019 const operand = try self.resolveInst(ty_op.operand);
2975 const err_ty = self.air.getRefType(ty_op.ty);3020 const err_ty = self.air.getRefType(ty_op.ty);
3021 const pl_ty = err_ty.errorUnionPayload();
29763022
2977 if (!err_ty.errorUnionPayload().hasRuntimeBitsIgnoreComptime()) return operand;3023 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {
3024 return operand;
3025 }
29783026
2979 const err_union = try self.allocStack(err_ty);3027 const err_union = try self.allocStack(err_ty);
2980 try self.store(err_union, operand, err_ty.errorUnionSet(), 0);3028 // store error value
3029 try self.store(err_union, operand, Type.anyerror, errUnionErrorOffset(pl_ty, self.target));
29813030
2982 // write 'undefined' to the payload3031 // write 'undefined' to the payload
2983 const err_align = err_ty.abiAlignment(self.target);3032 const payload_ptr = try self.buildPointerOffset(err_union, errUnionPayloadOffset(pl_ty, self.target), .new);
2984 const set_size = err_ty.errorUnionSet().abiSize(self.target);
2985 const offset = mem.alignForwardGeneric(u64, set_size, err_align);
2986 const payload_ptr = try self.buildPointerOffset(err_union, offset, .new);
2987 const len = @intCast(u32, err_ty.errorUnionPayload().abiSize(self.target));3033 const len = @intCast(u32, err_ty.errorUnionPayload().abiSize(self.target));
2988 try self.memset(payload_ptr, .{ .imm32 = len }, .{ .imm32 = 0xaaaaaaaa });3034 try self.memset(payload_ptr, .{ .imm32 = len }, .{ .imm32 = 0xaaaaaaaa });
29893035
...@@ -3927,12 +3973,16 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -3927,12 +3973,16 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
3927fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) InnerError!WValue {3973fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
3928 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3974 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3929 const err_set_ty = self.air.typeOf(ty_op.operand).childType();3975 const err_set_ty = self.air.typeOf(ty_op.operand).childType();
3930 const err_ty = err_set_ty.errorUnionSet();
3931 const payload_ty = err_set_ty.errorUnionPayload();3976 const payload_ty = err_set_ty.errorUnionPayload();
3932 const operand = try self.resolveInst(ty_op.operand);3977 const operand = try self.resolveInst(ty_op.operand);
39333978
3934 // set error-tag to '0' to annotate error union is non-error3979 // set error-tag to '0' to annotate error union is non-error
3935 try self.store(operand, .{ .imm32 = 0 }, err_ty, 0);3980 try self.store(
3981 operand,
3982 .{ .imm32 = 0 },
3983 Type.anyerror,
3984 errUnionErrorOffset(payload_ty, self.target),
3985 );
39363986
3937 if (self.liveness.isUnused(inst)) return WValue{ .none = {} };3987 if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
39383988
...@@ -3940,11 +3990,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) InnerError!WValue...@@ -3940,11 +3990,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) InnerError!WValue
3940 return operand;3990 return operand;
3941 }3991 }
39423992
3943 const err_align = err_set_ty.abiAlignment(self.target);3993 return self.buildPointerOffset(operand, errUnionPayloadOffset(payload_ty, self.target), .new);
3944 const set_size = err_ty.abiSize(self.target);
3945 const offset = mem.alignForwardGeneric(u64, set_size, err_align);
3946
3947 return self.buildPointerOffset(operand, @intCast(u32, offset), .new);
3948}3994}
39493995
3950fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {3996fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
...@@ -4572,3 +4618,17 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !WValue {...@@ -4572,3 +4618,17 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !WValue {
4572 } });4618 } });
4573 return WValue{ .none = {} };4619 return WValue{ .none = {} };
4574}4620}
4621
4622fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u32 {
4623 if (Type.anyerror.abiAlignment(target) > payload_ty.abiAlignment(target)) {
4624 return @intCast(u32, Type.anyerror.abiSize(target));
4625 }
4626 return 0;
4627}
4628
4629fn errUnionErrorOffset(payload_ty: Type, target: std.Target) u32 {
4630 if (Type.anyerror.abiAlignment(target) > payload_ty.abiAlignment(target)) {
4631 return 0;
4632 }
4633 return @intCast(u32, payload_ty.abiSize(target));
4634}
src/codegen.zig+3-3
...@@ -714,7 +714,7 @@ pub fn generateSymbol(...@@ -714,7 +714,7 @@ pub fn generateSymbol(
714 const is_payload = typed_value.val.errorUnionIsPayload();714 const is_payload = typed_value.val.errorUnionIsPayload();
715715
716 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {716 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
717 const err_val = if (!is_payload) typed_value.val else Value.initTag(.zero);717 const err_val = if (is_payload) Value.initTag(.zero) else typed_value.val;
718 return generateSymbol(bin_file, src_loc, .{718 return generateSymbol(bin_file, src_loc, .{
719 .ty = error_ty,719 .ty = error_ty,
720 .val = err_val,720 .val = err_val,
...@@ -763,7 +763,7 @@ pub fn generateSymbol(...@@ -763,7 +763,7 @@ pub fn generateSymbol(
763 }763 }
764764
765 // Payload size is larger than error set, so emit our error set last765 // Payload size is larger than error set, so emit our error set last
766 if (error_align < payload_align) {766 if (error_align <= payload_align) {
767 const begin = code.items.len;767 const begin = code.items.len;
768 switch (try generateSymbol(bin_file, src_loc, .{768 switch (try generateSymbol(bin_file, src_loc, .{
769 .ty = error_ty,769 .ty = error_ty,
...@@ -794,7 +794,7 @@ pub fn generateSymbol(...@@ -794,7 +794,7 @@ pub fn generateSymbol(
794 try code.writer().writeInt(u32, kv.value, endian);794 try code.writer().writeInt(u32, kv.value, endian);
795 },795 },
796 else => {796 else => {
797 try code.writer().writeByteNTimes(0, @intCast(usize, typed_value.ty.abiSize(target)));797 try code.writer().writeByteNTimes(0, @intCast(usize, Type.anyerror.abiSize(target)));
798 },798 },
799 }799 }
800 return Result{ .appended = {} };800 return Result{ .appended = {} };
test/behavior/error.zig-1
...@@ -260,7 +260,6 @@ fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) !void {...@@ -260,7 +260,6 @@ fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) !void {
260}260}
261261
262test "comptime err to int of error set with only 1 possible value" {262test "comptime err to int of error set with only 1 possible value" {
263 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
264 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO263 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
265 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO264 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
266 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO265 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO