mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
Merge pull request #11002 from topolarity/comptime-int-comparison
stage2: Add comptime result for certain unsigned/comptime comparisons
This commit is contained in:
commit
104a8840db
55
src/Sema.zig
55
src/Sema.zig
@ -11842,6 +11842,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
const operand = sema.resolveInst(inst_data.operand);
|
||||
const operand_ty = sema.typeOf(operand);
|
||||
|
||||
try sema.resolveTypeLayout(block, operand_src, operand_ty);
|
||||
const enum_ty = switch (operand_ty.zigTypeTag()) {
|
||||
.EnumLiteral => {
|
||||
const val = try sema.resolveConstValue(block, operand_src, operand);
|
||||
@ -17113,30 +17114,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 {
|
||||
@ -17148,30 +17160,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 {
|
||||
|
||||
@ -559,8 +559,6 @@ fn modifySomeBytes(bytes: []u8) void {
|
||||
}
|
||||
|
||||
test "comparisons 0 <= uint and 0 > uint should be comptime" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
testCompTimeUIntComparisons(1234);
|
||||
}
|
||||
fn testCompTimeUIntComparisons(x: u32) void {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user