| ... | @@ -44,7 +44,7 @@ const WValue = union(enum) { | ... | @@ -44,7 +44,7 @@ const WValue = union(enum) { |
| 44 | memory_offset: struct { | 44 | memory_offset: struct { |
| 45 | /// The symbol of the parent pointer | 45 | /// The symbol of the parent pointer |
| 46 | pointer: u32, | 46 | pointer: u32, |
| 47 | /// Offset will be set as 'addend' when relocating | 47 | /// Offset will be set as addend when relocating |
| 48 | offset: u32, | 48 | offset: u32, |
| 49 | }, | 49 | }, |
| 50 | /// Represents a function pointer | 50 | /// Represents a function pointer |
| ... | @@ -606,7 +606,10 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!WValue { | ... | @@ -606,7 +606,10 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!WValue { |
| 606 | // means we must generate it from a constant. | 606 | // means we must generate it from a constant. |
| 607 | const val = self.air.value(ref).?; | 607 | const val = self.air.value(ref).?; |
| 608 | const ty = self.air.typeOf(ref); | 608 | const ty = self.air.typeOf(ref); |
| 609 | if (!ty.hasRuntimeBits() and !ty.isInt()) return WValue{ .none = {} }; | 609 | if (!ty.hasRuntimeBits() and !ty.isInt()) { |
| | 610 | gop.value_ptr.* = WValue{ .none = {} }; |
| | 611 | return gop.value_ptr.*; |
| | 612 | } |
| 610 | | 613 | |
| 611 | // When we need to pass the value by reference (such as a struct), we will | 614 | // When we need to pass the value by reference (such as a struct), we will |
| 612 | // leverage `genTypedValue` to lower the constant to bytes and emit it | 615 | // leverage `genTypedValue` to lower the constant to bytes and emit it |
| ... | @@ -1644,6 +1647,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -1644,6 +1647,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 1644 | fn airRet(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 1647 | fn airRet(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 1645 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 1648 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 1646 | const operand = try self.resolveInst(un_op); | 1649 | const operand = try self.resolveInst(un_op); |
| | 1650 | |
| 1647 | // result must be stored in the stack and we return a pointer | 1651 | // result must be stored in the stack and we return a pointer |
| 1648 | // to the stack instead | 1652 | // to the stack instead |
| 1649 | if (self.return_value != .none) { | 1653 | if (self.return_value != .none) { |
| ... | @@ -1653,7 +1657,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -1653,7 +1657,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 1653 | } | 1657 | } |
| 1654 | try self.restoreStackPointer(); | 1658 | try self.restoreStackPointer(); |
| 1655 | try self.addTag(.@"return"); | 1659 | try self.addTag(.@"return"); |
| 1656 | return .none; | 1660 | return WValue{ .none = {} }; |
| 1657 | } | 1661 | } |
| 1658 | | 1662 | |
| 1659 | fn airRetPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 1663 | fn airRetPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| ... | @@ -1793,11 +1797,10 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro | ... | @@ -1793,11 +1797,10 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro |
| 1793 | const err_ty = ty.errorUnionSet(); | 1797 | const err_ty = ty.errorUnionSet(); |
| 1794 | const pl_ty = ty.errorUnionPayload(); | 1798 | const pl_ty = ty.errorUnionPayload(); |
| 1795 | if (!pl_ty.hasRuntimeBits()) { | 1799 | if (!pl_ty.hasRuntimeBits()) { |
| 1796 | const err_val = try self.load(rhs, err_ty, 0); | 1800 | return self.store(lhs, rhs, err_ty, 0); |
| 1797 | return self.store(lhs, err_val, err_ty, 0); | | |
| 1798 | } | 1801 | } |
| 1799 | | 1802 | |
| 1800 | return try self.memCopy(ty, lhs, rhs); | 1803 | return self.memCopy(ty, lhs, rhs); |
| 1801 | }, | 1804 | }, |
| 1802 | .Optional => { | 1805 | .Optional => { |
| 1803 | if (ty.isPtrLikeOptional()) { | 1806 | if (ty.isPtrLikeOptional()) { |
| ... | @@ -1812,7 +1815,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro | ... | @@ -1812,7 +1815,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro |
| 1812 | return self.memCopy(ty, lhs, rhs); | 1815 | return self.memCopy(ty, lhs, rhs); |
| 1813 | }, | 1816 | }, |
| 1814 | .Struct, .Array, .Union => { | 1817 | .Struct, .Array, .Union => { |
| 1815 | return try self.memCopy(ty, lhs, rhs); | 1818 | return self.memCopy(ty, lhs, rhs); |
| 1816 | }, | 1819 | }, |
| 1817 | .Pointer => { | 1820 | .Pointer => { |
| 1818 | if (ty.isSlice()) { | 1821 | if (ty.isSlice()) { |
| ... | @@ -1827,7 +1830,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro | ... | @@ -1827,7 +1830,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro |
| 1827 | } | 1830 | } |
| 1828 | }, | 1831 | }, |
| 1829 | .Int => if (ty.intInfo(self.target).bits > 64) { | 1832 | .Int => if (ty.intInfo(self.target).bits > 64) { |
| 1830 | return try self.memCopy(ty, lhs, rhs); | 1833 | return self.memCopy(ty, lhs, rhs); |
| 1831 | }, | 1834 | }, |
| 1832 | else => {}, | 1835 | else => {}, |
| 1833 | } | 1836 | } |
| ... | @@ -2587,11 +2590,11 @@ fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue | ... | @@ -2587,11 +2590,11 @@ fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue |
| 2587 | if (isByRef(payload_ty, self.target)) { | 2590 | if (isByRef(payload_ty, self.target)) { |
| 2588 | return self.buildPointerOffset(operand, offset, .new); | 2591 | return self.buildPointerOffset(operand, offset, .new); |
| 2589 | } | 2592 | } |
| 2590 | return try self.load(operand, payload_ty, offset); | 2593 | return self.load(operand, payload_ty, offset); |
| 2591 | } | 2594 | } |
| 2592 | | 2595 | |
| 2593 | fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 2596 | fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2594 | if (self.liveness.isUnused(inst)) return WValue.none; | 2597 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; |
| 2595 | | 2598 | |
| 2596 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2599 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2597 | const operand = try self.resolveInst(ty_op.operand); | 2600 | const operand = try self.resolveInst(ty_op.operand); |
| ... | @@ -2601,11 +2604,12 @@ fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -2601,11 +2604,12 @@ fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2601 | return operand; | 2604 | return operand; |
| 2602 | } | 2605 | } |
| 2603 | | 2606 | |
| 2604 | return try self.load(operand, err_ty.errorUnionSet(), 0); | 2607 | return self.load(operand, err_ty.errorUnionSet(), 0); |
| 2605 | } | 2608 | } |
| 2606 | | 2609 | |
| 2607 | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 2610 | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2608 | if (self.liveness.isUnused(inst)) return WValue.none; | 2611 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; |
| | 2612 | |
| 2609 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2613 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2610 | const operand = try self.resolveInst(ty_op.operand); | 2614 | const operand = try self.resolveInst(ty_op.operand); |
| 2611 | | 2615 | |
| ... | @@ -2627,11 +2631,14 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -2627,11 +2631,14 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2627 | } | 2631 | } |
| 2628 | | 2632 | |
| 2629 | fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 2633 | fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2630 | if (self.liveness.isUnused(inst)) return WValue.none; | 2634 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; |
| | 2635 | |
| 2631 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2636 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2632 | const operand = try self.resolveInst(ty_op.operand); | 2637 | const operand = try self.resolveInst(ty_op.operand); |
| 2633 | const err_ty = self.air.getRefType(ty_op.ty); | 2638 | const err_ty = self.air.getRefType(ty_op.ty); |
| 2634 | | 2639 | |
| | 2640 | if (!err_ty.errorUnionPayload().hasRuntimeBits()) return operand; |
| | 2641 | |
| 2635 | const err_union = try self.allocStack(err_ty); | 2642 | const err_union = try self.allocStack(err_ty); |
| 2636 | // TODO: Also write 'undefined' to the payload | 2643 | // TODO: Also write 'undefined' to the payload |
| 2637 | try self.store(err_union, operand, err_ty.errorUnionSet(), 0); | 2644 | try self.store(err_union, operand, err_ty.errorUnionSet(), 0); |
| ... | @@ -2813,16 +2820,16 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -2813,16 +2820,16 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2813 | } | 2820 | } |
| 2814 | | 2821 | |
| 2815 | fn airSliceLen(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 2822 | fn airSliceLen(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2816 | if (self.liveness.isUnused(inst)) return WValue.none; | 2823 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; |
| 2817 | | 2824 | |
| 2818 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2825 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2819 | const operand = try self.resolveInst(ty_op.operand); | 2826 | const operand = try self.resolveInst(ty_op.operand); |
| 2820 | | 2827 | |
| 2821 | return try self.load(operand, Type.usize, self.ptrSize()); | 2828 | return self.load(operand, Type.usize, self.ptrSize()); |
| 2822 | } | 2829 | } |
| 2823 | | 2830 | |
| 2824 | fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 2831 | fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2825 | if (self.liveness.isUnused(inst)) return WValue.none; | 2832 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; |
| 2826 | | 2833 | |
| 2827 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 2834 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 2828 | const slice_ty = self.air.typeOf(bin_op.lhs); | 2835 | const slice_ty = self.air.typeOf(bin_op.lhs); |
| ... | @@ -2847,7 +2854,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -2847,7 +2854,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2847 | if (isByRef(elem_ty, self.target)) { | 2854 | if (isByRef(elem_ty, self.target)) { |
| 2848 | return result; | 2855 | return result; |
| 2849 | } | 2856 | } |
| 2850 | return try self.load(result, elem_ty, 0); | 2857 | return self.load(result, elem_ty, 0); |
| 2851 | } | 2858 | } |
| 2852 | | 2859 | |
| 2853 | fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 2860 | fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| ... | @@ -2875,10 +2882,10 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -2875,10 +2882,10 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2875 | } | 2882 | } |
| 2876 | | 2883 | |
| 2877 | fn airSlicePtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 2884 | fn airSlicePtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2878 | if (self.liveness.isUnused(inst)) return WValue.none; | 2885 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; |
| 2879 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2886 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2880 | const operand = try self.resolveInst(ty_op.operand); | 2887 | const operand = try self.resolveInst(ty_op.operand); |
| 2881 | return try self.load(operand, Type.usize, 0); | 2888 | return self.load(operand, Type.usize, 0); |
| 2882 | } | 2889 | } |
| 2883 | | 2890 | |
| 2884 | fn airTrunc(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 2891 | fn airTrunc(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| ... | @@ -2943,7 +2950,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -2943,7 +2950,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2943 | | 2950 | |
| 2944 | fn airBoolToInt(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 2951 | fn airBoolToInt(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2945 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 2952 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 2946 | return try self.resolveInst(un_op); | 2953 | return self.resolveInst(un_op); |
| 2947 | } | 2954 | } |
| 2948 | | 2955 | |
| 2949 | fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 2956 | fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| ... | @@ -2975,7 +2982,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -2975,7 +2982,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2975 | fn airPtrToInt(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 2982 | fn airPtrToInt(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2976 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; | 2983 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; |
| 2977 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 2984 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 2978 | return try self.resolveInst(un_op); | 2985 | return self.resolveInst(un_op); |
| 2979 | } | 2986 | } |
| 2980 | | 2987 | |
| 2981 | fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 2988 | fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| ... | @@ -2990,7 +2997,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -2990,7 +2997,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2990 | | 2997 | |
| 2991 | // load pointer onto the stack | 2998 | // load pointer onto the stack |
| 2992 | if (ptr_ty.isSlice()) { | 2999 | if (ptr_ty.isSlice()) { |
| 2993 | const ptr_local = try self.load(pointer, ptr_ty, 0); | 3000 | const ptr_local = try self.load(pointer, Type.usize, 0); |
| 2994 | try self.addLabel(.local_get, ptr_local.local); | 3001 | try self.addLabel(.local_get, ptr_local.local); |
| 2995 | } else { | 3002 | } else { |
| 2996 | try self.emitWValue(pointer); | 3003 | try self.emitWValue(pointer); |
| ... | @@ -3007,7 +3014,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -3007,7 +3014,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3007 | if (isByRef(elem_ty, self.target)) { | 3014 | if (isByRef(elem_ty, self.target)) { |
| 3008 | return result; | 3015 | return result; |
| 3009 | } | 3016 | } |
| 3010 | return try self.load(result, elem_ty, 0); | 3017 | return self.load(result, elem_ty, 0); |
| 3011 | } | 3018 | } |
| 3012 | | 3019 | |
| 3013 | fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 3020 | fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| ... | @@ -3023,7 +3030,7 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -3023,7 +3030,7 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3023 | | 3030 | |
| 3024 | // load pointer onto the stack | 3031 | // load pointer onto the stack |
| 3025 | if (ptr_ty.isSlice()) { | 3032 | if (ptr_ty.isSlice()) { |
| 3026 | const ptr_local = try self.load(ptr, ptr_ty, 0); | 3033 | const ptr_local = try self.load(ptr, Type.usize, 0); |
| 3027 | try self.addLabel(.local_get, ptr_local.local); | 3034 | try self.addLabel(.local_get, ptr_local.local); |
| 3028 | } else { | 3035 | } else { |
| 3029 | try self.emitWValue(ptr); | 3036 | try self.emitWValue(ptr); |
| ... | @@ -3157,7 +3164,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -3157,7 +3164,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3157 | if (isByRef(elem_ty, self.target)) { | 3164 | if (isByRef(elem_ty, self.target)) { |
| 3158 | return result; | 3165 | return result; |
| 3159 | } | 3166 | } |
| 3160 | return try self.load(result, elem_ty, 0); | 3167 | return self.load(result, elem_ty, 0); |
| 3161 | } | 3168 | } |
| 3162 | | 3169 | |
| 3163 | fn airFloatToInt(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 3170 | fn airFloatToInt(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| ... | @@ -3201,8 +3208,63 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -3201,8 +3208,63 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3201 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 3208 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 3202 | const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); | 3209 | const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); |
| 3203 | | 3210 | |
| 3204 | _ = elements; | 3211 | switch (vector_ty.zigTypeTag()) { |
| 3205 | return self.fail("TODO: Wasm backend: implement airVectorInit", .{}); | 3212 | .Vector => return self.fail("TODO: Wasm backend: implement airVectorInit for vectors", .{}), |
| | 3213 | .Array => { |
| | 3214 | const result = try self.allocStack(vector_ty); |
| | 3215 | const elem_ty = vector_ty.childType(); |
| | 3216 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target)); |
| | 3217 | |
| | 3218 | // When the element type is by reference, we must copy the entire |
| | 3219 | // value. It is therefore safer to move the offset pointer and store |
| | 3220 | // each value individually, instead of using store offsets. |
| | 3221 | if (isByRef(elem_ty, self.target)) { |
| | 3222 | // copy stack pointer into a temporary local, which is |
| | 3223 | // moved for each element to store each value in the right position. |
| | 3224 | const offset = try self.allocLocal(Type.usize); |
| | 3225 | try self.emitWValue(result); |
| | 3226 | try self.addLabel(.local_set, offset.local); |
| | 3227 | for (elements) |elem, elem_index| { |
| | 3228 | const elem_val = try self.resolveInst(elem); |
| | 3229 | try self.store(offset, elem_val, elem_ty, 0); |
| | 3230 | |
| | 3231 | if (elem_index < elements.len - 1) { |
| | 3232 | _ = try self.buildPointerOffset(offset, elem_size, .modify); |
| | 3233 | } |
| | 3234 | } |
| | 3235 | } else { |
| | 3236 | var offset: u32 = 0; |
| | 3237 | for (elements) |elem| { |
| | 3238 | const elem_val = try self.resolveInst(elem); |
| | 3239 | try self.store(result, elem_val, elem_ty, offset); |
| | 3240 | offset += elem_size; |
| | 3241 | } |
| | 3242 | } |
| | 3243 | return result; |
| | 3244 | }, |
| | 3245 | .Struct => { |
| | 3246 | const tuple = vector_ty.castTag(.tuple).?.data; |
| | 3247 | const result = try self.allocStack(vector_ty); |
| | 3248 | const offset = try self.allocLocal(Type.usize); // pointer to offset |
| | 3249 | try self.emitWValue(result); |
| | 3250 | try self.addLabel(.local_set, offset.local); |
| | 3251 | for (elements) |elem, elem_index| { |
| | 3252 | if (tuple.values[elem_index].tag() != .unreachable_value) continue; |
| | 3253 | |
| | 3254 | const elem_ty = tuple.types[elem_index]; |
| | 3255 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target)); |
| | 3256 | const value = try self.resolveInst(elem); |
| | 3257 | try self.store(offset, value, elem_ty, 0); |
| | 3258 | |
| | 3259 | if (elem_index < elements.len - 1) { |
| | 3260 | _ = try self.buildPointerOffset(offset, elem_size, .modify); |
| | 3261 | } |
| | 3262 | } |
| | 3263 | |
| | 3264 | return result; |
| | 3265 | }, |
| | 3266 | else => unreachable, |
| | 3267 | } |
| 3206 | } | 3268 | } |
| 3207 | | 3269 | |
| 3208 | fn airPrefetch(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 3270 | fn airPrefetch(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |