| ... | ... | @@ -918,8 +918,11 @@ fn addLabel(func: *CodeGen, tag: Mir.Inst.Tag, label: u32) error{OutOfMemory}!vo |
| 918 | 918 | try func.addInst(.{ .tag = tag, .data = .{ .label = label } }); |
| 919 | 919 | } |
| 920 | 920 | |
| 921 | | fn addImm32(func: *CodeGen, imm: i32) error{OutOfMemory}!void { |
| 922 | | try func.addInst(.{ .tag = .i32_const, .data = .{ .imm32 = imm } }); |
| 921 | /// Accepts an unsigned 32bit integer rather than a signed integer to |
| 922 | /// prevent us from having to bitcast multiple times as most values |
| 923 | /// within codegen are represented as unsigned rather than signed. |
| 924 | fn addImm32(func: *CodeGen, imm: u32) error{OutOfMemory}!void { |
| 925 | try func.addInst(.{ .tag = .i32_const, .data = .{ .imm32 = @bitCast(imm) } }); |
| 923 | 926 | } |
| 924 | 927 | |
| 925 | 928 | /// Accepts an unsigned 64bit integer rather than a signed integer to |
| ... | ... | @@ -1049,7 +1052,7 @@ fn emitWValue(func: *CodeGen, value: WValue) InnerError!void { |
| 1049 | 1052 | .dead => unreachable, // reference to free'd `WValue` (missing reuseOperand?) |
| 1050 | 1053 | .none, .stack => {}, // no-op |
| 1051 | 1054 | .local => |idx| try func.addLabel(.local_get, idx.value), |
| 1052 | | .imm32 => |val| try func.addImm32(@as(i32, @bitCast(val))), |
| 1055 | .imm32 => |val| try func.addImm32(val), |
| 1053 | 1056 | .imm64 => |val| try func.addImm64(val), |
| 1054 | 1057 | .imm128 => |val| try func.addImm128(val), |
| 1055 | 1058 | .float32 => |val| try func.addInst(.{ .tag = .f32_const, .data = .{ .float32 = val } }), |
| ... | ... | @@ -1467,7 +1470,7 @@ fn lowerToStack(func: *CodeGen, value: WValue) !void { |
| 1467 | 1470 | if (offset.value > 0) { |
| 1468 | 1471 | switch (func.arch()) { |
| 1469 | 1472 | .wasm32 => { |
| 1470 | | try func.addImm32(@as(i32, @bitCast(offset.value))); |
| 1473 | try func.addImm32(offset.value); |
| 1471 | 1474 | try func.addTag(.i32_add); |
| 1472 | 1475 | }, |
| 1473 | 1476 | .wasm64 => { |
| ... | ... | @@ -1809,7 +1812,7 @@ fn buildPointerOffset(func: *CodeGen, ptr_value: WValue, offset: u64, action: en |
| 1809 | 1812 | if (offset + ptr_value.offset() > 0) { |
| 1810 | 1813 | switch (func.arch()) { |
| 1811 | 1814 | .wasm32 => { |
| 1812 | | try func.addImm32(@as(i32, @bitCast(@as(u32, @intCast(offset + ptr_value.offset()))))); |
| 1815 | try func.addImm32(@intCast(offset + ptr_value.offset())); |
| 1813 | 1816 | try func.addTag(.i32_add); |
| 1814 | 1817 | }, |
| 1815 | 1818 | .wasm64 => { |
| ... | ... | @@ -2794,11 +2797,9 @@ fn airAbs(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2794 | 2797 | return func.fail("TODO: airAbs for signed integers larger than '{d}' bits", .{int_bits}); |
| 2795 | 2798 | }; |
| 2796 | 2799 | |
| 2797 | | const op = try operand.toLocal(func, ty); |
| 2798 | | |
| 2799 | | try func.emitWValue(op); |
| 2800 | 2800 | switch (wasm_bits) { |
| 2801 | 2801 | 32 => { |
| 2802 | try func.emitWValue(operand); |
| 2802 | 2803 | if (wasm_bits != int_bits) { |
| 2803 | 2804 | try func.addImm32(wasm_bits - int_bits); |
| 2804 | 2805 | try func.addTag(.i32_shl); |
| ... | ... | @@ -2806,20 +2807,19 @@ fn airAbs(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2806 | 2807 | try func.addImm32(31); |
| 2807 | 2808 | try func.addTag(.i32_shr_s); |
| 2808 | 2809 | |
| 2809 | | const tmp = try func.allocLocal(ty); |
| 2810 | var tmp = try func.allocLocal(ty); |
| 2811 | defer tmp.free(func); |
| 2810 | 2812 | try func.addLabel(.local_tee, tmp.local.value); |
| 2811 | 2813 | |
| 2812 | | try func.emitWValue(op); |
| 2814 | try func.emitWValue(operand); |
| 2813 | 2815 | try func.addTag(.i32_xor); |
| 2814 | 2816 | try func.emitWValue(tmp); |
| 2815 | 2817 | try func.addTag(.i32_sub); |
| 2816 | 2818 | |
| 2817 | | if (int_bits != wasm_bits) { |
| 2818 | | try func.emitWValue(WValue{ .imm32 = (@as(u32, 1) << @intCast(int_bits)) - 1 }); |
| 2819 | | try func.addTag(.i32_and); |
| 2820 | | } |
| 2819 | _ = try func.wrapOperand(.stack, ty); |
| 2821 | 2820 | }, |
| 2822 | 2821 | 64 => { |
| 2822 | try func.emitWValue(operand); |
| 2823 | 2823 | if (wasm_bits != int_bits) { |
| 2824 | 2824 | try func.addImm64(wasm_bits - int_bits); |
| 2825 | 2825 | try func.addTag(.i64_shl); |
| ... | ... | @@ -2827,20 +2827,45 @@ fn airAbs(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2827 | 2827 | try func.addImm64(63); |
| 2828 | 2828 | try func.addTag(.i64_shr_s); |
| 2829 | 2829 | |
| 2830 | | const tmp = try func.allocLocal(ty); |
| 2830 | var tmp = try func.allocLocal(ty); |
| 2831 | defer tmp.free(func); |
| 2831 | 2832 | try func.addLabel(.local_tee, tmp.local.value); |
| 2832 | 2833 | |
| 2833 | | try func.emitWValue(op); |
| 2834 | try func.emitWValue(operand); |
| 2834 | 2835 | try func.addTag(.i64_xor); |
| 2835 | 2836 | try func.emitWValue(tmp); |
| 2836 | 2837 | try func.addTag(.i64_sub); |
| 2837 | 2838 | |
| 2838 | | if (int_bits != wasm_bits) { |
| 2839 | | try func.emitWValue(WValue{ .imm64 = (@as(u64, 1) << @intCast(int_bits)) - 1 }); |
| 2840 | | try func.addTag(.i64_and); |
| 2839 | _ = try func.wrapOperand(.stack, ty); |
| 2840 | }, |
| 2841 | 128 => { |
| 2842 | const mask = try func.allocStack(Type.u128); |
| 2843 | try func.emitWValue(mask); |
| 2844 | try func.emitWValue(mask); |
| 2845 | |
| 2846 | _ = try func.load(operand, Type.u64, 8); |
| 2847 | if (int_bits != 128) { |
| 2848 | try func.addImm64(128 - int_bits); |
| 2849 | try func.addTag(.i64_shl); |
| 2841 | 2850 | } |
| 2851 | try func.addImm64(63); |
| 2852 | try func.addTag(.i64_shr_s); |
| 2853 | |
| 2854 | var tmp = try func.allocLocal(Type.u64); |
| 2855 | defer tmp.free(func); |
| 2856 | try func.addLabel(.local_tee, tmp.local.value); |
| 2857 | try func.store(.stack, .stack, Type.u64, mask.offset() + 0); |
| 2858 | try func.emitWValue(tmp); |
| 2859 | try func.store(.stack, .stack, Type.u64, mask.offset() + 8); |
| 2860 | |
| 2861 | const a = try func.binOpBigInt(operand, mask, Type.u128, .xor); |
| 2862 | const b = try func.binOpBigInt(a, mask, Type.u128, .sub); |
| 2863 | const result = try func.wrapOperand(b, ty); |
| 2864 | |
| 2865 | func.finishAir(inst, result, &.{ty_op.operand}); |
| 2866 | return; |
| 2842 | 2867 | }, |
| 2843 | | else => return func.fail("TODO: Implement airAbs for {}", .{ty.fmt(mod)}), |
| 2868 | else => unreachable, |
| 2844 | 2869 | } |
| 2845 | 2870 | |
| 2846 | 2871 | const result = try (WValue{ .stack = {} }).toLocal(func, ty); |
| ... | ... | @@ -2932,7 +2957,7 @@ fn floatNeg(func: *CodeGen, ty: Type, arg: WValue) InnerError!WValue { |
| 2932 | 2957 | switch (float_bits) { |
| 2933 | 2958 | 16 => { |
| 2934 | 2959 | try func.emitWValue(arg); |
| 2935 | | try func.addImm32(std.math.minInt(i16)); |
| 2960 | try func.addImm32(0x8000); |
| 2936 | 2961 | try func.addTag(.i32_xor); |
| 2937 | 2962 | return .stack; |
| 2938 | 2963 | }, |
| ... | ... | @@ -3019,44 +3044,48 @@ fn wrapBinOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerEr |
| 3019 | 3044 | |
| 3020 | 3045 | /// Wraps an operand based on a given type's bitsize. |
| 3021 | 3046 | /// Asserts `Type` is <= 128 bits. |
| 3022 | | /// NOTE: When the Type is <= 64 bits, leaves the value on top of the stack. |
| 3047 | /// NOTE: When the Type is <= 64 bits, leaves the value on top of the stack, if wrapping was needed. |
| 3023 | 3048 | fn wrapOperand(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue { |
| 3024 | 3049 | const mod = func.bin_file.base.comp.module.?; |
| 3025 | 3050 | assert(ty.abiSize(mod) <= 16); |
| 3026 | | const bitsize = @as(u16, @intCast(ty.bitSize(mod))); |
| 3027 | | const wasm_bits = toWasmBits(bitsize) orelse { |
| 3028 | | return func.fail("TODO: Implement wrapOperand for bitsize '{d}'", .{bitsize}); |
| 3051 | const int_bits = @as(u16, @intCast(ty.bitSize(mod))); // TODO use ty.intInfo(mod).bits |
| 3052 | const wasm_bits = toWasmBits(int_bits) orelse { |
| 3053 | return func.fail("TODO: Implement wrapOperand for bitsize '{d}'", .{int_bits}); |
| 3029 | 3054 | }; |
| 3030 | 3055 | |
| 3031 | | if (wasm_bits == bitsize) return operand; |
| 3056 | if (wasm_bits == int_bits) return operand; |
| 3032 | 3057 | |
| 3033 | | if (wasm_bits == 128) { |
| 3034 | | assert(operand != .stack); |
| 3035 | | const lsb = try func.load(operand, Type.u64, 8); |
| 3058 | switch (wasm_bits) { |
| 3059 | 32 => { |
| 3060 | try func.emitWValue(operand); |
| 3061 | try func.addImm32((@as(u32, 1) << @intCast(int_bits)) - 1); |
| 3062 | try func.addTag(.i32_and); |
| 3063 | return .stack; |
| 3064 | }, |
| 3065 | 64 => { |
| 3066 | try func.emitWValue(operand); |
| 3067 | try func.addImm64((@as(u64, 1) << @intCast(int_bits)) - 1); |
| 3068 | try func.addTag(.i64_and); |
| 3069 | return .stack; |
| 3070 | }, |
| 3071 | 128 => { |
| 3072 | assert(operand != .stack); |
| 3073 | const result = try func.allocStack(ty); |
| 3036 | 3074 | |
| 3037 | | const result_ptr = try func.allocStack(ty); |
| 3038 | | try func.emitWValue(result_ptr); |
| 3039 | | try func.store(.{ .stack = {} }, lsb, Type.u64, 8 + result_ptr.offset()); |
| 3040 | | const result = (@as(u64, 1) << @as(u6, @intCast(64 - (wasm_bits - bitsize)))) - 1; |
| 3041 | | try func.emitWValue(result_ptr); |
| 3042 | | _ = try func.load(operand, Type.u64, 0); |
| 3043 | | try func.addImm64(result); |
| 3044 | | try func.addTag(.i64_and); |
| 3045 | | try func.addMemArg(.i64_store, .{ .offset = result_ptr.offset(), .alignment = 8 }); |
| 3046 | | return result_ptr; |
| 3047 | | } |
| 3075 | try func.emitWValue(result); |
| 3076 | _ = try func.load(operand, Type.u64, 0); |
| 3077 | try func.store(.stack, .stack, Type.u64, result.offset()); |
| 3048 | 3078 | |
| 3049 | | const result = (@as(u64, 1) << @as(u6, @intCast(bitsize))) - 1; |
| 3050 | | try func.emitWValue(operand); |
| 3051 | | if (bitsize <= 32) { |
| 3052 | | try func.addImm32(@as(i32, @bitCast(@as(u32, @intCast(result))))); |
| 3053 | | try func.addTag(.i32_and); |
| 3054 | | } else if (bitsize <= 64) { |
| 3055 | | try func.addImm64(result); |
| 3056 | | try func.addTag(.i64_and); |
| 3057 | | } else unreachable; |
| 3079 | try func.emitWValue(result); |
| 3080 | _ = try func.load(operand, Type.u64, 8); |
| 3081 | try func.addImm64((@as(u64, 1) << @intCast(int_bits - 64)) - 1); |
| 3082 | try func.addTag(.i64_and); |
| 3083 | try func.store(.stack, .stack, Type.u64, result.offset() + 8); |
| 3058 | 3084 | |
| 3059 | | return WValue{ .stack = {} }; |
| 3085 | return result; |
| 3086 | }, |
| 3087 | else => unreachable, |
| 3088 | } |
| 3060 | 3089 | } |
| 3061 | 3090 | |
| 3062 | 3091 | fn lowerPtr(func: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerError!WValue { |
| ... | ... | @@ -4062,11 +4091,11 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4062 | 4091 | if (lowest < 0) { |
| 4063 | 4092 | // since br_table works using indexes, starting from '0', we must ensure all values |
| 4064 | 4093 | // we put inside, are atleast 0. |
| 4065 | | try func.addImm32(lowest * -1); |
| 4094 | try func.addImm32(@bitCast(lowest * -1)); |
| 4066 | 4095 | try func.addTag(.i32_add); |
| 4067 | 4096 | } else if (lowest > 0) { |
| 4068 | 4097 | // make the index start from 0 by substracting the lowest value |
| 4069 | | try func.addImm32(lowest); |
| 4098 | try func.addImm32(@bitCast(lowest)); |
| 4070 | 4099 | try func.addTag(.i32_sub); |
| 4071 | 4100 | } |
| 4072 | 4101 | |
| ... | ... | @@ -4588,7 +4617,7 @@ fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4588 | 4617 | |
| 4589 | 4618 | // calculate index into slice |
| 4590 | 4619 | try func.emitWValue(index); |
| 4591 | | try func.addImm32(@as(i32, @bitCast(@as(u32, @intCast(elem_size))))); |
| 4620 | try func.addImm32(@intCast(elem_size)); |
| 4592 | 4621 | try func.addTag(.i32_mul); |
| 4593 | 4622 | try func.addTag(.i32_add); |
| 4594 | 4623 | |
| ... | ... | @@ -4618,7 +4647,7 @@ fn airSliceElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4618 | 4647 | |
| 4619 | 4648 | // calculate index into slice |
| 4620 | 4649 | try func.emitWValue(index); |
| 4621 | | try func.addImm32(@as(i32, @bitCast(@as(u32, @intCast(elem_size))))); |
| 4650 | try func.addImm32(@intCast(elem_size)); |
| 4622 | 4651 | try func.addTag(.i32_mul); |
| 4623 | 4652 | try func.addTag(.i32_add); |
| 4624 | 4653 | |
| ... | ... | @@ -4737,7 +4766,7 @@ fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4737 | 4766 | |
| 4738 | 4767 | // calculate index into slice |
| 4739 | 4768 | try func.emitWValue(index); |
| 4740 | | try func.addImm32(@as(i32, @bitCast(@as(u32, @intCast(elem_size))))); |
| 4769 | try func.addImm32(@intCast(elem_size)); |
| 4741 | 4770 | try func.addTag(.i32_mul); |
| 4742 | 4771 | try func.addTag(.i32_add); |
| 4743 | 4772 | |
| ... | ... | @@ -4776,7 +4805,7 @@ fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4776 | 4805 | |
| 4777 | 4806 | // calculate index into ptr |
| 4778 | 4807 | try func.emitWValue(index); |
| 4779 | | try func.addImm32(@as(i32, @bitCast(@as(u32, @intCast(elem_size))))); |
| 4808 | try func.addImm32(@intCast(elem_size)); |
| 4780 | 4809 | try func.addTag(.i32_mul); |
| 4781 | 4810 | try func.addTag(.i32_add); |
| 4782 | 4811 | |
| ... | ... | @@ -4804,7 +4833,7 @@ fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 4804 | 4833 | |
| 4805 | 4834 | try func.lowerToStack(ptr); |
| 4806 | 4835 | try func.emitWValue(offset); |
| 4807 | | try func.addImm32(@as(i32, @bitCast(@as(u32, @intCast(pointee_ty.abiSize(mod)))))); |
| 4836 | try func.addImm32(@intCast(pointee_ty.abiSize(mod))); |
| 4808 | 4837 | try func.addTag(Mir.Inst.Tag.fromOpcode(mul_opcode)); |
| 4809 | 4838 | try func.addTag(Mir.Inst.Tag.fromOpcode(bin_opcode)); |
| 4810 | 4839 | |
| ... | ... | @@ -4948,7 +4977,7 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4948 | 4977 | if (isByRef(array_ty, mod)) { |
| 4949 | 4978 | try func.lowerToStack(array); |
| 4950 | 4979 | try func.emitWValue(index); |
| 4951 | | try func.addImm32(@as(i32, @bitCast(@as(u32, @intCast(elem_size))))); |
| 4980 | try func.addImm32(@intCast(elem_size)); |
| 4952 | 4981 | try func.addTag(.i32_mul); |
| 4953 | 4982 | try func.addTag(.i32_add); |
| 4954 | 4983 | } else { |
| ... | ... | @@ -4981,7 +5010,7 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4981 | 5010 | // Is a non-unrolled vector (v128) |
| 4982 | 5011 | try func.lowerToStack(stack_vec); |
| 4983 | 5012 | try func.emitWValue(index); |
| 4984 | | try func.addImm32(@as(i32, @bitCast(@as(u32, @intCast(elem_size))))); |
| 5013 | try func.addImm32(@intCast(elem_size)); |
| 4985 | 5014 | try func.addTag(.i32_mul); |
| 4986 | 5015 | try func.addTag(.i32_add); |
| 4987 | 5016 | }, |
| ... | ... | @@ -5717,7 +5746,7 @@ fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5717 | 5746 | const result = if (field_offset != 0) result: { |
| 5718 | 5747 | const base = try func.buildPointerOffset(field_ptr, 0, .new); |
| 5719 | 5748 | try func.addLabel(.local_get, base.local.value); |
| 5720 | | try func.addImm32(@as(i32, @bitCast(@as(u32, @intCast(field_offset))))); |
| 5749 | try func.addImm32(@intCast(field_offset)); |
| 5721 | 5750 | try func.addTag(.i32_sub); |
| 5722 | 5751 | try func.addLabel(.local_set, base.local.value); |
| 5723 | 5752 | break :result base; |
| ... | ... | @@ -5938,7 +5967,7 @@ fn airErrorName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5938 | 5967 | try func.emitWValue(operand); |
| 5939 | 5968 | switch (func.arch()) { |
| 5940 | 5969 | .wasm32 => { |
| 5941 | | try func.addImm32(@as(i32, @bitCast(@as(u32, @intCast(abi_size))))); |
| 5970 | try func.addImm32(@intCast(abi_size)); |
| 5942 | 5971 | try func.addTag(.i32_mul); |
| 5943 | 5972 | try func.addTag(.i32_add); |
| 5944 | 5973 | }, |
| ... | ... | @@ -7078,7 +7107,7 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 7078 | 7107 | if (wasm_bits != int_info.bits and op == .add) { |
| 7079 | 7108 | const val: u64 = @as(u64, @intCast((@as(u65, 1) << @as(u7, @intCast(int_info.bits))) - 1)); |
| 7080 | 7109 | const imm_val = switch (wasm_bits) { |
| 7081 | | 32 => WValue{ .imm32 = @as(u32, @intCast(val)) }, |
| 7110 | 32 => WValue{ .imm32 = @intCast(val) }, |
| 7082 | 7111 | 64 => WValue{ .imm64 = val }, |
| 7083 | 7112 | else => unreachable, |
| 7084 | 7113 | }; |
| ... | ... | @@ -7088,8 +7117,8 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 7088 | 7117 | _ = try func.cmp(bin_result, imm_val, ty, .lt); |
| 7089 | 7118 | } else { |
| 7090 | 7119 | switch (wasm_bits) { |
| 7091 | | 32 => try func.addImm32(if (op == .add) @as(i32, -1) else 0), |
| 7092 | | 64 => try func.addImm64(if (op == .add) @as(u64, @bitCast(@as(i64, -1))) else 0), |
| 7120 | 32 => try func.addImm32(if (op == .add) std.math.maxInt(u32) else 0), |
| 7121 | 64 => try func.addImm64(if (op == .add) std.math.maxInt(u64) else 0), |
| 7093 | 7122 | else => unreachable, |
| 7094 | 7123 | } |
| 7095 | 7124 | try func.emitWValue(bin_result); |
| ... | ... | @@ -7192,21 +7221,21 @@ fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7192 | 7221 | switch (wasm_bits) { |
| 7193 | 7222 | 32 => blk: { |
| 7194 | 7223 | if (!is_signed) { |
| 7195 | | try func.addImm32(-1); |
| 7224 | try func.addImm32(std.math.maxInt(u32)); |
| 7196 | 7225 | break :blk; |
| 7197 | 7226 | } |
| 7198 | | try func.addImm32(std.math.minInt(i32)); |
| 7199 | | try func.addImm32(std.math.maxInt(i32)); |
| 7227 | try func.addImm32(@bitCast(@as(i32, std.math.minInt(i32)))); |
| 7228 | try func.addImm32(@bitCast(@as(i32, std.math.maxInt(i32)))); |
| 7200 | 7229 | _ = try func.cmp(lhs, .{ .imm32 = 0 }, ty, .lt); |
| 7201 | 7230 | try func.addTag(.select); |
| 7202 | 7231 | }, |
| 7203 | 7232 | 64 => blk: { |
| 7204 | 7233 | if (!is_signed) { |
| 7205 | | try func.addImm64(@as(u64, @bitCast(@as(i64, -1)))); |
| 7234 | try func.addImm64(std.math.maxInt(u64)); |
| 7206 | 7235 | break :blk; |
| 7207 | 7236 | } |
| 7208 | | try func.addImm64(@as(u64, @bitCast(@as(i64, std.math.minInt(i64))))); |
| 7209 | | try func.addImm64(@as(u64, @bitCast(@as(i64, std.math.maxInt(i64))))); |
| 7237 | try func.addImm64(@bitCast(@as(i64, std.math.minInt(i64)))); |
| 7238 | try func.addImm64(@bitCast(@as(i64, std.math.maxInt(i64)))); |
| 7210 | 7239 | _ = try func.cmp(lhs, .{ .imm64 = 0 }, ty, .lt); |
| 7211 | 7240 | try func.addTag(.select); |
| 7212 | 7241 | }, |
| ... | ... | @@ -7236,23 +7265,23 @@ fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7236 | 7265 | switch (wasm_bits) { |
| 7237 | 7266 | 32 => blk: { |
| 7238 | 7267 | if (!is_signed) { |
| 7239 | | try func.addImm32(-1); |
| 7268 | try func.addImm32(std.math.maxInt(u32)); |
| 7240 | 7269 | break :blk; |
| 7241 | 7270 | } |
| 7242 | 7271 | |
| 7243 | | try func.addImm32(std.math.minInt(i32)); |
| 7244 | | try func.addImm32(std.math.maxInt(i32)); |
| 7272 | try func.addImm32(@bitCast(@as(i32, std.math.minInt(i32)))); |
| 7273 | try func.addImm32(@bitCast(@as(i32, std.math.maxInt(i32)))); |
| 7245 | 7274 | _ = try func.cmp(shl_res, .{ .imm32 = 0 }, ext_ty, .lt); |
| 7246 | 7275 | try func.addTag(.select); |
| 7247 | 7276 | }, |
| 7248 | 7277 | 64 => blk: { |
| 7249 | 7278 | if (!is_signed) { |
| 7250 | | try func.addImm64(@as(u64, @bitCast(@as(i64, -1)))); |
| 7279 | try func.addImm64(std.math.maxInt(u64)); |
| 7251 | 7280 | break :blk; |
| 7252 | 7281 | } |
| 7253 | 7282 | |
| 7254 | | try func.addImm64(@as(u64, @bitCast(@as(i64, std.math.minInt(i64))))); |
| 7255 | | try func.addImm64(@as(u64, @bitCast(@as(i64, std.math.maxInt(i64))))); |
| 7283 | try func.addImm64(@bitCast(@as(i64, std.math.minInt(i64)))); |
| 7284 | try func.addImm64(@bitCast(@as(i64, std.math.maxInt(i64)))); |
| 7256 | 7285 | _ = try func.cmp(shl_res, .{ .imm64 = 0 }, ext_ty, .lt); |
| 7257 | 7286 | try func.addTag(.select); |
| 7258 | 7287 | }, |
| ... | ... | @@ -7546,7 +7575,7 @@ fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7546 | 7575 | |
| 7547 | 7576 | // lower operand to determine jump table target |
| 7548 | 7577 | try func.emitWValue(operand); |
| 7549 | | try func.addImm32(@as(i32, @intCast(lowest.?))); |
| 7578 | try func.addImm32(lowest.?); |
| 7550 | 7579 | try func.addTag(.i32_sub); |
| 7551 | 7580 | |
| 7552 | 7581 | // Account for default branch so always add '1' |
| ... | ... | @@ -7641,7 +7670,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7641 | 7670 | |
| 7642 | 7671 | const result_ptr = if (isByRef(result_ty, mod)) val: { |
| 7643 | 7672 | try func.emitWValue(cmp_result); |
| 7644 | | try func.addImm32(-1); |
| 7673 | try func.addImm32(~@as(u32, 0)); |
| 7645 | 7674 | try func.addTag(.i32_xor); |
| 7646 | 7675 | try func.addImm32(1); |
| 7647 | 7676 | try func.addTag(.i32_and); |
| ... | ... | @@ -7717,9 +7746,9 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7717 | 7746 | |
| 7718 | 7747 | const and_res = try func.binOp(value, operand, ty, .@"and"); |
| 7719 | 7748 | if (wasm_bits == 32) |
| 7720 | | try func.addImm32(-1) |
| 7749 | try func.addImm32(~@as(u32, 0)) |
| 7721 | 7750 | else if (wasm_bits == 64) |
| 7722 | | try func.addImm64(@as(u64, @bitCast(@as(i64, -1)))) |
| 7751 | try func.addImm64(~@as(u64, 0)) |
| 7723 | 7752 | else |
| 7724 | 7753 | return func.fail("TODO: `@atomicRmw` with operator `Nand` for types larger than 64 bits", .{}); |
| 7725 | 7754 | _ = try func.binOp(and_res, .stack, ty, .xor); |
| ... | ... | @@ -7849,9 +7878,9 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7849 | 7878 | try func.emitWValue(ptr); |
| 7850 | 7879 | const and_res = try func.binOp(result, operand, ty, .@"and"); |
| 7851 | 7880 | if (wasm_bits == 32) |
| 7852 | | try func.addImm32(-1) |
| 7881 | try func.addImm32(~@as(u32, 0)) |
| 7853 | 7882 | else if (wasm_bits == 64) |
| 7854 | | try func.addImm64(@as(u64, @bitCast(@as(i64, -1)))) |
| 7883 | try func.addImm64(~@as(u64, 0)) |
| 7855 | 7884 | else |
| 7856 | 7885 | return func.fail("TODO: `@atomicRmw` with operator `Nand` for types larger than 64 bits", .{}); |
| 7857 | 7886 | _ = try func.binOp(and_res, .stack, ty, .xor); |