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