authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-10-15 12:11:55-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-10-15 12:11:55-04:00
log16cc65242fd6e2fc9883fb87e5e78e1d1641db3e
tree93a82a9b42856d0e54aaf45889ee9670a14c9571
parent400319872ba2fd1707a90db232e9c790450f37eb
parent02d7292a8c1f478b77ef23dbe875b5443bba951c
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12918 from jacobly0/math-cast-comptime-int

std.math: fix behavior relating to comptime_int arguments

5 files changed, 65 insertions(+), 6 deletions(-)

build.zig+14
......@@ -554,6 +554,8 @@ fn addCmakeCfgOptionsToExe(
554554 }) catch unreachable);
555555 assert(cfg.lld_include_dir.len != 0);
556556 exe.addIncludePath(cfg.lld_include_dir);
557 exe.addIncludePath(cfg.llvm_include_dir);
558 exe.addLibraryPath(cfg.llvm_lib_dir);
557559 addCMakeLibraryList(exe, cfg.clang_libraries);
558560 addCMakeLibraryList(exe, cfg.lld_libraries);
559561 addCMakeLibraryList(exe, cfg.llvm_libraries);
......@@ -684,6 +686,8 @@ const CMakeConfig = struct {
684686 lld_include_dir: []const u8,
685687 lld_libraries: []const u8,
686688 clang_libraries: []const u8,
689 llvm_lib_dir: []const u8,
690 llvm_include_dir: []const u8,
687691 llvm_libraries: []const u8,
688692 dia_guids_lib: []const u8,
689693};
......@@ -745,6 +749,8 @@ fn parseConfigH(b: *Builder, config_h_text: []const u8) ?CMakeConfig {
745749 .lld_include_dir = undefined,
746750 .lld_libraries = undefined,
747751 .clang_libraries = undefined,
752 .llvm_lib_dir = undefined,
753 .llvm_include_dir = undefined,
748754 .llvm_libraries = undefined,
749755 .dia_guids_lib = undefined,
750756 };
......@@ -782,6 +788,14 @@ fn parseConfigH(b: *Builder, config_h_text: []const u8) ?CMakeConfig {
782788 .prefix = "#define ZIG_DIA_GUIDS_LIB ",
783789 .field = "dia_guids_lib",
784790 },
791 .{
792 .prefix = "#define ZIG_LLVM_INCLUDE_PATH ",
793 .field = "llvm_include_dir",
794 },
795 .{
796 .prefix = "#define ZIG_LLVM_LIB_PATH ",
797 .field = "llvm_lib_dir",
798 },
785799 // .prefix = ZIG_LLVM_LINK_MODE parsed manually below
786800 };
787801
lib/std/math.zig+10-3
......@@ -1063,10 +1063,11 @@ test "negateCast" {
10631063/// return null.
10641064pub fn cast(comptime T: type, x: anytype) ?T {
10651065 comptime assert(@typeInfo(T) == .Int); // must pass an integer
1066 comptime assert(@typeInfo(@TypeOf(x)) == .Int); // must pass an integer
1067 if (maxInt(@TypeOf(x)) > maxInt(T) and x > maxInt(T)) {
1066 const is_comptime = @TypeOf(x) == comptime_int;
1067 comptime assert(is_comptime or @typeInfo(@TypeOf(x)) == .Int); // must pass an integer
1068 if ((is_comptime or maxInt(@TypeOf(x)) > maxInt(T)) and x > maxInt(T)) {
10681069 return null;
1069 } else if (minInt(@TypeOf(x)) < minInt(T) and x < minInt(T)) {
1070 } else if ((is_comptime or minInt(@TypeOf(x)) < minInt(T)) and x < minInt(T)) {
10701071 return null;
10711072 } else {
10721073 return @intCast(T, x);
......@@ -1074,12 +1075,18 @@ pub fn cast(comptime T: type, x: anytype) ?T {
10741075}
10751076
10761077test "cast" {
1078 try testing.expect(cast(u8, 300) == null);
10771079 try testing.expect(cast(u8, @as(u32, 300)) == null);
1080 try testing.expect(cast(i8, -200) == null);
10781081 try testing.expect(cast(i8, @as(i32, -200)) == null);
1082 try testing.expect(cast(u8, -1) == null);
10791083 try testing.expect(cast(u8, @as(i8, -1)) == null);
1084 try testing.expect(cast(u64, -1) == null);
10801085 try testing.expect(cast(u64, @as(i8, -1)) == null);
10811086
1087 try testing.expect(cast(u8, 255).? == @as(u8, 255));
10821088 try testing.expect(cast(u8, @as(u32, 255)).? == @as(u8, 255));
1089 try testing.expect(@TypeOf(cast(u8, 255).?) == u8);
10831090 try testing.expect(@TypeOf(cast(u8, @as(u32, 255)).?) == u8);
10841091}
10851092
lib/std/math/big/int.zig+27-2
......@@ -21,6 +21,9 @@ const debug_safety = false;
2121
2222/// Returns the number of limbs needed to store `scalar`, which must be a
2323/// primitive integer value.
24/// Note: A comptime-known upper bound of this value that may be used
25/// instead if `scalar` is not already comptime-known is
26/// `calcTwosCompLimbCount(@typeInfo(@TypeOf(scalar)).Int.bits)`
2427pub fn calcLimbLen(scalar: anytype) usize {
2528 if (scalar == 0) {
2629 return 1;
......@@ -391,7 +394,18 @@ pub const Mutable = struct {
391394 /// Asserts the result fits in `r`. An upper bound on the number of limbs needed by
392395 /// r is `math.max(a.limbs.len, calcLimbLen(scalar)) + 1`.
393396 pub fn addScalar(r: *Mutable, a: Const, scalar: anytype) void {
394 var limbs: [calcLimbLen(scalar)]Limb = undefined;
397 // Normally we could just determine the number of limbs needed with calcLimbLen,
398 // but that is not comptime-known when scalar is not a comptime_int. Instead, we
399 // use calcTwosCompLimbCount for a non-comptime_int scalar, which can be pessimistic
400 // in the case that scalar happens to be small in magnitude within its type, but it
401 // is well worth being able to use the stack and not needing an allocator passed in.
402 // Note that Mutable.init still sets len to calcLimbLen(scalar) in any case.
403 const limb_len = comptime switch (@typeInfo(@TypeOf(scalar))) {
404 .ComptimeInt => calcLimbLen(scalar),
405 .Int => |info| calcTwosCompLimbCount(info.bits),
406 else => @compileError("expected scalar to be an int"),
407 };
408 var limbs: [limb_len]Limb = undefined;
395409 const operand = init(&limbs, scalar).toConst();
396410 return add(r, a, operand);
397411 }
......@@ -2303,7 +2317,18 @@ pub const Const = struct {
23032317
23042318 /// Same as `order` but the right-hand operand is a primitive integer.
23052319 pub fn orderAgainstScalar(lhs: Const, scalar: anytype) math.Order {
2306 var limbs: [calcLimbLen(scalar)]Limb = undefined;
2320 // Normally we could just determine the number of limbs needed with calcLimbLen,
2321 // but that is not comptime-known when scalar is not a comptime_int. Instead, we
2322 // use calcTwosCompLimbCount for a non-comptime_int scalar, which can be pessimistic
2323 // in the case that scalar happens to be small in magnitude within its type, but it
2324 // is well worth being able to use the stack and not needing an allocator passed in.
2325 // Note that Mutable.init still sets len to calcLimbLen(scalar) in any case.
2326 const limb_len = comptime switch (@typeInfo(@TypeOf(scalar))) {
2327 .ComptimeInt => calcLimbLen(scalar),
2328 .Int => |info| calcTwosCompLimbCount(info.bits),
2329 else => @compileError("expected scalar to be an int"),
2330 };
2331 var limbs: [limb_len]Limb = undefined;
23072332 const rhs = Mutable.init(&limbs, scalar);
23082333 return order(lhs, rhs.toConst());
23092334 }
lib/std/math/big/int_test.zig+12-1
......@@ -573,7 +573,7 @@ test "big.int add sign" {
573573 try testing.expect((try a.to(i32)) == -3);
574574}
575575
576test "big.int add scalar" {
576test "big.int add comptime scalar" {
577577 var a = try Managed.initSet(testing.allocator, 50);
578578 defer a.deinit();
579579
......@@ -584,6 +584,17 @@ test "big.int add scalar" {
584584 try testing.expect((try b.to(u32)) == 55);
585585}
586586
587test "big.int add scalar" {
588 var a = try Managed.initSet(testing.allocator, 123);
589 defer a.deinit();
590
591 var b = try Managed.init(testing.allocator);
592 defer b.deinit();
593 try b.addScalar(&a, @as(u32, 31));
594
595 try testing.expect((try b.to(u32)) == 154);
596}
597
587598test "big.int addWrap single-single, unsigned" {
588599 var a = try Managed.initSet(testing.allocator, maxInt(u17));
589600 defer a.deinit();
src/stage1/config.h.in+2
......@@ -22,6 +22,8 @@
2222#define ZIG_LLD_INCLUDE_PATH "@LLD_INCLUDE_DIRS@"
2323#define ZIG_LLD_LIBRARIES "@LLD_LIBRARIES@"
2424#define ZIG_CLANG_LIBRARIES "@CLANG_LIBRARIES@"
25#define ZIG_LLVM_INCLUDE_PATH "@LLVM_INCLUDE_DIRS@"
26#define ZIG_LLVM_LIB_PATH "@LLVM_LIBDIRS@"
2527#define ZIG_LLVM_LIBRARIES "@LLVM_LIBRARIES@"
2628#define ZIG_DIA_GUIDS_LIB "@ZIG_DIA_GUIDS_LIB_ESCAPED@"
2729