| ... | ... | @@ -44,7 +44,7 @@ const WValue = union(enum) { |
| 44 | 44 | memory_offset: struct { |
| 45 | 45 | /// The symbol of the parent pointer |
| 46 | 46 | pointer: u32, |
| 47 | | /// Offset will be set as 'addend' when relocating |
| 47 | /// Offset will be set as addend when relocating |
| 48 | 48 | offset: u32, |
| 49 | 49 | }, |
| 50 | 50 | /// Represents a function pointer |
| ... | ... | @@ -606,7 +606,10 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!WValue { |
| 606 | 606 | // means we must generate it from a constant. |
| 607 | 607 | const val = self.air.value(ref).?; |
| 608 | 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 | 614 | // When we need to pass the value by reference (such as a struct), we will |
| 612 | 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 | 1647 | fn airRet(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 1645 | 1648 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 1646 | 1649 | const operand = try self.resolveInst(un_op); |
| 1650 | |
| 1647 | 1651 | // result must be stored in the stack and we return a pointer |
| 1648 | 1652 | // to the stack instead |
| 1649 | 1653 | if (self.return_value != .none) { |
| ... | ... | @@ -1653,7 +1657,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 1653 | 1657 | } |
| 1654 | 1658 | try self.restoreStackPointer(); |
| 1655 | 1659 | try self.addTag(.@"return"); |
| 1656 | | return .none; |
| 1660 | return WValue{ .none = {} }; |
| 1657 | 1661 | } |
| 1658 | 1662 | |
| 1659 | 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 | 1797 | const err_ty = ty.errorUnionSet(); |
| 1794 | 1798 | const pl_ty = ty.errorUnionPayload(); |
| 1795 | 1799 | if (!pl_ty.hasRuntimeBits()) { |
| 1796 | | const err_val = try self.load(rhs, err_ty, 0); |
| 1797 | | return self.store(lhs, err_val, err_ty, 0); |
| 1800 | return self.store(lhs, rhs, 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 | 1805 | .Optional => { |
| 1803 | 1806 | if (ty.isPtrLikeOptional()) { |
| ... | ... | @@ -1812,7 +1815,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro |
| 1812 | 1815 | return self.memCopy(ty, lhs, rhs); |
| 1813 | 1816 | }, |
| 1814 | 1817 | .Struct, .Array, .Union => { |
| 1815 | | return try self.memCopy(ty, lhs, rhs); |
| 1818 | return self.memCopy(ty, lhs, rhs); |
| 1816 | 1819 | }, |
| 1817 | 1820 | .Pointer => { |
| 1818 | 1821 | if (ty.isSlice()) { |
| ... | ... | @@ -1827,7 +1830,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro |
| 1827 | 1830 | } |
| 1828 | 1831 | }, |
| 1829 | 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 | 1835 | else => {}, |
| 1833 | 1836 | } |
| ... | ... | @@ -2587,11 +2590,11 @@ fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue |
| 2587 | 2590 | if (isByRef(payload_ty, self.target)) { |
| 2588 | 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 | 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 | 2599 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2597 | 2600 | const operand = try self.resolveInst(ty_op.operand); |
| ... | ... | @@ -2601,11 +2604,12 @@ fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2601 | 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 | 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 | 2613 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2610 | 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 | 2631 | } |
| 2628 | 2632 | |
| 2629 | 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 | 2636 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2632 | 2637 | const operand = try self.resolveInst(ty_op.operand); |
| 2633 | 2638 | const err_ty = self.air.getRefType(ty_op.ty); |
| 2634 | 2639 | |
| 2640 | if (!err_ty.errorUnionPayload().hasRuntimeBits()) return operand; |
| 2641 | |
| 2635 | 2642 | const err_union = try self.allocStack(err_ty); |
| 2636 | 2643 | // TODO: Also write 'undefined' to the payload |
| 2637 | 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 | 2820 | } |
| 2814 | 2821 | |
| 2815 | 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 | 2825 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2819 | 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 | 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 | 2834 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 2828 | 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 | 2854 | if (isByRef(elem_ty, self.target)) { |
| 2848 | 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 | 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 | 2882 | } |
| 2876 | 2883 | |
| 2877 | 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 | 2886 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2880 | 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 | 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 | 2950 | |
| 2944 | 2951 | fn airBoolToInt(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2945 | 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 | 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 | 2982 | fn airPtrToInt(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2976 | 2983 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; |
| 2977 | 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 | 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 | 2997 | |
| 2991 | 2998 | // load pointer onto the stack |
| 2992 | 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 | 3001 | try self.addLabel(.local_get, ptr_local.local); |
| 2995 | 3002 | } else { |
| 2996 | 3003 | try self.emitWValue(pointer); |
| ... | ... | @@ -3007,7 +3014,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3007 | 3014 | if (isByRef(elem_ty, self.target)) { |
| 3008 | 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 | 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 | 3030 | |
| 3024 | 3031 | // load pointer onto the stack |
| 3025 | 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 | 3034 | try self.addLabel(.local_get, ptr_local.local); |
| 3028 | 3035 | } else { |
| 3029 | 3036 | try self.emitWValue(ptr); |
| ... | ... | @@ -3157,7 +3164,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3157 | 3164 | if (isByRef(elem_ty, self.target)) { |
| 3158 | 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 | 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 | 3208 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 3202 | 3209 | const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); |
| 3203 | 3210 | |
| 3204 | | _ = elements; |
| 3205 | | return self.fail("TODO: Wasm backend: implement airVectorInit", .{}); |
| 3211 | switch (vector_ty.zigTypeTag()) { |
| 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 | 3270 | fn airPrefetch(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |