| ... | @@ -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 | } |
| 808 | | 810 | |
| 809 | // param types | 811 | // 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 { |
| 1624 | fn airRet(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 1631 | fn 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; |
| 1628 | | 1636 | |
| 1629 | // result must be stored in the stack and we return a pointer | 1637 | // result must be stored in the stack and we return a pointer |
| 1630 | // to the stack instead | 1638 | // 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 value | 1643 | // 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 | } |
| 1679 | | 1697 | |
| 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. |
| 1723 | | 1741 | |
| 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 = {} }; |
| 1730 | | 1747 | |
| ... | @@ -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 | } |
| 1756 | | 1773 | |
| 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 | } |
| 1802 | | 1822 | |
| 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; |
| 2257 | | 2277 | |
| 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(); |
| 2894 | | 2919 | |
| 2895 | // load the error tag value | 2920 | 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 | } |
| 2903 | | 2935 | |
| ... | @@ -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)); |
| 2907 | | 2939 | |
| 2908 | const is_err_tmp = try self.allocLocal(Type.initTag(.i32)); // result is always an i32 | 2940 | 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 | } |
| 2929 | | 2965 | |
| 2930 | fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!WValue { | 2966 | fn 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 | } |
| 2941 | | 2982 | |
| 2942 | return self.load(operand, err_ty.errorUnionSet(), 0); | 2983 | return self.load(operand, Type.anyerror, errUnionErrorOffset(payload_ty, self.target)); |
| 2943 | } | 2984 | } |
| 2944 | | 2985 | |
| 2945 | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 2986 | fn 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 { |
| 2947 | | 2988 | |
| 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); |
| 2950 | | 2992 | |
| 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 | } |
| 2957 | | 3001 | |
| 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); |
| 2961 | | 3005 | |
| 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 }); |
| 2966 | | 3011 | |
| 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(); |
| 2976 | | 3022 | |
| 2977 | if (!err_ty.errorUnionPayload().hasRuntimeBitsIgnoreComptime()) return operand; | 3023 | if (!pl_ty.hasRuntimeBitsIgnoreComptime()) { |
| | 3024 | return operand; |
| | 3025 | } |
| 2978 | | 3026 | |
| 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)); |
| 2981 | | 3030 | |
| 2982 | // write 'undefined' to the payload | 3031 | // 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 }); |
| 2989 | | 3035 | |
| ... | @@ -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 { |
| 3927 | fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 3973 | fn 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); |
| 3933 | | 3978 | |
| 3934 | // set error-tag to '0' to annotate error union is non-error | 3979 | // 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 | ); |
| 3936 | | 3986 | |
| 3937 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; | 3987 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; |
| 3938 | | 3988 | |
| ... | @@ -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 | } |
| 3942 | | 3992 | |
| 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 | } |
| 3949 | | 3995 | |
| 3950 | fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 3996 | fn 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 | |
| | 4622 | fn 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 | |
| | 4629 | fn 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 | } |