| author | |
| committer | |
| log | d1bd9518f97abc9ab80795962b8e0dfd8e4d8768 |
| tree | 4e41594948a124da7f8e41602807f9ee3fefdcf7 |
| parent | a57479afc2cea1b7c2c6802b7e8a1a7db973a3a3 |
Unexpected to be found only now2 files changed, 97 insertions(+), 72 deletions(-)
src/arch/wasm/CodeGen.zig+28-28| ... | ... | @@ -2675,41 +2675,41 @@ fn binOpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) Inner |
| 2675 | 2675 | .@"and", .@"or", .xor => { |
| 2676 | 2676 | const result = try func.allocStack(ty); |
| 2677 | 2677 | try func.emitWValue(result); |
| 2678 | const lhs_high_bit = try func.load(lhs, Type.u64, 0); | |
| 2679 | const rhs_high_bit = try func.load(rhs, Type.u64, 0); | |
| 2680 | const op_high_bit = try func.binOp(lhs_high_bit, rhs_high_bit, Type.u64, op); | |
| 2681 | try func.store(.stack, op_high_bit, Type.u64, result.offset()); | |
| 2678 | const lhs_low_bit = try func.load(lhs, Type.u64, 0); | |
| 2679 | const rhs_low_bit = try func.load(rhs, Type.u64, 0); | |
| 2680 | const op_low_bit = try func.binOp(lhs_low_bit, rhs_low_bit, Type.u64, op); | |
| 2681 | try func.store(.stack, op_low_bit, Type.u64, result.offset()); | |
| 2682 | 2682 | |
| 2683 | 2683 | try func.emitWValue(result); |
| 2684 | const lhs_low_bit = try func.load(lhs, Type.u64, 8); | |
| 2685 | const rhs_low_bit = try func.load(rhs, Type.u64, 8); | |
| 2686 | const op_low_bit = try func.binOp(lhs_low_bit, rhs_low_bit, Type.u64, op); | |
| 2687 | try func.store(.stack, op_low_bit, Type.u64, result.offset() + 8); | |
| 2684 | const lhs_high_bit = try func.load(lhs, Type.u64, 8); | |
| 2685 | const rhs_high_bit = try func.load(rhs, Type.u64, 8); | |
| 2686 | const op_high_bit = try func.binOp(lhs_high_bit, rhs_high_bit, Type.u64, op); | |
| 2687 | try func.store(.stack, op_high_bit, Type.u64, result.offset() + 8); | |
| 2688 | 2688 | return result; |
| 2689 | 2689 | }, |
| 2690 | 2690 | .add, .sub => { |
| 2691 | 2691 | const result = try func.allocStack(ty); |
| 2692 | var lhs_high_bit = try (try func.load(lhs, Type.u64, 0)).toLocal(func, Type.u64); | |
| 2693 | defer lhs_high_bit.free(func); | |
| 2694 | var rhs_high_bit = try (try func.load(rhs, Type.u64, 0)).toLocal(func, Type.u64); | |
| 2695 | defer rhs_high_bit.free(func); | |
| 2696 | var high_op_res = try (try func.binOp(lhs_high_bit, rhs_high_bit, Type.u64, op)).toLocal(func, Type.u64); | |
| 2697 | defer high_op_res.free(func); | |
| 2692 | var lhs_low_bit = try (try func.load(lhs, Type.u64, 0)).toLocal(func, Type.u64); | |
| 2693 | defer lhs_low_bit.free(func); | |
| 2694 | var rhs_low_bit = try (try func.load(rhs, Type.u64, 0)).toLocal(func, Type.u64); | |
| 2695 | defer rhs_low_bit.free(func); | |
| 2696 | var low_op_res = try (try func.binOp(lhs_low_bit, rhs_low_bit, Type.u64, op)).toLocal(func, Type.u64); | |
| 2697 | defer low_op_res.free(func); | |
| 2698 | 2698 | |
| 2699 | const lhs_low_bit = try func.load(lhs, Type.u64, 8); | |
| 2700 | const rhs_low_bit = try func.load(rhs, Type.u64, 8); | |
| 2701 | const low_op_res = try func.binOp(lhs_low_bit, rhs_low_bit, Type.u64, op); | |
| 2699 | const lhs_high_bit = try func.load(lhs, Type.u64, 8); | |
| 2700 | const rhs_high_bit = try func.load(rhs, Type.u64, 8); | |
| 2701 | const high_op_res = try func.binOp(lhs_high_bit, rhs_high_bit, Type.u64, op); | |
| 2702 | 2702 | |
| 2703 | 2703 | const lt = if (op == .add) blk: { |
| 2704 | break :blk try func.cmp(high_op_res, rhs_high_bit, Type.u64, .lt); | |
| 2704 | break :blk try func.cmp(low_op_res, rhs_low_bit, Type.u64, .lt); | |
| 2705 | 2705 | } else if (op == .sub) blk: { |
| 2706 | break :blk try func.cmp(lhs_high_bit, rhs_high_bit, Type.u64, .lt); | |
| 2706 | break :blk try func.cmp(lhs_low_bit, rhs_low_bit, Type.u64, .lt); | |
| 2707 | 2707 | } else unreachable; |
| 2708 | 2708 | const tmp = try func.intcast(lt, Type.u32, Type.u64); |
| 2709 | var tmp_op = try (try func.binOp(low_op_res, tmp, Type.u64, op)).toLocal(func, Type.u64); | |
| 2709 | var tmp_op = try (try func.binOp(high_op_res, tmp, Type.u64, op)).toLocal(func, Type.u64); | |
| 2710 | 2710 | defer tmp_op.free(func); |
| 2711 | 2711 | |
| 2712 | try func.store(result, high_op_res, Type.u64, 0); | |
| 2712 | try func.store(result, low_op_res, Type.u64, 0); | |
| 2713 | 2713 | try func.store(result, tmp_op, Type.u64, 8); |
| 2714 | 2714 | return result; |
| 2715 | 2715 | }, |
| ... | ... | @@ -5523,16 +5523,16 @@ fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std |
| 5523 | 5523 | return func.fail("TODO: Support cmpBigInt for integer bitsize: '{d}'", .{operand_ty.bitSize(pt)}); |
| 5524 | 5524 | } |
| 5525 | 5525 | |
| 5526 | var lhs_high_bit = try (try func.load(lhs, Type.u64, 0)).toLocal(func, Type.u64); | |
| 5526 | var lhs_high_bit = try (try func.load(lhs, Type.u64, 8)).toLocal(func, Type.u64); | |
| 5527 | 5527 | defer lhs_high_bit.free(func); |
| 5528 | var rhs_high_bit = try (try func.load(rhs, Type.u64, 0)).toLocal(func, Type.u64); | |
| 5528 | var rhs_high_bit = try (try func.load(rhs, Type.u64, 8)).toLocal(func, Type.u64); | |
| 5529 | 5529 | defer rhs_high_bit.free(func); |
| 5530 | 5530 | |
| 5531 | 5531 | switch (op) { |
| 5532 | 5532 | .eq, .neq => { |
| 5533 | 5533 | const xor_high = try func.binOp(lhs_high_bit, rhs_high_bit, Type.u64, .xor); |
| 5534 | const lhs_low_bit = try func.load(lhs, Type.u64, 8); | |
| 5535 | const rhs_low_bit = try func.load(rhs, Type.u64, 8); | |
| 5534 | const lhs_low_bit = try func.load(lhs, Type.u64, 0); | |
| 5535 | const rhs_low_bit = try func.load(rhs, Type.u64, 0); | |
| 5536 | 5536 | const xor_low = try func.binOp(lhs_low_bit, rhs_low_bit, Type.u64, .xor); |
| 5537 | 5537 | const or_result = try func.binOp(xor_high, xor_low, Type.u64, .@"or"); |
| 5538 | 5538 | |
| ... | ... | @@ -5545,9 +5545,9 @@ fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std |
| 5545 | 5545 | else => { |
| 5546 | 5546 | const ty = if (operand_ty.isSignedInt(mod)) Type.i64 else Type.u64; |
| 5547 | 5547 | // leave those value on top of the stack for '.select' |
| 5548 | const lhs_low_bit = try func.load(lhs, Type.u64, 8); | |
| 5549 | const rhs_low_bit = try func.load(rhs, Type.u64, 8); | |
| 5550 | _ = try func.cmp(lhs_low_bit, rhs_low_bit, ty, op); | |
| 5548 | const lhs_low_bit = try func.load(lhs, Type.u64, 0); | |
| 5549 | const rhs_low_bit = try func.load(rhs, Type.u64, 0); | |
| 5550 | _ = try func.cmp(lhs_low_bit, rhs_low_bit, Type.u64, op); | |
| 5551 | 5551 | _ = try func.cmp(lhs_high_bit, rhs_high_bit, ty, op); |
| 5552 | 5552 | _ = try func.cmp(lhs_high_bit, rhs_high_bit, ty, .eq); |
| 5553 | 5553 | try func.addTag(.select); |
test/behavior/basic.zig+69-44| ... | ... | @@ -1134,55 +1134,80 @@ test "pointer to struct literal with runtime field is constant" { |
| 1134 | 1134 | try expect(@typeInfo(@TypeOf(ptr)).Pointer.is_const); |
| 1135 | 1135 | } |
| 1136 | 1136 | |
| 1137 | test "integer compare" { | |
| 1137 | fn testSignedCmp(comptime T: type) !void { | |
| 1138 | var z: T = 0; | |
| 1139 | var p: T = 123; | |
| 1140 | var n: T = -123; | |
| 1141 | var min: T = std.math.minInt(T); | |
| 1142 | var max: T = std.math.maxInt(T); | |
| 1143 | var half_min: T = std.math.minInt(T) / 2; | |
| 1144 | var half_max: T = std.math.minInt(T) / 2; | |
| 1145 | _ = .{ &z, &p, &n, &min, &max, &half_min, &half_max }; | |
| 1146 | try expect(z == z and z != p and z != n); | |
| 1147 | try expect(p == p and p != n and n == n); | |
| 1148 | try expect(z > n and z < p and z >= n and z <= p); | |
| 1149 | try expect(!(z < n or z > p or z <= n or z >= p or z > z or z < z)); | |
| 1150 | try expect(p > n and n < p and p >= n and n <= p and p >= p and p <= p and n >= n and n <= n); | |
| 1151 | try expect(!(p < n or n > p or p <= n or n >= p or p > p or p < p or n > n or n < n)); | |
| 1152 | try expect(z == 0 and z != 123 and z != -123 and 0 == z and 0 != p and 0 != n); | |
| 1153 | try expect(z > -123 and p > -123 and !(n > 123)); | |
| 1154 | try expect(z < 123 and !(p < 123) and n < 123); | |
| 1155 | try expect(-123 <= z and -123 <= p and -123 <= n); | |
| 1156 | try expect(123 >= z and 123 >= p and 123 >= n); | |
| 1157 | try expect(!(0 != z or 123 != p or -123 != n)); | |
| 1158 | try expect(!(z > 0 or -123 > p or 123 < n)); | |
| 1159 | ||
| 1160 | try expect(min <= max and z <= max and p <= max and n <= max and half_max <= max and half_min <= max); | |
| 1161 | try expect(min <= max and min <= z and min <= p and min <= n and min <= half_min and min <= half_max); | |
| 1162 | } | |
| 1163 | ||
| 1164 | fn testUnsignedCmp(comptime T: type) !void { | |
| 1165 | var z: T = 0; | |
| 1166 | var p: T = 123; | |
| 1167 | var max: T = std.math.maxInt(T); | |
| 1168 | var half_max: T = std.math.minInt(T) / 2; | |
| 1169 | _ = .{ &z, &p, &max, &half_max }; | |
| 1170 | try expect(z == z and z != p); | |
| 1171 | try expect(p == p); | |
| 1172 | try expect(z < p and z <= p); | |
| 1173 | try expect(!(z > p or z >= p or z > z or z < z)); | |
| 1174 | try expect(p >= p and p <= p); | |
| 1175 | try expect(!(p > p or p < p)); | |
| 1176 | try expect(z == 0 and z != 123 and z != -123 and 0 == z and 0 != p); | |
| 1177 | try expect(z > -123 and p > -123); | |
| 1178 | try expect(z < 123 and !(p < 123)); | |
| 1179 | try expect(-123 <= z and -123 <= p); | |
| 1180 | try expect(123 >= z and 123 >= p); | |
| 1181 | try expect(!(0 != z or 123 != p)); | |
| 1182 | try expect(!(z > 0 or -123 > p)); | |
| 1183 | ||
| 1184 | try expect(z <= max and p <= max and half_max <= max); | |
| 1185 | try expect(half_max != max); | |
| 1186 | } | |
| 1187 | ||
| 1188 | test "integer compare <= 64 bits" { | |
| 1138 | 1189 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1139 | 1190 | |
| 1140 | const S = struct { | |
| 1141 | fn doTheTestSigned(comptime T: type) !void { | |
| 1142 | var z: T = 0; | |
| 1143 | var p: T = 123; | |
| 1144 | var n: T = -123; | |
| 1145 | _ = .{ &z, &p, &n }; | |
| 1146 | try expect(z == z and z != p and z != n); | |
| 1147 | try expect(p == p and p != n and n == n); | |
| 1148 | try expect(z > n and z < p and z >= n and z <= p); | |
| 1149 | try expect(!(z < n or z > p or z <= n or z >= p or z > z or z < z)); | |
| 1150 | try expect(p > n and n < p and p >= n and n <= p and p >= p and p <= p and n >= n and n <= n); | |
| 1151 | try expect(!(p < n or n > p or p <= n or n >= p or p > p or p < p or n > n or n < n)); | |
| 1152 | try expect(z == 0 and z != 123 and z != -123 and 0 == z and 0 != p and 0 != n); | |
| 1153 | try expect(z > -123 and p > -123 and !(n > 123)); | |
| 1154 | try expect(z < 123 and !(p < 123) and n < 123); | |
| 1155 | try expect(-123 <= z and -123 <= p and -123 <= n); | |
| 1156 | try expect(123 >= z and 123 >= p and 123 >= n); | |
| 1157 | try expect(!(0 != z or 123 != p or -123 != n)); | |
| 1158 | try expect(!(z > 0 or -123 > p or 123 < n)); | |
| 1159 | } | |
| 1160 | fn doTheTestUnsigned(comptime T: type) !void { | |
| 1161 | var z: T = 0; | |
| 1162 | var p: T = 123; | |
| 1163 | _ = .{ &z, &p }; | |
| 1164 | try expect(z == z and z != p); | |
| 1165 | try expect(p == p); | |
| 1166 | try expect(z < p and z <= p); | |
| 1167 | try expect(!(z > p or z >= p or z > z or z < z)); | |
| 1168 | try expect(p >= p and p <= p); | |
| 1169 | try expect(!(p > p or p < p)); | |
| 1170 | try expect(z == 0 and z != 123 and z != -123 and 0 == z and 0 != p); | |
| 1171 | try expect(z > -123 and p > -123); | |
| 1172 | try expect(z < 123 and !(p < 123)); | |
| 1173 | try expect(-123 <= z and -123 <= p); | |
| 1174 | try expect(123 >= z and 123 >= p); | |
| 1175 | try expect(!(0 != z or 123 != p)); | |
| 1176 | try expect(!(z > 0 or -123 > p)); | |
| 1177 | } | |
| 1178 | }; | |
| 1179 | 1191 | inline for (.{ u8, u16, u32, u64, usize, u10, u20, u30, u60 }) |T| { |
| 1180 | try S.doTheTestUnsigned(T); | |
| 1181 | try comptime S.doTheTestUnsigned(T); | |
| 1192 | try testUnsignedCmp(T); | |
| 1193 | try comptime testUnsignedCmp(T); | |
| 1182 | 1194 | } |
| 1183 | 1195 | inline for (.{ i8, i16, i32, i64, isize, i10, i20, i30, i60 }) |T| { |
| 1184 | try S.doTheTestSigned(T); | |
| 1185 | try comptime S.doTheTestSigned(T); | |
| 1196 | try testSignedCmp(T); | |
| 1197 | try comptime testSignedCmp(T); | |
| 1198 | } | |
| 1199 | } | |
| 1200 | ||
| 1201 | test "integer compare <= 128 bits" { | |
| 1202 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 1203 | ||
| 1204 | inline for (.{ u65, u96, u127, u128 }) |T| { | |
| 1205 | try testUnsignedCmp(T); | |
| 1206 | try comptime testUnsignedCmp(T); | |
| 1207 | } | |
| 1208 | inline for (.{ i65, i96, i127, i128 }) |T| { | |
| 1209 | try testSignedCmp(T); | |
| 1210 | try comptime testSignedCmp(T); | |
| 1186 | 1211 | } |
| 1187 | 1212 | } |
| 1188 | 1213 |