aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorCody Tapscott <topolarity@tapscott.me>2022-02-27 01:19:02 -0700
committerCody Tapscott <topolarity@tapscott.me>2022-02-27 02:24:28 -0700
commita7a508fcd9a961ea9d903f9065556a02b4045b95 (patch)
tree32a18d391650f39f4b67bf679fc213b2446a6b21 /src/Sema.zig
parentb52948444f16c082f0e29bb75b246370c4b11326 (diff)
downloadzig-a7a508fcd9a961ea9d903f9065556a02b4045b95.tar.gz
zig-a7a508fcd9a961ea9d903f9065556a02b4045b95.zip
stage2 sema: Implement comptime result for comparison of uint to comptime value
This adds a comptime result when comparing a comptime value to an unsigned integer. For example: ( 0 <= (unsigned runtime value)) => true (-1 < (unsigned runtime value)) => true ((unsigned runtime value) < -15) => false
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig54
1 files changed, 38 insertions, 16 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 4dad9a6c8c..9b03b4c32e 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -17036,30 +17036,41 @@ fn cmpNumeric(
if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| {
if (lhs_val.isUndef())
return sema.addConstUndef(Type.bool);
- const is_unsigned = if (lhs_is_float) x: {
+ if (!rhs_is_signed) {
+ switch (lhs_val.orderAgainstZero()) {
+ .gt => {},
+ .eq => switch (op) { // LHS = 0, RHS is unsigned
+ .lte => return Air.Inst.Ref.bool_true,
+ .gt => return Air.Inst.Ref.bool_false,
+ else => {},
+ },
+ .lt => switch (op) { // LHS < 0, RHS is unsigned
+ .neq, .lt, .lte => return Air.Inst.Ref.bool_true,
+ .eq, .gt, .gte => return Air.Inst.Ref.bool_false,
+ },
+ }
+ }
+ if (lhs_is_float) {
var bigint_space: Value.BigIntSpace = undefined;
var bigint = try lhs_val.toBigInt(&bigint_space).toManaged(sema.gpa);
defer bigint.deinit();
- const zcmp = lhs_val.orderAgainstZero();
if (lhs_val.floatHasFraction()) {
switch (op) {
.eq => return Air.Inst.Ref.bool_false,
.neq => return Air.Inst.Ref.bool_true,
else => {},
}
- if (zcmp == .lt) {
+ if (lhs_is_signed) {
try bigint.addScalar(bigint.toConst(), -1);
} else {
try bigint.addScalar(bigint.toConst(), 1);
}
}
lhs_bits = bigint.toConst().bitCountTwosComp();
- break :x (zcmp != .lt);
- } else x: {
+ } else {
lhs_bits = lhs_val.intBitCountTwosComp(target);
- break :x (lhs_val.orderAgainstZero() != .lt);
- };
- lhs_bits += @boolToInt(is_unsigned and dest_int_is_signed);
+ }
+ lhs_bits += @boolToInt(!lhs_is_signed and dest_int_is_signed);
} else if (lhs_is_float) {
dest_float_type = lhs_ty;
} else {
@@ -17071,30 +17082,41 @@ fn cmpNumeric(
if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| {
if (rhs_val.isUndef())
return sema.addConstUndef(Type.bool);
- const is_unsigned = if (rhs_is_float) x: {
+ if (!lhs_is_signed) {
+ switch (rhs_val.orderAgainstZero()) {
+ .gt => {},
+ .eq => switch (op) { // RHS = 0, LHS is unsigned
+ .gte => return Air.Inst.Ref.bool_true,
+ .lt => return Air.Inst.Ref.bool_false,
+ else => {},
+ },
+ .lt => switch (op) { // RHS < 0, LHS is unsigned
+ .neq, .gt, .gte => return Air.Inst.Ref.bool_true,
+ .eq, .lt, .lte => return Air.Inst.Ref.bool_false,
+ },
+ }
+ }
+ if (rhs_is_float) {
var bigint_space: Value.BigIntSpace = undefined;
var bigint = try rhs_val.toBigInt(&bigint_space).toManaged(sema.gpa);
defer bigint.deinit();
- const zcmp = rhs_val.orderAgainstZero();
if (rhs_val.floatHasFraction()) {
switch (op) {
.eq => return Air.Inst.Ref.bool_false,
.neq => return Air.Inst.Ref.bool_true,
else => {},
}
- if (zcmp == .lt) {
+ if (rhs_is_signed) {
try bigint.addScalar(bigint.toConst(), -1);
} else {
try bigint.addScalar(bigint.toConst(), 1);
}
}
rhs_bits = bigint.toConst().bitCountTwosComp();
- break :x (zcmp != .lt);
- } else x: {
+ } else {
rhs_bits = rhs_val.intBitCountTwosComp(target);
- break :x (rhs_val.orderAgainstZero() != .lt);
- };
- rhs_bits += @boolToInt(is_unsigned and dest_int_is_signed);
+ }
+ rhs_bits += @boolToInt(!rhs_is_signed and dest_int_is_signed);
} else if (rhs_is_float) {
dest_float_type = rhs_ty;
} else {