| ... | ... | @@ -3602,11 +3602,6 @@ fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareO |
| 3602 | 3602 | return func.cmpBigInt(lhs, rhs, ty, op); |
| 3603 | 3603 | } |
| 3604 | 3604 | |
| 3605 | | // ensure that when we compare pointers, we emit |
| 3606 | | // the true pointer of a stack value, rather than the stack pointer. |
| 3607 | | try func.lowerToStack(lhs); |
| 3608 | | try func.lowerToStack(rhs); |
| 3609 | | |
| 3610 | 3605 | const signedness: std.builtin.Signedness = blk: { |
| 3611 | 3606 | // by default we tell the operand type is unsigned (i.e. bools and enum values) |
| 3612 | 3607 | if (ty.zigTypeTag(mod) != .Int) break :blk .unsigned; |
| ... | ... | @@ -3614,6 +3609,30 @@ fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareO |
| 3614 | 3609 | // incase of an actual integer, we emit the correct signedness |
| 3615 | 3610 | break :blk ty.intInfo(mod).signedness; |
| 3616 | 3611 | }; |
| 3612 | const extend_sign = blk: { |
| 3613 | // do we need to extend the sign bit? |
| 3614 | if (signedness != .signed) break :blk false; |
| 3615 | if (op == .eq or op == .neq) break :blk false; |
| 3616 | const int_bits = ty.intInfo(mod).bits; |
| 3617 | const wasm_bits = toWasmBits(int_bits) orelse unreachable; |
| 3618 | break :blk (wasm_bits != int_bits); |
| 3619 | }; |
| 3620 | |
| 3621 | const lhs_wasm = if (extend_sign) |
| 3622 | try func.signExtendInt(lhs, ty) |
| 3623 | else |
| 3624 | lhs; |
| 3625 | |
| 3626 | const rhs_wasm = if (extend_sign) |
| 3627 | try func.signExtendInt(rhs, ty) |
| 3628 | else |
| 3629 | rhs; |
| 3630 | |
| 3631 | // ensure that when we compare pointers, we emit |
| 3632 | // the true pointer of a stack value, rather than the stack pointer. |
| 3633 | try func.lowerToStack(lhs_wasm); |
| 3634 | try func.lowerToStack(rhs_wasm); |
| 3635 | |
| 3617 | 3636 | const opcode: wasm.Opcode = buildOpcode(.{ |
| 3618 | 3637 | .valtype1 = typeToValtype(ty, mod), |
| 3619 | 3638 | .op = switch (op) { |
| ... | ... | @@ -6920,12 +6939,13 @@ fn signedSat(func: *CodeGen, lhs_operand: WValue, rhs_operand: WValue, ty: Type, |
| 6920 | 6939 | const int_info = ty.intInfo(mod); |
| 6921 | 6940 | const wasm_bits = toWasmBits(int_info.bits).?; |
| 6922 | 6941 | const is_wasm_bits = wasm_bits == int_info.bits; |
| 6942 | const ext_ty = if (!is_wasm_bits) try mod.intType(int_info.signedness, wasm_bits) else ty; |
| 6923 | 6943 | |
| 6924 | 6944 | var lhs = if (!is_wasm_bits) lhs: { |
| 6925 | | break :lhs try (try func.signExtendInt(lhs_operand, ty)).toLocal(func, ty); |
| 6945 | break :lhs try (try func.signExtendInt(lhs_operand, ty)).toLocal(func, ext_ty); |
| 6926 | 6946 | } else lhs_operand; |
| 6927 | 6947 | var rhs = if (!is_wasm_bits) rhs: { |
| 6928 | | break :rhs try (try func.signExtendInt(rhs_operand, ty)).toLocal(func, ty); |
| 6948 | break :rhs try (try func.signExtendInt(rhs_operand, ty)).toLocal(func, ext_ty); |
| 6929 | 6949 | } else rhs_operand; |
| 6930 | 6950 | |
| 6931 | 6951 | const max_val: u64 = @as(u64, @intCast((@as(u65, 1) << @as(u7, @intCast(int_info.bits - 1))) - 1)); |
| ... | ... | @@ -6941,20 +6961,20 @@ fn signedSat(func: *CodeGen, lhs_operand: WValue, rhs_operand: WValue, ty: Type, |
| 6941 | 6961 | else => unreachable, |
| 6942 | 6962 | }; |
| 6943 | 6963 | |
| 6944 | | var bin_result = try (try func.binOp(lhs, rhs, ty, op)).toLocal(func, ty); |
| 6964 | var bin_result = try (try func.binOp(lhs, rhs, ext_ty, op)).toLocal(func, ext_ty); |
| 6945 | 6965 | if (!is_wasm_bits) { |
| 6946 | 6966 | defer bin_result.free(func); // not returned in this branch |
| 6947 | 6967 | defer lhs.free(func); // uses temporary local for absvalue |
| 6948 | 6968 | defer rhs.free(func); // uses temporary local for absvalue |
| 6949 | 6969 | try func.emitWValue(bin_result); |
| 6950 | 6970 | try func.emitWValue(max_wvalue); |
| 6951 | | _ = try func.cmp(bin_result, max_wvalue, ty, .lt); |
| 6971 | _ = try func.cmp(bin_result, max_wvalue, ext_ty, .lt); |
| 6952 | 6972 | try func.addTag(.select); |
| 6953 | 6973 | try func.addLabel(.local_set, bin_result.local.value); // re-use local |
| 6954 | 6974 | |
| 6955 | 6975 | try func.emitWValue(bin_result); |
| 6956 | 6976 | try func.emitWValue(min_wvalue); |
| 6957 | | _ = try func.cmp(bin_result, min_wvalue, ty, .gt); |
| 6977 | _ = try func.cmp(bin_result, min_wvalue, ext_ty, .gt); |
| 6958 | 6978 | try func.addTag(.select); |
| 6959 | 6979 | try func.addLabel(.local_set, bin_result.local.value); // re-use local |
| 6960 | 6980 | return (try func.wrapOperand(bin_result, ty)).toLocal(func, ty); |
| ... | ... | @@ -7036,12 +7056,13 @@ fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7036 | 7056 | 64 => WValue{ .imm64 = shift_size }, |
| 7037 | 7057 | else => unreachable, |
| 7038 | 7058 | }; |
| 7059 | const ext_ty = try mod.intType(int_info.signedness, wasm_bits); |
| 7039 | 7060 | |
| 7040 | | var shl_res = try (try func.binOp(lhs, shift_value, ty, .shl)).toLocal(func, ty); |
| 7061 | var shl_res = try (try func.binOp(lhs, shift_value, ext_ty, .shl)).toLocal(func, ext_ty); |
| 7041 | 7062 | defer shl_res.free(func); |
| 7042 | | var shl = try (try func.binOp(shl_res, rhs, ty, .shl)).toLocal(func, ty); |
| 7063 | var shl = try (try func.binOp(shl_res, rhs, ext_ty, .shl)).toLocal(func, ext_ty); |
| 7043 | 7064 | defer shl.free(func); |
| 7044 | | var shr = try (try func.binOp(shl, rhs, ty, .shr)).toLocal(func, ty); |
| 7065 | var shr = try (try func.binOp(shl, rhs, ext_ty, .shr)).toLocal(func, ext_ty); |
| 7045 | 7066 | defer shr.free(func); |
| 7046 | 7067 | |
| 7047 | 7068 | switch (wasm_bits) { |
| ... | ... | @@ -7053,7 +7074,7 @@ fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7053 | 7074 | |
| 7054 | 7075 | try func.addImm32(std.math.minInt(i32)); |
| 7055 | 7076 | try func.addImm32(std.math.maxInt(i32)); |
| 7056 | | _ = try func.cmp(shl_res, .{ .imm32 = 0 }, ty, .lt); |
| 7077 | _ = try func.cmp(shl_res, .{ .imm32 = 0 }, ext_ty, .lt); |
| 7057 | 7078 | try func.addTag(.select); |
| 7058 | 7079 | }, |
| 7059 | 7080 | 64 => blk: { |
| ... | ... | @@ -7064,16 +7085,16 @@ fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7064 | 7085 | |
| 7065 | 7086 | try func.addImm64(@as(u64, @bitCast(@as(i64, std.math.minInt(i64))))); |
| 7066 | 7087 | try func.addImm64(@as(u64, @bitCast(@as(i64, std.math.maxInt(i64))))); |
| 7067 | | _ = try func.cmp(shl_res, .{ .imm64 = 0 }, ty, .lt); |
| 7088 | _ = try func.cmp(shl_res, .{ .imm64 = 0 }, ext_ty, .lt); |
| 7068 | 7089 | try func.addTag(.select); |
| 7069 | 7090 | }, |
| 7070 | 7091 | else => unreachable, |
| 7071 | 7092 | } |
| 7072 | 7093 | try func.emitWValue(shl); |
| 7073 | | _ = try func.cmp(shl_res, shr, ty, .neq); |
| 7094 | _ = try func.cmp(shl_res, shr, ext_ty, .neq); |
| 7074 | 7095 | try func.addTag(.select); |
| 7075 | 7096 | try func.addLabel(.local_set, result.local.value); |
| 7076 | | var shift_result = try func.binOp(result, shift_value, ty, .shr); |
| 7097 | var shift_result = try func.binOp(result, shift_value, ext_ty, .shr); |
| 7077 | 7098 | if (is_signed) { |
| 7078 | 7099 | shift_result = try func.wrapOperand(shift_result, ty); |
| 7079 | 7100 | } |