From 440b3df702f1c8bfddabc1c594a3f49cf0011a63 Mon Sep 17 00:00:00 2001 From: kcbanner Date: Sat, 29 Apr 2023 11:54:21 -0400 Subject: main: parse --dynamicbase linker arg --- src/main.zig | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/main.zig') diff --git a/src/main.zig b/src/main.zig index 66b207aa43..45b0cf30b8 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2072,6 +2072,8 @@ fn buildOutputType( linker_tsaware = true; } else if (mem.eql(u8, arg, "--nxcompat")) { linker_nxcompat = true; + } else if (mem.eql(u8, arg, "--dynamicbase")) { + linker_dynamicbase = true; } else if (mem.eql(u8, arg, "--no-dynamicbase")) { linker_dynamicbase = false; } else if (mem.eql(u8, arg, "--high-entropy-va")) { -- cgit v1.2.3 From d70853ba39cb1694d91a763ea8492f3aed1494a7 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 5 May 2023 03:04:44 -0400 Subject: main: add debug dump-zir command --- src/Module.zig | 141 ++++++++++++++++++++++++++++++--------------------------- src/main.zig | 62 +++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 66 deletions(-) (limited to 'src/main.zig') diff --git a/src/Module.zig b/src/Module.zig index 93e247f7a3..538c716bc3 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -3671,74 +3671,13 @@ pub fn astGenFile(mod: *Module, file: *File) !void { file.sub_file_path, header.instructions_len, }); - var instructions: std.MultiArrayList(Zir.Inst) = .{}; - defer instructions.deinit(gpa); - - try instructions.setCapacity(gpa, header.instructions_len); - instructions.len = header.instructions_len; - - var zir: Zir = .{ - .instructions = instructions.toOwnedSlice(), - .string_bytes = &.{}, - .extra = &.{}, - }; - var keep_zir = false; - defer if (!keep_zir) zir.deinit(gpa); - - zir.string_bytes = try gpa.alloc(u8, header.string_bytes_len); - zir.extra = try gpa.alloc(u32, header.extra_len); - - const safety_buffer = if (data_has_safety_tag) - try gpa.alloc([8]u8, header.instructions_len) - else - undefined; - defer if (data_has_safety_tag) gpa.free(safety_buffer); - - const data_ptr = if (data_has_safety_tag) - @ptrCast([*]u8, safety_buffer.ptr) - else - @ptrCast([*]u8, zir.instructions.items(.data).ptr); - - var iovecs = [_]std.os.iovec{ - .{ - .iov_base = @ptrCast([*]u8, zir.instructions.items(.tag).ptr), - .iov_len = header.instructions_len, - }, - .{ - .iov_base = data_ptr, - .iov_len = header.instructions_len * 8, - }, - .{ - .iov_base = zir.string_bytes.ptr, - .iov_len = header.string_bytes_len, - }, - .{ - .iov_base = @ptrCast([*]u8, zir.extra.ptr), - .iov_len = header.extra_len * 4, + file.zir = loadZirCacheBody(gpa, header, cache_file) catch |err| switch (err) { + error.UnexpectedFileSize => { + log.warn("unexpected EOF reading cached ZIR for {s}", .{file.sub_file_path}); + break :update; }, + else => |e| return e, }; - const amt_read = try cache_file.readvAll(&iovecs); - const amt_expected = zir.instructions.len * 9 + - zir.string_bytes.len + - zir.extra.len * 4; - if (amt_read != amt_expected) { - log.warn("unexpected EOF reading cached ZIR for {s}", .{file.sub_file_path}); - break :update; - } - if (data_has_safety_tag) { - const tags = zir.instructions.items(.tag); - for (zir.instructions.items(.data), 0..) |*data, i| { - const union_tag = Zir.Inst.Tag.data_tags[@enumToInt(tags[i])]; - const as_struct = @ptrCast(*HackDataLayout, data); - as_struct.* = .{ - .safety_tag = @enumToInt(union_tag), - .data = safety_buffer[i], - }; - } - } - - keep_zir = true; - file.zir = zir; file.zir_loaded = true; file.stat = .{ .size = header.stat_size, @@ -3916,6 +3855,76 @@ pub fn astGenFile(mod: *Module, file: *File) !void { } } +pub fn loadZirCache(gpa: Allocator, cache_file: std.fs.File) !Zir { + return loadZirCacheBody(gpa, try cache_file.reader().readStruct(Zir.Header), cache_file); +} + +fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File) !Zir { + var instructions: std.MultiArrayList(Zir.Inst) = .{}; + errdefer instructions.deinit(gpa); + + try instructions.setCapacity(gpa, header.instructions_len); + instructions.len = header.instructions_len; + + var zir: Zir = .{ + .instructions = instructions.toOwnedSlice(), + .string_bytes = &.{}, + .extra = &.{}, + }; + errdefer zir.deinit(gpa); + + zir.string_bytes = try gpa.alloc(u8, header.string_bytes_len); + zir.extra = try gpa.alloc(u32, header.extra_len); + + const safety_buffer = if (data_has_safety_tag) + try gpa.alloc([8]u8, header.instructions_len) + else + undefined; + defer if (data_has_safety_tag) gpa.free(safety_buffer); + + const data_ptr = if (data_has_safety_tag) + @ptrCast([*]u8, safety_buffer.ptr) + else + @ptrCast([*]u8, zir.instructions.items(.data).ptr); + + var iovecs = [_]std.os.iovec{ + .{ + .iov_base = @ptrCast([*]u8, zir.instructions.items(.tag).ptr), + .iov_len = header.instructions_len, + }, + .{ + .iov_base = data_ptr, + .iov_len = header.instructions_len * 8, + }, + .{ + .iov_base = zir.string_bytes.ptr, + .iov_len = header.string_bytes_len, + }, + .{ + .iov_base = @ptrCast([*]u8, zir.extra.ptr), + .iov_len = header.extra_len * 4, + }, + }; + const amt_read = try cache_file.readvAll(&iovecs); + const amt_expected = zir.instructions.len * 9 + + zir.string_bytes.len + + zir.extra.len * 4; + if (amt_read != amt_expected) return error.UnexpectedFileSize; + if (data_has_safety_tag) { + const tags = zir.instructions.items(.tag); + for (zir.instructions.items(.data), 0..) |*data, i| { + const union_tag = Zir.Inst.Tag.data_tags[@enumToInt(tags[i])]; + const as_struct = @ptrCast(*HackDataLayout, data); + as_struct.* = .{ + .safety_tag = @enumToInt(union_tag), + .data = safety_buffer[i], + }; + } + } + + return zir; +} + /// Patch ups: /// * Struct.zir_index /// * Decl.zir_index diff --git a/src/main.zig b/src/main.zig index 45b0cf30b8..a680a5d89e 100644 --- a/src/main.zig +++ b/src/main.zig @@ -122,6 +122,7 @@ const debug_usage = normal_usage ++ \\Debug Commands: \\ \\ changelist Compute mappings from old ZIR to new ZIR + \\ dump-zir Dump a file containing cached ZIR \\ ; @@ -326,6 +327,8 @@ pub fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi return cmdAstCheck(gpa, arena, cmd_args); } else if (debug_extensions_enabled and mem.eql(u8, cmd, "changelist")) { return cmdChangelist(gpa, arena, cmd_args); + } else if (debug_extensions_enabled and mem.eql(u8, cmd, "dump-zir")) { + return cmdDumpZir(gpa, arena, cmd_args); } else { std.log.info("{s}", .{usage}); fatal("unknown command: {s}", .{args[1]}); @@ -5579,6 +5582,65 @@ pub fn cmdAstCheck( return @import("print_zir.zig").renderAsTextToFile(gpa, &file, io.getStdOut()); } +/// This is only enabled for debug builds. +pub fn cmdDumpZir( + gpa: Allocator, + arena: Allocator, + args: []const []const u8, +) !void { + _ = arena; + const Zir = @import("Zir.zig"); + + const cache_file = args[0]; + + var f = fs.cwd().openFile(cache_file, .{}) catch |err| { + fatal("unable to open zir cache file for dumping '{s}': {s}", .{ cache_file, @errorName(err) }); + }; + defer f.close(); + + var file: Module.File = .{ + .status = .never_loaded, + .source_loaded = false, + .tree_loaded = false, + .zir_loaded = true, + .sub_file_path = undefined, + .source = undefined, + .stat = undefined, + .tree = undefined, + .zir = try Module.loadZirCache(gpa, f), + .pkg = undefined, + .root_decl = .none, + }; + + { + const instruction_bytes = file.zir.instructions.len * + // Here we don't use @sizeOf(Zir.Inst.Data) because it would include + // the debug safety tag but we want to measure release size. + (@sizeOf(Zir.Inst.Tag) + 8); + const extra_bytes = file.zir.extra.len * @sizeOf(u32); + const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes + + file.zir.string_bytes.len * @sizeOf(u8); + const stdout = io.getStdOut(); + const fmtIntSizeBin = std.fmt.fmtIntSizeBin; + // zig fmt: off + try stdout.writer().print( + \\# Total ZIR bytes: {} + \\# Instructions: {d} ({}) + \\# String Table Bytes: {} + \\# Extra Data Items: {d} ({}) + \\ + , .{ + fmtIntSizeBin(total_bytes), + file.zir.instructions.len, fmtIntSizeBin(instruction_bytes), + fmtIntSizeBin(file.zir.string_bytes.len), + file.zir.extra.len, fmtIntSizeBin(extra_bytes), + }); + // zig fmt: on + } + + return @import("print_zir.zig").renderAsTextToFile(gpa, &file, io.getStdOut()); +} + /// This is only enabled for debug builds. pub fn cmdChangelist( gpa: Allocator, -- cgit v1.2.3 From ce9f3ec990cd556f2a9d06a6db2bb53e97a61172 Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Thu, 4 May 2023 18:34:41 -0700 Subject: Fix SplitIterator and TokenIterator type instantiation --- src/main.zig | 2 +- test/src/Cases.zig | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/main.zig') diff --git a/src/main.zig b/src/main.zig index a680a5d89e..c61e3f3719 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3531,7 +3531,7 @@ fn serveUpdateResults(s: *Server, comp: *Compilation) !void { } const ModuleDepIterator = struct { - split: mem.SplitIterator(u8), + split: mem.SplitIterator(u8, .scalar), fn init(deps_str: []const u8) ModuleDepIterator { return .{ .split = mem.split(u8, deps_str, ",") }; diff --git a/test/src/Cases.zig b/test/src/Cases.zig index 0451079a0e..68ecebc7bd 100644 --- a/test/src/Cases.zig +++ b/test/src/Cases.zig @@ -795,7 +795,7 @@ const TestManifest = struct { }; const TrailingIterator = struct { - inner: std.mem.TokenIterator(u8), + inner: std.mem.TokenIterator(u8, .any), fn next(self: *TrailingIterator) ?[]const u8 { const next_inner = self.inner.next() orelse return null; @@ -805,7 +805,7 @@ const TestManifest = struct { fn ConfigValueIterator(comptime T: type) type { return struct { - inner: std.mem.SplitIterator(u8), + inner: std.mem.SplitIterator(u8, .scalar), fn next(self: *@This()) !?T { const next_raw = self.inner.next() orelse return null; -- cgit v1.2.3 From 2129f28953b72da2f1bb58ff063a044d737c59c4 Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Thu, 4 May 2023 18:15:50 -0700 Subject: Update all std.mem.split calls to their appropriate function Everywhere that can now use `splitScalar` should get a nice little performance boost. --- build.zig | 6 +++--- doc/docgen.zig | 2 +- lib/std/Build/Step/Compile.zig | 2 +- lib/std/Build/Step/ConfigHeader.zig | 4 ++-- lib/std/SemanticVersion.zig | 10 +++++----- lib/std/builtin.zig | 2 +- lib/std/crypto/Certificate.zig | 4 ++-- lib/std/crypto/phc_encoding.zig | 9 ++++++--- lib/std/crypto/scrypt.zig | 2 +- lib/std/http/Client.zig | 2 +- lib/std/http/Server.zig | 2 +- lib/std/net.zig | 6 +++--- lib/std/process.zig | 2 +- lib/std/zig/CrossTarget.zig | 12 ++++++------ lib/std/zig/ErrorBundle.zig | 2 +- lib/std/zig/render.zig | 2 +- lib/std/zig/system/NativeTargetInfo.zig | 2 +- src/Autodoc.zig | 2 +- src/Compilation.zig | 6 +++--- src/libc_installation.zig | 2 +- src/link/MachO/Dylib.zig | 2 +- src/main.zig | 16 ++++++++-------- test/src/Cases.zig | 6 +++--- test/src/check-stack-trace.zig | 2 +- tools/gen_outline_atomics.zig | 2 +- tools/update_crc_catalog.zig | 2 +- tools/update_spirv_features.zig | 2 +- 27 files changed, 58 insertions(+), 55 deletions(-) (limited to 'src/main.zig') diff --git a/build.zig b/build.zig index 21b323df56..e7e3f17a82 100644 --- a/build.zig +++ b/build.zig @@ -239,7 +239,7 @@ pub fn build(b: *std.Build) !void { }, 2 => { // Untagged development build (e.g. 0.10.0-dev.2025+ecf0050a9). - var it = mem.split(u8, git_describe, "-"); + var it = mem.splitScalar(u8, git_describe, '-'); const tagged_ancestor = it.first(); const commit_height = it.next().?; const commit_id = it.next().?; @@ -859,14 +859,14 @@ fn parseConfigH(b: *std.Build, config_h_text: []const u8) ?CMakeConfig { while (lines_it.next()) |line| { inline for (mappings) |mapping| { if (mem.startsWith(u8, line, mapping.prefix)) { - var it = mem.split(u8, line, "\""); + var it = mem.splitScalar(u8, line, '"'); _ = it.first(); // skip the stuff before the quote const quoted = it.next().?; // the stuff inside the quote @field(ctx, mapping.field) = toNativePathSep(b, quoted); } } if (mem.startsWith(u8, line, "#define ZIG_LLVM_LINK_MODE ")) { - var it = mem.split(u8, line, "\""); + var it = mem.splitScalar(u8, line, '"'); _ = it.next().?; // skip the stuff before the quote const quoted = it.next().?; // the stuff inside the quote ctx.llvm_linkage = if (mem.eql(u8, quoted, "shared")) .dynamic else .static; diff --git a/doc/docgen.zig b/doc/docgen.zig index 07636fd152..82f2d9b199 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -1223,7 +1223,7 @@ fn printShell(out: anytype, shell_content: []const u8, escape: bool) !void { const trimmed_shell_content = mem.trim(u8, shell_content, " \n"); try out.writeAll("
Shell
");
     var cmd_cont: bool = false;
-    var iter = std.mem.split(u8, trimmed_shell_content, "\n");
+    var iter = std.mem.splitScalar(u8, trimmed_shell_content, '\n');
     while (iter.next()) |orig_line| {
         const line = mem.trimRight(u8, orig_line, " ");
         if (!cmd_cont and line.len > 1 and mem.eql(u8, line[0..2], "$ ") and line[line.len - 1] != '\\') {
diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig
index 6a05adc1a6..3355d7ccc5 100644
--- a/lib/std/Build/Step/Compile.zig
+++ b/lib/std/Build/Step/Compile.zig
@@ -2140,7 +2140,7 @@ fn checkCompileErrors(self: *Compile) !void {
     // Render the expected lines into a string that we can compare verbatim.
     var expected_generated = std.ArrayList(u8).init(arena);
 
-    var actual_line_it = mem.split(u8, actual_stderr, "\n");
+    var actual_line_it = mem.splitScalar(u8, actual_stderr, '\n');
     for (self.expect_errors) |expect_line| {
         const actual_line = actual_line_it.next() orelse {
             try expected_generated.appendSlice(expect_line);
diff --git a/lib/std/Build/Step/ConfigHeader.zig b/lib/std/Build/Step/ConfigHeader.zig
index cd97367218..4b76e24b26 100644
--- a/lib/std/Build/Step/ConfigHeader.zig
+++ b/lib/std/Build/Step/ConfigHeader.zig
@@ -250,7 +250,7 @@ fn render_autoconf(
 
     var any_errors = false;
     var line_index: u32 = 0;
-    var line_it = std.mem.split(u8, contents, "\n");
+    var line_it = std.mem.splitScalar(u8, contents, '\n');
     while (line_it.next()) |line| : (line_index += 1) {
         if (!std.mem.startsWith(u8, line, "#")) {
             try output.appendSlice(line);
@@ -297,7 +297,7 @@ fn render_cmake(
 
     var any_errors = false;
     var line_index: u32 = 0;
-    var line_it = std.mem.split(u8, contents, "\n");
+    var line_it = std.mem.splitScalar(u8, contents, '\n');
     while (line_it.next()) |line| : (line_index += 1) {
         if (!std.mem.startsWith(u8, line, "#")) {
             try output.appendSlice(line);
diff --git a/lib/std/SemanticVersion.zig b/lib/std/SemanticVersion.zig
index 26f6f581c8..4d505b4e30 100644
--- a/lib/std/SemanticVersion.zig
+++ b/lib/std/SemanticVersion.zig
@@ -42,8 +42,8 @@ pub fn order(lhs: Version, rhs: Version) std.math.Order {
     if (lhs.pre == null and rhs.pre != null) return .gt;
 
     // Iterate over pre-release identifiers until a difference is found.
-    var lhs_pre_it = std.mem.split(u8, lhs.pre.?, ".");
-    var rhs_pre_it = std.mem.split(u8, rhs.pre.?, ".");
+    var lhs_pre_it = std.mem.splitScalar(u8, lhs.pre.?, '.');
+    var rhs_pre_it = std.mem.splitScalar(u8, rhs.pre.?, '.');
     while (true) {
         const next_lid = lhs_pre_it.next();
         const next_rid = rhs_pre_it.next();
@@ -86,7 +86,7 @@ pub fn parse(text: []const u8) !Version {
     // Parse the required major, minor, and patch numbers.
     const extra_index = std.mem.indexOfAny(u8, text, "-+");
     const required = text[0..(extra_index orelse text.len)];
-    var it = std.mem.split(u8, required, ".");
+    var it = std.mem.splitScalar(u8, required, '.');
     var ver = Version{
         .major = try parseNum(it.first()),
         .minor = try parseNum(it.next() orelse return error.InvalidVersion),
@@ -108,7 +108,7 @@ pub fn parse(text: []const u8) !Version {
     // Check validity of optional pre-release identifiers.
     // See: https://semver.org/#spec-item-9
     if (ver.pre) |pre| {
-        it = std.mem.split(u8, pre, ".");
+        it = std.mem.splitScalar(u8, pre, '.');
         while (it.next()) |id| {
             // Identifiers MUST NOT be empty.
             if (id.len == 0) return error.InvalidVersion;
@@ -127,7 +127,7 @@ pub fn parse(text: []const u8) !Version {
     // Check validity of optional build metadata identifiers.
     // See: https://semver.org/#spec-item-10
     if (ver.build) |build| {
-        it = std.mem.split(u8, build, ".");
+        it = std.mem.splitScalar(u8, build, '.');
         while (it.next()) |id| {
             // Identifiers MUST NOT be empty.
             if (id.len == 0) return error.InvalidVersion;
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
index 684432bd40..7fe295123e 100644
--- a/lib/std/builtin.zig
+++ b/lib/std/builtin.zig
@@ -531,7 +531,7 @@ pub const Version = struct {
         // found no digits or '.' before unexpected character
         if (end == 0) return error.InvalidVersion;
 
-        var it = std.mem.split(u8, text[0..end], ".");
+        var it = std.mem.splitScalar(u8, text[0..end], '.');
         // substring is not empty, first call will succeed
         const major = it.first();
         if (major.len == 0) return error.InvalidVersion;
diff --git a/lib/std/crypto/Certificate.zig b/lib/std/crypto/Certificate.zig
index 113d169cbc..3da4269ba2 100644
--- a/lib/std/crypto/Certificate.zig
+++ b/lib/std/crypto/Certificate.zig
@@ -337,8 +337,8 @@ pub const Parsed = struct {
             return true; // exact match
         }
 
-        var it_host = std.mem.split(u8, host_name, ".");
-        var it_dns = std.mem.split(u8, dns_name, ".");
+        var it_host = std.mem.splitScalar(u8, host_name, '.');
+        var it_dns = std.mem.splitScalar(u8, dns_name, '.');
 
         const len_match = while (true) {
             const host = it_host.next();
diff --git a/lib/std/crypto/phc_encoding.zig b/lib/std/crypto/phc_encoding.zig
index cc0f10e395..1eeee39a5a 100644
--- a/lib/std/crypto/phc_encoding.zig
+++ b/lib/std/crypto/phc_encoding.zig
@@ -7,9 +7,12 @@ const mem = std.mem;
 const meta = std.meta;
 
 const fields_delimiter = "$";
+const fields_delimiter_scalar = '$';
 const version_param_name = "v";
 const params_delimiter = ",";
+const params_delimiter_scalar = ',';
 const kv_delimiter = "=";
+const kv_delimiter_scalar = '=';
 
 pub const Error = std.crypto.errors.EncodingError || error{NoSpaceLeft};
 
@@ -73,7 +76,7 @@ pub fn BinValue(comptime max_len: usize) type {
 /// Other fields will also be deserialized from the function parameters section.
 pub fn deserialize(comptime HashResult: type, str: []const u8) Error!HashResult {
     var out = mem.zeroes(HashResult);
-    var it = mem.split(u8, str, fields_delimiter);
+    var it = mem.splitScalar(u8, str, fields_delimiter_scalar);
     var set_fields: usize = 0;
 
     while (true) {
@@ -104,7 +107,7 @@ pub fn deserialize(comptime HashResult: type, str: []const u8) Error!HashResult
 
         // Read optional parameters
         var has_params = false;
-        var it_params = mem.split(u8, field, params_delimiter);
+        var it_params = mem.splitScalar(u8, field, params_delimiter_scalar);
         while (it_params.next()) |params| {
             const param = kvSplit(params) catch break;
             var found = false;
@@ -252,7 +255,7 @@ fn serializeTo(params: anytype, out: anytype) !void {
 
 // Split a `key=value` string into `key` and `value`
 fn kvSplit(str: []const u8) !struct { key: []const u8, value: []const u8 } {
-    var it = mem.split(u8, str, kv_delimiter);
+    var it = mem.splitScalar(u8, str, kv_delimiter_scalar);
     const key = it.first();
     const value = it.next() orelse return Error.InvalidEncoding;
     const ret = .{ .key = key, .value = value };
diff --git a/lib/std/crypto/scrypt.zig b/lib/std/crypto/scrypt.zig
index 077de3b510..b8e8ef55e2 100644
--- a/lib/std/crypto/scrypt.zig
+++ b/lib/std/crypto/scrypt.zig
@@ -287,7 +287,7 @@ const crypt_format = struct {
         out.r = try Codec.intDecode(u30, str[4..9]);
         out.p = try Codec.intDecode(u30, str[9..14]);
 
-        var it = mem.split(u8, str[14..], "$");
+        var it = mem.splitScalar(u8, str[14..], '$');
 
         const salt = it.first();
         if (@hasField(T, "salt")) out.salt = salt;
diff --git a/lib/std/http/Client.zig b/lib/std/http/Client.zig
index 5626864ceb..9aaf13d333 100644
--- a/lib/std/http/Client.zig
+++ b/lib/std/http/Client.zig
@@ -426,7 +426,7 @@ pub const Response = struct {
             } else if (std.ascii.eqlIgnoreCase(header_name, "transfer-encoding")) {
                 // Transfer-Encoding: second, first
                 // Transfer-Encoding: deflate, chunked
-                var iter = mem.splitBackwards(u8, header_value, ",");
+                var iter = mem.splitBackwardsScalar(u8, header_value, ',');
 
                 if (iter.next()) |first| {
                     const trimmed = mem.trim(u8, first, " ");
diff --git a/lib/std/http/Server.zig b/lib/std/http/Server.zig
index 51ab6c086b..1af64805b3 100644
--- a/lib/std/http/Server.zig
+++ b/lib/std/http/Server.zig
@@ -277,7 +277,7 @@ pub const Request = struct {
             } else if (std.ascii.eqlIgnoreCase(header_name, "transfer-encoding")) {
                 // Transfer-Encoding: second, first
                 // Transfer-Encoding: deflate, chunked
-                var iter = mem.splitBackwards(u8, header_value, ",");
+                var iter = mem.splitBackwardsScalar(u8, header_value, ',');
 
                 if (iter.next()) |first| {
                     const trimmed = mem.trim(u8, first, " ");
diff --git a/lib/std/net.zig b/lib/std/net.zig
index 4360cc29f4..4e72ed3256 100644
--- a/lib/std/net.zig
+++ b/lib/std/net.zig
@@ -1263,7 +1263,7 @@ fn linuxLookupNameFromHosts(
         },
         else => |e| return e,
     }) |line| {
-        var split_it = mem.split(u8, line, "#");
+        var split_it = mem.splitScalar(u8, line, '#');
         const no_comment_line = split_it.first();
 
         var line_it = mem.tokenizeAny(u8, no_comment_line, " \t");
@@ -1465,7 +1465,7 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void {
         else => |e| return e,
     }) |line| {
         const no_comment_line = no_comment_line: {
-            var split = mem.split(u8, line, "#");
+            var split = mem.splitScalar(u8, line, '#');
             break :no_comment_line split.first();
         };
         var line_it = mem.tokenizeAny(u8, no_comment_line, " \t");
@@ -1473,7 +1473,7 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void {
         const token = line_it.next() orelse continue;
         if (mem.eql(u8, token, "options")) {
             while (line_it.next()) |sub_tok| {
-                var colon_it = mem.split(u8, sub_tok, ":");
+                var colon_it = mem.splitScalar(u8, sub_tok, ':');
                 const name = colon_it.first();
                 const value_txt = colon_it.next() orelse continue;
                 const value = std.fmt.parseInt(u8, value_txt, 10) catch |err| switch (err) {
diff --git a/lib/std/process.zig b/lib/std/process.zig
index c33fd92db6..80be705187 100644
--- a/lib/std/process.zig
+++ b/lib/std/process.zig
@@ -310,7 +310,7 @@ pub fn getEnvMap(allocator: Allocator) !EnvMap {
 
         for (environ) |env| {
             const pair = mem.sliceTo(env, 0);
-            var parts = mem.split(u8, pair, "=");
+            var parts = mem.splitScalar(u8, pair, '=');
             const key = parts.first();
             const value = parts.rest();
             try result.put(key, value);
diff --git a/lib/std/zig/CrossTarget.zig b/lib/std/zig/CrossTarget.zig
index 93b6d97d75..d072a4dbad 100644
--- a/lib/std/zig/CrossTarget.zig
+++ b/lib/std/zig/CrossTarget.zig
@@ -239,7 +239,7 @@ pub fn parse(args: ParseOptions) !CrossTarget {
         .dynamic_linker = DynamicLinker.init(args.dynamic_linker),
     };
 
-    var it = mem.split(u8, args.arch_os_abi, "-");
+    var it = mem.splitScalar(u8, args.arch_os_abi, '-');
     const arch_name = it.first();
     const arch_is_native = mem.eql(u8, arch_name, "native");
     if (!arch_is_native) {
@@ -257,7 +257,7 @@ pub fn parse(args: ParseOptions) !CrossTarget {
 
     const opt_abi_text = it.next();
     if (opt_abi_text) |abi_text| {
-        var abi_it = mem.split(u8, abi_text, ".");
+        var abi_it = mem.splitScalar(u8, abi_text, '.');
         const abi = std.meta.stringToEnum(Target.Abi, abi_it.first()) orelse
             return error.UnknownApplicationBinaryInterface;
         result.abi = abi;
@@ -343,7 +343,7 @@ pub fn parse(args: ParseOptions) !CrossTarget {
 /// This is intended to be used if the API user of CrossTarget needs to learn the
 /// target CPU architecture in order to fully populate `ParseOptions`.
 pub fn parseCpuArch(args: ParseOptions) ?Target.Cpu.Arch {
-    var it = mem.split(u8, args.arch_os_abi, "-");
+    var it = mem.splitScalar(u8, args.arch_os_abi, '-');
     const arch_name = it.first();
     const arch_is_native = mem.eql(u8, arch_name, "native");
     if (arch_is_native) {
@@ -645,7 +645,7 @@ pub fn updateCpuFeatures(self: CrossTarget, set: *Target.Cpu.Feature.Set) void {
 }
 
 fn parseOs(result: *CrossTarget, diags: *ParseOptions.Diagnostics, text: []const u8) !void {
-    var it = mem.split(u8, text, ".");
+    var it = mem.splitScalar(u8, text, '.');
     const os_name = it.first();
     diags.os_name = os_name;
     const os_is_native = mem.eql(u8, os_name, "native");
@@ -706,7 +706,7 @@ fn parseOs(result: *CrossTarget, diags: *ParseOptions.Diagnostics, text: []const
         .linux,
         .dragonfly,
         => {
-            var range_it = mem.split(u8, version_text, "...");
+            var range_it = mem.splitFull(u8, version_text, "...");
 
             const min_text = range_it.next().?;
             const min_ver = SemVer.parse(min_text) catch |err| switch (err) {
@@ -726,7 +726,7 @@ fn parseOs(result: *CrossTarget, diags: *ParseOptions.Diagnostics, text: []const
         },
 
         .windows => {
-            var range_it = mem.split(u8, version_text, "...");
+            var range_it = mem.splitFull(u8, version_text, "...");
 
             const min_text = range_it.first();
             const min_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, min_text) orelse
diff --git a/lib/std/zig/ErrorBundle.zig b/lib/std/zig/ErrorBundle.zig
index ffe748203e..fe0ae3c0f6 100644
--- a/lib/std/zig/ErrorBundle.zig
+++ b/lib/std/zig/ErrorBundle.zig
@@ -294,7 +294,7 @@ fn renderErrorMessageToWriter(
 ///
 /// This is used to split the message in `@compileError("hello\nworld")` for example.
 fn writeMsg(eb: ErrorBundle, err_msg: ErrorMessage, stderr: anytype, indent: usize) !void {
-    var lines = std.mem.split(u8, eb.nullTerminatedString(err_msg.msg), "\n");
+    var lines = std.mem.splitScalar(u8, eb.nullTerminatedString(err_msg.msg), '\n');
     while (lines.next()) |line| {
         try stderr.writeAll(line);
         if (lines.index == null) break;
diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig
index e1ccc8e0e8..83fa68567f 100644
--- a/lib/std/zig/render.zig
+++ b/lib/std/zig/render.zig
@@ -1995,7 +1995,7 @@ fn renderArrayInit(
             if (!expr_newlines[i]) {
                 try ais.writer().writeAll(expr_text);
             } else {
-                var by_line = std.mem.split(u8, expr_text, "\n");
+                var by_line = std.mem.splitScalar(u8, expr_text, '\n');
                 var last_line_was_empty = false;
                 try ais.writer().writeAll(by_line.first());
                 while (by_line.next()) |line| {
diff --git a/lib/std/zig/system/NativeTargetInfo.zig b/lib/std/zig/system/NativeTargetInfo.zig
index 808a1bda8d..5cbc274ffd 100644
--- a/lib/std/zig/system/NativeTargetInfo.zig
+++ b/lib/std/zig/system/NativeTargetInfo.zig
@@ -556,7 +556,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.builtin.Version {
     const dynstr_size = @intCast(usize, dynstr.size);
     const dynstr_bytes = buf[0..dynstr_size];
     _ = try preadMin(file, dynstr_bytes, dynstr.offset, dynstr_bytes.len);
-    var it = mem.split(u8, dynstr_bytes, &.{0});
+    var it = mem.splitScalar(u8, dynstr_bytes, 0);
     var max_ver: std.builtin.Version = .{ .major = 2, .minor = 2, .patch = 5 };
     while (it.next()) |s| {
         if (mem.startsWith(u8, s, "GLIBC_2.")) {
diff --git a/src/Autodoc.zig b/src/Autodoc.zig
index 5e1c4c7822..ce6bc2e7d9 100644
--- a/src/Autodoc.zig
+++ b/src/Autodoc.zig
@@ -4951,7 +4951,7 @@ fn findGuidePaths(self: *Autodoc, file: *File, str: []const u8) ![]const u8 {
 
     // TODO: this algo is kinda inefficient
 
-    var it = std.mem.split(u8, str, "\n");
+    var it = std.mem.splitScalar(u8, str, '\n');
     while (it.next()) |line| {
         const trimmed_line = std.mem.trim(u8, line, " ");
         if (std.mem.startsWith(u8, trimmed_line, guide_prefix)) {
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 1b6d805bb3..7599d8a80f 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -4636,7 +4636,7 @@ pub fn hasSharedLibraryExt(filename: []const u8) bool {
         return true;
     }
     // Look for .so.X, .so.X.Y, .so.X.Y.Z
-    var it = mem.split(u8, filename, ".");
+    var it = mem.splitScalar(u8, filename, '.');
     _ = it.first();
     var so_txt = it.next() orelse return false;
     while (!mem.eql(u8, so_txt, "so")) {
@@ -5016,14 +5016,14 @@ fn parseLldStderr(comp: *Compilation, comptime prefix: []const u8, stderr: []con
     defer context_lines.deinit();
 
     var current_err: ?*LldError = null;
-    var lines = mem.split(u8, stderr, std.cstr.line_sep);
+    var lines = mem.splitFull(u8, stderr, std.cstr.line_sep);
     while (lines.next()) |line| {
         if (mem.startsWith(u8, line, prefix ++ ":")) {
             if (current_err) |err| {
                 err.context_lines = try context_lines.toOwnedSlice();
             }
 
-            var split = std.mem.split(u8, line, "error: ");
+            var split = std.mem.splitFull(u8, line, "error: ");
             _ = split.first();
 
             const duped_msg = try std.fmt.allocPrint(comp.gpa, "{s}: {s}", .{ prefix, split.rest() });
diff --git a/src/libc_installation.zig b/src/libc_installation.zig
index a62da6b9c7..355c3bad8d 100644
--- a/src/libc_installation.zig
+++ b/src/libc_installation.zig
@@ -63,7 +63,7 @@ pub const LibCInstallation = struct {
         var it = std.mem.tokenizeScalar(u8, contents, '\n');
         while (it.next()) |line| {
             if (line.len == 0 or line[0] == '#') continue;
-            var line_it = std.mem.split(u8, line, "=");
+            var line_it = std.mem.splitScalar(u8, line, '=');
             const name = line_it.first();
             const value = line_it.rest();
             inline for (fields, 0..) |field, i| {
diff --git a/src/link/MachO/Dylib.zig b/src/link/MachO/Dylib.zig
index 863f1e805a..971706dae6 100644
--- a/src/link/MachO/Dylib.zig
+++ b/src/link/MachO/Dylib.zig
@@ -91,7 +91,7 @@ pub const Id = struct {
         var out: u32 = 0;
         var values: [3][]const u8 = undefined;
 
-        var split = mem.split(u8, string, ".");
+        var split = mem.splitScalar(u8, string, '.');
         var count: u4 = 0;
         while (split.next()) |value| {
             if (count > 2) {
diff --git a/src/main.zig b/src/main.zig
index c61e3f3719..82269ebc93 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -976,7 +976,7 @@ fn buildOutputType(
                         }
                     } else if (mem.eql(u8, arg, "--mod")) {
                         const info = args_iter.nextOrFatal();
-                        var info_it = mem.split(u8, info, ":");
+                        var info_it = mem.splitScalar(u8, info, ':');
                         const mod_name = info_it.next() orelse fatal("expected non-empty argument after {s}", .{arg});
                         const deps_str = info_it.next() orelse fatal("expected 'name:deps:path' after {s}", .{arg});
                         const root_src_orig = info_it.rest();
@@ -1176,7 +1176,7 @@ fn buildOutputType(
                         } else {
                             if (build_options.omit_pkg_fetching_code) unreachable;
                             // example: --listen 127.0.0.1:9000
-                            var it = std.mem.split(u8, next_arg, ":");
+                            var it = std.mem.splitScalar(u8, next_arg, ':');
                             const host = it.next().?;
                             const port_text = it.next() orelse "14735";
                             const port = std.fmt.parseInt(u16, port_text, 10) catch |err|
@@ -1673,7 +1673,7 @@ fn buildOutputType(
                     },
                     .rdynamic => rdynamic = true,
                     .wl => {
-                        var split_it = mem.split(u8, it.only_arg, ",");
+                        var split_it = mem.splitScalar(u8, it.only_arg, ',');
                         while (split_it.next()) |linker_arg| {
                             // Handle nested-joined args like `-Wl,-rpath=foo`.
                             // Must be prefixed with 1 or 2 dashes.
@@ -2183,17 +2183,17 @@ fn buildOutputType(
                     const next_arg = linker_args_it.nextOrFatal();
                     try symbol_wrap_set.put(arena, next_arg, {});
                 } else if (mem.startsWith(u8, arg, "/subsystem:")) {
-                    var split_it = mem.splitBackwards(u8, arg, ":");
+                    var split_it = mem.splitBackwardsScalar(u8, arg, ':');
                     subsystem = try parseSubSystem(split_it.first());
                 } else if (mem.startsWith(u8, arg, "/implib:")) {
-                    var split_it = mem.splitBackwards(u8, arg, ":");
+                    var split_it = mem.splitBackwardsScalar(u8, arg, ':');
                     emit_implib = .{ .yes = split_it.first() };
                     emit_implib_arg_provided = true;
                 } else if (mem.startsWith(u8, arg, "/pdb:")) {
-                    var split_it = mem.splitBackwards(u8, arg, ":");
+                    var split_it = mem.splitBackwardsScalar(u8, arg, ':');
                     pdb_out_path = split_it.first();
                 } else if (mem.startsWith(u8, arg, "/version:")) {
-                    var split_it = mem.splitBackwards(u8, arg, ":");
+                    var split_it = mem.splitBackwardsScalar(u8, arg, ':');
                     const version_arg = split_it.first();
                     version = std.builtin.Version.parse(version_arg) catch |err| {
                         fatal("unable to parse /version '{s}': {s}", .{ arg, @errorName(err) });
@@ -3534,7 +3534,7 @@ const ModuleDepIterator = struct {
     split: mem.SplitIterator(u8, .scalar),
 
     fn init(deps_str: []const u8) ModuleDepIterator {
-        return .{ .split = mem.split(u8, deps_str, ",") };
+        return .{ .split = mem.splitScalar(u8, deps_str, ',') };
     }
 
     const Dependency = struct {
diff --git a/test/src/Cases.zig b/test/src/Cases.zig
index aa5369af93..7188e20859 100644
--- a/test/src/Cases.zig
+++ b/test/src/Cases.zig
@@ -877,7 +877,7 @@ const TestManifest = struct {
             if (trimmed.len == 0) break;
 
             // Parse key=value(s)
-            var kv_it = std.mem.split(u8, trimmed, "=");
+            var kv_it = std.mem.splitScalar(u8, trimmed, '=');
             const key = kv_it.first();
             try manifest.config_map.putNoClobber(key, kv_it.next() orelse return error.MissingValuesForConfig);
         }
@@ -895,7 +895,7 @@ const TestManifest = struct {
     ) ConfigValueIterator(T) {
         const bytes = self.config_map.get(key) orelse TestManifestConfigDefaults.get(self.type, key);
         return ConfigValueIterator(T){
-            .inner = std.mem.split(u8, bytes, ","),
+            .inner = std.mem.splitScalar(u8, bytes, ','),
         };
     }
 
@@ -1399,7 +1399,7 @@ fn runOneCase(
                 // Render the expected lines into a string that we can compare verbatim.
                 var expected_generated = std.ArrayList(u8).init(arena);
 
-                var actual_line_it = std.mem.split(u8, actual_stderr.items, "\n");
+                var actual_line_it = std.mem.splitScalar(u8, actual_stderr.items, '\n');
                 for (expected_errors) |expect_line| {
                     const actual_line = actual_line_it.next() orelse {
                         try expected_generated.appendSlice(expect_line);
diff --git a/test/src/check-stack-trace.zig b/test/src/check-stack-trace.zig
index bb1db55076..9856b5738e 100644
--- a/test/src/check-stack-trace.zig
+++ b/test/src/check-stack-trace.zig
@@ -27,7 +27,7 @@ pub fn main() !void {
         var buf = std.ArrayList(u8).init(arena);
         defer buf.deinit();
         if (stderr.len != 0 and stderr[stderr.len - 1] == '\n') stderr = stderr[0 .. stderr.len - 1];
-        var it = mem.split(u8, stderr, "\n");
+        var it = mem.splitScalar(u8, stderr, '\n');
         process_lines: while (it.next()) |line| {
             if (line.len == 0) continue;
 
diff --git a/tools/gen_outline_atomics.zig b/tools/gen_outline_atomics.zig
index c04591d032..0cfdacffd1 100644
--- a/tools/gen_outline_atomics.zig
+++ b/tools/gen_outline_atomics.zig
@@ -88,7 +88,7 @@ fn writeFunction(
         \\    asm volatile (
         \\
     );
-    var iter = std.mem.split(u8, body, "\n");
+    var iter = std.mem.splitScalar(u8, body, '\n');
     while (iter.next()) |line| {
         try w.writeAll("        \\\\");
         try w.writeAll(line);
diff --git a/tools/update_crc_catalog.zig b/tools/update_crc_catalog.zig
index 034b7afc9d..2fdb9b030f 100644
--- a/tools/update_crc_catalog.zig
+++ b/tools/update_crc_catalog.zig
@@ -78,7 +78,7 @@ pub fn main() anyerror!void {
         var residue: []const u8 = undefined;
         var name: []const u8 = undefined;
 
-        var it = mem.split(u8, line, "  ");
+        var it = mem.splitFull(u8, line, "  ");
         while (it.next()) |property| {
             const i = mem.indexOf(u8, property, "=").?;
             const key = property[0..i];
diff --git a/tools/update_spirv_features.zig b/tools/update_spirv_features.zig
index 8d398f58de..766a9b7a24 100644
--- a/tools/update_spirv_features.zig
+++ b/tools/update_spirv_features.zig
@@ -19,7 +19,7 @@ const Version = struct {
     minor: u32,
 
     fn parse(str: []const u8) !Version {
-        var it = std.mem.split(u8, str, ".");
+        var it = std.mem.splitScalar(u8, str, '.');
 
         const major = it.first();
         const minor = it.next() orelse return error.InvalidVersion;
-- 
cgit v1.2.3


From 2e692312f104e1e5533c9f389d73488ea4a1ef68 Mon Sep 17 00:00:00 2001
From: Motiejus Jakštys 
Date: Mon, 23 Jan 2023 21:59:03 +0200
Subject: zig cc: support reading from non-files

    echo 'some C program' | $CC -x c -

Is a common pattern to test for compiler or linker features. This patch
adds support for reading from non-regular files.

This will make at least one more Go test to pass.
---
 lib/std/Build/Cache.zig | 10 ++++++
 src/Compilation.zig     | 20 +++++------
 src/main.zig            | 37 +++++++++++++++++++-
 test/tests.zig          | 93 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 148 insertions(+), 12 deletions(-)

(limited to 'src/main.zig')

diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig
index 17429c0370..4fc6784684 100644
--- a/lib/std/Build/Cache.zig
+++ b/lib/std/Build/Cache.zig
@@ -31,6 +31,16 @@ pub const Directory = struct {
         }
     }
 
+    pub fn tmpFilePath(self: Directory, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 {
+        const s = std.fs.path.sep_str;
+        const rand_int = std.crypto.random.int(u64);
+        if (self.path) |p| {
+            return std.fmt.allocPrint(ally, "{s}" ++ s ++ "tmp" ++ s ++ "{x}-{s}", .{ p, rand_int, suffix });
+        } else {
+            return std.fmt.allocPrint(ally, "tmp" ++ s ++ "{x}-{s}", .{ rand_int, suffix });
+        }
+    }
+
     /// Whether or not the handle should be closed, or the path should be freed
     /// is determined by usage, however this function is provided for convenience
     /// if it happens to be what the caller needs.
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 1b6d805bb3..3ae43773e3 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -3981,7 +3981,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
 
         // We can't know the digest until we do the C compiler invocation,
         // so we need a temporary filename.
-        const out_obj_path = try comp.tmpFilePath(arena, o_basename);
+        const out_obj_path = try comp.local_cache_directory.tmpFilePath(arena, o_basename);
         var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{});
         defer zig_cache_tmp_dir.close();
 
@@ -4129,16 +4129,6 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
     };
 }
 
-pub fn tmpFilePath(comp: *Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 {
-    const s = std.fs.path.sep_str;
-    const rand_int = std.crypto.random.int(u64);
-    if (comp.local_cache_directory.path) |p| {
-        return std.fmt.allocPrint(ally, "{s}" ++ s ++ "tmp" ++ s ++ "{x}-{s}", .{ p, rand_int, suffix });
-    } else {
-        return std.fmt.allocPrint(ally, "tmp" ++ s ++ "{x}-{s}", .{ rand_int, suffix });
-    }
-}
-
 pub fn addTranslateCCArgs(
     comp: *Compilation,
     arena: Allocator,
@@ -4597,6 +4587,14 @@ pub const FileExt = enum {
             => false,
         };
     }
+
+    // maximum length of @tagName(ext: FileExt)
+    pub const max_len = blk: {
+        var max: u16 = 0;
+        inline for (std.meta.tags(FileExt)) |ext|
+            max = std.math.max(@tagName(ext).len, max);
+        break :blk max;
+    };
 };
 
 pub fn hasObjectExt(filename: []const u8) bool {
diff --git a/src/main.zig b/src/main.zig
index a680a5d89e..a1f95aaf21 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -3020,6 +3020,41 @@ fn buildOutputType(
         break :l global_cache_directory;
     };
 
+    var temp_stdin_file: ?[]const u8 = null;
+    defer {
+        if (temp_stdin_file) |file| {
+            // some garbage may stay in the file system if removal fails.
+            // Alternatively, we could tell the user that the removal failed,
+            // but it's not as much of a deal: it's a temporary cache directory
+            // at all.
+            local_cache_directory.handle.deleteFile(file) catch {};
+        }
+    }
+
+    for (c_source_files.items) |*src| {
+        if (!mem.eql(u8, src.src_path, "-")) continue;
+
+        const ext = src.ext orelse
+            fatal("-E or -x is required when reading from a non-regular file", .{});
+
+        // "-" is stdin. Dump it to a real file.
+        const new_file = blk: {
+            var buf: ["stdin.".len + Compilation.FileExt.max_len]u8 = undefined;
+            const fname = try std.fmt.bufPrint(&buf, "stdin.{s}", .{@tagName(ext)});
+            const new_name = try local_cache_directory.tmpFilePath(arena, fname);
+
+            try local_cache_directory.handle.makePath("tmp");
+            var outfile = try local_cache_directory.handle.createFile(new_name, .{});
+            defer outfile.close();
+            errdefer local_cache_directory.handle.deleteFile(new_name) catch {};
+
+            try outfile.writeFileAll(io.getStdIn(), .{});
+            break :blk new_name;
+        };
+        temp_stdin_file = new_file;
+        src.src_path = new_file;
+    }
+
     if (build_options.have_llvm and emit_asm != .no) {
         // LLVM has no way to set this non-globally.
         const argv = [_][*:0]const u8{ "zig (LLVM option parsing)", "--x86-asm-syntax=intel" };
@@ -3873,7 +3908,7 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Translate
 
             const c_src_basename = fs.path.basename(c_source_file.src_path);
             const dep_basename = try std.fmt.allocPrint(arena, "{s}.d", .{c_src_basename});
-            const out_dep_path = try comp.tmpFilePath(arena, dep_basename);
+            const out_dep_path = try comp.local_cache_directory.tmpFilePath(arena, dep_basename);
             break :blk out_dep_path;
         };
 
diff --git a/test/tests.zig b/test/tests.zig
index 641914aabe..26d81ead12 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -777,6 +777,52 @@ pub fn addCliTests(b: *std.Build) *Step {
         step.dependOn(&cleanup.step);
     }
 
+    // Test `zig cc -x c -`
+    // Test author was not able to figure out how to start a child process and
+    // give an fd to it's stdin. fork/exec works, but we are limiting ourselves
+    // to POSIX.
+    //
+    // TODO: the "zig cc <..." step should be a RunStep.create(...)
+    // However, how do I create a command (RunStep) that invokes a command
+    // with a specific file descriptor in the stdin?
+    //if (builtin.os.tag != .windows) {
+    //    const tmp_path = b.makeTempPath();
+    //    var dir = std.fs.cwd().openDir(tmp_path, .{}) catch @panic("unhandled");
+    //    dir.writeFile("truth.c", "int main() { return 42; }") catch @panic("unhandled");
+    //    var infile = dir.openFile("truth.c", .{}) catch @panic("unhandled");
+
+    //    const outfile = std.fs.path.joinZ(
+    //        b.allocator,
+    //        &[_][]const u8{ tmp_path, "truth" },
+    //    ) catch @panic("unhandled");
+
+    //    const pid_result = std.os.fork() catch @panic("unhandled");
+    //    if (pid_result == 0) { // child
+    //        std.os.dup2(infile.handle, std.os.STDIN_FILENO) catch @panic("unhandled");
+    //        const argv = &[_:null]?[*:0]const u8{
+    //            b.zig_exe, "cc",
+    //            "-o",      outfile,
+    //            "-x",      "c",
+    //            "-",
+    //        };
+    //        const envp = &[_:null]?[*:0]const u8{
+    //            std.fmt.allocPrintZ(b.allocator, "ZIG_GLOBAL_CACHE_DIR={s}", .{tmp_path}) catch @panic("unhandled"),
+    //        };
+    //        const err = std.os.execveZ(b.zig_exe, argv, envp);
+    //        std.debug.print("execve error: {any}\n", .{err});
+    //        std.os.exit(1);
+    //    }
+
+    //    const res = std.os.waitpid(pid_result, 0);
+    //    assert(0 == res.status);
+
+    //    // run the compiled executable and check if it's telling the truth.
+    //    _ = exec(b.allocator, tmp_path, 42, &[_][]const u8{outfile}) catch @panic("unhandled");
+
+    //    const cleanup = b.addRemoveDirTree(tmp_path);
+    //    step.dependOn(&cleanup.step);
+    //}
+
     {
         // Test `zig fmt`.
         // This test must use a temporary directory rather than a cache
@@ -1154,3 +1200,50 @@ pub fn addCases(
         check_case_exe,
     );
 }
+
+fn exec(
+    allocator: std.mem.Allocator,
+    cwd: []const u8,
+    expect_code: u8,
+    argv: []const []const u8,
+) !std.ChildProcess.ExecResult {
+    const max_output_size = 100 * 1024;
+    const result = std.ChildProcess.exec(.{
+        .allocator = allocator,
+        .argv = argv,
+        .cwd = cwd,
+        .max_output_bytes = max_output_size,
+    }) catch |err| {
+        std.debug.print("The following command failed:\n", .{});
+        printCmd(cwd, argv);
+        return err;
+    };
+    switch (result.term) {
+        .Exited => |code| {
+            if (code != expect_code) {
+                std.debug.print(
+                    "The following command exited with error code {}, expected {}:\n",
+                    .{ code, expect_code },
+                );
+                printCmd(cwd, argv);
+                std.debug.print("stderr:\n{s}\n", .{result.stderr});
+                return error.CommandFailed;
+            }
+        },
+        else => {
+            std.debug.print("The following command terminated unexpectedly:\n", .{});
+            printCmd(cwd, argv);
+            std.debug.print("stderr:\n{s}\n", .{result.stderr});
+            return error.CommandFailed;
+        },
+    }
+    return result;
+}
+
+fn printCmd(cwd: []const u8, argv: []const []const u8) void {
+    std.debug.print("cd {s} && ", .{cwd});
+    for (argv) |arg| {
+        std.debug.print("{s} ", .{arg});
+    }
+    std.debug.print("\n", .{});
+}
-- 
cgit v1.2.3


From ae119a9a8d5b8dec21bd314e91afcec122eb8631 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Tue, 16 May 2023 16:29:20 -0700
Subject: CLI: fix stdin dumping behavior

 * no need to move `tmpFilePath` around
 * no need for calculating max length of `FileExt` tag name
 * provide a canonical file extension name for `FileExt` so that, e.g.
   the file will be named `stdin.S` instead of
   `stdin.assembly_with_cpp`.
 * move temp file cleanup to a function to reduce defer bloat in a large
   function.
 * fix bug caused by mixing relative and absolute paths in the cleanup
   logic.
 * remove commented out test and dead code
---
 lib/std/Build/Cache.zig | 10 ------
 src/Compilation.zig     | 39 ++++++++++++++++-----
 src/main.zig            | 54 ++++++++++++++++------------
 test/tests.zig          | 93 -------------------------------------------------
 4 files changed, 62 insertions(+), 134 deletions(-)

(limited to 'src/main.zig')

diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig
index 4fc6784684..17429c0370 100644
--- a/lib/std/Build/Cache.zig
+++ b/lib/std/Build/Cache.zig
@@ -31,16 +31,6 @@ pub const Directory = struct {
         }
     }
 
-    pub fn tmpFilePath(self: Directory, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 {
-        const s = std.fs.path.sep_str;
-        const rand_int = std.crypto.random.int(u64);
-        if (self.path) |p| {
-            return std.fmt.allocPrint(ally, "{s}" ++ s ++ "tmp" ++ s ++ "{x}-{s}", .{ p, rand_int, suffix });
-        } else {
-            return std.fmt.allocPrint(ally, "tmp" ++ s ++ "{x}-{s}", .{ rand_int, suffix });
-        }
-    }
-
     /// Whether or not the handle should be closed, or the path should be freed
     /// is determined by usage, however this function is provided for convenience
     /// if it happens to be what the caller needs.
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 3ae43773e3..0818eaafdd 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -3981,7 +3981,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
 
         // We can't know the digest until we do the C compiler invocation,
         // so we need a temporary filename.
-        const out_obj_path = try comp.local_cache_directory.tmpFilePath(arena, o_basename);
+        const out_obj_path = try comp.tmpFilePath(arena, o_basename);
         var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{});
         defer zig_cache_tmp_dir.close();
 
@@ -4129,6 +4129,16 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
     };
 }
 
+pub fn tmpFilePath(comp: *Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 {
+    const s = std.fs.path.sep_str;
+    const rand_int = std.crypto.random.int(u64);
+    if (comp.local_cache_directory.path) |p| {
+        return std.fmt.allocPrint(ally, "{s}" ++ s ++ "tmp" ++ s ++ "{x}-{s}", .{ p, rand_int, suffix });
+    } else {
+        return std.fmt.allocPrint(ally, "tmp" ++ s ++ "{x}-{s}", .{ rand_int, suffix });
+    }
+}
+
 pub fn addTranslateCCArgs(
     comp: *Compilation,
     arena: Allocator,
@@ -4588,13 +4598,26 @@ pub const FileExt = enum {
         };
     }
 
-    // maximum length of @tagName(ext: FileExt)
-    pub const max_len = blk: {
-        var max: u16 = 0;
-        inline for (std.meta.tags(FileExt)) |ext|
-            max = std.math.max(@tagName(ext).len, max);
-        break :blk max;
-    };
+    pub fn canonicalName(ext: FileExt, target: Target) [:0]const u8 {
+        return switch (ext) {
+            .c => ".c",
+            .cpp => ".cpp",
+            .cu => ".cu",
+            .h => ".h",
+            .m => ".m",
+            .mm => ".mm",
+            .ll => ".ll",
+            .bc => ".bc",
+            .assembly => ".s",
+            .assembly_with_cpp => ".S",
+            .shared_library => target.dynamicLibSuffix(),
+            .object => target.ofmt.fileExt(target.cpu.arch),
+            .static_library => target.staticLibSuffix(),
+            .zig => ".zig",
+            .def => ".def",
+            .unknown => "",
+        };
+    }
 };
 
 pub fn hasObjectExt(filename: []const u8) bool {
diff --git a/src/main.zig b/src/main.zig
index a1f95aaf21..46dbf1de1e 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -705,6 +705,17 @@ const ArgsIterator = struct {
     }
 };
 
+fn cleanupTempStdinFile(
+    temp_stdin_file: ?[]const u8,
+    local_cache_directory: Compilation.Directory,
+) void {
+    if (temp_stdin_file) |file| {
+        // Some garbage may stay in the file system if removal fails; this
+        // is harmless so no warning is needed.
+        local_cache_directory.handle.deleteFile(file) catch {};
+    }
+}
+
 fn buildOutputType(
     gpa: Allocator,
     arena: Allocator,
@@ -3021,15 +3032,11 @@ fn buildOutputType(
     };
 
     var temp_stdin_file: ?[]const u8 = null;
-    defer {
-        if (temp_stdin_file) |file| {
-            // some garbage may stay in the file system if removal fails.
-            // Alternatively, we could tell the user that the removal failed,
-            // but it's not as much of a deal: it's a temporary cache directory
-            // at all.
-            local_cache_directory.handle.deleteFile(file) catch {};
-        }
-    }
+    // Note that in one of the happy paths, execve() is used to switch to clang
+    // in which case this cleanup logic does not run and this temp file is
+    // leaked. Oh well. It's a minor punishment for using `-x c` which nobody
+    // should be doing.
+    defer cleanupTempStdinFile(temp_stdin_file, local_cache_directory);
 
     for (c_source_files.items) |*src| {
         if (!mem.eql(u8, src.src_path, "-")) continue;
@@ -3038,21 +3045,22 @@ fn buildOutputType(
             fatal("-E or -x is required when reading from a non-regular file", .{});
 
         // "-" is stdin. Dump it to a real file.
-        const new_file = blk: {
-            var buf: ["stdin.".len + Compilation.FileExt.max_len]u8 = undefined;
-            const fname = try std.fmt.bufPrint(&buf, "stdin.{s}", .{@tagName(ext)});
-            const new_name = try local_cache_directory.tmpFilePath(arena, fname);
-
+        const sub_path = blk: {
+            const sep = fs.path.sep_str;
+            const sub_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-stdin{s}", .{
+                std.crypto.random.int(u64), ext.canonicalName(target_info.target),
+            });
             try local_cache_directory.handle.makePath("tmp");
-            var outfile = try local_cache_directory.handle.createFile(new_name, .{});
-            defer outfile.close();
-            errdefer local_cache_directory.handle.deleteFile(new_name) catch {};
-
-            try outfile.writeFileAll(io.getStdIn(), .{});
-            break :blk new_name;
+            var f = try local_cache_directory.handle.createFile(sub_path, .{});
+            defer f.close();
+            errdefer local_cache_directory.handle.deleteFile(sub_path) catch {};
+            try f.writeFileAll(io.getStdIn(), .{});
+            break :blk sub_path;
         };
-        temp_stdin_file = new_file;
-        src.src_path = new_file;
+        // Relative to `local_cache_directory`.
+        temp_stdin_file = sub_path;
+        // Relative to current working directory.
+        src.src_path = try local_cache_directory.join(arena, &.{sub_path});
     }
 
     if (build_options.have_llvm and emit_asm != .no) {
@@ -3908,7 +3916,7 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Translate
 
             const c_src_basename = fs.path.basename(c_source_file.src_path);
             const dep_basename = try std.fmt.allocPrint(arena, "{s}.d", .{c_src_basename});
-            const out_dep_path = try comp.local_cache_directory.tmpFilePath(arena, dep_basename);
+            const out_dep_path = try comp.tmpFilePath(arena, dep_basename);
             break :blk out_dep_path;
         };
 
diff --git a/test/tests.zig b/test/tests.zig
index 26d81ead12..641914aabe 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -777,52 +777,6 @@ pub fn addCliTests(b: *std.Build) *Step {
         step.dependOn(&cleanup.step);
     }
 
-    // Test `zig cc -x c -`
-    // Test author was not able to figure out how to start a child process and
-    // give an fd to it's stdin. fork/exec works, but we are limiting ourselves
-    // to POSIX.
-    //
-    // TODO: the "zig cc <..." step should be a RunStep.create(...)
-    // However, how do I create a command (RunStep) that invokes a command
-    // with a specific file descriptor in the stdin?
-    //if (builtin.os.tag != .windows) {
-    //    const tmp_path = b.makeTempPath();
-    //    var dir = std.fs.cwd().openDir(tmp_path, .{}) catch @panic("unhandled");
-    //    dir.writeFile("truth.c", "int main() { return 42; }") catch @panic("unhandled");
-    //    var infile = dir.openFile("truth.c", .{}) catch @panic("unhandled");
-
-    //    const outfile = std.fs.path.joinZ(
-    //        b.allocator,
-    //        &[_][]const u8{ tmp_path, "truth" },
-    //    ) catch @panic("unhandled");
-
-    //    const pid_result = std.os.fork() catch @panic("unhandled");
-    //    if (pid_result == 0) { // child
-    //        std.os.dup2(infile.handle, std.os.STDIN_FILENO) catch @panic("unhandled");
-    //        const argv = &[_:null]?[*:0]const u8{
-    //            b.zig_exe, "cc",
-    //            "-o",      outfile,
-    //            "-x",      "c",
-    //            "-",
-    //        };
-    //        const envp = &[_:null]?[*:0]const u8{
-    //            std.fmt.allocPrintZ(b.allocator, "ZIG_GLOBAL_CACHE_DIR={s}", .{tmp_path}) catch @panic("unhandled"),
-    //        };
-    //        const err = std.os.execveZ(b.zig_exe, argv, envp);
-    //        std.debug.print("execve error: {any}\n", .{err});
-    //        std.os.exit(1);
-    //    }
-
-    //    const res = std.os.waitpid(pid_result, 0);
-    //    assert(0 == res.status);
-
-    //    // run the compiled executable and check if it's telling the truth.
-    //    _ = exec(b.allocator, tmp_path, 42, &[_][]const u8{outfile}) catch @panic("unhandled");
-
-    //    const cleanup = b.addRemoveDirTree(tmp_path);
-    //    step.dependOn(&cleanup.step);
-    //}
-
     {
         // Test `zig fmt`.
         // This test must use a temporary directory rather than a cache
@@ -1200,50 +1154,3 @@ pub fn addCases(
         check_case_exe,
     );
 }
-
-fn exec(
-    allocator: std.mem.Allocator,
-    cwd: []const u8,
-    expect_code: u8,
-    argv: []const []const u8,
-) !std.ChildProcess.ExecResult {
-    const max_output_size = 100 * 1024;
-    const result = std.ChildProcess.exec(.{
-        .allocator = allocator,
-        .argv = argv,
-        .cwd = cwd,
-        .max_output_bytes = max_output_size,
-    }) catch |err| {
-        std.debug.print("The following command failed:\n", .{});
-        printCmd(cwd, argv);
-        return err;
-    };
-    switch (result.term) {
-        .Exited => |code| {
-            if (code != expect_code) {
-                std.debug.print(
-                    "The following command exited with error code {}, expected {}:\n",
-                    .{ code, expect_code },
-                );
-                printCmd(cwd, argv);
-                std.debug.print("stderr:\n{s}\n", .{result.stderr});
-                return error.CommandFailed;
-            }
-        },
-        else => {
-            std.debug.print("The following command terminated unexpectedly:\n", .{});
-            printCmd(cwd, argv);
-            std.debug.print("stderr:\n{s}\n", .{result.stderr});
-            return error.CommandFailed;
-        },
-    }
-    return result;
-}
-
-fn printCmd(cwd: []const u8, argv: []const []const u8) void {
-    std.debug.print("cd {s} && ", .{cwd});
-    for (argv) |arg| {
-        std.debug.print("{s} ", .{arg});
-    }
-    std.debug.print("\n", .{});
-}
-- 
cgit v1.2.3


From 233a0d399135cdb581c5c080726c4cacc71695fe Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Tue, 16 May 2023 16:37:07 -0700
Subject: CLI: remove cleanup logic for stdin temp file

In one of the happy paths, execve() is used to switch to clang in which
case any cleanup logic that exists for this temporary file will not run
and this temp file will be leaked. Oh well. It's a minor punishment for
using `-x c` which nobody should be doing. Therefore, we make no effort
to clean up. Using `-` for stdin as a source file always leaks a temp
file.

Note that the standard `zig build-exe` CLI does not support stdin as an
input file. This is only for `zig cc` C compiler compatibility.
---
 src/main.zig | 49 ++++++++++++++++---------------------------------
 1 file changed, 16 insertions(+), 33 deletions(-)

(limited to 'src/main.zig')

diff --git a/src/main.zig b/src/main.zig
index 46dbf1de1e..2fd314def8 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -705,17 +705,6 @@ const ArgsIterator = struct {
     }
 };
 
-fn cleanupTempStdinFile(
-    temp_stdin_file: ?[]const u8,
-    local_cache_directory: Compilation.Directory,
-) void {
-    if (temp_stdin_file) |file| {
-        // Some garbage may stay in the file system if removal fails; this
-        // is harmless so no warning is needed.
-        local_cache_directory.handle.deleteFile(file) catch {};
-    }
-}
-
 fn buildOutputType(
     gpa: Allocator,
     arena: Allocator,
@@ -3031,13 +3020,6 @@ fn buildOutputType(
         break :l global_cache_directory;
     };
 
-    var temp_stdin_file: ?[]const u8 = null;
-    // Note that in one of the happy paths, execve() is used to switch to clang
-    // in which case this cleanup logic does not run and this temp file is
-    // leaked. Oh well. It's a minor punishment for using `-x c` which nobody
-    // should be doing.
-    defer cleanupTempStdinFile(temp_stdin_file, local_cache_directory);
-
     for (c_source_files.items) |*src| {
         if (!mem.eql(u8, src.src_path, "-")) continue;
 
@@ -3045,21 +3027,22 @@ fn buildOutputType(
             fatal("-E or -x is required when reading from a non-regular file", .{});
 
         // "-" is stdin. Dump it to a real file.
-        const sub_path = blk: {
-            const sep = fs.path.sep_str;
-            const sub_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-stdin{s}", .{
-                std.crypto.random.int(u64), ext.canonicalName(target_info.target),
-            });
-            try local_cache_directory.handle.makePath("tmp");
-            var f = try local_cache_directory.handle.createFile(sub_path, .{});
-            defer f.close();
-            errdefer local_cache_directory.handle.deleteFile(sub_path) catch {};
-            try f.writeFileAll(io.getStdIn(), .{});
-            break :blk sub_path;
-        };
-        // Relative to `local_cache_directory`.
-        temp_stdin_file = sub_path;
-        // Relative to current working directory.
+        const sep = fs.path.sep_str;
+        const sub_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-stdin{s}", .{
+            std.crypto.random.int(u64), ext.canonicalName(target_info.target),
+        });
+        try local_cache_directory.handle.makePath("tmp");
+        // Note that in one of the happy paths, execve() is used to switch
+        // to clang in which case any cleanup logic that exists for this
+        // temporary file will not run and this temp file will be leaked.
+        // Oh well. It's a minor punishment for using `-x c` which nobody
+        // should be doing. Therefore, we make no effort to clean up. Using
+        // `-` for stdin as a source file always leaks a temp file.
+        var f = try local_cache_directory.handle.createFile(sub_path, .{});
+        defer f.close();
+        try f.writeFileAll(io.getStdIn(), .{});
+
+        // Convert `sub_path` to be relative to current working directory.
         src.src_path = try local_cache_directory.join(arena, &.{sub_path});
     }
 
-- 
cgit v1.2.3


From df5085bde012773b974f58e8ee28ed90ff686468 Mon Sep 17 00:00:00 2001
From: Motiejus Jakštys 
Date: Tue, 25 Apr 2023 16:57:43 +0300
Subject: stage2: implement --build-id styles

---
 build.zig                      |   5 +-
 lib/std/Build/Step/Compile.zig | 119 ++++++++++++++++++++++++++++++++++++++++-
 src/Compilation.zig            |  12 +++--
 src/link.zig                   |   3 +-
 src/link/Elf.zig               |  11 ++--
 src/link/Wasm.zig              |  49 ++++++++++-------
 src/main.zig                   |  34 +++++++-----
 7 files changed, 191 insertions(+), 42 deletions(-)

(limited to 'src/main.zig')

diff --git a/build.zig b/build.zig
index a98845d6cc..62f1d86441 100644
--- a/build.zig
+++ b/build.zig
@@ -165,8 +165,11 @@ pub fn build(b: *std.Build) !void {
     exe.strip = strip;
     exe.pie = pie;
     exe.sanitize_thread = sanitize_thread;
-    exe.build_id = b.option(bool, "build-id", "Include a build id note") orelse false;
     exe.entitlements = entitlements;
+
+    if (b.option([]const u8, "build-id", "Include a build id note")) |build_id|
+        exe.build_id = try std.Build.CompileStep.BuildId.parse(b.allocator, build_id);
+
     b.installArtifact(exe);
 
     test_step.dependOn(&exe.step);
diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig
index 2371f49daf..25492eb73d 100644
--- a/lib/std/Build/Step/Compile.zig
+++ b/lib/std/Build/Step/Compile.zig
@@ -116,7 +116,7 @@ each_lib_rpath: ?bool = null,
 /// As an example, the bloaty project refuses to work unless its inputs have
 /// build ids, in order to prevent accidental mismatches.
 /// The default is to not include this section because it slows down linking.
-build_id: ?bool = null,
+build_id: ?BuildId = null,
 
 /// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF
 /// file.
@@ -288,6 +288,68 @@ pub const Options = struct {
     use_lld: ?bool = null,
 };
 
+pub const BuildId = union(enum) {
+    none,
+    fast,
+    uuid,
+    sha1,
+    md5,
+    hexstring: []const u8,
+
+    pub fn hash(self: BuildId, hasher: anytype) void {
+        switch (self) {
+            .none, .fast, .uuid, .sha1, .md5 => {
+                hasher.update(@tagName(self));
+            },
+            .hexstring => |str| {
+                hasher.update("0x");
+                hasher.update(str);
+            },
+        }
+    }
+
+    // parses the incoming BuildId. If returns a hexstring, it is allocated
+    // by the provided allocator.
+    pub fn parse(allocator: std.mem.Allocator, text: []const u8) error{
+        InvalidHexInt,
+        InvalidBuildId,
+        OutOfMemory,
+    }!BuildId {
+        if (mem.eql(u8, text, "none")) {
+            return .none;
+        } else if (mem.eql(u8, text, "fast")) {
+            return .fast;
+        } else if (mem.eql(u8, text, "uuid")) {
+            return .uuid;
+        } else if (mem.eql(u8, text, "sha1") or mem.eql(u8, text, "tree")) {
+            return .sha1;
+        } else if (mem.eql(u8, text, "md5")) {
+            return .md5;
+        } else if (mem.startsWith(u8, text, "0x")) {
+            var clean_hex_string = try allocator.alloc(u8, text.len);
+            errdefer allocator.free(clean_hex_string);
+
+            var i: usize = 0;
+            for (text["0x".len..]) |c| {
+                if (std.ascii.isHex(c)) {
+                    clean_hex_string[i] = c;
+                    i += 1;
+                } else if (c == '-' or c == ':') {
+                    continue;
+                } else {
+                    return error.InvalidHexInt;
+                }
+            }
+            if (i < text.len)
+                _ = allocator.resize(clean_hex_string, i);
+
+            return BuildId{ .hexstring = clean_hex_string[0..i] };
+        }
+
+        return error.InvalidBuildId;
+    }
+};
+
 pub const Kind = enum {
     exe,
     lib,
@@ -1810,7 +1872,13 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
 
     try addFlag(&zig_args, "valgrind", self.valgrind_support);
     try addFlag(&zig_args, "each-lib-rpath", self.each_lib_rpath);
-    try addFlag(&zig_args, "build-id", self.build_id);
+    if (self.build_id) |build_id| {
+        const fmt_str = "--build-id={s}{s}";
+        try zig_args.append(switch (build_id) {
+            .hexstring => |str| try std.fmt.allocPrint(b.allocator, fmt_str, .{ "0x", str }),
+            .none, .fast, .uuid, .sha1, .md5 => try std.fmt.allocPrint(b.allocator, fmt_str, .{ "", @tagName(build_id) }),
+        });
+    }
 
     if (self.zig_lib_dir) |dir| {
         try zig_args.append("--zig-lib-dir");
@@ -2175,3 +2243,50 @@ fn checkCompileErrors(self: *Compile) !void {
         \\=========================================
     , .{ expected_generated.items, actual_stderr });
 }
+
+const testing = std.testing;
+
+test "BuildId.parse" {
+    const tests = &[_]struct {
+        []const u8,
+        ?BuildId,
+        ?anyerror,
+    }{
+        .{ "0x", BuildId{ .hexstring = "" }, null },
+        .{ "0x12-34:", BuildId{ .hexstring = "1234" }, null },
+        .{ "0x123456", BuildId{ .hexstring = "123456" }, null },
+        .{ "md5", .md5, null },
+        .{ "none", .none, null },
+        .{ "fast", .fast, null },
+        .{ "uuid", .uuid, null },
+        .{ "sha1", .sha1, null },
+        .{ "tree", .sha1, null },
+        .{ "0xfoobbb", null, error.InvalidHexInt },
+        .{ "yaddaxxx", null, error.InvalidBuildId },
+    };
+
+    for (tests) |tt| {
+        const input = tt[0];
+        const expected = tt[1];
+        const expected_err = tt[2];
+
+        _ = (if (expected_err) |err| {
+            try testing.expectError(err, BuildId.parse(testing.allocator, input));
+        } else blk: {
+            const actual = BuildId.parse(testing.allocator, input) catch |e| break :blk e;
+            switch (expected.?) {
+                .hexstring => |expected_str| {
+                    try testing.expectEqualStrings(expected_str, actual.hexstring);
+                    testing.allocator.free(actual.hexstring);
+                },
+                else => try testing.expectEqual(expected.?, actual),
+            }
+        }) catch |e| {
+            std.log.err(
+                "BuildId.parse failed on {s}: expected {} got {!}",
+                .{ input, expected.?, e },
+            );
+            return e;
+        };
+    }
+}
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 1b6d805bb3..5a547346a5 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -29,6 +29,7 @@ const wasi_libc = @import("wasi_libc.zig");
 const fatal = @import("main.zig").fatal;
 const clangMain = @import("main.zig").clangMain;
 const Module = @import("Module.zig");
+const BuildId = std.Build.CompileStep.BuildId;
 const Cache = std.Build.Cache;
 const translate_c = @import("translate_c.zig");
 const clang = @import("clang.zig");
@@ -563,7 +564,7 @@ pub const InitOptions = struct {
     linker_print_map: bool = false,
     linker_opt_bisect_limit: i32 = -1,
     each_lib_rpath: ?bool = null,
-    build_id: ?bool = null,
+    build_id: ?BuildId = null,
     disable_c_depfile: bool = false,
     linker_z_nodelete: bool = false,
     linker_z_notext: bool = false,
@@ -797,7 +798,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
         const unwind_tables = options.want_unwind_tables orelse
             (link_libunwind or target_util.needUnwindTables(options.target));
         const link_eh_frame_hdr = options.link_eh_frame_hdr or unwind_tables;
-        const build_id = options.build_id orelse false;
 
         // Make a decision on whether to use LLD or our own linker.
         const use_lld = options.use_lld orelse blk: {
@@ -828,7 +828,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
                 options.output_mode == .Lib or
                 options.linker_script != null or options.version_script != null or
                 options.emit_implib != null or
-                build_id or
+                options.build_id != null or
                 options.symbol_wrap_set.count() > 0)
             {
                 break :blk true;
@@ -1514,7 +1514,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
             .skip_linker_dependencies = options.skip_linker_dependencies,
             .parent_compilation_link_libc = options.parent_compilation_link_libc,
             .each_lib_rpath = options.each_lib_rpath orelse options.is_native_os,
-            .build_id = build_id,
+            .build_id = options.build_id,
             .cache_mode = cache_mode,
             .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole,
             .subsystem = options.subsystem,
@@ -2269,7 +2269,9 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
     man.hash.addListOfBytes(comp.bin_file.options.rpath_list);
     man.hash.addListOfBytes(comp.bin_file.options.symbol_wrap_set.keys());
     man.hash.add(comp.bin_file.options.each_lib_rpath);
-    man.hash.add(comp.bin_file.options.build_id);
+    if (comp.bin_file.options.build_id) |build_id| {
+        build_id.hash(&man.hash.hasher);
+    }
     man.hash.add(comp.bin_file.options.skip_linker_dependencies);
     man.hash.add(comp.bin_file.options.z_nodelete);
     man.hash.add(comp.bin_file.options.z_notext);
diff --git a/src/link.zig b/src/link.zig
index 74e3ca85fc..eccf389d05 100644
--- a/src/link.zig
+++ b/src/link.zig
@@ -10,6 +10,7 @@ const wasi_libc = @import("wasi_libc.zig");
 
 const Air = @import("Air.zig");
 const Allocator = std.mem.Allocator;
+const BuildId = std.Build.CompileStep.BuildId;
 const Cache = std.Build.Cache;
 const Compilation = @import("Compilation.zig");
 const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
@@ -157,7 +158,7 @@ pub const Options = struct {
     skip_linker_dependencies: bool,
     parent_compilation_link_libc: bool,
     each_lib_rpath: bool,
-    build_id: bool,
+    build_id: ?BuildId,
     disable_lld_caching: bool,
     is_test: bool,
     hash_style: HashStyle,
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index 724ec76500..289c687270 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -1399,7 +1399,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
         man.hash.add(self.base.options.each_lib_rpath);
         if (self.base.options.output_mode == .Exe) {
             man.hash.add(stack_size);
-            man.hash.add(self.base.options.build_id);
+            if (self.base.options.build_id) |build_id|
+                build_id.hash(&man.hash.hasher);
         }
         man.hash.addListOfBytes(self.base.options.symbol_wrap_set.keys());
         man.hash.add(self.base.options.skip_linker_dependencies);
@@ -1542,8 +1543,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
             try argv.append("-z");
             try argv.append(try std.fmt.allocPrint(arena, "stack-size={d}", .{stack_size}));
 
-            if (self.base.options.build_id) {
-                try argv.append("--build-id");
+            if (self.base.options.build_id) |build_id| {
+                const fmt_str = "--build-id={s}{s}";
+                try argv.append(switch (build_id) {
+                    .hexstring => |str| try std.fmt.allocPrint(arena, fmt_str, .{ "0x", str }),
+                    .none, .fast, .uuid, .sha1, .md5 => try std.fmt.allocPrint(arena, fmt_str, .{ "", @tagName(build_id) }),
+                });
             }
         }
 
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
index b6f4a4cc59..9396377c73 100644
--- a/src/link/Wasm.zig
+++ b/src/link/Wasm.zig
@@ -3163,7 +3163,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
         try man.addOptionalFile(compiler_rt_path);
         man.hash.addOptionalBytes(options.entry);
         man.hash.addOptional(options.stack_size_override);
-        man.hash.add(wasm.base.options.build_id);
+        if (wasm.base.options.build_id) |build_id|
+            build_id.hash(&man.hash.hasher);
         man.hash.add(options.import_memory);
         man.hash.add(options.import_table);
         man.hash.add(options.export_table);
@@ -3797,8 +3798,27 @@ fn writeToFile(
     if (!wasm.base.options.strip) {
         // The build id must be computed on the main sections only,
         // so we have to do it now, before the debug sections.
-        if (wasm.base.options.build_id) {
-            try emitBuildIdSection(&binary_bytes);
+        if (wasm.base.options.build_id) |build_id| {
+            switch (build_id) {
+                .none => {},
+                .fast => {
+                    var id: [16]u8 = undefined;
+                    std.crypto.hash.sha3.TurboShake128(null).hash(binary_bytes.items, &id, .{});
+                    var uuid: [36]u8 = undefined;
+                    _ = try std.fmt.bufPrint(&uuid, "{s}-{s}-{s}-{s}-{s}", .{
+                        std.fmt.fmtSliceHexLower(id[0..4]),
+                        std.fmt.fmtSliceHexLower(id[4..6]),
+                        std.fmt.fmtSliceHexLower(id[6..8]),
+                        std.fmt.fmtSliceHexLower(id[8..10]),
+                        std.fmt.fmtSliceHexLower(id[10..]),
+                    });
+                    try emitBuildIdSection(&binary_bytes, &uuid);
+                },
+                .hexstring => |str| {
+                    try emitBuildIdSection(&binary_bytes, str);
+                },
+                else => |mode| log.err("build-id '{s}' is not supported for WASM", .{@tagName(mode)}),
+            }
         }
 
         // if (wasm.dwarf) |*dwarf| {
@@ -3942,25 +3962,17 @@ fn emitProducerSection(binary_bytes: *std.ArrayList(u8)) !void {
     );
 }
 
-fn emitBuildIdSection(binary_bytes: *std.ArrayList(u8)) !void {
+fn emitBuildIdSection(binary_bytes: *std.ArrayList(u8), build_id: []const u8) !void {
     const header_offset = try reserveCustomSectionHeader(binary_bytes);
 
     const writer = binary_bytes.writer();
-    const build_id = "build_id";
-    try leb.writeULEB128(writer, @intCast(u32, build_id.len));
-    try writer.writeAll(build_id);
-
-    var id: [16]u8 = undefined;
-    std.crypto.hash.sha3.TurboShake128(null).hash(binary_bytes.items, &id, .{});
-    var uuid: [36]u8 = undefined;
-    _ = try std.fmt.bufPrint(&uuid, "{s}-{s}-{s}-{s}-{s}", .{
-        std.fmt.fmtSliceHexLower(id[0..4]),  std.fmt.fmtSliceHexLower(id[4..6]), std.fmt.fmtSliceHexLower(id[6..8]),
-        std.fmt.fmtSliceHexLower(id[8..10]), std.fmt.fmtSliceHexLower(id[10..]),
-    });
+    const hdr_build_id = "build_id";
+    try leb.writeULEB128(writer, @intCast(u32, hdr_build_id.len));
+    try writer.writeAll(hdr_build_id);
 
     try leb.writeULEB128(writer, @as(u32, 1));
-    try leb.writeULEB128(writer, @as(u32, uuid.len));
-    try writer.writeAll(&uuid);
+    try leb.writeULEB128(writer, @intCast(u32, build_id.len));
+    try writer.writeAll(build_id);
 
     try writeCustomSectionHeader(
         binary_bytes.items,
@@ -4199,7 +4211,8 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
         try man.addOptionalFile(compiler_rt_path);
         man.hash.addOptionalBytes(wasm.base.options.entry);
         man.hash.addOptional(wasm.base.options.stack_size_override);
-        man.hash.add(wasm.base.options.build_id);
+        if (wasm.base.options.build_id) |build_id|
+            build_id.hash(&man.hash.hasher);
         man.hash.add(wasm.base.options.import_memory);
         man.hash.add(wasm.base.options.import_table);
         man.hash.add(wasm.base.options.export_table);
diff --git a/src/main.zig b/src/main.zig
index a680a5d89e..93199f9566 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -22,6 +22,7 @@ const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
 const wasi_libc = @import("wasi_libc.zig");
 const translate_c = @import("translate_c.zig");
 const clang = @import("clang.zig");
+const BuildId = std.Build.CompileStep.BuildId;
 const Cache = std.Build.Cache;
 const target_util = @import("target.zig");
 const crash_report = @import("crash_report.zig");
@@ -493,8 +494,7 @@ const usage_build_generic =
     \\  -fno-each-lib-rpath            Prevent adding rpath for each used dynamic library
     \\  -fallow-shlib-undefined        Allows undefined symbols in shared libraries
     \\  -fno-allow-shlib-undefined     Disallows undefined symbols in shared libraries
-    \\  -fbuild-id                     Helps coordinate stripped binaries with debug symbols
-    \\  -fno-build-id                  (default) Saves a bit of time linking
+    \\  --build-id[=style]             Generate a build ID note
     \\  --eh-frame-hdr                 Enable C++ exception handling by passing --eh-frame-hdr to linker
     \\  --emit-relocs                  Enable output of relocation sections for post build tools
     \\  -z [arg]                       Set linker extension flags
@@ -817,7 +817,7 @@ fn buildOutputType(
     var link_eh_frame_hdr = false;
     var link_emit_relocs = false;
     var each_lib_rpath: ?bool = null;
-    var build_id: ?bool = null;
+    var build_id: ?BuildId = null;
     var sysroot: ?[]const u8 = null;
     var libc_paths_file: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_LIBC");
     var machine_code_model: std.builtin.CodeModel = .default;
@@ -1202,10 +1202,6 @@ fn buildOutputType(
                         each_lib_rpath = true;
                     } else if (mem.eql(u8, arg, "-fno-each-lib-rpath")) {
                         each_lib_rpath = false;
-                    } else if (mem.eql(u8, arg, "-fbuild-id")) {
-                        build_id = true;
-                    } else if (mem.eql(u8, arg, "-fno-build-id")) {
-                        build_id = false;
                     } else if (mem.eql(u8, arg, "--test-cmd-bin")) {
                         try test_exec_args.append(null);
                     } else if (mem.eql(u8, arg, "--test-evented-io")) {
@@ -1446,6 +1442,15 @@ fn buildOutputType(
                         linker_gc_sections = true;
                     } else if (mem.eql(u8, arg, "--no-gc-sections")) {
                         linker_gc_sections = false;
+                    } else if (mem.eql(u8, arg, "--build-id")) {
+                        build_id = .fast;
+                    } else if (mem.startsWith(u8, arg, "--build-id=")) {
+                        const value = arg["--build-id=".len..];
+                        build_id = BuildId.parse(arena, value) catch |err| switch (err) {
+                            error.InvalidHexInt => fatal("failed to parse hex value {s}", .{value}),
+                            error.InvalidBuildId => fatal("invalid --build-id={s}", .{value}),
+                            error.OutOfMemory => fatal("OOM", .{}),
+                        };
                     } else if (mem.eql(u8, arg, "--debug-compile-errors")) {
                         if (!crash_report.is_enabled) {
                             std.log.warn("Zig was compiled in a release mode. --debug-compile-errors has no effect.", .{});
@@ -1684,11 +1689,7 @@ fn buildOutputType(
                                 if (mem.indexOfScalar(u8, linker_arg, '=')) |equals_pos| {
                                     const key = linker_arg[0..equals_pos];
                                     const value = linker_arg[equals_pos + 1 ..];
-                                    if (mem.eql(u8, key, "build-id")) {
-                                        build_id = true;
-                                        warn("ignoring build-id style argument: '{s}'", .{value});
-                                        continue;
-                                    } else if (mem.eql(u8, key, "--sort-common")) {
+                                    if (mem.eql(u8, key, "--sort-common")) {
                                         // this ignores --sort=common=; ignoring plain --sort-common
                                         // is done below.
                                         continue;
@@ -1730,6 +1731,15 @@ fn buildOutputType(
                                 search_strategy = .paths_first;
                             } else if (mem.eql(u8, linker_arg, "-search_dylibs_first")) {
                                 search_strategy = .dylibs_first;
+                            } else if (mem.eql(u8, linker_arg, "--build-id")) {
+                                build_id = .fast;
+                            } else if (mem.startsWith(u8, linker_arg, "--build-id=")) {
+                                const value = linker_arg["--build-id=".len..];
+                                build_id = BuildId.parse(arena, value) catch |err| switch (err) {
+                                    error.InvalidHexInt => fatal("failed to parse hex value {s}", .{value}),
+                                    error.InvalidBuildId => fatal("invalid --build-id={s}", .{value}),
+                                    error.OutOfMemory => fatal("OOM", .{}),
+                                };
                             } else {
                                 try linker_args.append(linker_arg);
                             }
-- 
cgit v1.2.3


From 728ce2d7c18e23ca6c36d86f4ee1ea4ce3ac81e2 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Tue, 16 May 2023 20:00:47 -0700
Subject: tweaks to --build-id

 * build.zig: the result of b.option() can be assigned directly in many
   cases thanks to the return type being an optional
 * std.Build: make the build system aware of the
   std.Build.Step.Compile.BuildId type when used as an option.
   - remove extraneous newlines in error logs
 * simplify caching logic
 * simplify hexstring parsing tests and use a doc test
 * simplify hashing logic. don't use an optional when the `none` tag
   already provides this meaning.
 * CLI: fix incorrect linker arg parsing
---
 build.zig                      |   7 +-
 lib/std/Build.zig              |  62 ++++++++++++------
 lib/std/Build/Cache.zig        |   4 ++
 lib/std/Build/Step/Compile.zig | 141 ++++++++++++++++-------------------------
 src/Compilation.zig            |   9 ++-
 src/link.zig                   |   2 +-
 src/link/Elf.zig               |  21 +++---
 src/link/Wasm.zig              |  50 +++++++--------
 src/main.zig                   |  37 ++++++-----
 9 files changed, 169 insertions(+), 164 deletions(-)

(limited to 'src/main.zig')

diff --git a/build.zig b/build.zig
index 62f1d86441..a75269083f 100644
--- a/build.zig
+++ b/build.zig
@@ -167,8 +167,11 @@ pub fn build(b: *std.Build) !void {
     exe.sanitize_thread = sanitize_thread;
     exe.entitlements = entitlements;
 
-    if (b.option([]const u8, "build-id", "Include a build id note")) |build_id|
-        exe.build_id = try std.Build.CompileStep.BuildId.parse(b.allocator, build_id);
+    exe.build_id = b.option(
+        std.Build.Step.Compile.BuildId,
+        "build-id",
+        "Request creation of '.note.gnu.build-id' section",
+    );
 
     b.installArtifact(exe);
 
diff --git a/lib/std/Build.zig b/lib/std/Build.zig
index ca55d23937..7ef504851e 100644
--- a/lib/std/Build.zig
+++ b/lib/std/Build.zig
@@ -181,6 +181,7 @@ const TypeId = enum {
     @"enum",
     string,
     list,
+    build_id,
 };
 
 const TopLevelStep = struct {
@@ -832,13 +833,13 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
                 } else if (mem.eql(u8, s, "false")) {
                     return false;
                 } else {
-                    log.err("Expected -D{s} to be a boolean, but received '{s}'\n", .{ name, s });
+                    log.err("Expected -D{s} to be a boolean, but received '{s}'", .{ name, s });
                     self.markInvalidUserInput();
                     return null;
                 }
             },
             .list, .map => {
-                log.err("Expected -D{s} to be a boolean, but received a {s}.\n", .{
+                log.err("Expected -D{s} to be a boolean, but received a {s}.", .{
                     name, @tagName(option_ptr.value),
                 });
                 self.markInvalidUserInput();
@@ -847,7 +848,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
         },
         .int => switch (option_ptr.value) {
             .flag, .list, .map => {
-                log.err("Expected -D{s} to be an integer, but received a {s}.\n", .{
+                log.err("Expected -D{s} to be an integer, but received a {s}.", .{
                     name, @tagName(option_ptr.value),
                 });
                 self.markInvalidUserInput();
@@ -856,12 +857,12 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
             .scalar => |s| {
                 const n = std.fmt.parseInt(T, s, 10) catch |err| switch (err) {
                     error.Overflow => {
-                        log.err("-D{s} value {s} cannot fit into type {s}.\n", .{ name, s, @typeName(T) });
+                        log.err("-D{s} value {s} cannot fit into type {s}.", .{ name, s, @typeName(T) });
                         self.markInvalidUserInput();
                         return null;
                     },
                     else => {
-                        log.err("Expected -D{s} to be an integer of type {s}.\n", .{ name, @typeName(T) });
+                        log.err("Expected -D{s} to be an integer of type {s}.", .{ name, @typeName(T) });
                         self.markInvalidUserInput();
                         return null;
                     },
@@ -871,7 +872,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
         },
         .float => switch (option_ptr.value) {
             .flag, .map, .list => {
-                log.err("Expected -D{s} to be a float, but received a {s}.\n", .{
+                log.err("Expected -D{s} to be a float, but received a {s}.", .{
                     name, @tagName(option_ptr.value),
                 });
                 self.markInvalidUserInput();
@@ -879,7 +880,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
             },
             .scalar => |s| {
                 const n = std.fmt.parseFloat(T, s) catch {
-                    log.err("Expected -D{s} to be a float of type {s}.\n", .{ name, @typeName(T) });
+                    log.err("Expected -D{s} to be a float of type {s}.", .{ name, @typeName(T) });
                     self.markInvalidUserInput();
                     return null;
                 };
@@ -888,7 +889,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
         },
         .@"enum" => switch (option_ptr.value) {
             .flag, .map, .list => {
-                log.err("Expected -D{s} to be an enum, but received a {s}.\n", .{
+                log.err("Expected -D{s} to be an enum, but received a {s}.", .{
                     name, @tagName(option_ptr.value),
                 });
                 self.markInvalidUserInput();
@@ -898,7 +899,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
                 if (std.meta.stringToEnum(T, s)) |enum_lit| {
                     return enum_lit;
                 } else {
-                    log.err("Expected -D{s} to be of type {s}.\n", .{ name, @typeName(T) });
+                    log.err("Expected -D{s} to be of type {s}.", .{ name, @typeName(T) });
                     self.markInvalidUserInput();
                     return null;
                 }
@@ -906,7 +907,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
         },
         .string => switch (option_ptr.value) {
             .flag, .list, .map => {
-                log.err("Expected -D{s} to be a string, but received a {s}.\n", .{
+                log.err("Expected -D{s} to be a string, but received a {s}.", .{
                     name, @tagName(option_ptr.value),
                 });
                 self.markInvalidUserInput();
@@ -914,9 +915,27 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
             },
             .scalar => |s| return s,
         },
+        .build_id => switch (option_ptr.value) {
+            .flag, .map, .list => {
+                log.err("Expected -D{s} to be an enum, but received a {s}.", .{
+                    name, @tagName(option_ptr.value),
+                });
+                self.markInvalidUserInput();
+                return null;
+            },
+            .scalar => |s| {
+                if (Step.Compile.BuildId.parse(s)) |build_id| {
+                    return build_id;
+                } else |err| {
+                    log.err("unable to parse option '-D{s}': {s}", .{ name, @errorName(err) });
+                    self.markInvalidUserInput();
+                    return null;
+                }
+            },
+        },
         .list => switch (option_ptr.value) {
             .flag, .map => {
-                log.err("Expected -D{s} to be a list, but received a {s}.\n", .{
+                log.err("Expected -D{s} to be a list, but received a {s}.", .{
                     name, @tagName(option_ptr.value),
                 });
                 self.markInvalidUserInput();
@@ -1183,15 +1202,18 @@ pub fn addUserInputFlag(self: *Build, name_raw: []const u8) !bool {
 }
 
 fn typeToEnum(comptime T: type) TypeId {
-    return switch (@typeInfo(T)) {
-        .Int => .int,
-        .Float => .float,
-        .Bool => .bool,
-        .Enum => .@"enum",
-        else => switch (T) {
-            []const u8 => .string,
-            []const []const u8 => .list,
-            else => @compileError("Unsupported type: " ++ @typeName(T)),
+    return switch (T) {
+        Step.Compile.BuildId => .build_id,
+        else => return switch (@typeInfo(T)) {
+            .Int => .int,
+            .Float => .float,
+            .Bool => .bool,
+            .Enum => .@"enum",
+            else => switch (T) {
+                []const u8 => .string,
+                []const []const u8 => .list,
+                else => @compileError("Unsupported type: " ++ @typeName(T)),
+            },
         },
     };
 }
diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig
index 17429c0370..e991aff5b5 100644
--- a/lib/std/Build/Cache.zig
+++ b/lib/std/Build/Cache.zig
@@ -235,6 +235,10 @@ pub const HashHelper = struct {
                     .none => {},
                 }
             },
+            std.Build.Step.Compile.BuildId => switch (x) {
+                .none, .fast, .uuid, .sha1, .md5 => hh.add(std.meta.activeTag(x)),
+                .hexstring => |hex_string| hh.addBytes(hex_string.toSlice()),
+            },
             else => switch (@typeInfo(@TypeOf(x))) {
                 .Bool, .Int, .Enum, .Array => hh.addBytes(mem.asBytes(&x)),
                 else => @compileError("unable to hash type " ++ @typeName(@TypeOf(x))),
diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig
index 25492eb73d..d0a2d69bfe 100644
--- a/lib/std/Build/Step/Compile.zig
+++ b/lib/std/Build/Step/Compile.zig
@@ -294,27 +294,41 @@ pub const BuildId = union(enum) {
     uuid,
     sha1,
     md5,
-    hexstring: []const u8,
+    hexstring: HexString,
+
+    pub fn eql(a: BuildId, b: BuildId) bool {
+        const a_tag = std.meta.activeTag(a);
+        const b_tag = std.meta.activeTag(b);
+        if (a_tag != b_tag) return false;
+        return switch (a) {
+            .none, .fast, .uuid, .sha1, .md5 => true,
+            .hexstring => |a_hexstring| mem.eql(u8, a_hexstring.toSlice(), b.hexstring.toSlice()),
+        };
+    }
 
-    pub fn hash(self: BuildId, hasher: anytype) void {
-        switch (self) {
-            .none, .fast, .uuid, .sha1, .md5 => {
-                hasher.update(@tagName(self));
-            },
-            .hexstring => |str| {
-                hasher.update("0x");
-                hasher.update(str);
-            },
+    pub const HexString = struct {
+        bytes: [32]u8,
+        len: u8,
+
+        /// Result is byte values, *not* hex-encoded.
+        pub fn toSlice(hs: *const HexString) []const u8 {
+            return hs.bytes[0..hs.len];
         }
+    };
+
+    /// Input is byte values, *not* hex-encoded.
+    /// Asserts `bytes` fits inside `HexString`
+    pub fn initHexString(bytes: []const u8) BuildId {
+        var result: BuildId = .{ .hexstring = .{
+            .bytes = undefined,
+            .len = @intCast(u8, bytes.len),
+        } };
+        @memcpy(result.hexstring.bytes[0..bytes.len], bytes);
+        return result;
     }
 
-    // parses the incoming BuildId. If returns a hexstring, it is allocated
-    // by the provided allocator.
-    pub fn parse(allocator: std.mem.Allocator, text: []const u8) error{
-        InvalidHexInt,
-        InvalidBuildId,
-        OutOfMemory,
-    }!BuildId {
+    /// Converts UTF-8 text to a `BuildId`.
+    pub fn parse(text: []const u8) !BuildId {
         if (mem.eql(u8, text, "none")) {
             return .none;
         } else if (mem.eql(u8, text, "fast")) {
@@ -326,27 +340,27 @@ pub const BuildId = union(enum) {
         } else if (mem.eql(u8, text, "md5")) {
             return .md5;
         } else if (mem.startsWith(u8, text, "0x")) {
-            var clean_hex_string = try allocator.alloc(u8, text.len);
-            errdefer allocator.free(clean_hex_string);
-
-            var i: usize = 0;
-            for (text["0x".len..]) |c| {
-                if (std.ascii.isHex(c)) {
-                    clean_hex_string[i] = c;
-                    i += 1;
-                } else if (c == '-' or c == ':') {
-                    continue;
-                } else {
-                    return error.InvalidHexInt;
-                }
-            }
-            if (i < text.len)
-                _ = allocator.resize(clean_hex_string, i);
-
-            return BuildId{ .hexstring = clean_hex_string[0..i] };
+            var result: BuildId = .{ .hexstring = undefined };
+            const slice = try std.fmt.hexToBytes(&result.hexstring.bytes, text[2..]);
+            result.hexstring.len = @intCast(u8, slice.len);
+            return result;
         }
+        return error.InvalidBuildIdStyle;
+    }
+
+    test parse {
+        try std.testing.expectEqual(BuildId.md5, try parse("md5"));
+        try std.testing.expectEqual(BuildId.none, try parse("none"));
+        try std.testing.expectEqual(BuildId.fast, try parse("fast"));
+        try std.testing.expectEqual(BuildId.uuid, try parse("uuid"));
+        try std.testing.expectEqual(BuildId.sha1, try parse("sha1"));
+        try std.testing.expectEqual(BuildId.sha1, try parse("tree"));
 
-        return error.InvalidBuildId;
+        try std.testing.expect(BuildId.initHexString("").eql(try parse("0x")));
+        try std.testing.expect(BuildId.initHexString("\x12\x34\x56").eql(try parse("0x123456")));
+        try std.testing.expectError(error.InvalidLength, parse("0x12-34"));
+        try std.testing.expectError(error.InvalidCharacter, parse("0xfoobbb"));
+        try std.testing.expectError(error.InvalidBuildIdStyle, parse("yaddaxxx"));
     }
 };
 
@@ -1872,11 +1886,13 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
 
     try addFlag(&zig_args, "valgrind", self.valgrind_support);
     try addFlag(&zig_args, "each-lib-rpath", self.each_lib_rpath);
+
     if (self.build_id) |build_id| {
-        const fmt_str = "--build-id={s}{s}";
         try zig_args.append(switch (build_id) {
-            .hexstring => |str| try std.fmt.allocPrint(b.allocator, fmt_str, .{ "0x", str }),
-            .none, .fast, .uuid, .sha1, .md5 => try std.fmt.allocPrint(b.allocator, fmt_str, .{ "", @tagName(build_id) }),
+            .hexstring => |hs| b.fmt("--build-id=0x{s}", .{
+                std.fmt.fmtSliceHexLower(hs.toSlice()),
+            }),
+            .none, .fast, .uuid, .sha1, .md5 => b.fmt("--build-id={s}", .{@tagName(build_id)}),
         });
     }
 
@@ -2243,50 +2259,3 @@ fn checkCompileErrors(self: *Compile) !void {
         \\=========================================
     , .{ expected_generated.items, actual_stderr });
 }
-
-const testing = std.testing;
-
-test "BuildId.parse" {
-    const tests = &[_]struct {
-        []const u8,
-        ?BuildId,
-        ?anyerror,
-    }{
-        .{ "0x", BuildId{ .hexstring = "" }, null },
-        .{ "0x12-34:", BuildId{ .hexstring = "1234" }, null },
-        .{ "0x123456", BuildId{ .hexstring = "123456" }, null },
-        .{ "md5", .md5, null },
-        .{ "none", .none, null },
-        .{ "fast", .fast, null },
-        .{ "uuid", .uuid, null },
-        .{ "sha1", .sha1, null },
-        .{ "tree", .sha1, null },
-        .{ "0xfoobbb", null, error.InvalidHexInt },
-        .{ "yaddaxxx", null, error.InvalidBuildId },
-    };
-
-    for (tests) |tt| {
-        const input = tt[0];
-        const expected = tt[1];
-        const expected_err = tt[2];
-
-        _ = (if (expected_err) |err| {
-            try testing.expectError(err, BuildId.parse(testing.allocator, input));
-        } else blk: {
-            const actual = BuildId.parse(testing.allocator, input) catch |e| break :blk e;
-            switch (expected.?) {
-                .hexstring => |expected_str| {
-                    try testing.expectEqualStrings(expected_str, actual.hexstring);
-                    testing.allocator.free(actual.hexstring);
-                },
-                else => try testing.expectEqual(expected.?, actual),
-            }
-        }) catch |e| {
-            std.log.err(
-                "BuildId.parse failed on {s}: expected {} got {!}",
-                .{ input, expected.?, e },
-            );
-            return e;
-        };
-    }
-}
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 5a547346a5..de09a78c77 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -798,6 +798,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
         const unwind_tables = options.want_unwind_tables orelse
             (link_libunwind or target_util.needUnwindTables(options.target));
         const link_eh_frame_hdr = options.link_eh_frame_hdr or unwind_tables;
+        const build_id = options.build_id orelse .none;
 
         // Make a decision on whether to use LLD or our own linker.
         const use_lld = options.use_lld orelse blk: {
@@ -828,7 +829,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
                 options.output_mode == .Lib or
                 options.linker_script != null or options.version_script != null or
                 options.emit_implib != null or
-                options.build_id != null or
+                build_id != .none or
                 options.symbol_wrap_set.count() > 0)
             {
                 break :blk true;
@@ -1514,7 +1515,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
             .skip_linker_dependencies = options.skip_linker_dependencies,
             .parent_compilation_link_libc = options.parent_compilation_link_libc,
             .each_lib_rpath = options.each_lib_rpath orelse options.is_native_os,
-            .build_id = options.build_id,
+            .build_id = build_id,
             .cache_mode = cache_mode,
             .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole,
             .subsystem = options.subsystem,
@@ -2269,9 +2270,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
     man.hash.addListOfBytes(comp.bin_file.options.rpath_list);
     man.hash.addListOfBytes(comp.bin_file.options.symbol_wrap_set.keys());
     man.hash.add(comp.bin_file.options.each_lib_rpath);
-    if (comp.bin_file.options.build_id) |build_id| {
-        build_id.hash(&man.hash.hasher);
-    }
+    man.hash.add(comp.bin_file.options.build_id);
     man.hash.add(comp.bin_file.options.skip_linker_dependencies);
     man.hash.add(comp.bin_file.options.z_nodelete);
     man.hash.add(comp.bin_file.options.z_notext);
diff --git a/src/link.zig b/src/link.zig
index eccf389d05..79ac33b892 100644
--- a/src/link.zig
+++ b/src/link.zig
@@ -158,7 +158,7 @@ pub const Options = struct {
     skip_linker_dependencies: bool,
     parent_compilation_link_libc: bool,
     each_lib_rpath: bool,
-    build_id: ?BuildId,
+    build_id: BuildId,
     disable_lld_caching: bool,
     is_test: bool,
     hash_style: HashStyle,
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index 289c687270..f90f4ebd46 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -1399,8 +1399,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
         man.hash.add(self.base.options.each_lib_rpath);
         if (self.base.options.output_mode == .Exe) {
             man.hash.add(stack_size);
-            if (self.base.options.build_id) |build_id|
-                build_id.hash(&man.hash.hasher);
+            man.hash.add(self.base.options.build_id);
         }
         man.hash.addListOfBytes(self.base.options.symbol_wrap_set.keys());
         man.hash.add(self.base.options.skip_linker_dependencies);
@@ -1543,12 +1542,18 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
             try argv.append("-z");
             try argv.append(try std.fmt.allocPrint(arena, "stack-size={d}", .{stack_size}));
 
-            if (self.base.options.build_id) |build_id| {
-                const fmt_str = "--build-id={s}{s}";
-                try argv.append(switch (build_id) {
-                    .hexstring => |str| try std.fmt.allocPrint(arena, fmt_str, .{ "0x", str }),
-                    .none, .fast, .uuid, .sha1, .md5 => try std.fmt.allocPrint(arena, fmt_str, .{ "", @tagName(build_id) }),
-                });
+            switch (self.base.options.build_id) {
+                .none => {},
+                .fast, .uuid, .sha1, .md5 => {
+                    try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{
+                        @tagName(self.base.options.build_id),
+                    }));
+                },
+                .hexstring => |hs| {
+                    try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{s}", .{
+                        std.fmt.fmtSliceHexLower(hs.toSlice()),
+                    }));
+                },
             }
         }
 
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
index 9396377c73..cd9c44d656 100644
--- a/src/link/Wasm.zig
+++ b/src/link/Wasm.zig
@@ -3163,8 +3163,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
         try man.addOptionalFile(compiler_rt_path);
         man.hash.addOptionalBytes(options.entry);
         man.hash.addOptional(options.stack_size_override);
-        if (wasm.base.options.build_id) |build_id|
-            build_id.hash(&man.hash.hasher);
+        man.hash.add(wasm.base.options.build_id);
         man.hash.add(options.import_memory);
         man.hash.add(options.import_table);
         man.hash.add(options.export_table);
@@ -3798,27 +3797,29 @@ fn writeToFile(
     if (!wasm.base.options.strip) {
         // The build id must be computed on the main sections only,
         // so we have to do it now, before the debug sections.
-        if (wasm.base.options.build_id) |build_id| {
-            switch (build_id) {
-                .none => {},
-                .fast => {
-                    var id: [16]u8 = undefined;
-                    std.crypto.hash.sha3.TurboShake128(null).hash(binary_bytes.items, &id, .{});
-                    var uuid: [36]u8 = undefined;
-                    _ = try std.fmt.bufPrint(&uuid, "{s}-{s}-{s}-{s}-{s}", .{
-                        std.fmt.fmtSliceHexLower(id[0..4]),
-                        std.fmt.fmtSliceHexLower(id[4..6]),
-                        std.fmt.fmtSliceHexLower(id[6..8]),
-                        std.fmt.fmtSliceHexLower(id[8..10]),
-                        std.fmt.fmtSliceHexLower(id[10..]),
-                    });
-                    try emitBuildIdSection(&binary_bytes, &uuid);
-                },
-                .hexstring => |str| {
-                    try emitBuildIdSection(&binary_bytes, str);
-                },
-                else => |mode| log.err("build-id '{s}' is not supported for WASM", .{@tagName(mode)}),
-            }
+        switch (wasm.base.options.build_id) {
+            .none => {},
+            .fast => {
+                var id: [16]u8 = undefined;
+                std.crypto.hash.sha3.TurboShake128(null).hash(binary_bytes.items, &id, .{});
+                var uuid: [36]u8 = undefined;
+                _ = try std.fmt.bufPrint(&uuid, "{s}-{s}-{s}-{s}-{s}", .{
+                    std.fmt.fmtSliceHexLower(id[0..4]),
+                    std.fmt.fmtSliceHexLower(id[4..6]),
+                    std.fmt.fmtSliceHexLower(id[6..8]),
+                    std.fmt.fmtSliceHexLower(id[8..10]),
+                    std.fmt.fmtSliceHexLower(id[10..]),
+                });
+                try emitBuildIdSection(&binary_bytes, &uuid);
+            },
+            .hexstring => |hs| {
+                var buffer: [32 * 2]u8 = undefined;
+                const str = std.fmt.bufPrint(&buffer, "{s}", .{
+                    std.fmt.fmtSliceHexLower(hs.toSlice()),
+                }) catch unreachable;
+                try emitBuildIdSection(&binary_bytes, str);
+            },
+            else => |mode| log.err("build-id '{s}' is not supported for WASM", .{@tagName(mode)}),
         }
 
         // if (wasm.dwarf) |*dwarf| {
@@ -4211,8 +4212,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
         try man.addOptionalFile(compiler_rt_path);
         man.hash.addOptionalBytes(wasm.base.options.entry);
         man.hash.addOptional(wasm.base.options.stack_size_override);
-        if (wasm.base.options.build_id) |build_id|
-            build_id.hash(&man.hash.hasher);
+        man.hash.add(wasm.base.options.build_id);
         man.hash.add(wasm.base.options.import_memory);
         man.hash.add(wasm.base.options.import_table);
         man.hash.add(wasm.base.options.export_table);
diff --git a/src/main.zig b/src/main.zig
index 93199f9566..aa7d587983 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -494,7 +494,10 @@ const usage_build_generic =
     \\  -fno-each-lib-rpath            Prevent adding rpath for each used dynamic library
     \\  -fallow-shlib-undefined        Allows undefined symbols in shared libraries
     \\  -fno-allow-shlib-undefined     Disallows undefined symbols in shared libraries
-    \\  --build-id[=style]             Generate a build ID note
+    \\  --build-id[=style]             At a minor link-time expense, coordinates stripped binaries
+    \\      fast, uuid, sha1, md5      with debug symbols via a '.note.gnu.build-id' section
+    \\      0x[hexstring]              Maximum 32 bytes
+    \\      none                       (default) Disable build-id
     \\  --eh-frame-hdr                 Enable C++ exception handling by passing --eh-frame-hdr to linker
     \\  --emit-relocs                  Enable output of relocation sections for post build tools
     \\  -z [arg]                       Set linker extension flags
@@ -1445,11 +1448,11 @@ fn buildOutputType(
                     } else if (mem.eql(u8, arg, "--build-id")) {
                         build_id = .fast;
                     } else if (mem.startsWith(u8, arg, "--build-id=")) {
-                        const value = arg["--build-id=".len..];
-                        build_id = BuildId.parse(arena, value) catch |err| switch (err) {
-                            error.InvalidHexInt => fatal("failed to parse hex value {s}", .{value}),
-                            error.InvalidBuildId => fatal("invalid --build-id={s}", .{value}),
-                            error.OutOfMemory => fatal("OOM", .{}),
+                        const style = arg["--build-id=".len..];
+                        build_id = BuildId.parse(style) catch |err| {
+                            fatal("unable to parse --build-id style '{s}': {s}", .{
+                                style, @errorName(err),
+                            });
                         };
                     } else if (mem.eql(u8, arg, "--debug-compile-errors")) {
                         if (!crash_report.is_enabled) {
@@ -1689,7 +1692,14 @@ fn buildOutputType(
                                 if (mem.indexOfScalar(u8, linker_arg, '=')) |equals_pos| {
                                     const key = linker_arg[0..equals_pos];
                                     const value = linker_arg[equals_pos + 1 ..];
-                                    if (mem.eql(u8, key, "--sort-common")) {
+                                    if (mem.eql(u8, key, "--build-id")) {
+                                        build_id = BuildId.parse(value) catch |err| {
+                                            fatal("unable to parse --build-id style '{s}': {s}", .{
+                                                value, @errorName(err),
+                                            });
+                                        };
+                                        continue;
+                                    } else if (mem.eql(u8, key, "--sort-common")) {
                                         // this ignores --sort=common=; ignoring plain --sort-common
                                         // is done below.
                                         continue;
@@ -1699,7 +1709,9 @@ fn buildOutputType(
                                     continue;
                                 }
                             }
-                            if (mem.eql(u8, linker_arg, "--as-needed")) {
+                            if (mem.eql(u8, linker_arg, "--build-id")) {
+                                build_id = .fast;
+                            } else if (mem.eql(u8, linker_arg, "--as-needed")) {
                                 needed = false;
                             } else if (mem.eql(u8, linker_arg, "--no-as-needed")) {
                                 needed = true;
@@ -1731,15 +1743,6 @@ fn buildOutputType(
                                 search_strategy = .paths_first;
                             } else if (mem.eql(u8, linker_arg, "-search_dylibs_first")) {
                                 search_strategy = .dylibs_first;
-                            } else if (mem.eql(u8, linker_arg, "--build-id")) {
-                                build_id = .fast;
-                            } else if (mem.startsWith(u8, linker_arg, "--build-id=")) {
-                                const value = linker_arg["--build-id=".len..];
-                                build_id = BuildId.parse(arena, value) catch |err| switch (err) {
-                                    error.InvalidHexInt => fatal("failed to parse hex value {s}", .{value}),
-                                    error.InvalidBuildId => fatal("invalid --build-id={s}", .{value}),
-                                    error.OutOfMemory => fatal("OOM", .{}),
-                                };
                             } else {
                                 try linker_args.append(linker_arg);
                             }
-- 
cgit v1.2.3


From 5b06daf52bdeaf18b40909ef878e8b19b3d14019 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Tue, 16 May 2023 17:01:27 -0700
Subject: zig cc: implement `-###` (dry run)

closes #7170
---
 src/main.zig | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'src/main.zig')

diff --git a/src/main.zig b/src/main.zig
index 2fd314def8..6ac8636c88 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -1796,11 +1796,11 @@ fn buildOutputType(
                         try clang_argv.append("-v");
                     },
                     .dry_run => {
+                        // This flag means "dry run". Clang will not actually output anything
+                        // to the file system.
                         verbose_link = true;
+                        disable_c_depfile = true;
                         try clang_argv.append("-###");
-                        // This flag is supposed to mean "dry run" but currently this
-                        // will actually still execute. The tracking issue for this is
-                        // https://github.com/ziglang/zig/issues/7170
                     },
                     .for_linker => try linker_args.append(it.only_arg),
                     .linker_input_z => {
-- 
cgit v1.2.3


From fea615710268582f488b894e4276938c5e385636 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Wed, 17 May 2023 15:43:15 -0700
Subject: zig2.c: omit non-essential subcommands

When producing zig2.c, don't waste time emitting C code for subcommands
that won't be used, such as objcopy.

This takes zig2.c down from 111M to 109M, and sidesteps some unfortunate
warnings that are currently emitted by GCC.
---
 src/main.zig | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

(limited to 'src/main.zig')

diff --git a/src/main.zig b/src/main.zig
index 4e64c06aa9..2771b64622 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -281,12 +281,8 @@ pub fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
         mem.eql(u8, cmd, "ar"))
     {
         return process.exit(try llvmArMain(arena, args));
-    } else if (mem.eql(u8, cmd, "cc")) {
-        return buildOutputType(gpa, arena, args, .cc);
-    } else if (mem.eql(u8, cmd, "c++")) {
-        return buildOutputType(gpa, arena, args, .cpp);
-    } else if (mem.eql(u8, cmd, "translate-c")) {
-        return buildOutputType(gpa, arena, args, .translate_c);
+    } else if (mem.eql(u8, cmd, "build")) {
+        return cmdBuild(gpa, arena, cmd_args);
     } else if (mem.eql(u8, cmd, "clang") or
         mem.eql(u8, cmd, "-cc1") or mem.eql(u8, cmd, "-cc1as"))
     {
@@ -296,8 +292,14 @@ pub fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
         mem.eql(u8, cmd, "wasm-ld"))
     {
         return process.exit(try lldMain(arena, args, true));
-    } else if (mem.eql(u8, cmd, "build")) {
-        return cmdBuild(gpa, arena, cmd_args);
+    } else if (build_options.omit_pkg_fetching_code) {
+        @panic("only a few subcommands are supported in a zig2.c build");
+    } else if (mem.eql(u8, cmd, "cc")) {
+        return buildOutputType(gpa, arena, args, .cc);
+    } else if (mem.eql(u8, cmd, "c++")) {
+        return buildOutputType(gpa, arena, args, .cpp);
+    } else if (mem.eql(u8, cmd, "translate-c")) {
+        return buildOutputType(gpa, arena, args, .translate_c);
     } else if (mem.eql(u8, cmd, "fmt")) {
         return cmdFmt(gpa, arena, cmd_args);
     } else if (mem.eql(u8, cmd, "objcopy")) {
-- 
cgit v1.2.3


From f52189834c8554f6358244471c789e2233c260f0 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Wed, 17 May 2023 16:00:24 -0700
Subject: rename omit_pkg_fetching_code to only_core_functionality

No functional changes. This renames an internal build option to better
reflect how it is used.
---
 build.zig            |  6 +++---
 src/Compilation.zig  |  2 +-
 src/main.zig         | 10 +++++-----
 stage1/config.zig.in |  2 +-
 4 files changed, 10 insertions(+), 10 deletions(-)

(limited to 'src/main.zig')

diff --git a/build.zig b/build.zig
index a75269083f..aaef526af1 100644
--- a/build.zig
+++ b/build.zig
@@ -197,7 +197,7 @@ pub fn build(b: *std.Build) !void {
     exe_options.addOption(bool, "llvm_has_xtensa", llvm_has_xtensa);
     exe_options.addOption(bool, "force_gpa", force_gpa);
     exe_options.addOption(bool, "only_c", only_c);
-    exe_options.addOption(bool, "omit_pkg_fetching_code", only_c);
+    exe_options.addOption(bool, "only_core_functionality", only_c);
 
     if (link_libc) {
         exe.linkLibC();
@@ -353,7 +353,7 @@ pub fn build(b: *std.Build) !void {
     test_cases_options.addOption(bool, "llvm_has_xtensa", llvm_has_xtensa);
     test_cases_options.addOption(bool, "force_gpa", force_gpa);
     test_cases_options.addOption(bool, "only_c", only_c);
-    test_cases_options.addOption(bool, "omit_pkg_fetching_code", true);
+    test_cases_options.addOption(bool, "only_core_functionality", true);
     test_cases_options.addOption(bool, "enable_qemu", b.enable_qemu);
     test_cases_options.addOption(bool, "enable_wine", b.enable_wine);
     test_cases_options.addOption(bool, "enable_wasmtime", b.enable_wasmtime);
@@ -505,7 +505,7 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
     exe_options.addOption(bool, "enable_tracy_callstack", false);
     exe_options.addOption(bool, "enable_tracy_allocation", false);
     exe_options.addOption(bool, "value_tracing", false);
-    exe_options.addOption(bool, "omit_pkg_fetching_code", true);
+    exe_options.addOption(bool, "only_core_functionality", true);
 
     const run_opt = b.addSystemCommand(&.{
         "wasm-opt",
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 0a01e9465c..b485800329 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -2056,7 +2056,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
         return;
     }
 
-    if (!build_options.only_c and !build_options.omit_pkg_fetching_code) {
+    if (!build_options.only_c and !build_options.only_core_functionality) {
         if (comp.emit_docs) |doc_location| {
             if (comp.bin_file.options.module) |module| {
                 var autodoc = Autodoc.init(module, doc_location);
diff --git a/src/main.zig b/src/main.zig
index 2771b64622..650741e5e4 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -292,7 +292,7 @@ pub fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
         mem.eql(u8, cmd, "wasm-ld"))
     {
         return process.exit(try lldMain(arena, args, true));
-    } else if (build_options.omit_pkg_fetching_code) {
+    } else if (build_options.only_core_functionality) {
         @panic("only a few subcommands are supported in a zig2.c build");
     } else if (mem.eql(u8, cmd, "cc")) {
         return buildOutputType(gpa, arena, args, .cc);
@@ -680,7 +680,7 @@ const ArgMode = union(enum) {
 
 /// Avoid dragging networking into zig2.c because it adds dependencies on some
 /// linker symbols that are annoying to satisfy while bootstrapping.
-const Ip4Address = if (build_options.omit_pkg_fetching_code) void else std.net.Ip4Address;
+const Ip4Address = if (build_options.only_core_functionality) void else std.net.Ip4Address;
 
 const Listen = union(enum) {
     none,
@@ -1179,7 +1179,7 @@ fn buildOutputType(
                         if (mem.eql(u8, next_arg, "-")) {
                             listen = .stdio;
                         } else {
-                            if (build_options.omit_pkg_fetching_code) unreachable;
+                            if (build_options.only_core_functionality) unreachable;
                             // example: --listen 127.0.0.1:9000
                             var it = std.mem.split(u8, next_arg, ":");
                             const host = it.next().?;
@@ -3268,7 +3268,7 @@ fn buildOutputType(
             return cleanExit();
         },
         .ip4 => |ip4_addr| {
-            if (build_options.omit_pkg_fetching_code) unreachable;
+            if (build_options.only_core_functionality) unreachable;
 
             var server = std.net.StreamServer.init(.{
                 .reuse_address = true,
@@ -4415,7 +4415,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
             .root_src_directory = build_directory,
             .root_src_path = build_zig_basename,
         };
-        if (!build_options.omit_pkg_fetching_code) {
+        if (!build_options.only_core_functionality) {
             var http_client: std.http.Client = .{ .allocator = gpa };
             defer http_client.deinit();
 
diff --git a/stage1/config.zig.in b/stage1/config.zig.in
index 33a74b6bfb..2b38d858f3 100644
--- a/stage1/config.zig.in
+++ b/stage1/config.zig.in
@@ -13,4 +13,4 @@ pub const have_stage1 = false;
 pub const skip_non_native = false;
 pub const only_c = false;
 pub const force_gpa = false;
-pub const omit_pkg_fetching_code = true;
+pub const only_core_functionality = true;
-- 
cgit v1.2.3


From 0f6fa3f20b3b28958921bd63a9a9d96468455e9c Mon Sep 17 00:00:00 2001
From: Linus Groh 
Date: Sun, 21 May 2023 14:27:28 +0100
Subject: std: Move std.debug.{TTY.Config,detectTTYConfig} to std.io.tty

Also get rid of the TTY wrapper struct, which was exlusively used as a
namespace - this is done by the tty.zig root struct now.

detectTTYConfig has been renamed to just detectConfig, which is enough
given the new namespace. Additionally, a doc comment had been added.
---
 lib/build_runner.zig        |  12 ++--
 lib/std/Build.zig           |   2 +-
 lib/std/Build/Step.zig      |   2 +-
 lib/std/builtin.zig         |   2 +-
 lib/std/debug.zig           | 137 ++++----------------------------------------
 lib/std/io.zig              |   2 +
 lib/std/io/tty.zig          | 121 ++++++++++++++++++++++++++++++++++++++
 lib/std/testing.zig         |   8 +--
 lib/std/zig/ErrorBundle.zig |   4 +-
 src/main.zig                |   4 +-
 test/src/Cases.zig          |   2 +-
 11 files changed, 152 insertions(+), 144 deletions(-)
 create mode 100644 lib/std/io/tty.zig

(limited to 'src/main.zig')

diff --git a/lib/build_runner.zig b/lib/build_runner.zig
index 7eec164871..a09ec2cf1f 100644
--- a/lib/build_runner.zig
+++ b/lib/build_runner.zig
@@ -333,7 +333,7 @@ const Run = struct {
 
     claimed_rss: usize,
     enable_summary: ?bool,
-    ttyconf: std.debug.TTY.Config,
+    ttyconf: std.io.tty.Config,
     stderr: std.fs.File,
 };
 
@@ -535,7 +535,7 @@ const PrintNode = struct {
     last: bool = false,
 };
 
-fn printPrefix(node: *PrintNode, stderr: std.fs.File, ttyconf: std.debug.TTY.Config) !void {
+fn printPrefix(node: *PrintNode, stderr: std.fs.File, ttyconf: std.io.tty.Config) !void {
     const parent = node.parent orelse return;
     if (parent.parent == null) return;
     try printPrefix(parent, stderr, ttyconf);
@@ -553,7 +553,7 @@ fn printTreeStep(
     b: *std.Build,
     s: *Step,
     stderr: std.fs.File,
-    ttyconf: std.debug.TTY.Config,
+    ttyconf: std.io.tty.Config,
     parent_node: *PrintNode,
     step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void),
 ) !void {
@@ -1026,15 +1026,15 @@ fn cleanExit() void {
 
 const Color = enum { auto, off, on };
 
-fn get_tty_conf(color: Color, stderr: std.fs.File) std.debug.TTY.Config {
+fn get_tty_conf(color: Color, stderr: std.fs.File) std.io.tty.Config {
     return switch (color) {
-        .auto => std.debug.detectTTYConfig(stderr),
+        .auto => std.io.tty.detectConfig(stderr),
         .on => .escape_codes,
         .off => .no_color,
     };
 }
 
-fn renderOptions(ttyconf: std.debug.TTY.Config) std.zig.ErrorBundle.RenderOptions {
+fn renderOptions(ttyconf: std.io.tty.Config) std.zig.ErrorBundle.RenderOptions {
     return .{
         .ttyconf = ttyconf,
         .include_source_line = ttyconf != .no_color,
diff --git a/lib/std/Build.zig b/lib/std/Build.zig
index b36e815f72..bb642b5e66 100644
--- a/lib/std/Build.zig
+++ b/lib/std/Build.zig
@@ -1712,7 +1712,7 @@ fn dumpBadGetPathHelp(
         s.name,
     });
 
-    const tty_config = std.debug.detectTTYConfig(stderr);
+    const tty_config = std.io.tty.detectConfig(stderr);
     tty_config.setColor(w, .red) catch {};
     try stderr.writeAll("    The step was created by this stack trace:\n");
     tty_config.setColor(w, .reset) catch {};
diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig
index 40c88df2b9..a0d7a6a296 100644
--- a/lib/std/Build/Step.zig
+++ b/lib/std/Build/Step.zig
@@ -237,7 +237,7 @@ pub fn dump(step: *Step) void {
 
     const stderr = std.io.getStdErr();
     const w = stderr.writer();
-    const tty_config = std.debug.detectTTYConfig(stderr);
+    const tty_config = std.io.tty.detectConfig(stderr);
     const debug_info = std.debug.getSelfDebugInfo() catch |err| {
         w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{
             @errorName(err),
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
index 56fab05d88..710aaefd5a 100644
--- a/lib/std/builtin.zig
+++ b/lib/std/builtin.zig
@@ -51,7 +51,7 @@ pub const StackTrace = struct {
         const debug_info = std.debug.getSelfDebugInfo() catch |err| {
             return writer.print("\nUnable to print stack trace: Unable to open debug info: {s}\n", .{@errorName(err)});
         };
-        const tty_config = std.debug.detectTTYConfig(std.io.getStdErr());
+        const tty_config = std.io.tty.detectConfig(std.io.getStdErr());
         try writer.writeAll("\n");
         std.debug.writeStackTrace(self, writer, arena.allocator(), debug_info, tty_config) catch |err| {
             try writer.print("Unable to print stack trace: {s}\n", .{@errorName(err)});
diff --git a/lib/std/debug.zig b/lib/std/debug.zig
index d98cf8f27d..08407023d6 100644
--- a/lib/std/debug.zig
+++ b/lib/std/debug.zig
@@ -5,7 +5,6 @@ const mem = std.mem;
 const io = std.io;
 const os = std.os;
 const fs = std.fs;
-const process = std.process;
 const testing = std.testing;
 const elf = std.elf;
 const DW = std.dwarf;
@@ -109,31 +108,6 @@ pub fn getSelfDebugInfo() !*DebugInfo {
     }
 }
 
-pub fn detectTTYConfig(file: std.fs.File) TTY.Config {
-    if (builtin.os.tag == .wasi) {
-        // Per https://github.com/WebAssembly/WASI/issues/162 ANSI codes
-        // aren't currently supported.
-        return .no_color;
-    } else if (process.hasEnvVarConstant("ZIG_DEBUG_COLOR")) {
-        return .escape_codes;
-    } else if (process.hasEnvVarConstant("NO_COLOR")) {
-        return .no_color;
-    } else if (file.supportsAnsiEscapeCodes()) {
-        return .escape_codes;
-    } else if (native_os == .windows and file.isTty()) {
-        var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
-        if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE) {
-            // TODO: Should this return an error instead?
-            return .no_color;
-        }
-        return .{ .windows_api = .{
-            .handle = file.handle,
-            .reset_attributes = info.wAttributes,
-        } };
-    }
-    return .no_color;
-}
-
 /// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned.
 /// TODO multithreaded awareness
 pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
@@ -154,7 +128,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
             stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return;
             return;
         };
-        writeCurrentStackTrace(stderr, debug_info, detectTTYConfig(io.getStdErr()), start_addr) catch |err| {
+        writeCurrentStackTrace(stderr, debug_info, io.tty.detectConfig(io.getStdErr()), start_addr) catch |err| {
             stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return;
             return;
         };
@@ -182,7 +156,7 @@ pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void {
             stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return;
             return;
         };
-        const tty_config = detectTTYConfig(io.getStdErr());
+        const tty_config = io.tty.detectConfig(io.getStdErr());
         if (native_os == .windows) {
             writeCurrentStackTraceWindows(stderr, debug_info, tty_config, ip) catch return;
             return;
@@ -265,7 +239,7 @@ pub fn dumpStackTrace(stack_trace: std.builtin.StackTrace) void {
             stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return;
             return;
         };
-        writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, detectTTYConfig(io.getStdErr())) catch |err| {
+        writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, io.tty.detectConfig(io.getStdErr())) catch |err| {
             stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return;
             return;
         };
@@ -403,7 +377,7 @@ pub fn writeStackTrace(
     out_stream: anytype,
     allocator: mem.Allocator,
     debug_info: *DebugInfo,
-    tty_config: TTY.Config,
+    tty_config: io.tty.Config,
 ) !void {
     _ = allocator;
     if (builtin.strip_debug_info) return error.MissingDebugInfo;
@@ -562,7 +536,7 @@ pub const StackIterator = struct {
 pub fn writeCurrentStackTrace(
     out_stream: anytype,
     debug_info: *DebugInfo,
-    tty_config: TTY.Config,
+    tty_config: io.tty.Config,
     start_addr: ?usize,
 ) !void {
     if (native_os == .windows) {
@@ -634,7 +608,7 @@ pub noinline fn walkStackWindows(addresses: []usize) usize {
 pub fn writeCurrentStackTraceWindows(
     out_stream: anytype,
     debug_info: *DebugInfo,
-    tty_config: TTY.Config,
+    tty_config: io.tty.Config,
     start_addr: ?usize,
 ) !void {
     var addr_buf: [1024]usize = undefined;
@@ -651,95 +625,6 @@ pub fn writeCurrentStackTraceWindows(
     }
 }
 
-/// Provides simple functionality for manipulating the terminal in some way,
-/// for debugging purposes, such as coloring text, etc.
-pub const TTY = struct {
-    pub const Color = enum {
-        red,
-        green,
-        yellow,
-        cyan,
-        white,
-        dim,
-        bold,
-        reset,
-    };
-
-    pub const Config = union(enum) {
-        no_color,
-        escape_codes,
-        windows_api: if (native_os == .windows) WindowsContext else void,
-
-        pub const WindowsContext = struct {
-            handle: File.Handle,
-            reset_attributes: u16,
-        };
-
-        pub fn setColor(conf: Config, out_stream: anytype, color: Color) !void {
-            nosuspend switch (conf) {
-                .no_color => return,
-                .escape_codes => {
-                    const color_string = switch (color) {
-                        .red => "\x1b[31;1m",
-                        .green => "\x1b[32;1m",
-                        .yellow => "\x1b[33;1m",
-                        .cyan => "\x1b[36;1m",
-                        .white => "\x1b[37;1m",
-                        .bold => "\x1b[1m",
-                        .dim => "\x1b[2m",
-                        .reset => "\x1b[0m",
-                    };
-                    try out_stream.writeAll(color_string);
-                },
-                .windows_api => |ctx| if (native_os == .windows) {
-                    const attributes = switch (color) {
-                        .red => windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY,
-                        .green => windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY,
-                        .yellow => windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY,
-                        .cyan => windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY,
-                        .white, .bold => windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY,
-                        .dim => windows.FOREGROUND_INTENSITY,
-                        .reset => ctx.reset_attributes,
-                    };
-                    try windows.SetConsoleTextAttribute(ctx.handle, attributes);
-                } else {
-                    unreachable;
-                },
-            };
-        }
-
-        pub fn writeDEC(conf: Config, writer: anytype, codepoint: u8) !void {
-            const bytes = switch (conf) {
-                .no_color, .windows_api => switch (codepoint) {
-                    0x50...0x5e => @as(*const [1]u8, &codepoint),
-                    0x6a => "+", // ┘
-                    0x6b => "+", // ┐
-                    0x6c => "+", // ┌
-                    0x6d => "+", // └
-                    0x6e => "+", // ┼
-                    0x71 => "-", // ─
-                    0x74 => "+", // ├
-                    0x75 => "+", // ┤
-                    0x76 => "+", // ┴
-                    0x77 => "+", // ┬
-                    0x78 => "|", // │
-                    else => " ", // TODO
-                },
-                .escape_codes => switch (codepoint) {
-                    // Here we avoid writing the DEC beginning sequence and
-                    // ending sequence in separate syscalls by putting the
-                    // beginning and ending sequence into the same string
-                    // literals, to prevent terminals ending up in bad states
-                    // in case a crash happens between syscalls.
-                    inline 0x50...0x7f => |x| "\x1B\x28\x30" ++ [1]u8{x} ++ "\x1B\x28\x42",
-                    else => unreachable,
-                },
-            };
-            return writer.writeAll(bytes);
-        }
-    };
-};
-
 fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const MachoSymbol {
     var min: usize = 0;
     var max: usize = symbols.len - 1;
@@ -785,7 +670,7 @@ test "machoSearchSymbols" {
     try testing.expectEqual(&symbols[2], machoSearchSymbols(&symbols, 5000).?);
 }
 
-fn printUnknownSource(debug_info: *DebugInfo, out_stream: anytype, address: usize, tty_config: TTY.Config) !void {
+fn printUnknownSource(debug_info: *DebugInfo, out_stream: anytype, address: usize, tty_config: io.tty.Config) !void {
     const module_name = debug_info.getModuleNameForAddress(address);
     return printLineInfo(
         out_stream,
@@ -798,7 +683,7 @@ fn printUnknownSource(debug_info: *DebugInfo, out_stream: anytype, address: usiz
     );
 }
 
-pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: anytype, address: usize, tty_config: TTY.Config) !void {
+pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: anytype, address: usize, tty_config: io.tty.Config) !void {
     const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {
         error.MissingDebugInfo, error.InvalidDebugInfo => return printUnknownSource(debug_info, out_stream, address, tty_config),
         else => return err,
@@ -827,7 +712,7 @@ fn printLineInfo(
     address: usize,
     symbol_name: []const u8,
     compile_unit_name: []const u8,
-    tty_config: TTY.Config,
+    tty_config: io.tty.Config,
     comptime printLineFromFile: anytype,
 ) !void {
     nosuspend {
@@ -2193,7 +2078,7 @@ test "manage resources correctly" {
     const writer = std.io.null_writer;
     var di = try openSelfDebugInfo(testing.allocator);
     defer di.deinit();
-    try printSourceAtAddress(&di, writer, showMyTrace(), detectTTYConfig(std.io.getStdErr()));
+    try printSourceAtAddress(&di, writer, showMyTrace(), io.tty.detectConfig(std.io.getStdErr()));
 }
 
 noinline fn showMyTrace() usize {
@@ -2253,7 +2138,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize
         pub fn dump(t: @This()) void {
             if (!enabled) return;
 
-            const tty_config = detectTTYConfig(std.io.getStdErr());
+            const tty_config = io.tty.detectConfig(std.io.getStdErr());
             const stderr = io.getStdErr().writer();
             const end = @min(t.index, size);
             const debug_info = getSelfDebugInfo() catch |err| {
diff --git a/lib/std/io.zig b/lib/std/io.zig
index d95997f853..f6d893c7dd 100644
--- a/lib/std/io.zig
+++ b/lib/std/io.zig
@@ -155,6 +155,8 @@ pub const BufferedAtomicFile = @import("io/buffered_atomic_file.zig").BufferedAt
 
 pub const StreamSource = @import("io/stream_source.zig").StreamSource;
 
+pub const tty = @import("io/tty.zig");
+
 /// A Writer that doesn't write to anything.
 pub const null_writer = @as(NullWriter, .{ .context = {} });
 
diff --git a/lib/std/io/tty.zig b/lib/std/io/tty.zig
new file mode 100644
index 0000000000..ea1c52db00
--- /dev/null
+++ b/lib/std/io/tty.zig
@@ -0,0 +1,121 @@
+const std = @import("std");
+const builtin = @import("builtin");
+const File = std.fs.File;
+const process = std.process;
+const windows = std.os.windows;
+const native_os = builtin.os.tag;
+
+/// Detect suitable TTY configuration options for the given file (commonly stdout/stderr).
+/// This includes feature checks for ANSI escape codes and the Windows console API, as well as
+/// respecting the `NO_COLOR` environment variable.
+pub fn detectConfig(file: File) Config {
+    if (builtin.os.tag == .wasi) {
+        // Per https://github.com/WebAssembly/WASI/issues/162 ANSI codes
+        // aren't currently supported.
+        return .no_color;
+    } else if (process.hasEnvVarConstant("ZIG_DEBUG_COLOR")) {
+        return .escape_codes;
+    } else if (process.hasEnvVarConstant("NO_COLOR")) {
+        return .no_color;
+    } else if (file.supportsAnsiEscapeCodes()) {
+        return .escape_codes;
+    } else if (native_os == .windows and file.isTty()) {
+        var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
+        if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE) {
+            // TODO: Should this return an error instead?
+            return .no_color;
+        }
+        return .{ .windows_api = .{
+            .handle = file.handle,
+            .reset_attributes = info.wAttributes,
+        } };
+    }
+    return .no_color;
+}
+
+pub const Color = enum {
+    red,
+    green,
+    yellow,
+    cyan,
+    white,
+    dim,
+    bold,
+    reset,
+};
+
+/// Provides simple functionality for manipulating the terminal in some way,
+/// such as coloring text, etc.
+pub const Config = union(enum) {
+    no_color,
+    escape_codes,
+    windows_api: if (native_os == .windows) WindowsContext else void,
+
+    pub const WindowsContext = struct {
+        handle: File.Handle,
+        reset_attributes: u16,
+    };
+
+    pub fn setColor(conf: Config, out_stream: anytype, color: Color) !void {
+        nosuspend switch (conf) {
+            .no_color => return,
+            .escape_codes => {
+                const color_string = switch (color) {
+                    .red => "\x1b[31;1m",
+                    .green => "\x1b[32;1m",
+                    .yellow => "\x1b[33;1m",
+                    .cyan => "\x1b[36;1m",
+                    .white => "\x1b[37;1m",
+                    .bold => "\x1b[1m",
+                    .dim => "\x1b[2m",
+                    .reset => "\x1b[0m",
+                };
+                try out_stream.writeAll(color_string);
+            },
+            .windows_api => |ctx| if (native_os == .windows) {
+                const attributes = switch (color) {
+                    .red => windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY,
+                    .green => windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY,
+                    .yellow => windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY,
+                    .cyan => windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY,
+                    .white, .bold => windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY,
+                    .dim => windows.FOREGROUND_INTENSITY,
+                    .reset => ctx.reset_attributes,
+                };
+                try windows.SetConsoleTextAttribute(ctx.handle, attributes);
+            } else {
+                unreachable;
+            },
+        };
+    }
+
+    pub fn writeDEC(conf: Config, writer: anytype, codepoint: u8) !void {
+        const bytes = switch (conf) {
+            .no_color, .windows_api => switch (codepoint) {
+                0x50...0x5e => @as(*const [1]u8, &codepoint),
+                0x6a => "+", // ┘
+                0x6b => "+", // ┐
+                0x6c => "+", // ┌
+                0x6d => "+", // └
+                0x6e => "+", // ┼
+                0x71 => "-", // ─
+                0x74 => "+", // ├
+                0x75 => "+", // ┤
+                0x76 => "+", // ┴
+                0x77 => "+", // ┬
+                0x78 => "|", // │
+                else => " ", // TODO
+            },
+            .escape_codes => switch (codepoint) {
+                // Here we avoid writing the DEC beginning sequence and
+                // ending sequence in separate syscalls by putting the
+                // beginning and ending sequence into the same string
+                // literals, to prevent terminals ending up in bad states
+                // in case a crash happens between syscalls.
+                inline 0x50...0x7f => |x| "\x1B\x28\x30" ++ [1]u8{x} ++ "\x1B\x28\x42",
+                else => unreachable,
+            },
+        };
+        return writer.writeAll(bytes);
+    }
+};
diff --git a/lib/std/testing.zig b/lib/std/testing.zig
index 8576ec0c83..7986c50eaf 100644
--- a/lib/std/testing.zig
+++ b/lib/std/testing.zig
@@ -279,7 +279,7 @@ test "expectApproxEqRel" {
 /// This function is intended to be used only in tests. When the two slices are not
 /// equal, prints diagnostics to stderr to show exactly how they are not equal (with
 /// the differences highlighted in red), then returns a test failure error.
-/// The colorized output is optional and controlled by the return of `std.debug.detectTTYConfig()`.
+/// The colorized output is optional and controlled by the return of `std.io.tty.detectConfig()`.
 /// If your inputs are UTF-8 encoded strings, consider calling `expectEqualStrings` instead.
 pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const T) !void {
     if (expected.ptr == actual.ptr and expected.len == actual.len) {
@@ -312,7 +312,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
     const actual_window = actual[window_start..@min(actual.len, window_start + max_window_size)];
     const actual_truncated = window_start + actual_window.len < actual.len;
 
-    const ttyconf = std.debug.detectTTYConfig(std.io.getStdErr());
+    const ttyconf = std.io.tty.detectConfig(std.io.getStdErr());
     var differ = if (T == u8) BytesDiffer{
         .expected = expected_window,
         .actual = actual_window,
@@ -379,7 +379,7 @@ fn SliceDiffer(comptime T: type) type {
         start_index: usize,
         expected: []const T,
         actual: []const T,
-        ttyconf: std.debug.TTY.Config,
+        ttyconf: std.io.tty.Config,
 
         const Self = @This();
 
@@ -398,7 +398,7 @@ fn SliceDiffer(comptime T: type) type {
 const BytesDiffer = struct {
     expected: []const u8,
     actual: []const u8,
-    ttyconf: std.debug.TTY.Config,
+    ttyconf: std.io.tty.Config,
 
     pub fn write(self: BytesDiffer, writer: anytype) !void {
         var expected_iterator = ChunkIterator{ .bytes = self.expected };
diff --git a/lib/std/zig/ErrorBundle.zig b/lib/std/zig/ErrorBundle.zig
index f74d82273a..46b5799807 100644
--- a/lib/std/zig/ErrorBundle.zig
+++ b/lib/std/zig/ErrorBundle.zig
@@ -148,7 +148,7 @@ pub fn nullTerminatedString(eb: ErrorBundle, index: usize) [:0]const u8 {
 }
 
 pub const RenderOptions = struct {
-    ttyconf: std.debug.TTY.Config,
+    ttyconf: std.io.tty.Config,
     include_reference_trace: bool = true,
     include_source_line: bool = true,
     include_log_text: bool = true,
@@ -181,7 +181,7 @@ fn renderErrorMessageToWriter(
     err_msg_index: MessageIndex,
     stderr: anytype,
     kind: []const u8,
-    color: std.debug.TTY.Color,
+    color: std.io.tty.Color,
     indent: usize,
 ) anyerror!void {
     const ttyconf = options.ttyconf;
diff --git a/src/main.zig b/src/main.zig
index 650741e5e4..afda88cebd 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -6044,9 +6044,9 @@ const ClangSearchSanitizer = struct {
     };
 };
 
-fn get_tty_conf(color: Color) std.debug.TTY.Config {
+fn get_tty_conf(color: Color) std.io.tty.Config {
     return switch (color) {
-        .auto => std.debug.detectTTYConfig(std.io.getStdErr()),
+        .auto => std.io.tty.detectConfig(std.io.getStdErr()),
         .on => .escape_codes,
         .off => .no_color,
     };
diff --git a/test/src/Cases.zig b/test/src/Cases.zig
index 63dd2fd3da..08568d0dd6 100644
--- a/test/src/Cases.zig
+++ b/test/src/Cases.zig
@@ -1354,7 +1354,7 @@ fn runOneCase(
             defer all_errors.deinit(allocator);
             if (all_errors.errorMessageCount() > 0) {
                 all_errors.renderToStdErr(.{
-                    .ttyconf = std.debug.detectTTYConfig(std.io.getStdErr()),
+                    .ttyconf = std.io.tty.detectConfig(std.io.getStdErr()),
                 });
                 // TODO print generated C code
                 return error.UnexpectedCompileErrors;
-- 
cgit v1.2.3


From 4159add4abe92e903d8797a005344d8325def2fc Mon Sep 17 00:00:00 2001
From: Linus Groh 
Date: Sat, 20 May 2023 23:06:42 +0100
Subject: std.fs.file: Rename File.Kind enum values to snake case

---
 lib/std/Build/Step/InstallDir.zig     |   4 +-
 lib/std/crypto/Certificate/Bundle.zig |   2 +-
 lib/std/fs.zig                        | 132 +++++++++++++++++-----------------
 lib/std/fs/file.zig                   | 120 +++++++++++++++----------------
 lib/std/fs/test.zig                   |  20 +++---
 src/Package.zig                       |   4 +-
 src/main.zig                          |   6 +-
 test/src/Cases.zig                    |   4 +-
 tools/process_headers.zig             |   4 +-
 tools/update-linux-headers.zig        |   4 +-
 tools/update_glibc.zig                |   4 +-
 tools/update_spirv_features.zig       |   2 +-
 12 files changed, 153 insertions(+), 153 deletions(-)

(limited to 'src/main.zig')

diff --git a/lib/std/Build/Step/InstallDir.zig b/lib/std/Build/Step/InstallDir.zig
index 28280dcb7f..597601ce4e 100644
--- a/lib/std/Build/Step/InstallDir.zig
+++ b/lib/std/Build/Step/InstallDir.zig
@@ -80,8 +80,8 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
         const cwd = fs.cwd();
 
         switch (entry.kind) {
-            .Directory => try cwd.makePath(dest_path),
-            .File => {
+            .directory => try cwd.makePath(dest_path),
+            .file => {
                 for (self.options.blank_extensions) |ext| {
                     if (mem.endsWith(u8, entry.path, ext)) {
                         try dest_builder.truncateFile(dest_path);
diff --git a/lib/std/crypto/Certificate/Bundle.zig b/lib/std/crypto/Certificate/Bundle.zig
index fe1ef4c0c3..434de6e0a8 100644
--- a/lib/std/crypto/Certificate/Bundle.zig
+++ b/lib/std/crypto/Certificate/Bundle.zig
@@ -169,7 +169,7 @@ pub fn addCertsFromDir(cb: *Bundle, gpa: Allocator, iterable_dir: fs.IterableDir
     var it = iterable_dir.iterate();
     while (try it.next()) |entry| {
         switch (entry.kind) {
-            .File, .SymLink => {},
+            .file, .sym_link => {},
             else => continue,
         }
 
diff --git a/lib/std/fs.zig b/lib/std/fs.zig
index 041e49d549..496dbf5f0a 100644
--- a/lib/std/fs.zig
+++ b/lib/std/fs.zig
@@ -385,16 +385,16 @@ pub const IterableDir = struct {
                         continue :start_over;
                     }
 
-                    const entry_kind = switch (darwin_entry.d_type) {
-                        os.DT.BLK => Entry.Kind.BlockDevice,
-                        os.DT.CHR => Entry.Kind.CharacterDevice,
-                        os.DT.DIR => Entry.Kind.Directory,
-                        os.DT.FIFO => Entry.Kind.NamedPipe,
-                        os.DT.LNK => Entry.Kind.SymLink,
-                        os.DT.REG => Entry.Kind.File,
-                        os.DT.SOCK => Entry.Kind.UnixDomainSocket,
-                        os.DT.WHT => Entry.Kind.Whiteout,
-                        else => Entry.Kind.Unknown,
+                    const entry_kind: Entry.Kind = switch (darwin_entry.d_type) {
+                        os.DT.BLK => .block_device,
+                        os.DT.CHR => .character_device,
+                        os.DT.DIR => .directory,
+                        os.DT.FIFO => .named_pipe,
+                        os.DT.LNK => .sym_link,
+                        os.DT.REG => .file,
+                        os.DT.SOCK => .unix_domain_socket,
+                        os.DT.WHT => .whiteout,
+                        else => .unknown,
                     };
                     return Entry{
                         .name = name,
@@ -442,17 +442,17 @@ pub const IterableDir = struct {
                         error.FileNotFound => unreachable, // lost the race
                         else => |e| return e,
                     };
-                    const entry_kind = switch (stat_info.mode & os.S.IFMT) {
-                        os.S.IFIFO => Entry.Kind.NamedPipe,
-                        os.S.IFCHR => Entry.Kind.CharacterDevice,
-                        os.S.IFDIR => Entry.Kind.Directory,
-                        os.S.IFBLK => Entry.Kind.BlockDevice,
-                        os.S.IFREG => Entry.Kind.File,
-                        os.S.IFLNK => Entry.Kind.SymLink,
-                        os.S.IFSOCK => Entry.Kind.UnixDomainSocket,
-                        os.S.IFDOOR => Entry.Kind.Door,
-                        os.S.IFPORT => Entry.Kind.EventPort,
-                        else => Entry.Kind.Unknown,
+                    const entry_kind: Entry.Kind = switch (stat_info.mode & os.S.IFMT) {
+                        os.S.IFIFO => .named_pipe,
+                        os.S.IFCHR => .character_device,
+                        os.S.IFDIR => .directory,
+                        os.S.IFBLK => .block_device,
+                        os.S.IFREG => .file,
+                        os.S.IFLNK => .sym_link,
+                        os.S.IFSOCK => .unix_domain_socket,
+                        os.S.IFDOOR => .door,
+                        os.S.IFPORT => .event_port,
+                        else => .unknown,
                     };
                     return Entry{
                         .name = name,
@@ -501,16 +501,16 @@ pub const IterableDir = struct {
                         continue :start_over;
                     }
 
-                    const entry_kind = switch (bsd_entry.d_type) {
-                        os.DT.BLK => Entry.Kind.BlockDevice,
-                        os.DT.CHR => Entry.Kind.CharacterDevice,
-                        os.DT.DIR => Entry.Kind.Directory,
-                        os.DT.FIFO => Entry.Kind.NamedPipe,
-                        os.DT.LNK => Entry.Kind.SymLink,
-                        os.DT.REG => Entry.Kind.File,
-                        os.DT.SOCK => Entry.Kind.UnixDomainSocket,
-                        os.DT.WHT => Entry.Kind.Whiteout,
-                        else => Entry.Kind.Unknown,
+                    const entry_kind: Entry.Kind = switch (bsd_entry.d_type) {
+                        os.DT.BLK => .block_device,
+                        os.DT.CHR => .character_device,
+                        os.DT.DIR => .directory,
+                        os.DT.FIFO => .named_pipe,
+                        os.DT.LNK => .sym_link,
+                        os.DT.REG => .file,
+                        os.DT.SOCK => .unix_domain_socket,
+                        os.DT.WHT => .whiteout,
+                        else => .unknown,
                     };
                     return Entry{
                         .name = name,
@@ -595,14 +595,14 @@ pub const IterableDir = struct {
                     }
                     const statmode = stat_info.mode & os.S.IFMT;
 
-                    const entry_kind = switch (statmode) {
-                        os.S.IFDIR => Entry.Kind.Directory,
-                        os.S.IFBLK => Entry.Kind.BlockDevice,
-                        os.S.IFCHR => Entry.Kind.CharacterDevice,
-                        os.S.IFLNK => Entry.Kind.SymLink,
-                        os.S.IFREG => Entry.Kind.File,
-                        os.S.IFIFO => Entry.Kind.NamedPipe,
-                        else => Entry.Kind.Unknown,
+                    const entry_kind: Entry.Kind = switch (statmode) {
+                        os.S.IFDIR => .directory,
+                        os.S.IFBLK => .block_device,
+                        os.S.IFCHR => .character_device,
+                        os.S.IFLNK => .sym_link,
+                        os.S.IFREG => .file,
+                        os.S.IFIFO => .named_pipe,
+                        else => .unknown,
                     };
 
                     return Entry{
@@ -679,15 +679,15 @@ pub const IterableDir = struct {
                         continue :start_over;
                     }
 
-                    const entry_kind = switch (linux_entry.d_type) {
-                        linux.DT.BLK => Entry.Kind.BlockDevice,
-                        linux.DT.CHR => Entry.Kind.CharacterDevice,
-                        linux.DT.DIR => Entry.Kind.Directory,
-                        linux.DT.FIFO => Entry.Kind.NamedPipe,
-                        linux.DT.LNK => Entry.Kind.SymLink,
-                        linux.DT.REG => Entry.Kind.File,
-                        linux.DT.SOCK => Entry.Kind.UnixDomainSocket,
-                        else => Entry.Kind.Unknown,
+                    const entry_kind: Entry.Kind = switch (linux_entry.d_type) {
+                        linux.DT.BLK => .block_device,
+                        linux.DT.CHR => .character_device,
+                        linux.DT.DIR => .directory,
+                        linux.DT.FIFO => .named_pipe,
+                        linux.DT.LNK => .sym_link,
+                        linux.DT.REG => .file,
+                        linux.DT.SOCK => .unix_domain_socket,
+                        else => .unknown,
                     };
                     return Entry{
                         .name = name,
@@ -761,11 +761,11 @@ pub const IterableDir = struct {
                     // Trust that Windows gives us valid UTF-16LE
                     const name_utf8_len = std.unicode.utf16leToUtf8(self.name_data[0..], name_utf16le) catch unreachable;
                     const name_utf8 = self.name_data[0..name_utf8_len];
-                    const kind = blk: {
+                    const kind: Entry.Kind = blk: {
                         const attrs = dir_info.FileAttributes;
-                        if (attrs & w.FILE_ATTRIBUTE_DIRECTORY != 0) break :blk Entry.Kind.Directory;
-                        if (attrs & w.FILE_ATTRIBUTE_REPARSE_POINT != 0) break :blk Entry.Kind.SymLink;
-                        break :blk Entry.Kind.File;
+                        if (attrs & w.FILE_ATTRIBUTE_DIRECTORY != 0) break :blk .directory;
+                        if (attrs & w.FILE_ATTRIBUTE_REPARSE_POINT != 0) break :blk .sym_link;
+                        break :blk .file;
                     };
                     return Entry{
                         .name = name_utf8,
@@ -850,14 +850,14 @@ pub const IterableDir = struct {
                         continue :start_over;
                     }
 
-                    const entry_kind = switch (entry.d_type) {
-                        .BLOCK_DEVICE => Entry.Kind.BlockDevice,
-                        .CHARACTER_DEVICE => Entry.Kind.CharacterDevice,
-                        .DIRECTORY => Entry.Kind.Directory,
-                        .SYMBOLIC_LINK => Entry.Kind.SymLink,
-                        .REGULAR_FILE => Entry.Kind.File,
-                        .SOCKET_STREAM, .SOCKET_DGRAM => Entry.Kind.UnixDomainSocket,
-                        else => Entry.Kind.Unknown,
+                    const entry_kind: Entry.Kind = switch (entry.d_type) {
+                        .BLOCK_DEVICE => .block_device,
+                        .CHARACTER_DEVICE => .character_device,
+                        .DIRECTORY => .directory,
+                        .SYMBOLIC_LINK => .sym_link,
+                        .REGULAR_FILE => .file,
+                        .SOCKET_STREAM, .SOCKET_DGRAM => .unix_domain_socket,
+                        else => .unknown,
                     };
                     return Entry{
                         .name = name,
@@ -964,7 +964,7 @@ pub const IterableDir = struct {
                         dirname_len += 1;
                     }
                     try self.name_buffer.appendSlice(base.name);
-                    if (base.kind == .Directory) {
+                    if (base.kind == .directory) {
                         var new_dir = top.iter.dir.openIterableDir(base.name, .{}) catch |err| switch (err) {
                             error.NameTooLong => unreachable, // no path sep in base.name
                             else => |e| return e,
@@ -2106,7 +2106,7 @@ pub const Dir = struct {
     /// this function recursively removes its entries and then tries again.
     /// This operation is not atomic on most file systems.
     pub fn deleteTree(self: Dir, sub_path: []const u8) DeleteTreeError!void {
-        var initial_iterable_dir = (try self.deleteTreeOpenInitialSubpath(sub_path, .File)) orelse return;
+        var initial_iterable_dir = (try self.deleteTreeOpenInitialSubpath(sub_path, .file)) orelse return;
 
         const StackItem = struct {
             name: []const u8,
@@ -2130,7 +2130,7 @@ pub const Dir = struct {
         process_stack: while (stack.len != 0) {
             var top = &(stack.slice()[stack.len - 1]);
             while (try top.iter.next()) |entry| {
-                var treat_as_dir = entry.kind == .Directory;
+                var treat_as_dir = entry.kind == .directory;
                 handle_entry: while (true) {
                     if (treat_as_dir) {
                         if (stack.ensureUnusedCapacity(1)) {
@@ -2291,7 +2291,7 @@ pub const Dir = struct {
     /// Like `deleteTree`, but only keeps one `Iterator` active at a time to minimize the function's stack size.
     /// This is slower than `deleteTree` but uses less stack space.
     pub fn deleteTreeMinStackSize(self: Dir, sub_path: []const u8) DeleteTreeError!void {
-        return self.deleteTreeMinStackSizeWithKindHint(sub_path, .File);
+        return self.deleteTreeMinStackSizeWithKindHint(sub_path, .file);
     }
 
     fn deleteTreeMinStackSizeWithKindHint(self: Dir, sub_path: []const u8, kind_hint: File.Kind) DeleteTreeError!void {
@@ -2316,7 +2316,7 @@ pub const Dir = struct {
             scan_dir: while (true) {
                 var dir_it = iterable_dir.iterateAssumeFirstIteration();
                 dir_it: while (try dir_it.next()) |entry| {
-                    var treat_as_dir = entry.kind == .Directory;
+                    var treat_as_dir = entry.kind == .directory;
                     handle_entry: while (true) {
                         if (treat_as_dir) {
                             const new_dir = iterable_dir.dir.openIterableDir(entry.name, .{ .no_follow = true }) catch |err| switch (err) {
@@ -2407,7 +2407,7 @@ pub const Dir = struct {
     fn deleteTreeOpenInitialSubpath(self: Dir, sub_path: []const u8, kind_hint: File.Kind) !?IterableDir {
         return iterable_dir: {
             // Treat as a file by default
-            var treat_as_dir = kind_hint == .Directory;
+            var treat_as_dir = kind_hint == .directory;
 
             handle_entry: while (true) {
                 if (treat_as_dir) {
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig
index 23021a26f5..83db10ef32 100644
--- a/lib/std/fs/file.zig
+++ b/lib/std/fs/file.zig
@@ -35,17 +35,17 @@ pub const File = struct {
     pub const Gid = os.gid_t;
 
     pub const Kind = enum {
-        BlockDevice,
-        CharacterDevice,
-        Directory,
-        NamedPipe,
-        SymLink,
-        File,
-        UnixDomainSocket,
-        Whiteout,
-        Door,
-        EventPort,
-        Unknown,
+        block_device,
+        character_device,
+        directory,
+        named_pipe,
+        sym_link,
+        file,
+        unix_domain_socket,
+        whiteout,
+        door,
+        event_port,
+        unknown,
     };
 
     /// This is the default mode given to POSIX operating systems for creating
@@ -329,32 +329,32 @@ pub const File = struct {
             const mtime = st.mtime();
             const ctime = st.ctime();
             const kind: Kind = if (builtin.os.tag == .wasi and !builtin.link_libc) switch (st.filetype) {
-                .BLOCK_DEVICE => Kind.BlockDevice,
-                .CHARACTER_DEVICE => Kind.CharacterDevice,
-                .DIRECTORY => Kind.Directory,
-                .SYMBOLIC_LINK => Kind.SymLink,
-                .REGULAR_FILE => Kind.File,
-                .SOCKET_STREAM, .SOCKET_DGRAM => Kind.UnixDomainSocket,
-                else => Kind.Unknown,
+                .BLOCK_DEVICE => .block_device,
+                .CHARACTER_DEVICE => .character_device,
+                .DIRECTORY => .directory,
+                .SYMBOLIC_LINK => .sym_link,
+                .REGULAR_FILE => .file,
+                .SOCKET_STREAM, .SOCKET_DGRAM => .unix_domain_socket,
+                else => .unknown,
             } else blk: {
                 const m = st.mode & os.S.IFMT;
                 switch (m) {
-                    os.S.IFBLK => break :blk Kind.BlockDevice,
-                    os.S.IFCHR => break :blk Kind.CharacterDevice,
-                    os.S.IFDIR => break :blk Kind.Directory,
-                    os.S.IFIFO => break :blk Kind.NamedPipe,
-                    os.S.IFLNK => break :blk Kind.SymLink,
-                    os.S.IFREG => break :blk Kind.File,
-                    os.S.IFSOCK => break :blk Kind.UnixDomainSocket,
+                    os.S.IFBLK => break :blk .block_device,
+                    os.S.IFCHR => break :blk .character_device,
+                    os.S.IFDIR => break :blk .directory,
+                    os.S.IFIFO => break :blk .named_pipe,
+                    os.S.IFLNK => break :blk .sym_link,
+                    os.S.IFREG => break :blk .file,
+                    os.S.IFSOCK => break :blk .unix_domain_socket,
                     else => {},
                 }
                 if (builtin.os.tag == .solaris) switch (m) {
-                    os.S.IFDOOR => break :blk Kind.Door,
-                    os.S.IFPORT => break :blk Kind.EventPort,
+                    os.S.IFDOOR => break :blk .door,
+                    os.S.IFPORT => break :blk .event_port,
                     else => {},
                 };
 
-                break :blk .Unknown;
+                break :blk .unknown;
             };
 
             return Stat{
@@ -391,7 +391,7 @@ pub const File = struct {
                 .inode = info.InternalInformation.IndexNumber,
                 .size = @bitCast(u64, info.StandardInformation.EndOfFile),
                 .mode = 0,
-                .kind = if (info.StandardInformation.Directory == 0) .File else .Directory,
+                .kind = if (info.StandardInformation.Directory == 0) .file else .directory,
                 .atime = windows.fromSysTime(info.BasicInformation.LastAccessTime),
                 .mtime = windows.fromSysTime(info.BasicInformation.LastWriteTime),
                 .ctime = windows.fromSysTime(info.BasicInformation.CreationTime),
@@ -609,7 +609,7 @@ pub const File = struct {
         }
 
         /// Returns the `Kind` of file.
-        /// On Windows, can only return: `.File`, `.Directory`, `.SymLink` or `.Unknown`
+        /// On Windows, can only return: `.file`, `.directory`, `.sym_link` or `.unknown`
         pub fn kind(self: Self) Kind {
             return self.inner.kind();
         }
@@ -652,35 +652,35 @@ pub const File = struct {
         /// Returns the `Kind` of the file
         pub fn kind(self: Self) Kind {
             if (builtin.os.tag == .wasi and !builtin.link_libc) return switch (self.stat.filetype) {
-                .BLOCK_DEVICE => Kind.BlockDevice,
-                .CHARACTER_DEVICE => Kind.CharacterDevice,
-                .DIRECTORY => Kind.Directory,
-                .SYMBOLIC_LINK => Kind.SymLink,
-                .REGULAR_FILE => Kind.File,
-                .SOCKET_STREAM, .SOCKET_DGRAM => Kind.UnixDomainSocket,
-                else => Kind.Unknown,
+                .BLOCK_DEVICE => .block_device,
+                .CHARACTER_DEVICE => .character_device,
+                .DIRECTORY => .directory,
+                .SYMBOLIC_LINK => .sym_link,
+                .REGULAR_FILE => .file,
+                .SOCKET_STREAM, .SOCKET_DGRAM => .unix_domain_socket,
+                else => .unknown,
             };
 
             const m = self.stat.mode & os.S.IFMT;
 
             switch (m) {
-                os.S.IFBLK => return Kind.BlockDevice,
-                os.S.IFCHR => return Kind.CharacterDevice,
-                os.S.IFDIR => return Kind.Directory,
-                os.S.IFIFO => return Kind.NamedPipe,
-                os.S.IFLNK => return Kind.SymLink,
-                os.S.IFREG => return Kind.File,
-                os.S.IFSOCK => return Kind.UnixDomainSocket,
+                os.S.IFBLK => return .block_device,
+                os.S.IFCHR => return .character_device,
+                os.S.IFDIR => return .directory,
+                os.S.IFIFO => return .named_pipe,
+                os.S.IFLNK => return .sym_link,
+                os.S.IFREG => return .file,
+                os.S.IFSOCK => return .unix_domain_socket,
                 else => {},
             }
 
             if (builtin.os.tag == .solaris) switch (m) {
-                os.S.IFDOOR => return Kind.Door,
-                os.S.IFPORT => return Kind.EventPort,
+                os.S.IFDOOR => return .door,
+                os.S.IFPORT => return .event_port,
                 else => {},
             };
 
-            return .Unknown;
+            return .unknown;
         }
 
         /// Returns the last time the file was accessed in nanoseconds since UTC 1970-01-01
@@ -738,17 +738,17 @@ pub const File = struct {
             const m = self.statx.mode & os.S.IFMT;
 
             switch (m) {
-                os.S.IFBLK => return Kind.BlockDevice,
-                os.S.IFCHR => return Kind.CharacterDevice,
-                os.S.IFDIR => return Kind.Directory,
-                os.S.IFIFO => return Kind.NamedPipe,
-                os.S.IFLNK => return Kind.SymLink,
-                os.S.IFREG => return Kind.File,
-                os.S.IFSOCK => return Kind.UnixDomainSocket,
+                os.S.IFBLK => return .block_device,
+                os.S.IFCHR => return .character_device,
+                os.S.IFDIR => return .directory,
+                os.S.IFIFO => return .named_pipe,
+                os.S.IFLNK => return .sym_link,
+                os.S.IFREG => return .file,
+                os.S.IFSOCK => return .unix_domain_socket,
                 else => {},
             }
 
-            return .Unknown;
+            return .unknown;
         }
 
         /// Returns the last time the file was accessed in nanoseconds since UTC 1970-01-01
@@ -790,18 +790,18 @@ pub const File = struct {
         }
 
         /// Returns the `Kind` of the file.
-        /// Can only return: `.File`, `.Directory`, `.SymLink` or `.Unknown`
+        /// Can only return: `.file`, `.directory`, `.sym_link` or `.unknown`
         pub fn kind(self: Self) Kind {
             if (self.attributes & windows.FILE_ATTRIBUTE_REPARSE_POINT != 0) {
                 if (self.reparse_tag & 0x20000000 != 0) {
-                    return .SymLink;
+                    return .sym_link;
                 }
             } else if (self.attributes & windows.FILE_ATTRIBUTE_DIRECTORY != 0) {
-                return .Directory;
+                return .directory;
             } else {
-                return .File;
+                return .file;
             }
-            return .Unknown;
+            return .unknown;
         }
 
         /// Returns the last time the file was accessed in nanoseconds since UTC 1970-01-01
diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig
index 15c8307f58..16677007f9 100644
--- a/lib/std/fs/test.zig
+++ b/lib/std/fs/test.zig
@@ -179,8 +179,8 @@ test "Dir.Iterator" {
     }
 
     try testing.expect(entries.items.len == 2); // note that the Iterator skips '.' and '..'
-    try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .File }));
-    try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .Directory }));
+    try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file }));
+    try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .directory }));
 }
 
 test "Dir.Iterator many entries" {
@@ -214,7 +214,7 @@ test "Dir.Iterator many entries" {
     i = 0;
     while (i < num) : (i += 1) {
         const name = try std.fmt.bufPrint(&buf, "{}", .{i});
-        try testing.expect(contains(&entries, .{ .name = name, .kind = .File }));
+        try testing.expect(contains(&entries, .{ .name = name, .kind = .file }));
     }
 }
 
@@ -246,8 +246,8 @@ test "Dir.Iterator twice" {
         }
 
         try testing.expect(entries.items.len == 2); // note that the Iterator skips '.' and '..'
-        try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .File }));
-        try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .Directory }));
+        try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file }));
+        try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .directory }));
     }
 }
 
@@ -280,8 +280,8 @@ test "Dir.Iterator reset" {
         }
 
         try testing.expect(entries.items.len == 2); // note that the Iterator skips '.' and '..'
-        try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .File }));
-        try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .Directory }));
+        try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file }));
+        try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .directory }));
 
         iter.reset();
     }
@@ -428,7 +428,7 @@ test "directory operations on files" {
     // ensure the file still exists and is a file as a sanity check
     file = try tmp_dir.dir.openFile(test_file_name, .{});
     const stat = try file.stat();
-    try testing.expect(stat.kind == .File);
+    try testing.expect(stat.kind == .file);
     file.close();
 }
 
@@ -664,7 +664,7 @@ test "renameAbsolute" {
     try testing.expectError(error.FileNotFound, tmp_dir.dir.openFile(test_file_name, .{}));
     file = try tmp_dir.dir.openFile(renamed_test_file_name, .{});
     const stat = try file.stat();
-    try testing.expect(stat.kind == .File);
+    try testing.expect(stat.kind == .file);
     file.close();
 
     // Renaming directories
@@ -1348,7 +1348,7 @@ test "File.Metadata" {
     defer file.close();
 
     const metadata = try file.metadata();
-    try testing.expect(metadata.kind() == .File);
+    try testing.expect(metadata.kind() == .file);
     try testing.expect(metadata.size() == 0);
     _ = metadata.accessed();
     _ = metadata.modified();
diff --git a/src/Package.zig b/src/Package.zig
index d3ac71af1a..532439c60c 100644
--- a/src/Package.zig
+++ b/src/Package.zig
@@ -651,8 +651,8 @@ fn computePackageHash(
 
         while (try walker.next()) |entry| {
             switch (entry.kind) {
-                .Directory => continue,
-                .File => {},
+                .directory => continue,
+                .file => {},
                 else => return error.IllegalFileTypeInPackage,
             }
             const hashed_file = try arena.create(HashedFile);
diff --git a/src/main.zig b/src/main.zig
index afda88cebd..f7afbe767b 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -4830,11 +4830,11 @@ fn fmtPathDir(
 
     var dir_it = iterable_dir.iterate();
     while (try dir_it.next()) |entry| {
-        const is_dir = entry.kind == .Directory;
+        const is_dir = entry.kind == .directory;
 
         if (is_dir and (mem.eql(u8, entry.name, "zig-cache") or mem.eql(u8, entry.name, "zig-out"))) continue;
 
-        if (is_dir or entry.kind == .File and (mem.endsWith(u8, entry.name, ".zig") or mem.endsWith(u8, entry.name, ".zon"))) {
+        if (is_dir or entry.kind == .file and (mem.endsWith(u8, entry.name, ".zig") or mem.endsWith(u8, entry.name, ".zon"))) {
             const full_path = try fs.path.join(fmt.gpa, &[_][]const u8{ file_path, entry.name });
             defer fmt.gpa.free(full_path);
 
@@ -4864,7 +4864,7 @@ fn fmtPathFile(
 
     const stat = try source_file.stat();
 
-    if (stat.kind == .Directory)
+    if (stat.kind == .directory)
         return error.IsDir;
 
     const gpa = fmt.gpa;
diff --git a/test/src/Cases.zig b/test/src/Cases.zig
index e4f3d532ce..589438297d 100644
--- a/test/src/Cases.zig
+++ b/test/src/Cases.zig
@@ -349,7 +349,7 @@ fn addFromDirInner(
     var filenames = std.ArrayList([]const u8).init(ctx.arena);
 
     while (try it.next()) |entry| {
-        if (entry.kind != .File) continue;
+        if (entry.kind != .file) continue;
 
         // Ignore stuff such as .swp files
         switch (Compilation.classifyFileExt(entry.basename)) {
@@ -1039,7 +1039,7 @@ pub fn main() !void {
         const stem = case_file_path[case_dirname.len + 1 .. case_file_path.len - "0.zig".len];
         var it = iterable_dir.iterate();
         while (try it.next()) |entry| {
-            if (entry.kind != .File) continue;
+            if (entry.kind != .file) continue;
             if (!std.mem.startsWith(u8, entry.name, stem)) continue;
             try filenames.append(try std.fs.path.join(arena, &.{ case_dirname, entry.name }));
         }
diff --git a/tools/process_headers.zig b/tools/process_headers.zig
index 0321c0e0eb..b93cd07a2c 100644
--- a/tools/process_headers.zig
+++ b/tools/process_headers.zig
@@ -393,8 +393,8 @@ pub fn main() !void {
                 while (try dir_it.next()) |entry| {
                     const full_path = try std.fs.path.join(allocator, &[_][]const u8{ full_dir_name, entry.name });
                     switch (entry.kind) {
-                        .Directory => try dir_stack.append(full_path),
-                        .File => {
+                        .directory => try dir_stack.append(full_path),
+                        .file => {
                             const rel_path = try std.fs.path.relative(allocator, target_include_dir, full_path);
                             const max_size = 2 * 1024 * 1024 * 1024;
                             const raw_bytes = try std.fs.cwd().readFileAlloc(allocator, full_path, max_size);
diff --git a/tools/update-linux-headers.zig b/tools/update-linux-headers.zig
index 0f31e5e893..d20bc8dd11 100644
--- a/tools/update-linux-headers.zig
+++ b/tools/update-linux-headers.zig
@@ -193,8 +193,8 @@ pub fn main() !void {
                 while (try dir_it.next()) |entry| {
                     const full_path = try std.fs.path.join(arena, &[_][]const u8{ full_dir_name, entry.name });
                     switch (entry.kind) {
-                        .Directory => try dir_stack.append(full_path),
-                        .File => {
+                        .directory => try dir_stack.append(full_path),
+                        .file => {
                             const rel_path = try std.fs.path.relative(arena, target_include_dir, full_path);
                             const max_size = 2 * 1024 * 1024 * 1024;
                             const raw_bytes = try std.fs.cwd().readFileAlloc(arena, full_path, max_size);
diff --git a/tools/update_glibc.zig b/tools/update_glibc.zig
index 24b0f45de7..dcc797f59f 100644
--- a/tools/update_glibc.zig
+++ b/tools/update_glibc.zig
@@ -57,7 +57,7 @@ pub fn main() !void {
         defer walker.deinit();
 
         walk: while (try walker.next()) |entry| {
-            if (entry.kind != .File) continue;
+            if (entry.kind != .file) continue;
             if (mem.startsWith(u8, entry.basename, ".")) continue;
             for (exempt_files) |p| {
                 if (mem.eql(u8, entry.path, p)) continue :walk;
@@ -98,7 +98,7 @@ pub fn main() !void {
     defer walker.deinit();
 
     walk: while (try walker.next()) |entry| {
-        if (entry.kind != .File) continue;
+        if (entry.kind != .file) continue;
         if (mem.startsWith(u8, entry.basename, ".")) continue;
         for (exempt_files) |p| {
             if (mem.eql(u8, entry.path, p)) continue :walk;
diff --git a/tools/update_spirv_features.zig b/tools/update_spirv_features.zig
index 44d8b6a445..31bdf40ef7 100644
--- a/tools/update_spirv_features.zig
+++ b/tools/update_spirv_features.zig
@@ -227,7 +227,7 @@ fn gather_extensions(allocator: Allocator, spirv_registry_root: []const u8) ![]c
 
     var vendor_it = extensions_dir.iterate();
     while (try vendor_it.next()) |vendor_entry| {
-        std.debug.assert(vendor_entry.kind == .Directory); // If this fails, the structure of SPIRV-Registry has changed.
+        std.debug.assert(vendor_entry.kind == .directory); // If this fails, the structure of SPIRV-Registry has changed.
 
         const vendor_dir = try extensions_dir.dir.openIterableDir(vendor_entry.name, .{});
         var ext_it = vendor_dir.iterate();
-- 
cgit v1.2.3


From ac9f72d87e8eeb4a9d0dead80b61420485279ddd Mon Sep 17 00:00:00 2001
From: Motiejus Jakštys 
Date: Tue, 23 May 2023 10:50:15 +0300
Subject: zig ld: handle `--library :path/to/lib.so`

`-l :path/to/lib.so` behavior on gcc/clang is:

- the path is recorded as-is: no paths, exact filename (`libX.so.Y`).
- no rpaths.

The previous version removed the `:` and pretended it's a positional
argument to the linker. That works in almost all cases, except in how
rules_go[1] does things (the Bazel wrapper for Go).

Test case in #15743, output:

    gcc rpath:
     0x0000000000000001 (NEEDED)     Shared library: [libversioned.so.2]
     0x000000000000001d (RUNPATH)    Library runpath: [$ORIGIN/x]
    gcc plain:
     0x0000000000000001 (NEEDED)     Shared library: [libversioned.so.2]
    zig cc rpath:
     0x0000000000000001 (NEEDED)     Shared library: [libversioned.so.2]
     0x000000000000001d (RUNPATH)    Library runpath: [$ORIGIN/x]
    zig cc plain:
     0x0000000000000001 (NEEDED)     Shared library: [libversioned.so.2]

Fixes #15743

[1]: https://github.com/bazelbuild/rules_go
---
 src/Compilation.zig    | 10 ++++++++--
 src/link.zig           |  1 +
 src/link/Coff/lld.zig  |  2 +-
 src/link/Elf.zig       | 10 +++++++++-
 src/link/MachO/zld.zig |  2 +-
 src/link/Wasm.zig      |  4 ++--
 src/main.zig           | 43 ++++++-------------------------------------
 7 files changed, 28 insertions(+), 44 deletions(-)

(limited to 'src/main.zig')

diff --git a/src/Compilation.zig b/src/Compilation.zig
index cc2e2a916b..2ab9dde35c 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -451,6 +451,11 @@ pub const CacheMode = link.CacheMode;
 pub const LinkObject = struct {
     path: []const u8,
     must_link: bool = false,
+    // When the library is passed via a positional argument, it will be
+    // added as a full path. If it's `-l`, then just the basename.
+    //
+    // Consistent with `withLOption` variable name in lld ELF driver.
+    loption: bool = false,
 };
 
 pub const InitOptions = struct {
@@ -2196,7 +2201,7 @@ fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemo
 /// to remind the programmer to update multiple related pieces of code that
 /// are in different locations. Bump this number when adding or deleting
 /// anything from the link cache manifest.
-pub const link_hash_implementation_version = 8;
+pub const link_hash_implementation_version = 9;
 
 fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifest) !void {
     const gpa = comp.gpa;
@@ -2206,7 +2211,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
     defer arena_allocator.deinit();
     const arena = arena_allocator.allocator();
 
-    comptime assert(link_hash_implementation_version == 8);
+    comptime assert(link_hash_implementation_version == 9);
 
     if (comp.bin_file.options.module) |mod| {
         const main_zig_file = try mod.main_pkg.root_src_directory.join(arena, &[_][]const u8{
@@ -2244,6 +2249,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
     for (comp.bin_file.options.objects) |obj| {
         _ = try man.addFile(obj.path, null);
         man.hash.add(obj.must_link);
+        man.hash.add(obj.loption);
     }
 
     for (comp.c_object_table.keys()) |key| {
diff --git a/src/link.zig b/src/link.zig
index 79ac33b892..471b26ae9f 100644
--- a/src/link.zig
+++ b/src/link.zig
@@ -1020,6 +1020,7 @@ pub const File = struct {
             for (base.options.objects) |obj| {
                 _ = try man.addFile(obj.path, null);
                 man.hash.add(obj.must_link);
+                man.hash.add(obj.loption);
             }
             for (comp.c_object_table.keys()) |key| {
                 _ = try man.addFile(key.status.success.object_path, null);
diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig
index 656b0f9a97..6be20efe11 100644
--- a/src/link/Coff/lld.zig
+++ b/src/link/Coff/lld.zig
@@ -63,7 +63,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
         man = comp.cache_parent.obtain();
         self.base.releaseLock();
 
-        comptime assert(Compilation.link_hash_implementation_version == 8);
+        comptime assert(Compilation.link_hash_implementation_version == 9);
 
         for (self.base.options.objects) |obj| {
             _ = try man.addFile(obj.path, null);
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index 9fa48a9e62..2a28f880ac 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -1371,13 +1371,14 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
         // We are about to obtain this lock, so here we give other processes a chance first.
         self.base.releaseLock();
 
-        comptime assert(Compilation.link_hash_implementation_version == 8);
+        comptime assert(Compilation.link_hash_implementation_version == 9);
 
         try man.addOptionalFile(self.base.options.linker_script);
         try man.addOptionalFile(self.base.options.version_script);
         for (self.base.options.objects) |obj| {
             _ = try man.addFile(obj.path, null);
             man.hash.add(obj.must_link);
+            man.hash.add(obj.loption);
         }
         for (comp.c_object_table.keys()) |key| {
             _ = try man.addFile(key.status.success.object_path, null);
@@ -1719,6 +1720,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
             for (self.base.options.objects) |obj| {
                 if (Compilation.classifyFileExt(obj.path) == .shared_library) {
                     const lib_dir_path = std.fs.path.dirname(obj.path) orelse continue;
+                    if (obj.loption) continue;
+
                     if ((try rpath_table.fetchPut(lib_dir_path, {})) == null) {
                         try argv.append("-rpath");
                         try argv.append(lib_dir_path);
@@ -1767,6 +1770,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
                 try argv.append("-no-whole-archive");
                 whole_archive = false;
             }
+
+            if (obj.loption) {
+                assert(obj.path[0] == ':');
+                try argv.append("-l");
+            }
             try argv.append(obj.path);
         }
         if (whole_archive) {
diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig
index b151aee19b..4f7e615c79 100644
--- a/src/link/MachO/zld.zig
+++ b/src/link/MachO/zld.zig
@@ -3494,7 +3494,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
         // We are about to obtain this lock, so here we give other processes a chance first.
         macho_file.base.releaseLock();
 
-        comptime assert(Compilation.link_hash_implementation_version == 8);
+        comptime assert(Compilation.link_hash_implementation_version == 9);
 
         for (options.objects) |obj| {
             _ = try man.addFile(obj.path, null);
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
index 5dfc91d4ce..befd2d68c9 100644
--- a/src/link/Wasm.zig
+++ b/src/link/Wasm.zig
@@ -3150,7 +3150,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
         // We are about to obtain this lock, so here we give other processes a chance first.
         wasm.base.releaseLock();
 
-        comptime assert(Compilation.link_hash_implementation_version == 8);
+        comptime assert(Compilation.link_hash_implementation_version == 9);
 
         for (options.objects) |obj| {
             _ = try man.addFile(obj.path, null);
@@ -4199,7 +4199,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
         // We are about to obtain this lock, so here we give other processes a chance first.
         wasm.base.releaseLock();
 
-        comptime assert(Compilation.link_hash_implementation_version == 8);
+        comptime assert(Compilation.link_hash_implementation_version == 9);
 
         for (wasm.base.options.objects) |obj| {
             _ = try man.addFile(obj.path, null);
diff --git a/src/main.zig b/src/main.zig
index f7afbe767b..b4778c1b00 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -889,14 +889,6 @@ fn buildOutputType(
     var link_objects = std.ArrayList(Compilation.LinkObject).init(gpa);
     defer link_objects.deinit();
 
-    // This map is a flag per link_objects item, used to represent the
-    // `-l :file.so` syntax from gcc/clang.
-    // This is only exposed from the `zig cc` interface. It means that the `path`
-    // field from the corresponding `link_objects` element is a suffix, and is
-    // to be tried against each library path as a prefix until an existing file is found.
-    // This map remains empty for the main CLI.
-    var link_objects_lib_search_paths: std.AutoHashMapUnmanaged(u32, void) = .{};
-
     var framework_dirs = std.ArrayList([]const u8).init(gpa);
     defer framework_dirs.deinit();
 
@@ -1627,14 +1619,15 @@ fn buildOutputType(
                         // We don't know whether this library is part of libc or libc++ until
                         // we resolve the target, so we simply append to the list for now.
                         if (mem.startsWith(u8, it.only_arg, ":")) {
-                            // This "feature" of gcc/clang means to treat this as a positional
-                            // link object, but using the library search directories as a prefix.
+                            // -l :path/to/filename is used when callers need
+                            // more control over what's in the resulting
+                            // binary: no extra rpaths and DSO filename exactly
+                            // as provided. Hello, Go.
                             try link_objects.append(.{
-                                .path = it.only_arg[1..],
+                                .path = it.only_arg,
                                 .must_link = must_link,
+                                .loption = true,
                             });
-                            const index = @intCast(u32, link_objects.items.len - 1);
-                            try link_objects_lib_search_paths.put(arena, index, {});
                         } else if (force_static_libs) {
                             try static_libs.append(it.only_arg);
                         } else {
@@ -2640,30 +2633,6 @@ fn buildOutputType(
         }
     }
 
-    // Resolve `-l :file.so` syntax from `zig cc`. We use a separate map for this data
-    // since this is an uncommon case.
-    {
-        var it = link_objects_lib_search_paths.iterator();
-        while (it.next()) |item| {
-            const link_object_i = item.key_ptr.*;
-            const suffix = link_objects.items[link_object_i].path;
-
-            for (lib_dirs.items) |lib_dir_path| {
-                const test_path = try fs.path.join(arena, &.{ lib_dir_path, suffix });
-                fs.cwd().access(test_path, .{}) catch |err| switch (err) {
-                    error.FileNotFound => continue,
-                    else => |e| fatal("unable to search for library '{s}': {s}", .{
-                        test_path, @errorName(e),
-                    }),
-                };
-                link_objects.items[link_object_i].path = test_path;
-                break;
-            } else {
-                fatal("library '{s}' not found", .{suffix});
-            }
-        }
-    }
-
     const object_format = target_info.target.ofmt;
 
     if (output_mode == .Obj and (object_format == .coff or object_format == .macho)) {
-- 
cgit v1.2.3


From 6c2f3745564aefa669b336e249888bb7390b3a3f Mon Sep 17 00:00:00 2001
From: Evin Yulo 
Date: Sat, 20 May 2023 20:58:28 -0400
Subject: Use the word 'base' consistently instead of 'radix'

---
 lib/std/fmt.zig                     | 98 ++++++++++++++++++-------------------
 lib/std/fmt/parse_float/decimal.zig |  4 +-
 lib/std/math/big/int.zig            | 16 +++---
 lib/std/math/scalbn.zig             |  4 +-
 lib/std/zig/c_translation.zig       | 13 +++--
 src/main.zig                        |  8 +--
 src/translate_c.zig                 | 10 ++--
 src/translate_c/ast.zig             |  6 +--
 8 files changed, 81 insertions(+), 78 deletions(-)

(limited to 'src/main.zig')

diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig
index be6ebf20ac..92e15f06ba 100644
--- a/lib/std/fmt.zig
+++ b/lib/std/fmt.zig
@@ -748,7 +748,7 @@ pub fn formatIntValue(
     options: FormatOptions,
     writer: anytype,
 ) !void {
-    comptime var radix = 10;
+    comptime var base = 10;
     comptime var case: Case = .lower;
 
     const int_value = if (@TypeOf(value) == comptime_int) blk: {
@@ -757,7 +757,7 @@ pub fn formatIntValue(
     } else value;
 
     if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "d")) {
-        radix = 10;
+        base = 10;
         case = .lower;
     } else if (comptime std.mem.eql(u8, fmt, "c")) {
         if (@typeInfo(@TypeOf(int_value)).Int.bits <= 8) {
@@ -772,22 +772,22 @@ pub fn formatIntValue(
             @compileError("cannot print integer that is larger than 21 bits as an UTF-8 sequence");
         }
     } else if (comptime std.mem.eql(u8, fmt, "b")) {
-        radix = 2;
+        base = 2;
         case = .lower;
     } else if (comptime std.mem.eql(u8, fmt, "x")) {
-        radix = 16;
+        base = 16;
         case = .lower;
     } else if (comptime std.mem.eql(u8, fmt, "X")) {
-        radix = 16;
+        base = 16;
         case = .upper;
     } else if (comptime std.mem.eql(u8, fmt, "o")) {
-        radix = 8;
+        base = 8;
         case = .lower;
     } else {
         invalidFmtError(fmt, value);
     }
 
-    return formatInt(int_value, radix, case, options, writer);
+    return formatInt(int_value, base, case, options, writer);
 }
 
 fn formatFloatValue(
@@ -906,7 +906,7 @@ pub fn fmtSliceEscapeUpper(bytes: []const u8) std.fmt.Formatter(formatSliceEscap
     return .{ .data = bytes };
 }
 
-fn formatSizeImpl(comptime radix: comptime_int) type {
+fn formatSizeImpl(comptime base: comptime_int) type {
     return struct {
         fn formatSizeImpl(
             value: u64,
@@ -926,13 +926,13 @@ fn formatSizeImpl(comptime radix: comptime_int) type {
             const mags_iec = " KMGTPEZY";
 
             const log2 = math.log2(value);
-            const magnitude = switch (radix) {
+            const magnitude = switch (base) {
                 1000 => math.min(log2 / comptime math.log2(1000), mags_si.len - 1),
                 1024 => math.min(log2 / 10, mags_iec.len - 1),
                 else => unreachable,
             };
-            const new_value = lossyCast(f64, value) / math.pow(f64, lossyCast(f64, radix), lossyCast(f64, magnitude));
-            const suffix = switch (radix) {
+            const new_value = lossyCast(f64, value) / math.pow(f64, lossyCast(f64, base), lossyCast(f64, magnitude));
+            const suffix = switch (base) {
                 1000 => mags_si[magnitude],
                 1024 => mags_iec[magnitude],
                 else => unreachable,
@@ -944,7 +944,7 @@ fn formatSizeImpl(comptime radix: comptime_int) type {
 
             bufstream.writer().writeAll(if (suffix == ' ')
                 "B"
-            else switch (radix) {
+            else switch (base) {
                 1000 => &[_]u8{ suffix, 'B' },
                 1024 => &[_]u8{ suffix, 'i', 'B' },
                 else => unreachable,
@@ -1730,21 +1730,21 @@ pub fn Formatter(comptime format_fn: anytype) type {
 }
 
 /// Parses the string `buf` as signed or unsigned representation in the
-/// specified radix of an integral value of type `T`.
+/// specified base of an integral value of type `T`.
 ///
-/// When `radix` is zero the string prefix is examined to detect the true radix:
-///  * A prefix of "0b" implies radix=2,
-///  * A prefix of "0o" implies radix=8,
-///  * A prefix of "0x" implies radix=16,
-///  * Otherwise radix=10 is assumed.
+/// When `base` is zero the string prefix is examined to detect the true base:
+///  * A prefix of "0b" implies base=2,
+///  * A prefix of "0o" implies base=8,
+///  * A prefix of "0x" implies base=16,
+///  * Otherwise base=10 is assumed.
 ///
 /// Ignores '_' character in `buf`.
 /// See also `parseUnsigned`.
-pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) ParseIntError!T {
+pub fn parseInt(comptime T: type, buf: []const u8, base: u8) ParseIntError!T {
     if (buf.len == 0) return error.InvalidCharacter;
-    if (buf[0] == '+') return parseWithSign(T, buf[1..], radix, .pos);
-    if (buf[0] == '-') return parseWithSign(T, buf[1..], radix, .neg);
-    return parseWithSign(T, buf, radix, .pos);
+    if (buf[0] == '+') return parseWithSign(T, buf[1..], base, .pos);
+    if (buf[0] == '-') return parseWithSign(T, buf[1..], base, .neg);
+    return parseWithSign(T, buf, base, .pos);
 }
 
 test "parseInt" {
@@ -1777,7 +1777,7 @@ test "parseInt" {
     try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "-", 10));
     try std.testing.expectError(error.InvalidCharacter, parseInt(i32, "-", 10));
 
-    // autodectect the radix
+    // autodectect the base
     try std.testing.expect((try parseInt(i32, "111", 0)) == 111);
     try std.testing.expect((try parseInt(i32, "1_1_1", 0)) == 111);
     try std.testing.expect((try parseInt(i32, "1_1_1", 0)) == 111);
@@ -1804,29 +1804,29 @@ test "parseInt" {
 fn parseWithSign(
     comptime T: type,
     buf: []const u8,
-    radix: u8,
+    base: u8,
     comptime sign: enum { pos, neg },
 ) ParseIntError!T {
     if (buf.len == 0) return error.InvalidCharacter;
 
-    var buf_radix = radix;
+    var buf_base = base;
     var buf_start = buf;
-    if (radix == 0) {
+    if (base == 0) {
         // Treat is as a decimal number by default.
-        buf_radix = 10;
-        // Detect the radix by looking at buf prefix.
+        buf_base = 10;
+        // Detect the base by looking at buf prefix.
         if (buf.len > 2 and buf[0] == '0') {
             switch (std.ascii.toLower(buf[1])) {
                 'b' => {
-                    buf_radix = 2;
+                    buf_base = 2;
                     buf_start = buf[2..];
                 },
                 'o' => {
-                    buf_radix = 8;
+                    buf_base = 8;
                     buf_start = buf[2..];
                 },
                 'x' => {
-                    buf_radix = 16;
+                    buf_base = 16;
                     buf_start = buf[2..];
                 },
                 else => {},
@@ -1845,28 +1845,28 @@ fn parseWithSign(
 
     for (buf_start) |c| {
         if (c == '_') continue;
-        const digit = try charToDigit(c, buf_radix);
+        const digit = try charToDigit(c, buf_base);
 
-        if (x != 0) x = try math.mul(T, x, math.cast(T, buf_radix) orelse return error.Overflow);
+        if (x != 0) x = try math.mul(T, x, math.cast(T, buf_base) orelse return error.Overflow);
         x = try add(T, x, math.cast(T, digit) orelse return error.Overflow);
     }
 
     return x;
 }
 
-/// Parses the string `buf` as  unsigned representation in the specified radix
+/// Parses the string `buf` as unsigned representation in the specified base
 /// of an integral value of type `T`.
 ///
-/// When `radix` is zero the string prefix is examined to detect the true radix:
-///  * A prefix of "0b" implies radix=2,
-///  * A prefix of "0o" implies radix=8,
-///  * A prefix of "0x" implies radix=16,
-///  * Otherwise radix=10 is assumed.
+/// When `base` is zero the string prefix is examined to detect the true base:
+///  * A prefix of "0b" implies base=2,
+///  * A prefix of "0o" implies base=8,
+///  * A prefix of "0x" implies base=16,
+///  * Otherwise base=10 is assumed.
 ///
 /// Ignores '_' character in `buf`.
 /// See also `parseInt`.
-pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseIntError!T {
-    return parseWithSign(T, buf, radix, .pos);
+pub fn parseUnsigned(comptime T: type, buf: []const u8, base: u8) ParseIntError!T {
+    return parseWithSign(T, buf, base, .pos);
 }
 
 test "parseUnsigned" {
@@ -1889,7 +1889,7 @@ test "parseUnsigned" {
 
     try std.testing.expect((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747);
 
-    // these numbers should fit even though the radix itself doesn't fit in the destination type
+    // these numbers should fit even though the base itself doesn't fit in the destination type
     try std.testing.expect((try parseUnsigned(u1, "0", 10)) == 0);
     try std.testing.expect((try parseUnsigned(u1, "1", 10)) == 1);
     try std.testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));
@@ -1906,14 +1906,14 @@ test "parseUnsigned" {
 }
 
 /// Parses a number like '2G', '2Gi', or '2GiB'.
-pub fn parseIntSizeSuffix(buf: []const u8, radix: u8) ParseIntError!usize {
+pub fn parseIntSizeSuffix(buf: []const u8, digit_base: u8) ParseIntError!usize {
     var without_B = buf;
     if (mem.endsWith(u8, buf, "B")) without_B.len -= 1;
     var without_i = without_B;
-    var base: usize = 1000;
+    var magnitude_base: usize = 1000;
     if (mem.endsWith(u8, without_B, "i")) {
         without_i.len -= 1;
-        base = 1024;
+        magnitude_base = 1024;
     }
     if (without_i.len == 0) return error.InvalidCharacter;
     const orders_of_magnitude: usize = switch (without_i[without_i.len - 1]) {
@@ -1935,11 +1935,11 @@ pub fn parseIntSizeSuffix(buf: []const u8, radix: u8) ParseIntError!usize {
     } else if (without_i.len != without_B.len) {
         return error.InvalidCharacter;
     }
-    const multiplier = math.powi(usize, base, orders_of_magnitude) catch |err| switch (err) {
+    const multiplier = math.powi(usize, magnitude_base, orders_of_magnitude) catch |err| switch (err) {
         error.Underflow => unreachable,
         error.Overflow => return error.Overflow,
     };
-    const number = try std.fmt.parseInt(usize, without_suffix, radix);
+    const number = try std.fmt.parseInt(usize, without_suffix, digit_base);
     return math.mul(usize, number, multiplier);
 }
 
@@ -1962,7 +1962,7 @@ test {
     _ = &parseFloat;
 }
 
-pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
+pub fn charToDigit(c: u8, base: u8) (error{InvalidCharacter}!u8) {
     const value = switch (c) {
         '0'...'9' => c - '0',
         'A'...'Z' => c - 'A' + 10,
@@ -1970,7 +1970,7 @@ pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
         else => return error.InvalidCharacter,
     };
 
-    if (value >= radix) return error.InvalidCharacter;
+    if (value >= base) return error.InvalidCharacter;
 
     return value;
 }
diff --git a/lib/std/fmt/parse_float/decimal.zig b/lib/std/fmt/parse_float/decimal.zig
index 9dbe7095ac..5bb5fa8d5e 100644
--- a/lib/std/fmt/parse_float/decimal.zig
+++ b/lib/std/fmt/parse_float/decimal.zig
@@ -34,13 +34,13 @@ pub fn Decimal(comptime T: type) type {
         /// For a double-precision IEEE-754 float, this required 767 digits,
         /// so we store the max digits + 1.
         ///
-        /// We can exactly represent a float in radix `b` from radix 2 if
+        /// We can exactly represent a float in base `b` from base 2 if
         /// `b` is divisible by 2. This function calculates the exact number of
         /// digits required to exactly represent that float.
         ///
         /// According to the "Handbook of Floating Point Arithmetic",
         /// for IEEE754, with emin being the min exponent, p2 being the
-        /// precision, and b being the radix, the number of digits follows as:
+        /// precision, and b being the base, the number of digits follows as:
         ///
         /// `−emin + p2 + ⌊(emin + 1) log(2, b) − log(1 − 2^(−p2), b)⌋`
         ///
diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig
index fdee6b6190..c4d3ccf077 100644
--- a/lib/std/math/big/int.zig
+++ b/lib/std/math/big/int.zig
@@ -1627,7 +1627,7 @@ pub const Mutable = struct {
         // while x >= y * b^(n - t):
         //    x -= y * b^(n - t)
         //    q[n - t] += 1
-        // Note, this algorithm is performed only once if y[t] > radix/2 and y is even, which we
+        // Note, this algorithm is performed only once if y[t] > base/2 and y is even, which we
         // enforced in step 0. This means we can replace the while with an if.
         // Note, multiplication by b^(n - t) comes down to shifting to the right by n - t limbs.
         // We can also replace x >= y * b^(n - t) by x/b^(n - t) >= y, and use shifts for that.
@@ -2206,20 +2206,20 @@ pub const Const = struct {
         out_stream: anytype,
     ) !void {
         _ = options;
-        comptime var radix = 10;
+        comptime var base = 10;
         comptime var case: std.fmt.Case = .lower;
 
         if (fmt.len == 0 or comptime mem.eql(u8, fmt, "d")) {
-            radix = 10;
+            base = 10;
             case = .lower;
         } else if (comptime mem.eql(u8, fmt, "b")) {
-            radix = 2;
+            base = 2;
             case = .lower;
         } else if (comptime mem.eql(u8, fmt, "x")) {
-            radix = 16;
+            base = 16;
             case = .lower;
         } else if (comptime mem.eql(u8, fmt, "X")) {
-            radix = 16;
+            base = 16;
             case = .upper;
         } else {
             std.fmt.invalidFmtError(fmt, self);
@@ -2237,8 +2237,8 @@ pub const Const = struct {
             .limbs = &([1]Limb{comptime math.maxInt(Limb)} ** available_len),
             .positive = false,
         };
-        var buf: [biggest.sizeInBaseUpperBound(radix)]u8 = undefined;
-        const len = self.toString(&buf, radix, case, &limbs);
+        var buf: [biggest.sizeInBaseUpperBound(base)]u8 = undefined;
+        const len = self.toString(&buf, base, case, &limbs);
         return out_stream.writeAll(buf[0..len]);
     }
 
diff --git a/lib/std/math/scalbn.zig b/lib/std/math/scalbn.zig
index 294ee4abf0..2c8c3733fa 100644
--- a/lib/std/math/scalbn.zig
+++ b/lib/std/math/scalbn.zig
@@ -3,11 +3,11 @@ const expect = std.testing.expect;
 
 /// Returns a * FLT_RADIX ^ exp.
 ///
-/// Zig only supports binary radix IEEE-754 floats. Hence FLT_RADIX=2, and this is an alias for ldexp.
+/// Zig only supports binary base IEEE-754 floats. Hence FLT_RADIX=2, and this is an alias for ldexp.
 pub const scalbn = @import("ldexp.zig").ldexp;
 
 test "math.scalbn" {
-    // Verify we are using radix 2.
+    // Verify we are using base 2.
     try expect(scalbn(@as(f16, 1.5), 4) == 24.0);
     try expect(scalbn(@as(f32, 1.5), 4) == 24.0);
     try expect(scalbn(@as(f64, 1.5), 4) == 24.0);
diff --git a/lib/std/zig/c_translation.zig b/lib/std/zig/c_translation.zig
index 6e95ab53ab..1273527358 100644
--- a/lib/std/zig/c_translation.zig
+++ b/lib/std/zig/c_translation.zig
@@ -262,16 +262,19 @@ test "sizeof" {
     try testing.expect(sizeof(anyopaque) == 1);
 }
 
-pub const CIntLiteralRadix = enum { decimal, octal, hexadecimal };
+pub const CIntLiteralBase = enum { decimal, octal, hexadecimal };
 
-fn PromoteIntLiteralReturnType(comptime SuffixType: type, comptime number: comptime_int, comptime radix: CIntLiteralRadix) type {
+/// Deprecated: use `CIntLiteralBase`
+pub const CIntLiteralRadix = CIntLiteralBase;
+
+fn PromoteIntLiteralReturnType(comptime SuffixType: type, comptime number: comptime_int, comptime base: CIntLiteralBase) type {
     const signed_decimal = [_]type{ c_int, c_long, c_longlong, c_ulonglong };
     const signed_oct_hex = [_]type{ c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong };
     const unsigned = [_]type{ c_uint, c_ulong, c_ulonglong };
 
     const list: []const type = if (@typeInfo(SuffixType).Int.signedness == .unsigned)
         &unsigned
-    else if (radix == .decimal)
+    else if (base == .decimal)
         &signed_decimal
     else
         &signed_oct_hex;
@@ -290,8 +293,8 @@ fn PromoteIntLiteralReturnType(comptime SuffixType: type, comptime number: compt
 pub fn promoteIntLiteral(
     comptime SuffixType: type,
     comptime number: comptime_int,
-    comptime radix: CIntLiteralRadix,
-) PromoteIntLiteralReturnType(SuffixType, number, radix) {
+    comptime base: CIntLiteralBase,
+) PromoteIntLiteralReturnType(SuffixType, number, base) {
     return number;
 }
 
diff --git a/src/main.zig b/src/main.zig
index b4778c1b00..bc40dbc431 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -5786,12 +5786,12 @@ pub fn cmdChangelist(
     try bw.flush();
 }
 
-fn eatIntPrefix(arg: []const u8, radix: u8) []const u8 {
+fn eatIntPrefix(arg: []const u8, base: u8) []const u8 {
     if (arg.len > 2 and arg[0] == '0') {
         switch (std.ascii.toLower(arg[1])) {
-            'b' => if (radix == 2) return arg[2..],
-            'o' => if (radix == 8) return arg[2..],
-            'x' => if (radix == 16) return arg[2..],
+            'b' => if (base == 2) return arg[2..],
+            'o' => if (base == 8) return arg[2..],
+            'x' => if (base == 16) return arg[2..],
             else => {},
         }
     }
diff --git a/src/translate_c.zig b/src/translate_c.zig
index becb2779b2..8cc2d1856c 100644
--- a/src/translate_c.zig
+++ b/src/translate_c.zig
@@ -5735,21 +5735,21 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
 
     switch (m.list[m.i].id) {
         .IntegerLiteral => |suffix| {
-            var radix: []const u8 = "decimal";
+            var base: []const u8 = "decimal";
             if (lit_bytes.len >= 2 and lit_bytes[0] == '0') {
                 switch (lit_bytes[1]) {
                     '0'...'7' => {
                         // Octal
                         lit_bytes = try std.fmt.allocPrint(c.arena, "0o{s}", .{lit_bytes[1..]});
-                        radix = "octal";
+                        base = "octal";
                     },
                     'X' => {
                         // Hexadecimal with capital X, valid in C but not in Zig
                         lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}", .{lit_bytes[2..]});
-                        radix = "hexadecimal";
+                        base = "hexadecimal";
                     },
                     'x' => {
-                        radix = "hexadecimal";
+                        base = "hexadecimal";
                     },
                     else => {},
                 }
@@ -5794,7 +5794,7 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
                 return Tag.helpers_promoteIntLiteral.create(c.arena, .{
                     .type = type_node,
                     .value = literal_node,
-                    .radix = try Tag.enum_literal.create(c.arena, radix),
+                    .base = try Tag.enum_literal.create(c.arena, base),
                 });
             }
         },
diff --git a/src/translate_c/ast.zig b/src/translate_c/ast.zig
index 328feb989a..6c6bbf28bd 100644
--- a/src/translate_c/ast.zig
+++ b/src/translate_c/ast.zig
@@ -120,7 +120,7 @@ pub const Node = extern union {
         std_math_Log2Int,
         /// @intCast(lhs, rhs)
         int_cast,
-        /// @import("std").zig.c_translation.promoteIntLiteral(value, type, radix)
+        /// @import("std").zig.c_translation.promoteIntLiteral(value, type, base)
         helpers_promoteIntLiteral,
         /// @import("std").meta.alignment(value)
         std_meta_alignment,
@@ -699,7 +699,7 @@ pub const Payload = struct {
         data: struct {
             value: Node,
             type: Node,
-            radix: Node,
+            base: Node,
         },
     };
 
@@ -898,7 +898,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
         .helpers_promoteIntLiteral => {
             const payload = node.castTag(.helpers_promoteIntLiteral).?.data;
             const import_node = try renderStdImport(c, &.{ "zig", "c_translation", "promoteIntLiteral" });
-            return renderCall(c, import_node, &.{ payload.type, payload.value, payload.radix });
+            return renderCall(c, import_node, &.{ payload.type, payload.value, payload.base });
         },
         .std_meta_alignment => {
             const payload = node.castTag(.std_meta_alignment).?.data;
-- 
cgit v1.2.3


From a596ea683c35d90c6af3e1fbeae2e06312ce392f Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Fri, 26 May 2023 17:44:23 -0700
Subject: CLI: introduce --verbose-intern-pool

and stop dumping to stderr without the user's consent.
---
 src/Compilation.zig | 15 +++++++++++----
 src/main.zig        |  5 +++++
 2 files changed, 16 insertions(+), 4 deletions(-)

(limited to 'src/main.zig')

diff --git a/src/Compilation.zig b/src/Compilation.zig
index 30ac499955..0ee916c446 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -87,6 +87,7 @@ clang_preprocessor_mode: ClangPreprocessorMode,
 /// Whether to print clang argvs to stdout.
 verbose_cc: bool,
 verbose_air: bool,
+verbose_intern_pool: bool,
 verbose_llvm_ir: ?[]const u8,
 verbose_llvm_bc: ?[]const u8,
 verbose_cimport: bool,
@@ -593,6 +594,7 @@ pub const InitOptions = struct {
     verbose_cc: bool = false,
     verbose_link: bool = false,
     verbose_air: bool = false,
+    verbose_intern_pool: bool = false,
     verbose_llvm_ir: ?[]const u8 = null,
     verbose_llvm_bc: ?[]const u8 = null,
     verbose_cimport: bool = false,
@@ -1574,6 +1576,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
             .clang_preprocessor_mode = options.clang_preprocessor_mode,
             .verbose_cc = options.verbose_cc,
             .verbose_air = options.verbose_air,
+            .verbose_intern_pool = options.verbose_intern_pool,
             .verbose_llvm_ir = options.verbose_llvm_ir,
             .verbose_llvm_bc = options.verbose_llvm_bc,
             .verbose_cimport = options.verbose_cimport,
@@ -2026,10 +2029,12 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
     try comp.performAllTheWork(main_progress_node);
 
     if (comp.bin_file.options.module) |module| {
-        std.debug.print("intern pool stats for '{s}':\n", .{
-            comp.bin_file.options.root_name,
-        });
-        module.intern_pool.dump();
+        if (builtin.mode == .Debug and comp.verbose_intern_pool) {
+            std.debug.print("intern pool stats for '{s}':\n", .{
+                comp.bin_file.options.root_name,
+            });
+            module.intern_pool.dump();
+        }
 
         if (comp.bin_file.options.is_test and comp.totalErrorCount() == 0) {
             // The `test_functions` decl has been intentionally postponed until now,
@@ -5422,6 +5427,7 @@ fn buildOutputFromZig(
         .verbose_cc = comp.verbose_cc,
         .verbose_link = comp.bin_file.options.verbose_link,
         .verbose_air = comp.verbose_air,
+        .verbose_intern_pool = comp.verbose_intern_pool,
         .verbose_llvm_ir = comp.verbose_llvm_ir,
         .verbose_llvm_bc = comp.verbose_llvm_bc,
         .verbose_cimport = comp.verbose_cimport,
@@ -5500,6 +5506,7 @@ pub fn build_crt_file(
         .verbose_cc = comp.verbose_cc,
         .verbose_link = comp.bin_file.options.verbose_link,
         .verbose_air = comp.verbose_air,
+        .verbose_intern_pool = comp.verbose_intern_pool,
         .verbose_llvm_ir = comp.verbose_llvm_ir,
         .verbose_llvm_bc = comp.verbose_llvm_bc,
         .verbose_cimport = comp.verbose_cimport,
diff --git a/src/main.zig b/src/main.zig
index 4acd305ce7..5d666840c0 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -569,6 +569,7 @@ const usage_build_generic =
     \\  --verbose-link               Display linker invocations
     \\  --verbose-cc                 Display C compiler invocations
     \\  --verbose-air                Enable compiler debug output for Zig AIR
+    \\  --verbose-intern-pool        Enable compiler debug output for InternPool
     \\  --verbose-llvm-ir[=path]     Enable compiler debug output for unoptimized LLVM IR
     \\  --verbose-llvm-bc=[path]     Enable compiler debug output for unoptimized LLVM BC
     \\  --verbose-cimport            Enable compiler debug output for C imports
@@ -735,6 +736,7 @@ fn buildOutputType(
     var verbose_link = (builtin.os.tag != .wasi or builtin.link_libc) and std.process.hasEnvVarConstant("ZIG_VERBOSE_LINK");
     var verbose_cc = (builtin.os.tag != .wasi or builtin.link_libc) and std.process.hasEnvVarConstant("ZIG_VERBOSE_CC");
     var verbose_air = false;
+    var verbose_intern_pool = false;
     var verbose_llvm_ir: ?[]const u8 = null;
     var verbose_llvm_bc: ?[]const u8 = null;
     var verbose_cimport = false;
@@ -1460,6 +1462,8 @@ fn buildOutputType(
                         verbose_cc = true;
                     } else if (mem.eql(u8, arg, "--verbose-air")) {
                         verbose_air = true;
+                    } else if (mem.eql(u8, arg, "--verbose-intern-pool")) {
+                        verbose_intern_pool = true;
                     } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
                         verbose_llvm_ir = "-";
                     } else if (mem.startsWith(u8, arg, "--verbose-llvm-ir=")) {
@@ -3156,6 +3160,7 @@ fn buildOutputType(
         .verbose_cc = verbose_cc,
         .verbose_link = verbose_link,
         .verbose_air = verbose_air,
+        .verbose_intern_pool = verbose_intern_pool,
         .verbose_llvm_ir = verbose_llvm_ir,
         .verbose_llvm_bc = verbose_llvm_bc,
         .verbose_cimport = verbose_cimport,
-- 
cgit v1.2.3


From 259315606827620daaabf82b479e59ee710097cd Mon Sep 17 00:00:00 2001
From: r00ster91 
Date: Fri, 2 Jun 2023 22:02:45 -0400
Subject: migration: std.math.{min, min3, max, max3} -> `@min` & `@max`

---
 doc/docgen.zig                          |   2 +-
 lib/compiler_rt/divc3.zig               |   3 +-
 lib/compiler_rt/emutls.zig              |   4 +-
 lib/std/Build/Cache/DepTokenizer.zig    |   2 +-
 lib/std/Thread.zig                      |   6 +-
 lib/std/Uri.zig                         |   4 +-
 lib/std/array_hash_map.zig              |   6 +-
 lib/std/ascii.zig                       |   2 +-
 lib/std/compress/lzma/decode.zig        |   2 +-
 lib/std/crypto/blake3.zig               |   8 +--
 lib/std/crypto/ff.zig                   |   2 +-
 lib/std/crypto/ghash_polyval.zig        |   2 +-
 lib/std/crypto/keccak_p.zig             |   4 +-
 lib/std/crypto/poly1305.zig             |   2 +-
 lib/std/crypto/salsa20.zig              |   2 +-
 lib/std/crypto/scrypt.zig               |   4 +-
 lib/std/crypto/sha3.zig                 |   2 +-
 lib/std/crypto/siphash.zig              |   2 +-
 lib/std/debug.zig                       |   4 +-
 lib/std/dynamic_library.zig             |   3 +-
 lib/std/event/loop.zig                  |   2 +-
 lib/std/fifo.zig                        |   2 +-
 lib/std/fmt.zig                         |  18 +++---
 lib/std/hash/wyhash.zig                 |   2 +-
 lib/std/hash_map.zig                    |   6 +-
 lib/std/heap/arena_allocator.zig        |   2 +-
 lib/std/heap/memory_pool.zig            |   4 +-
 lib/std/http/protocol.zig               |   2 +-
 lib/std/io/fixed_buffer_stream.zig      |   4 +-
 lib/std/io/limited_reader.zig           |   2 +-
 lib/std/io/reader.zig                   |   2 +-
 lib/std/io/writer.zig                   |   2 +-
 lib/std/math.zig                        | 103 +++-----------------------------
 lib/std/math/big/int.zig                |  96 ++++++++++++++---------------
 lib/std/math/ldexp.zig                  |   2 +-
 lib/std/mem.zig                         |  12 ++--
 lib/std/net.zig                         |   8 +--
 lib/std/os/linux.zig                    |   4 +-
 lib/std/os/linux/io_uring.zig           |   4 +-
 lib/std/os/windows.zig                  |   4 +-
 lib/std/pdb.zig                         |   2 +-
 lib/std/rand.zig                        |   2 +-
 lib/std/sort/block.zig                  |  10 ++--
 lib/std/zig/render.zig                  |   4 +-
 lib/std/zig/system/NativeTargetInfo.zig |   6 +-
 src/Sema.zig                            |  10 ++--
 src/TypedValue.zig                      |  10 ++--
 src/arch/x86_64/CodeGen.zig             |   4 +-
 src/link/Elf.zig                        |   2 +-
 src/link/MachO/CodeSignature.zig        |   6 +-
 src/link/MachO/Object.zig               |   2 +-
 src/link/Wasm.zig                       |   2 +-
 src/link/Wasm/Object.zig                |   2 +-
 src/main.zig                            |   2 +-
 src/translate_c.zig                     |   2 +-
 src/translate_c/ast.zig                 |  14 ++---
 src/type.zig                            |   2 +-
 src/value.zig                           |   8 +--
 58 files changed, 173 insertions(+), 264 deletions(-)

(limited to 'src/main.zig')

diff --git a/doc/docgen.zig b/doc/docgen.zig
index bdbde6f5d2..4a9e33fbdd 100644
--- a/doc/docgen.zig
+++ b/doc/docgen.zig
@@ -276,7 +276,7 @@ fn parseError(tokenizer: *Tokenizer, token: Token, comptime fmt: []const u8, arg
             }
         }
         {
-            const caret_count = std.math.min(token.end, loc.line_end) - token.start;
+            const caret_count = @min(token.end, loc.line_end) - token.start;
             var i: usize = 0;
             while (i < caret_count) : (i += 1) {
                 print("~", .{});
diff --git a/lib/compiler_rt/divc3.zig b/lib/compiler_rt/divc3.zig
index 4e4dba2856..c4241c1483 100644
--- a/lib/compiler_rt/divc3.zig
+++ b/lib/compiler_rt/divc3.zig
@@ -3,7 +3,6 @@ const isNan = std.math.isNan;
 const isInf = std.math.isInf;
 const scalbn = std.math.scalbn;
 const ilogb = std.math.ilogb;
-const max = std.math.max;
 const fabs = std.math.fabs;
 const maxInt = std.math.maxInt;
 const minInt = std.math.minInt;
@@ -17,7 +16,7 @@ pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) {
     var d = d_in;
 
     // logbw used to prevent under/over-flow
-    const logbw = ilogb(max(fabs(c), fabs(d)));
+    const logbw = ilogb(@max(fabs(c), fabs(d)));
     const logbw_finite = logbw != maxInt(i32) and logbw != minInt(i32);
     const ilogbw = if (logbw_finite) b: {
         c = scalbn(c, -logbw);
diff --git a/lib/compiler_rt/emutls.zig b/lib/compiler_rt/emutls.zig
index 05a2de97a8..47c71efadd 100644
--- a/lib/compiler_rt/emutls.zig
+++ b/lib/compiler_rt/emutls.zig
@@ -49,7 +49,7 @@ const simple_allocator = struct {
 
     /// Allocate a memory chunk.
     pub fn advancedAlloc(alignment: u29, size: usize) [*]u8 {
-        const minimal_alignment = std.math.max(@alignOf(usize), alignment);
+        const minimal_alignment = @max(@alignOf(usize), alignment);
 
         var aligned_ptr: ?*anyopaque = undefined;
         if (std.c.posix_memalign(&aligned_ptr, minimal_alignment, size) != 0) {
@@ -170,7 +170,7 @@ const current_thread_storage = struct {
 
         // make it to contains at least 16 objects (to avoid too much
         // reallocation at startup).
-        const size = std.math.max(16, index);
+        const size = @max(16, index);
 
         // create a new array and store it.
         var array: *ObjectArray = ObjectArray.init(size);
diff --git a/lib/std/Build/Cache/DepTokenizer.zig b/lib/std/Build/Cache/DepTokenizer.zig
index 1a4e2ddb74..0e5224edc0 100644
--- a/lib/std/Build/Cache/DepTokenizer.zig
+++ b/lib/std/Build/Cache/DepTokenizer.zig
@@ -983,7 +983,7 @@ fn hexDump(out: anytype, bytes: []const u8) !void {
         try printDecValue(out, offset, 8);
         try out.writeAll(":");
         try out.writeAll(" ");
-        var end1 = std.math.min(offset + n, offset + 8);
+        var end1 = @min(offset + n, offset + 8);
         for (bytes[offset..end1]) |b| {
             try out.writeAll(" ");
             try printHexValue(out, b, 2);
diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig
index ed6a9383e3..76650a9072 100644
--- a/lib/std/Thread.zig
+++ b/lib/std/Thread.zig
@@ -541,7 +541,7 @@ const WindowsThreadImpl = struct {
         // Going lower makes it default to that specified in the executable (~1mb).
         // Its also fine if the limit here is incorrect as stack size is only a hint.
         var stack_size = std.math.cast(u32, config.stack_size) orelse std.math.maxInt(u32);
-        stack_size = std.math.max(64 * 1024, stack_size);
+        stack_size = @max(64 * 1024, stack_size);
 
         instance.thread.thread_handle = windows.kernel32.CreateThread(
             null,
@@ -690,7 +690,7 @@ const PosixThreadImpl = struct {
         defer assert(c.pthread_attr_destroy(&attr) == .SUCCESS);
 
         // Use the same set of parameters used by the libc-less impl.
-        const stack_size = std.math.max(config.stack_size, c.PTHREAD_STACK_MIN);
+        const stack_size = @max(config.stack_size, c.PTHREAD_STACK_MIN);
         assert(c.pthread_attr_setstacksize(&attr, stack_size) == .SUCCESS);
         assert(c.pthread_attr_setguardsize(&attr, std.mem.page_size) == .SUCCESS);
 
@@ -930,7 +930,7 @@ const LinuxThreadImpl = struct {
             var bytes: usize = page_size;
             guard_offset = bytes;
 
-            bytes += std.math.max(page_size, config.stack_size);
+            bytes += @max(page_size, config.stack_size);
             bytes = std.mem.alignForward(bytes, page_size);
             stack_offset = bytes;
 
diff --git a/lib/std/Uri.zig b/lib/std/Uri.zig
index 7a9755bd28..198ab461ae 100644
--- a/lib/std/Uri.zig
+++ b/lib/std/Uri.zig
@@ -177,13 +177,13 @@ pub fn parseWithoutScheme(text: []const u8) ParseError!Uri {
 
             if (std.mem.lastIndexOf(u8, authority, ":")) |index| {
                 if (index >= end_of_host) { // if not part of the V6 address field
-                    end_of_host = std.math.min(end_of_host, index);
+                    end_of_host = @min(end_of_host, index);
                     uri.port = std.fmt.parseInt(u16, authority[index + 1 ..], 10) catch return error.InvalidPort;
                 }
             }
         } else if (std.mem.lastIndexOf(u8, authority, ":")) |index| {
             if (index >= start_of_host) { // if not part of the userinfo field
-                end_of_host = std.math.min(end_of_host, index);
+                end_of_host = @min(end_of_host, index);
                 uri.port = std.fmt.parseInt(u16, authority[index + 1 ..], 10) catch return error.InvalidPort;
             }
         }
diff --git a/lib/std/array_hash_map.zig b/lib/std/array_hash_map.zig
index 55b9aac6e4..b46b5c12f0 100644
--- a/lib/std/array_hash_map.zig
+++ b/lib/std/array_hash_map.zig
@@ -815,9 +815,9 @@ pub fn ArrayHashMapUnmanaged(
         /// no longer guaranteed that no allocations will be performed.
         pub fn capacity(self: Self) usize {
             const entry_cap = self.entries.capacity;
-            const header = self.index_header orelse return math.min(linear_scan_max, entry_cap);
+            const header = self.index_header orelse return @min(linear_scan_max, entry_cap);
             const indexes_cap = header.capacity();
-            return math.min(entry_cap, indexes_cap);
+            return @min(entry_cap, indexes_cap);
         }
 
         /// Clobbers any existing data. To detect if a put would clobber
@@ -1821,7 +1821,7 @@ fn Index(comptime I: type) type {
 /// length * the size of an Index(u32).  The index is 8 bytes (3 bits repr)
 /// and max_usize + 1 is not representable, so we need to subtract out 4 bits.
 const max_representable_index_len = @bitSizeOf(usize) - 4;
-const max_bit_index = math.min(32, max_representable_index_len);
+const max_bit_index = @min(32, max_representable_index_len);
 const min_bit_index = 5;
 const max_capacity = (1 << max_bit_index) - 1;
 const index_capacities = blk: {
diff --git a/lib/std/ascii.zig b/lib/std/ascii.zig
index 941f398f20..e47ef4db65 100644
--- a/lib/std/ascii.zig
+++ b/lib/std/ascii.zig
@@ -422,7 +422,7 @@ test "indexOfIgnoreCase" {
 
 /// Returns the lexicographical order of two slices. O(n).
 pub fn orderIgnoreCase(lhs: []const u8, rhs: []const u8) std.math.Order {
-    const n = std.math.min(lhs.len, rhs.len);
+    const n = @min(lhs.len, rhs.len);
     var i: usize = 0;
     while (i < n) : (i += 1) {
         switch (std.math.order(toLower(lhs[i]), toLower(rhs[i]))) {
diff --git a/lib/std/compress/lzma/decode.zig b/lib/std/compress/lzma/decode.zig
index dc220d8e87..f539abf8b1 100644
--- a/lib/std/compress/lzma/decode.zig
+++ b/lib/std/compress/lzma/decode.zig
@@ -59,7 +59,7 @@ pub const Params = struct {
         const pb = @intCast(u3, props);
 
         const dict_size_provided = try reader.readIntLittle(u32);
-        const dict_size = math.max(0x1000, dict_size_provided);
+        const dict_size = @max(0x1000, dict_size_provided);
 
         const unpacked_size = switch (options.unpacked_size) {
             .read_from_header => blk: {
diff --git a/lib/std/crypto/blake3.zig b/lib/std/crypto/blake3.zig
index fb580fda13..7ad1511e79 100644
--- a/lib/std/crypto/blake3.zig
+++ b/lib/std/crypto/blake3.zig
@@ -20,7 +20,7 @@ const ChunkIterator = struct {
     }
 
     fn next(self: *ChunkIterator) ?[]u8 {
-        const next_chunk = self.slice[0..math.min(self.chunk_len, self.slice.len)];
+        const next_chunk = self.slice[0..@min(self.chunk_len, self.slice.len)];
         self.slice = self.slice[next_chunk.len..];
         return if (next_chunk.len > 0) next_chunk else null;
     }
@@ -283,7 +283,7 @@ const ChunkState = struct {
 
     fn fillBlockBuf(self: *ChunkState, input: []const u8) []const u8 {
         const want = BLOCK_LEN - self.block_len;
-        const take = math.min(want, input.len);
+        const take = @min(want, input.len);
         @memcpy(self.block[self.block_len..][0..take], input[0..take]);
         self.block_len += @truncate(u8, take);
         return input[take..];
@@ -450,7 +450,7 @@ pub const Blake3 = struct {
 
             // Compress input bytes into the current chunk state.
             const want = CHUNK_LEN - self.chunk_state.len();
-            const take = math.min(want, input.len);
+            const take = @min(want, input.len);
             self.chunk_state.update(input[0..take]);
             input = input[take..];
         }
@@ -663,7 +663,7 @@ fn testBlake3(hasher: *Blake3, input_len: usize, expected_hex: [262]u8) !void {
     // Write repeating input pattern to hasher
     var input_counter = input_len;
     while (input_counter > 0) {
-        const update_len = math.min(input_counter, input_pattern.len);
+        const update_len = @min(input_counter, input_pattern.len);
         hasher.update(input_pattern[0..update_len]);
         input_counter -= update_len;
     }
diff --git a/lib/std/crypto/ff.zig b/lib/std/crypto/ff.zig
index 84753ddefb..37e3d1c1b3 100644
--- a/lib/std/crypto/ff.zig
+++ b/lib/std/crypto/ff.zig
@@ -570,7 +570,7 @@ pub fn Modulus(comptime max_bits: comptime_int) type {
             var out = self.zero;
             var i = x.limbs_count() - 1;
             if (self.limbs_count() >= 2) {
-                const start = math.min(i, self.limbs_count() - 2);
+                const start = @min(i, self.limbs_count() - 2);
                 var j = start;
                 while (true) : (j -= 1) {
                     out.v.limbs.set(j, x.limbs.get(i));
diff --git a/lib/std/crypto/ghash_polyval.zig b/lib/std/crypto/ghash_polyval.zig
index 46645d710f..2fbff25f72 100644
--- a/lib/std/crypto/ghash_polyval.zig
+++ b/lib/std/crypto/ghash_polyval.zig
@@ -363,7 +363,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type {
             var mb = m;
 
             if (st.leftover > 0) {
-                const want = math.min(block_length - st.leftover, mb.len);
+                const want = @min(block_length - st.leftover, mb.len);
                 const mc = mb[0..want];
                 for (mc, 0..) |x, i| {
                     st.buf[st.leftover + i] = x;
diff --git a/lib/std/crypto/keccak_p.zig b/lib/std/crypto/keccak_p.zig
index 9226f2f6d4..ddc9b1b847 100644
--- a/lib/std/crypto/keccak_p.zig
+++ b/lib/std/crypto/keccak_p.zig
@@ -214,7 +214,7 @@ pub fn State(comptime f: u11, comptime capacity: u11, comptime delim: u8, compti
         pub fn absorb(self: *Self, bytes_: []const u8) void {
             var bytes = bytes_;
             if (self.offset > 0) {
-                const left = math.min(rate - self.offset, bytes.len);
+                const left = @min(rate - self.offset, bytes.len);
                 @memcpy(self.buf[self.offset..][0..left], bytes[0..left]);
                 self.offset += left;
                 if (self.offset == rate) {
@@ -249,7 +249,7 @@ pub fn State(comptime f: u11, comptime capacity: u11, comptime delim: u8, compti
         pub fn squeeze(self: *Self, out: []u8) void {
             var i: usize = 0;
             while (i < out.len) : (i += rate) {
-                const left = math.min(rate, out.len - i);
+                const left = @min(rate, out.len - i);
                 self.st.extractBytes(out[i..][0..left]);
                 self.st.permuteR(rounds);
             }
diff --git a/lib/std/crypto/poly1305.zig b/lib/std/crypto/poly1305.zig
index a2873f1145..51e1c2ab24 100644
--- a/lib/std/crypto/poly1305.zig
+++ b/lib/std/crypto/poly1305.zig
@@ -112,7 +112,7 @@ pub const Poly1305 = struct {
 
         // handle leftover
         if (st.leftover > 0) {
-            const want = std.math.min(block_length - st.leftover, mb.len);
+            const want = @min(block_length - st.leftover, mb.len);
             const mc = mb[0..want];
             for (mc, 0..) |x, i| {
                 st.buf[st.leftover + i] = x;
diff --git a/lib/std/crypto/salsa20.zig b/lib/std/crypto/salsa20.zig
index 7f57e6cecb..c8a639ad0b 100644
--- a/lib/std/crypto/salsa20.zig
+++ b/lib/std/crypto/salsa20.zig
@@ -404,7 +404,7 @@ pub const XSalsa20Poly1305 = struct {
         debug.assert(c.len == m.len);
         const extended = extend(rounds, k, npub);
         var block0 = [_]u8{0} ** 64;
-        const mlen0 = math.min(32, c.len);
+        const mlen0 = @min(32, c.len);
         @memcpy(block0[32..][0..mlen0], c[0..mlen0]);
         Salsa20.xor(block0[0..], block0[0..], 0, extended.key, extended.nonce);
         var mac = Poly1305.init(block0[0..32]);
diff --git a/lib/std/crypto/scrypt.zig b/lib/std/crypto/scrypt.zig
index b8e8ef55e2..97dd9b95d0 100644
--- a/lib/std/crypto/scrypt.zig
+++ b/lib/std/crypto/scrypt.zig
@@ -143,7 +143,7 @@ pub const Params = struct {
 
     /// Create parameters from ops and mem limits, where mem_limit given in bytes
     pub fn fromLimits(ops_limit: u64, mem_limit: usize) Self {
-        const ops = math.max(32768, ops_limit);
+        const ops = @max(32768, ops_limit);
         const r: u30 = 8;
         if (ops < mem_limit / 32) {
             const max_n = ops / (r * 4);
@@ -151,7 +151,7 @@ pub const Params = struct {
         } else {
             const max_n = mem_limit / (@intCast(usize, r) * 128);
             const ln = @intCast(u6, math.log2(max_n));
-            const max_rp = math.min(0x3fffffff, (ops / 4) / (@as(u64, 1) << ln));
+            const max_rp = @min(0x3fffffff, (ops / 4) / (@as(u64, 1) << ln));
             return Self{ .r = r, .p = @intCast(u30, max_rp / @as(u64, r)), .ln = ln };
         }
     }
diff --git a/lib/std/crypto/sha3.zig b/lib/std/crypto/sha3.zig
index 23f9e65534..0226490881 100644
--- a/lib/std/crypto/sha3.zig
+++ b/lib/std/crypto/sha3.zig
@@ -148,7 +148,7 @@ fn ShakeLike(comptime security_level: u11, comptime delim: u8, comptime rounds:
             if (self.offset > 0) {
                 const left = self.buf.len - self.offset;
                 if (left > 0) {
-                    const n = math.min(left, out.len);
+                    const n = @min(left, out.len);
                     @memcpy(out[0..n], self.buf[self.offset..][0..n]);
                     out = out[n..];
                     self.offset += n;
diff --git a/lib/std/crypto/siphash.zig b/lib/std/crypto/siphash.zig
index 37d219f868..70f4f2fd53 100644
--- a/lib/std/crypto/siphash.zig
+++ b/lib/std/crypto/siphash.zig
@@ -433,7 +433,7 @@ test "iterative non-divisible update" {
         var siphash = Siphash.init(key);
         var i: usize = 0;
         while (i < end) : (i += 7) {
-            siphash.update(buf[i..std.math.min(i + 7, end)]);
+            siphash.update(buf[i..@min(i + 7, end)]);
         }
         const iterative_hash = siphash.finalInt();
 
diff --git a/lib/std/debug.zig b/lib/std/debug.zig
index ea0d467085..3015c30bfb 100644
--- a/lib/std/debug.zig
+++ b/lib/std/debug.zig
@@ -198,7 +198,7 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *std.builtin.StackT
             stack_trace.index = 0;
             return;
         };
-        const end_index = math.min(first_index + addrs.len, n);
+        const end_index = @min(first_index + addrs.len, n);
         const slice = addr_buf[first_index..end_index];
         // We use a for loop here because slice and addrs may alias.
         for (slice, 0..) |addr, i| {
@@ -380,7 +380,7 @@ pub fn writeStackTrace(
     _ = allocator;
     if (builtin.strip_debug_info) return error.MissingDebugInfo;
     var frame_index: usize = 0;
-    var frames_left: usize = std.math.min(stack_trace.index, stack_trace.instruction_addresses.len);
+    var frames_left: usize = @min(stack_trace.index, stack_trace.instruction_addresses.len);
 
     while (frames_left != 0) : ({
         frames_left -= 1;
diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig
index 59ad7429cf..94da2f4d6d 100644
--- a/lib/std/dynamic_library.zig
+++ b/lib/std/dynamic_library.zig
@@ -8,7 +8,6 @@ const elf = std.elf;
 const windows = std.os.windows;
 const system = std.os.system;
 const maxInt = std.math.maxInt;
-const max = std.math.max;
 
 pub const DynLib = switch (builtin.os.tag) {
     .linux => if (builtin.link_libc) DlDynlib else ElfDynLib,
@@ -152,7 +151,7 @@ pub const ElfDynLib = struct {
             }) {
                 const ph = @intToPtr(*elf.Phdr, ph_addr);
                 switch (ph.p_type) {
-                    elf.PT_LOAD => virt_addr_end = max(virt_addr_end, ph.p_vaddr + ph.p_memsz),
+                    elf.PT_LOAD => virt_addr_end = @max(virt_addr_end, ph.p_vaddr + ph.p_memsz),
                     elf.PT_DYNAMIC => maybe_dynv = @intToPtr([*]usize, elf_addr + ph.p_offset),
                     else => {},
                 }
diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig
index c8d41d3eb0..bc0162423b 100644
--- a/lib/std/event/loop.zig
+++ b/lib/std/event/loop.zig
@@ -179,7 +179,7 @@ pub const Loop = struct {
 
         // We need at least one of these in case the fs thread wants to use onNextTick
         const extra_thread_count = thread_count - 1;
-        const resume_node_count = std.math.max(extra_thread_count, 1);
+        const resume_node_count = @max(extra_thread_count, 1);
         self.eventfd_resume_nodes = try self.arena.allocator().alloc(
             std.atomic.Stack(ResumeNode.EventFd).Node,
             resume_node_count,
diff --git a/lib/std/fifo.zig b/lib/std/fifo.zig
index bc88e61d76..535376d38f 100644
--- a/lib/std/fifo.zig
+++ b/lib/std/fifo.zig
@@ -150,7 +150,7 @@ pub fn LinearFifo(
                 start -= self.buf.len;
                 return self.buf[start .. start + (self.count - offset)];
             } else {
-                const end = math.min(self.head + self.count, self.buf.len);
+                const end = @min(self.head + self.count, self.buf.len);
                 return self.buf[start..end];
             }
         }
diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig
index 6896d0a7a0..c9d8e611ca 100644
--- a/lib/std/fmt.zig
+++ b/lib/std/fmt.zig
@@ -921,8 +921,8 @@ fn formatSizeImpl(comptime base: comptime_int) type {
 
             const log2 = math.log2(value);
             const magnitude = switch (base) {
-                1000 => math.min(log2 / comptime math.log2(1000), mags_si.len - 1),
-                1024 => math.min(log2 / 10, mags_iec.len - 1),
+                1000 => @min(log2 / comptime math.log2(1000), mags_si.len - 1),
+                1024 => @min(log2 / 10, mags_iec.len - 1),
                 else => unreachable,
             };
             const new_value = lossyCast(f64, value) / math.pow(f64, lossyCast(f64, base), lossyCast(f64, magnitude));
@@ -1103,7 +1103,7 @@ pub fn formatFloatScientific(
 
             var printed: usize = 0;
             if (float_decimal.digits.len > 1) {
-                const num_digits = math.min(float_decimal.digits.len, precision + 1);
+                const num_digits = @min(float_decimal.digits.len, precision + 1);
                 try writer.writeAll(float_decimal.digits[1..num_digits]);
                 printed += num_digits - 1;
             }
@@ -1116,7 +1116,7 @@ pub fn formatFloatScientific(
         try writer.writeAll(float_decimal.digits[0..1]);
         try writer.writeAll(".");
         if (float_decimal.digits.len > 1) {
-            const num_digits = if (@TypeOf(value) == f32) math.min(@as(usize, 9), float_decimal.digits.len) else float_decimal.digits.len;
+            const num_digits = if (@TypeOf(value) == f32) @min(@as(usize, 9), float_decimal.digits.len) else float_decimal.digits.len;
 
             try writer.writeAll(float_decimal.digits[1..num_digits]);
         } else {
@@ -1299,7 +1299,7 @@ pub fn formatFloatDecimal(
         var num_digits_whole = if (float_decimal.exp > 0) @intCast(usize, float_decimal.exp) else 0;
 
         // the actual slice into the buffer, we may need to zero-pad between num_digits_whole and this.
-        var num_digits_whole_no_pad = math.min(num_digits_whole, float_decimal.digits.len);
+        var num_digits_whole_no_pad = @min(num_digits_whole, float_decimal.digits.len);
 
         if (num_digits_whole > 0) {
             // We may have to zero pad, for instance 1e4 requires zero padding.
@@ -1326,7 +1326,7 @@ pub fn formatFloatDecimal(
         // Zero-fill until we reach significant digits or run out of precision.
         if (float_decimal.exp <= 0) {
             const zero_digit_count = @intCast(usize, -float_decimal.exp);
-            const zeros_to_print = math.min(zero_digit_count, precision);
+            const zeros_to_print = @min(zero_digit_count, precision);
 
             var i: usize = 0;
             while (i < zeros_to_print) : (i += 1) {
@@ -1357,7 +1357,7 @@ pub fn formatFloatDecimal(
         var num_digits_whole = if (float_decimal.exp > 0) @intCast(usize, float_decimal.exp) else 0;
 
         // the actual slice into the buffer, we may need to zero-pad between num_digits_whole and this.
-        var num_digits_whole_no_pad = math.min(num_digits_whole, float_decimal.digits.len);
+        var num_digits_whole_no_pad = @min(num_digits_whole, float_decimal.digits.len);
 
         if (num_digits_whole > 0) {
             // We may have to zero pad, for instance 1e4 requires zero padding.
@@ -1410,12 +1410,12 @@ pub fn formatInt(
 
     // The type must have the same size as `base` or be wider in order for the
     // division to work
-    const min_int_bits = comptime math.max(value_info.bits, 8);
+    const min_int_bits = comptime @max(value_info.bits, 8);
     const MinInt = std.meta.Int(.unsigned, min_int_bits);
 
     const abs_value = math.absCast(int_value);
     // The worst case in terms of space needed is base 2, plus 1 for the sign
-    var buf: [1 + math.max(value_info.bits, 1)]u8 = undefined;
+    var buf: [1 + @max(@as(comptime_int, value_info.bits), 1)]u8 = undefined;
 
     var a: MinInt = abs_value;
     var index: usize = buf.len;
diff --git a/lib/std/hash/wyhash.zig b/lib/std/hash/wyhash.zig
index 3426bca9f4..c36c3fe87c 100644
--- a/lib/std/hash/wyhash.zig
+++ b/lib/std/hash/wyhash.zig
@@ -252,7 +252,7 @@ test "iterative non-divisible update" {
         var wy = Wyhash.init(seed);
         var i: usize = 0;
         while (i < end) : (i += 33) {
-            wy.update(buf[i..std.math.min(i + 33, end)]);
+            wy.update(buf[i..@min(i + 33, end)]);
         }
         const iterative_hash = wy.final();
 
diff --git a/lib/std/hash_map.zig b/lib/std/hash_map.zig
index 041d99606e..5b539ddaad 100644
--- a/lib/std/hash_map.zig
+++ b/lib/std/hash_map.zig
@@ -1507,7 +1507,7 @@ pub fn HashMapUnmanaged(
 
         fn grow(self: *Self, allocator: Allocator, new_capacity: Size, ctx: Context) Allocator.Error!void {
             @setCold(true);
-            const new_cap = std.math.max(new_capacity, minimal_capacity);
+            const new_cap = @max(new_capacity, minimal_capacity);
             assert(new_cap > self.capacity());
             assert(std.math.isPowerOfTwo(new_cap));
 
@@ -1540,7 +1540,7 @@ pub fn HashMapUnmanaged(
             const header_align = @alignOf(Header);
             const key_align = if (@sizeOf(K) == 0) 1 else @alignOf(K);
             const val_align = if (@sizeOf(V) == 0) 1 else @alignOf(V);
-            const max_align = comptime math.max3(header_align, key_align, val_align);
+            const max_align = comptime @max(header_align, key_align, val_align);
 
             const meta_size = @sizeOf(Header) + new_capacity * @sizeOf(Metadata);
             comptime assert(@alignOf(Metadata) == 1);
@@ -1575,7 +1575,7 @@ pub fn HashMapUnmanaged(
             const header_align = @alignOf(Header);
             const key_align = if (@sizeOf(K) == 0) 1 else @alignOf(K);
             const val_align = if (@sizeOf(V) == 0) 1 else @alignOf(V);
-            const max_align = comptime math.max3(header_align, key_align, val_align);
+            const max_align = comptime @max(header_align, key_align, val_align);
 
             const cap = self.capacity();
             const meta_size = @sizeOf(Header) + cap * @sizeOf(Metadata);
diff --git a/lib/std/heap/arena_allocator.zig b/lib/std/heap/arena_allocator.zig
index c0eeae6e61..c7e0569067 100644
--- a/lib/std/heap/arena_allocator.zig
+++ b/lib/std/heap/arena_allocator.zig
@@ -110,7 +110,7 @@ pub const ArenaAllocator = struct {
         // value.
         const requested_capacity = switch (mode) {
             .retain_capacity => self.queryCapacity(),
-            .retain_with_limit => |limit| std.math.min(limit, self.queryCapacity()),
+            .retain_with_limit => |limit| @min(limit, self.queryCapacity()),
             .free_all => 0,
         };
         if (requested_capacity == 0) {
diff --git a/lib/std/heap/memory_pool.zig b/lib/std/heap/memory_pool.zig
index ca6eb7f518..3fc7dfbfca 100644
--- a/lib/std/heap/memory_pool.zig
+++ b/lib/std/heap/memory_pool.zig
@@ -40,11 +40,11 @@ pub fn MemoryPoolExtra(comptime Item: type, comptime pool_options: Options) type
 
         /// Size of the memory pool items. This is not necessarily the same
         /// as `@sizeOf(Item)` as the pool also uses the items for internal means.
-        pub const item_size = std.math.max(@sizeOf(Node), @sizeOf(Item));
+        pub const item_size = @max(@sizeOf(Node), @sizeOf(Item));
 
         /// Alignment of the memory pool items. This is not necessarily the same
         /// as `@alignOf(Item)` as the pool also uses the items for internal means.
-        pub const item_alignment = std.math.max(@alignOf(Node), pool_options.alignment orelse 0);
+        pub const item_alignment = @max(@alignOf(Node), pool_options.alignment orelse 0);
 
         const Node = struct {
             next: ?*@This(),
diff --git a/lib/std/http/protocol.zig b/lib/std/http/protocol.zig
index b001b3cddf..b5c2cdfa0c 100644
--- a/lib/std/http/protocol.zig
+++ b/lib/std/http/protocol.zig
@@ -82,7 +82,7 @@ pub const HeadersParser = struct {
     /// If the amount returned is less than `bytes.len`, you may assume that the parser is in a content state and the
     /// first byte of content is located at `bytes[result]`.
     pub fn findHeadersEnd(r: *HeadersParser, bytes: []const u8) u32 {
-        const vector_len: comptime_int = comptime std.math.max(std.simd.suggestVectorSize(u8) orelse 1, 8);
+        const vector_len: comptime_int = comptime @max(std.simd.suggestVectorSize(u8) orelse 1, 8);
         const len = @intCast(u32, bytes.len);
         var index: u32 = 0;
 
diff --git a/lib/std/io/fixed_buffer_stream.zig b/lib/std/io/fixed_buffer_stream.zig
index c170dd1f74..27b978744c 100644
--- a/lib/std/io/fixed_buffer_stream.zig
+++ b/lib/std/io/fixed_buffer_stream.zig
@@ -76,7 +76,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
         }
 
         pub fn seekTo(self: *Self, pos: u64) SeekError!void {
-            self.pos = if (std.math.cast(usize, pos)) |x| std.math.min(self.buffer.len, x) else self.buffer.len;
+            self.pos = if (std.math.cast(usize, pos)) |x| @min(self.buffer.len, x) else self.buffer.len;
         }
 
         pub fn seekBy(self: *Self, amt: i64) SeekError!void {
@@ -91,7 +91,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
             } else {
                 const amt_usize = std.math.cast(usize, amt) orelse std.math.maxInt(usize);
                 const new_pos = std.math.add(usize, self.pos, amt_usize) catch std.math.maxInt(usize);
-                self.pos = std.math.min(self.buffer.len, new_pos);
+                self.pos = @min(self.buffer.len, new_pos);
             }
         }
 
diff --git a/lib/std/io/limited_reader.zig b/lib/std/io/limited_reader.zig
index aa00af0d09..09d76007da 100644
--- a/lib/std/io/limited_reader.zig
+++ b/lib/std/io/limited_reader.zig
@@ -14,7 +14,7 @@ pub fn LimitedReader(comptime ReaderType: type) type {
         const Self = @This();
 
         pub fn read(self: *Self, dest: []u8) Error!usize {
-            const max_read = std.math.min(self.bytes_left, dest.len);
+            const max_read = @min(self.bytes_left, dest.len);
             const n = try self.inner_reader.read(dest[0..max_read]);
             self.bytes_left -= n;
             return n;
diff --git a/lib/std/io/reader.zig b/lib/std/io/reader.zig
index 344515d07b..abdca56d3c 100644
--- a/lib/std/io/reader.zig
+++ b/lib/std/io/reader.zig
@@ -325,7 +325,7 @@ pub fn Reader(
             var remaining = num_bytes;
 
             while (remaining > 0) {
-                const amt = std.math.min(remaining, options.buf_size);
+                const amt = @min(remaining, options.buf_size);
                 try self.readNoEof(buf[0..amt]);
                 remaining -= amt;
             }
diff --git a/lib/std/io/writer.zig b/lib/std/io/writer.zig
index cfc76de452..d0b7fa11ee 100644
--- a/lib/std/io/writer.zig
+++ b/lib/std/io/writer.zig
@@ -39,7 +39,7 @@ pub fn Writer(
 
             var remaining: usize = n;
             while (remaining > 0) {
-                const to_write = std.math.min(remaining, bytes.len);
+                const to_write = @min(remaining, bytes.len);
                 try self.writeAll(bytes[0..to_write]);
                 remaining -= to_write;
             }
diff --git a/lib/std/math.zig b/lib/std/math.zig
index 46a7e40a37..e60e964747 100644
--- a/lib/std/math.zig
+++ b/lib/std/math.zig
@@ -165,7 +165,7 @@ pub fn approxEqRel(comptime T: type, x: T, y: T, tolerance: T) bool {
     if (isNan(x) or isNan(y))
         return false;
 
-    return @fabs(x - y) <= max(@fabs(x), @fabs(y)) * tolerance;
+    return @fabs(x - y) <= @max(@fabs(x), @fabs(y)) * tolerance;
 }
 
 test "approxEqAbs and approxEqRel" {
@@ -434,104 +434,15 @@ pub fn Min(comptime A: type, comptime B: type) type {
     return @TypeOf(@as(A, 0) + @as(B, 0));
 }
 
-/// Returns the smaller number. When one parameter's type's full range
-/// fits in the other, the return type is the smaller type.
-pub fn min(x: anytype, y: anytype) Min(@TypeOf(x), @TypeOf(y)) {
-    const Result = Min(@TypeOf(x), @TypeOf(y));
-    if (x < y) {
-        // TODO Zig should allow this as an implicit cast because x is
-        // immutable and in this scope it is known to fit in the
-        // return type.
-        switch (@typeInfo(Result)) {
-            .Int => return @intCast(Result, x),
-            else => return x,
-        }
-    } else {
-        // TODO Zig should allow this as an implicit cast because y is
-        // immutable and in this scope it is known to fit in the
-        // return type.
-        switch (@typeInfo(Result)) {
-            .Int => return @intCast(Result, y),
-            else => return y,
-        }
-    }
-}
-
-test "min" {
-    try testing.expect(min(@as(i32, -1), @as(i32, 2)) == -1);
-    {
-        var a: u16 = 999;
-        var b: u32 = 10;
-        var result = min(a, b);
-        try testing.expect(@TypeOf(result) == u16);
-        try testing.expect(result == 10);
-    }
-    {
-        var a: f64 = 10.34;
-        var b: f32 = 999.12;
-        var result = min(a, b);
-        try testing.expect(@TypeOf(result) == f64);
-        try testing.expect(result == 10.34);
-    }
-    {
-        var a: i8 = -127;
-        var b: i16 = -200;
-        var result = min(a, b);
-        try testing.expect(@TypeOf(result) == i16);
-        try testing.expect(result == -200);
-    }
-    {
-        const a = 10.34;
-        var b: f32 = 999.12;
-        var result = min(a, b);
-        try testing.expect(@TypeOf(result) == f32);
-        try testing.expect(result == 10.34);
-    }
-}
-
-/// Finds the minimum of three numbers.
-pub fn min3(x: anytype, y: anytype, z: anytype) @TypeOf(x, y, z) {
-    return min(x, min(y, z));
-}
-
-test "min3" {
-    try testing.expect(min3(@as(i32, 0), @as(i32, 1), @as(i32, 2)) == 0);
-    try testing.expect(min3(@as(i32, 0), @as(i32, 2), @as(i32, 1)) == 0);
-    try testing.expect(min3(@as(i32, 1), @as(i32, 0), @as(i32, 2)) == 0);
-    try testing.expect(min3(@as(i32, 1), @as(i32, 2), @as(i32, 0)) == 0);
-    try testing.expect(min3(@as(i32, 2), @as(i32, 0), @as(i32, 1)) == 0);
-    try testing.expect(min3(@as(i32, 2), @as(i32, 1), @as(i32, 0)) == 0);
-}
-
-/// Returns the maximum of two numbers. Return type is the one with the
-/// larger range.
-pub fn max(x: anytype, y: anytype) @TypeOf(x, y) {
-    return if (x > y) x else y;
-}
-
-test "max" {
-    try testing.expect(max(@as(i32, -1), @as(i32, 2)) == 2);
-    try testing.expect(max(@as(i32, 2), @as(i32, -1)) == 2);
-}
-
-/// Finds the maximum of three numbers.
-pub fn max3(x: anytype, y: anytype, z: anytype) @TypeOf(x, y, z) {
-    return max(x, max(y, z));
-}
-
-test "max3" {
-    try testing.expect(max3(@as(i32, 0), @as(i32, 1), @as(i32, 2)) == 2);
-    try testing.expect(max3(@as(i32, 0), @as(i32, 2), @as(i32, 1)) == 2);
-    try testing.expect(max3(@as(i32, 1), @as(i32, 0), @as(i32, 2)) == 2);
-    try testing.expect(max3(@as(i32, 1), @as(i32, 2), @as(i32, 0)) == 2);
-    try testing.expect(max3(@as(i32, 2), @as(i32, 0), @as(i32, 1)) == 2);
-    try testing.expect(max3(@as(i32, 2), @as(i32, 1), @as(i32, 0)) == 2);
-}
+pub const min = @compileError("deprecated; use @min instead");
+pub const max = @compileError("deprecated; use @max instead");
+pub const min3 = @compileError("deprecated; use @min instead");
+pub const max3 = @compileError("deprecated; use @max instead");
 
 /// Limit val to the inclusive range [lower, upper].
 pub fn clamp(val: anytype, lower: anytype, upper: anytype) @TypeOf(val, lower, upper) {
     assert(lower <= upper);
-    return max(lower, min(val, upper));
+    return @max(lower, @min(val, upper));
 }
 test "clamp" {
     // Within range
@@ -795,7 +706,7 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t
         return u0;
     }
     const signedness: std.builtin.Signedness = if (from < 0) .signed else .unsigned;
-    const largest_positive_integer = max(if (from < 0) (-from) - 1 else from, to); // two's complement
+    const largest_positive_integer = @max(if (from < 0) (-from) - 1 else from, to); // two's complement
     const base = log2(largest_positive_integer);
     const upper = (1 << base) - 1;
     var magnitude_bits = if (upper >= largest_positive_integer) base else base + 1;
diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig
index ec79d843da..487812e1de 100644
--- a/lib/std/math/big/int.zig
+++ b/lib/std/math/big/int.zig
@@ -44,12 +44,12 @@ pub fn calcDivLimbsBufferLen(a_len: usize, b_len: usize) usize {
 }
 
 pub fn calcMulLimbsBufferLen(a_len: usize, b_len: usize, aliases: usize) usize {
-    return aliases * math.max(a_len, b_len);
+    return aliases * @max(a_len, b_len);
 }
 
 pub fn calcMulWrapLimbsBufferLen(bit_count: usize, a_len: usize, b_len: usize, aliases: usize) usize {
     const req_limbs = calcTwosCompLimbCount(bit_count);
-    return aliases * math.min(req_limbs, math.max(a_len, b_len));
+    return aliases * @min(req_limbs, @max(a_len, b_len));
 }
 
 pub fn calcSetStringLimbsBufferLen(base: u8, string_len: usize) usize {
@@ -396,7 +396,7 @@ pub const Mutable = struct {
     /// scalar is a primitive integer type.
     ///
     /// Asserts the result fits in `r`. An upper bound on the number of limbs needed by
-    /// r is `math.max(a.limbs.len, calcLimbLen(scalar)) + 1`.
+    /// r is `@max(a.limbs.len, calcLimbLen(scalar)) + 1`.
     pub fn addScalar(r: *Mutable, a: Const, scalar: anytype) void {
         // Normally we could just determine the number of limbs needed with calcLimbLen,
         // but that is not comptime-known when scalar is not a comptime_int.  Instead, we
@@ -414,11 +414,11 @@ pub const Mutable = struct {
         return add(r, a, operand);
     }
 
-    /// Base implementation for addition. Adds `max(a.limbs.len, b.limbs.len)` elements from a and b,
+    /// Base implementation for addition. Adds `@max(a.limbs.len, b.limbs.len)` elements from a and b,
     /// and returns whether any overflow occurred.
     /// r, a and b may be aliases.
     ///
-    /// Asserts r has enough elements to hold the result. The upper bound is `max(a.limbs.len, b.limbs.len)`.
+    /// Asserts r has enough elements to hold the result. The upper bound is `@max(a.limbs.len, b.limbs.len)`.
     fn addCarry(r: *Mutable, a: Const, b: Const) bool {
         if (a.eqZero()) {
             r.copy(b);
@@ -452,12 +452,12 @@ pub const Mutable = struct {
     /// r, a and b may be aliases.
     ///
     /// Asserts the result fits in `r`. An upper bound on the number of limbs needed by
-    /// r is `math.max(a.limbs.len, b.limbs.len) + 1`.
+    /// r is `@max(a.limbs.len, b.limbs.len) + 1`.
     pub fn add(r: *Mutable, a: Const, b: Const) void {
         if (r.addCarry(a, b)) {
             // Fix up the result. Note that addCarry normalizes by a.limbs.len or b.limbs.len,
             // so we need to set the length here.
-            const msl = math.max(a.limbs.len, b.limbs.len);
+            const msl = @max(a.limbs.len, b.limbs.len);
             // `[add|sub]Carry` normalizes by `msl`, so we need to fix up the result manually here.
             // Note, the fact that it normalized means that the intermediary limbs are zero here.
             r.len = msl + 1;
@@ -477,12 +477,12 @@ pub const Mutable = struct {
         // if an overflow occurred.
         const x = Const{
             .positive = a.positive,
-            .limbs = a.limbs[0..math.min(req_limbs, a.limbs.len)],
+            .limbs = a.limbs[0..@min(req_limbs, a.limbs.len)],
         };
 
         const y = Const{
             .positive = b.positive,
-            .limbs = b.limbs[0..math.min(req_limbs, b.limbs.len)],
+            .limbs = b.limbs[0..@min(req_limbs, b.limbs.len)],
         };
 
         var carry_truncated = false;
@@ -492,7 +492,7 @@ pub const Mutable = struct {
             //   truncate anyway.
             // - a and b had less elements than req_limbs, and those were overflowed. This case needs to be handled.
             //   Note: after this we still might need to wrap.
-            const msl = math.max(a.limbs.len, b.limbs.len);
+            const msl = @max(a.limbs.len, b.limbs.len);
             if (msl < req_limbs) {
                 r.limbs[msl] = 1;
                 r.len = req_limbs;
@@ -522,12 +522,12 @@ pub const Mutable = struct {
         // if an overflow occurred.
         const x = Const{
             .positive = a.positive,
-            .limbs = a.limbs[0..math.min(req_limbs, a.limbs.len)],
+            .limbs = a.limbs[0..@min(req_limbs, a.limbs.len)],
         };
 
         const y = Const{
             .positive = b.positive,
-            .limbs = b.limbs[0..math.min(req_limbs, b.limbs.len)],
+            .limbs = b.limbs[0..@min(req_limbs, b.limbs.len)],
         };
 
         if (r.addCarry(x, y)) {
@@ -535,7 +535,7 @@ pub const Mutable = struct {
             // - We overflowed req_limbs, in which case we need to saturate.
             // - a and b had less elements than req_limbs, and those were overflowed.
             //   Note: In this case, might _also_ need to saturate.
-            const msl = math.max(a.limbs.len, b.limbs.len);
+            const msl = @max(a.limbs.len, b.limbs.len);
             if (msl < req_limbs) {
                 r.limbs[msl] = 1;
                 r.len = req_limbs;
@@ -550,11 +550,11 @@ pub const Mutable = struct {
         r.saturate(r.toConst(), signedness, bit_count);
     }
 
-    /// Base implementation for subtraction. Subtracts `max(a.limbs.len, b.limbs.len)` elements from a and b,
+    /// Base implementation for subtraction. Subtracts `@max(a.limbs.len, b.limbs.len)` elements from a and b,
     /// and returns whether any overflow occurred.
     /// r, a and b may be aliases.
     ///
-    /// Asserts r has enough elements to hold the result. The upper bound is `max(a.limbs.len, b.limbs.len)`.
+    /// Asserts r has enough elements to hold the result. The upper bound is `@max(a.limbs.len, b.limbs.len)`.
     fn subCarry(r: *Mutable, a: Const, b: Const) bool {
         if (a.eqZero()) {
             r.copy(b);
@@ -607,7 +607,7 @@ pub const Mutable = struct {
     /// r, a and b may be aliases.
     ///
     /// Asserts the result fits in `r`. An upper bound on the number of limbs needed by
-    /// r is `math.max(a.limbs.len, b.limbs.len) + 1`. The +1 is not needed if both operands are positive.
+    /// r is `@max(a.limbs.len, b.limbs.len) + 1`. The +1 is not needed if both operands are positive.
     pub fn sub(r: *Mutable, a: Const, b: Const) void {
         r.add(a, b.negate());
     }
@@ -714,7 +714,7 @@ pub const Mutable = struct {
 
         const a_copy = if (rma.limbs.ptr == a.limbs.ptr) blk: {
             const start = buf_index;
-            const a_len = math.min(req_limbs, a.limbs.len);
+            const a_len = @min(req_limbs, a.limbs.len);
             @memcpy(limbs_buffer[buf_index..][0..a_len], a.limbs[0..a_len]);
             buf_index += a_len;
             break :blk a.toMutable(limbs_buffer[start..buf_index]).toConst();
@@ -722,7 +722,7 @@ pub const Mutable = struct {
 
         const b_copy = if (rma.limbs.ptr == b.limbs.ptr) blk: {
             const start = buf_index;
-            const b_len = math.min(req_limbs, b.limbs.len);
+            const b_len = @min(req_limbs, b.limbs.len);
             @memcpy(limbs_buffer[buf_index..][0..b_len], b.limbs[0..b_len]);
             buf_index += b_len;
             break :blk a.toMutable(limbs_buffer[start..buf_index]).toConst();
@@ -755,13 +755,13 @@ pub const Mutable = struct {
         const req_limbs = calcTwosCompLimbCount(bit_count);
 
         // We can ignore the upper bits here, those results will be discarded anyway.
-        const a_limbs = a.limbs[0..math.min(req_limbs, a.limbs.len)];
-        const b_limbs = b.limbs[0..math.min(req_limbs, b.limbs.len)];
+        const a_limbs = a.limbs[0..@min(req_limbs, a.limbs.len)];
+        const b_limbs = b.limbs[0..@min(req_limbs, b.limbs.len)];
 
         @memset(rma.limbs[0..req_limbs], 0);
 
         llmulacc(.add, allocator, rma.limbs, a_limbs, b_limbs);
-        rma.normalize(math.min(req_limbs, a.limbs.len + b.limbs.len));
+        rma.normalize(@min(req_limbs, a.limbs.len + b.limbs.len));
         rma.positive = (a.positive == b.positive);
         rma.truncate(rma.toConst(), signedness, bit_count);
     }
@@ -1211,7 +1211,7 @@ pub const Mutable = struct {
     ///
     /// a and b are zero-extended to the longer of a or b.
     ///
-    /// Asserts that r has enough limbs to store the result. Upper bound is `math.max(a.limbs.len, b.limbs.len)`.
+    /// Asserts that r has enough limbs to store the result. Upper bound is `@max(a.limbs.len, b.limbs.len)`.
     pub fn bitOr(r: *Mutable, a: Const, b: Const) void {
         // Trivial cases, llsignedor does not support zero.
         if (a.eqZero()) {
@@ -1235,8 +1235,8 @@ pub const Mutable = struct {
     /// r may alias with a or b.
     ///
     /// Asserts that r has enough limbs to store the result.
-    /// If a or b is positive, the upper bound is `math.min(a.limbs.len, b.limbs.len)`.
-    /// If a and b are negative, the upper bound is `math.max(a.limbs.len, b.limbs.len) + 1`.
+    /// If a or b is positive, the upper bound is `@min(a.limbs.len, b.limbs.len)`.
+    /// If a and b are negative, the upper bound is `@max(a.limbs.len, b.limbs.len) + 1`.
     pub fn bitAnd(r: *Mutable, a: Const, b: Const) void {
         // Trivial cases, llsignedand does not support zero.
         if (a.eqZero()) {
@@ -1260,8 +1260,8 @@ pub const Mutable = struct {
     /// r may alias with a or b.
     ///
     /// Asserts that r has enough limbs to store the result. If a and b share the same signedness, the
-    /// upper bound is `math.max(a.limbs.len, b.limbs.len)`. Otherwise, if either a or b is negative
-    /// but not both, the upper bound is `math.max(a.limbs.len, b.limbs.len) + 1`.
+    /// upper bound is `@max(a.limbs.len, b.limbs.len)`. Otherwise, if either a or b is negative
+    /// but not both, the upper bound is `@max(a.limbs.len, b.limbs.len) + 1`.
     pub fn bitXor(r: *Mutable, a: Const, b: Const) void {
         // Trivial cases, because llsignedxor does not support negative zero.
         if (a.eqZero()) {
@@ -1284,7 +1284,7 @@ pub const Mutable = struct {
     /// rma may alias x or y.
     /// x and y may alias each other.
     /// Asserts that `rma` has enough limbs to store the result. Upper bound is
-    /// `math.min(x.limbs.len, y.limbs.len)`.
+    /// `@min(x.limbs.len, y.limbs.len)`.
     ///
     /// `limbs_buffer` is used for temporary storage during the operation. When this function returns,
     /// it will have the same length as it had when the function was called.
@@ -1546,7 +1546,7 @@ pub const Mutable = struct {
             if (yi != 0) break i;
         } else unreachable;
 
-        const xy_trailing = math.min(x_trailing, y_trailing);
+        const xy_trailing = @min(x_trailing, y_trailing);
 
         if (y.len - xy_trailing == 1) {
             const divisor = y.limbs[y.len - 1];
@@ -2589,7 +2589,7 @@ pub const Managed = struct {
             .allocator = allocator,
             .metadata = 1,
             .limbs = block: {
-                const limbs = try allocator.alloc(Limb, math.max(default_capacity, capacity));
+                const limbs = try allocator.alloc(Limb, @max(default_capacity, capacity));
                 limbs[0] = 0;
                 break :block limbs;
             },
@@ -2918,7 +2918,7 @@ pub const Managed = struct {
     ///
     /// Returns an error if memory could not be allocated.
     pub fn sub(r: *Managed, a: *const Managed, b: *const Managed) !void {
-        try r.ensureCapacity(math.max(a.len(), b.len()) + 1);
+        try r.ensureCapacity(@max(a.len(), b.len()) + 1);
         var m = r.toMutable();
         m.sub(a.toConst(), b.toConst());
         r.setMetadata(m.positive, m.len);
@@ -3025,11 +3025,11 @@ pub const Managed = struct {
     }
 
     pub fn ensureAddScalarCapacity(r: *Managed, a: Const, scalar: anytype) !void {
-        try r.ensureCapacity(math.max(a.limbs.len, calcLimbLen(scalar)) + 1);
+        try r.ensureCapacity(@max(a.limbs.len, calcLimbLen(scalar)) + 1);
     }
 
     pub fn ensureAddCapacity(r: *Managed, a: Const, b: Const) !void {
-        try r.ensureCapacity(math.max(a.limbs.len, b.limbs.len) + 1);
+        try r.ensureCapacity(@max(a.limbs.len, b.limbs.len) + 1);
     }
 
     pub fn ensureMulCapacity(rma: *Managed, a: Const, b: Const) !void {
@@ -3123,7 +3123,7 @@ pub const Managed = struct {
     ///
     /// a and b are zero-extended to the longer of a or b.
     pub fn bitOr(r: *Managed, a: *const Managed, b: *const Managed) !void {
-        try r.ensureCapacity(math.max(a.len(), b.len()));
+        try r.ensureCapacity(@max(a.len(), b.len()));
         var m = r.toMutable();
         m.bitOr(a.toConst(), b.toConst());
         r.setMetadata(m.positive, m.len);
@@ -3132,9 +3132,9 @@ pub const Managed = struct {
     /// r = a & b
     pub fn bitAnd(r: *Managed, a: *const Managed, b: *const Managed) !void {
         const cap = if (a.isPositive() or b.isPositive())
-            math.min(a.len(), b.len())
+            @min(a.len(), b.len())
         else
-            math.max(a.len(), b.len()) + 1;
+            @max(a.len(), b.len()) + 1;
         try r.ensureCapacity(cap);
         var m = r.toMutable();
         m.bitAnd(a.toConst(), b.toConst());
@@ -3143,7 +3143,7 @@ pub const Managed = struct {
 
     /// r = a ^ b
     pub fn bitXor(r: *Managed, a: *const Managed, b: *const Managed) !void {
-        var cap = math.max(a.len(), b.len()) + @boolToInt(a.isPositive() != b.isPositive());
+        var cap = @max(a.len(), b.len()) + @boolToInt(a.isPositive() != b.isPositive());
         try r.ensureCapacity(cap);
 
         var m = r.toMutable();
@@ -3156,7 +3156,7 @@ pub const Managed = struct {
     ///
     /// rma's allocator is used for temporary storage to boost multiplication performance.
     pub fn gcd(rma: *Managed, x: *const Managed, y: *const Managed) !void {
-        try rma.ensureCapacity(math.min(x.len(), y.len()));
+        try rma.ensureCapacity(@min(x.len(), y.len()));
         var m = rma.toMutable();
         var limbs_buffer = std.ArrayList(Limb).init(rma.allocator);
         defer limbs_buffer.deinit();
@@ -3356,13 +3356,13 @@ fn llmulaccKaratsuba(
     // For a1 and b1 we only need `limbs_after_split` limbs.
     const a1 = blk: {
         var a1 = a[split..];
-        a1.len = math.min(llnormalize(a1), limbs_after_split);
+        a1.len = @min(llnormalize(a1), limbs_after_split);
         break :blk a1;
     };
 
     const b1 = blk: {
         var b1 = b[split..];
-        b1.len = math.min(llnormalize(b1), limbs_after_split);
+        b1.len = @min(llnormalize(b1), limbs_after_split);
         break :blk b1;
     };
 
@@ -3381,10 +3381,10 @@ fn llmulaccKaratsuba(
 
     // Compute p2.
     // Note, we don't need to compute all of p2, just enough limbs to satisfy r.
-    const p2_limbs = math.min(limbs_after_split, a1.len + b1.len);
+    const p2_limbs = @min(limbs_after_split, a1.len + b1.len);
 
     @memset(tmp[0..p2_limbs], 0);
-    llmulacc(.add, allocator, tmp[0..p2_limbs], a1[0..math.min(a1.len, p2_limbs)], b1[0..math.min(b1.len, p2_limbs)]);
+    llmulacc(.add, allocator, tmp[0..p2_limbs], a1[0..@min(a1.len, p2_limbs)], b1[0..@min(b1.len, p2_limbs)]);
     const p2 = tmp[0..llnormalize(tmp[0..p2_limbs])];
 
     // Add p2 * B to the result.
@@ -3392,7 +3392,7 @@ fn llmulaccKaratsuba(
 
     // Add p2 * B^2 to the result if required.
     if (limbs_after_split2 > 0) {
-        llaccum(op, r[split * 2 ..], p2[0..math.min(p2.len, limbs_after_split2)]);
+        llaccum(op, r[split * 2 ..], p2[0..@min(p2.len, limbs_after_split2)]);
     }
 
     // Compute p0.
@@ -3406,13 +3406,13 @@ fn llmulaccKaratsuba(
     llaccum(op, r, p0);
 
     // Add p0 * B to the result. In this case, we may not need all of it.
-    llaccum(op, r[split..], p0[0..math.min(limbs_after_split, p0.len)]);
+    llaccum(op, r[split..], p0[0..@min(limbs_after_split, p0.len)]);
 
     // Finally, compute and add p1.
     // From now on we only need `limbs_after_split` limbs for a0 and b0, since the result of the
     // following computation will be added * B.
-    const a0x = a0[0..std.math.min(a0.len, limbs_after_split)];
-    const b0x = b0[0..std.math.min(b0.len, limbs_after_split)];
+    const a0x = a0[0..@min(a0.len, limbs_after_split)];
+    const b0x = b0[0..@min(b0.len, limbs_after_split)];
 
     const j0_sign = llcmp(a0x, a1);
     const j1_sign = llcmp(b1, b0x);
@@ -3544,7 +3544,7 @@ fn llmulLimb(comptime op: AccOp, acc: []Limb, y: []const Limb, xi: Limb) bool {
         return false;
     }
 
-    const split = std.math.min(y.len, acc.len);
+    const split = @min(y.len, acc.len);
     var a_lo = acc[0..split];
     var a_hi = acc[split..];
 
@@ -4023,8 +4023,8 @@ fn llsignedand(r: []Limb, a: []const Limb, a_positive: bool, b: []const Limb, b_
 // r may alias.
 // a and b must not be -0.
 // Returns `true` when the result is positive.
-// If the sign of a and b is equal, then r requires at least `max(a.len, b.len)` limbs are required.
-// Otherwise, r requires at least `max(a.len, b.len) + 1` limbs.
+// If the sign of a and b is equal, then r requires at least `@max(a.len, b.len)` limbs are required.
+// Otherwise, r requires at least `@max(a.len, b.len) + 1` limbs.
 fn llsignedxor(r: []Limb, a: []const Limb, a_positive: bool, b: []const Limb, b_positive: bool) bool {
     @setRuntimeSafety(debug_safety);
     assert(a.len != 0 and b.len != 0);
diff --git a/lib/std/math/ldexp.zig b/lib/std/math/ldexp.zig
index d2fd8db9b7..8947475159 100644
--- a/lib/std/math/ldexp.zig
+++ b/lib/std/math/ldexp.zig
@@ -48,7 +48,7 @@ pub fn ldexp(x: anytype, n: i32) @TypeOf(x) {
                 return @bitCast(T, sign_bit); // Severe underflow. Return +/- 0
 
             // Result underflowed, we need to shift and round
-            const shift = @intCast(Log2Int(TBits), math.min(-n, -(exponent + n) + 1));
+            const shift = @intCast(Log2Int(TBits), @min(-n, -(exponent + n) + 1));
             const exact_tie: bool = @ctz(repr) == shift - 1;
             var result = repr & mantissa_mask;
 
diff --git a/lib/std/mem.zig b/lib/std/mem.zig
index c4ad708887..2f34745a64 100644
--- a/lib/std/mem.zig
+++ b/lib/std/mem.zig
@@ -596,7 +596,7 @@ pub fn sortUnstableContext(a: usize, b: usize, context: anytype) void {
 
 /// Compares two slices of numbers lexicographically. O(n).
 pub fn order(comptime T: type, lhs: []const T, rhs: []const T) math.Order {
-    const n = math.min(lhs.len, rhs.len);
+    const n = @min(lhs.len, rhs.len);
     var i: usize = 0;
     while (i < n) : (i += 1) {
         switch (math.order(lhs[i], rhs[i])) {
@@ -642,7 +642,7 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
 /// Compares two slices and returns the index of the first inequality.
 /// Returns null if the slices are equal.
 pub fn indexOfDiff(comptime T: type, a: []const T, b: []const T) ?usize {
-    const shortest = math.min(a.len, b.len);
+    const shortest = @min(a.len, b.len);
     if (a.ptr == b.ptr)
         return if (a.len == b.len) null else shortest;
     var index: usize = 0;
@@ -3296,7 +3296,7 @@ pub fn min(comptime T: type, slice: []const T) T {
     assert(slice.len > 0);
     var best = slice[0];
     for (slice[1..]) |item| {
-        best = math.min(best, item);
+        best = @min(best, item);
     }
     return best;
 }
@@ -3313,7 +3313,7 @@ pub fn max(comptime T: type, slice: []const T) T {
     assert(slice.len > 0);
     var best = slice[0];
     for (slice[1..]) |item| {
-        best = math.max(best, item);
+        best = @max(best, item);
     }
     return best;
 }
@@ -3332,8 +3332,8 @@ pub fn minMax(comptime T: type, slice: []const T) struct { min: T, max: T } {
     var minVal = slice[0];
     var maxVal = slice[0];
     for (slice[1..]) |item| {
-        minVal = math.min(minVal, item);
-        maxVal = math.max(maxVal, item);
+        minVal = @min(minVal, item);
+        maxVal = @max(maxVal, item);
     }
     return .{ .min = minVal, .max = maxVal };
 }
diff --git a/lib/std/net.zig b/lib/std/net.zig
index 64b13ec544..dfd6fe4a9e 100644
--- a/lib/std/net.zig
+++ b/lib/std/net.zig
@@ -1482,11 +1482,11 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void {
                     error.InvalidCharacter => continue,
                 };
                 if (mem.eql(u8, name, "ndots")) {
-                    rc.ndots = std.math.min(value, 15);
+                    rc.ndots = @min(value, 15);
                 } else if (mem.eql(u8, name, "attempts")) {
-                    rc.attempts = std.math.min(value, 10);
+                    rc.attempts = @min(value, 10);
                 } else if (mem.eql(u8, name, "timeout")) {
-                    rc.timeout = std.math.min(value, 60);
+                    rc.timeout = @min(value, 60);
                 }
             }
         } else if (mem.eql(u8, token, "nameserver")) {
@@ -1615,7 +1615,7 @@ fn resMSendRc(
         }
 
         // Wait for a response, or until time to retry
-        const clamped_timeout = std.math.min(@as(u31, std.math.maxInt(u31)), t1 + retry_interval - t2);
+        const clamped_timeout = @min(@as(u31, std.math.maxInt(u31)), t1 + retry_interval - t2);
         const nevents = os.poll(&pfd, clamped_timeout) catch 0;
         if (nevents == 0) continue;
 
diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig
index ef0ec94d3b..e4d6790505 100644
--- a/lib/std/os/linux.zig
+++ b/lib/std/os/linux.zig
@@ -317,7 +317,7 @@ pub fn getdents(fd: i32, dirp: [*]u8, len: usize) usize {
         .getdents,
         @bitCast(usize, @as(isize, fd)),
         @ptrToInt(dirp),
-        std.math.min(len, maxInt(c_int)),
+        @min(len, maxInt(c_int)),
     );
 }
 
@@ -326,7 +326,7 @@ pub fn getdents64(fd: i32, dirp: [*]u8, len: usize) usize {
         .getdents64,
         @bitCast(usize, @as(isize, fd)),
         @ptrToInt(dirp),
-        std.math.min(len, maxInt(c_int)),
+        @min(len, maxInt(c_int)),
     );
 }
 
diff --git a/lib/std/os/linux/io_uring.zig b/lib/std/os/linux/io_uring.zig
index b7467d765f..0610b214d5 100644
--- a/lib/std/os/linux/io_uring.zig
+++ b/lib/std/os/linux/io_uring.zig
@@ -277,7 +277,7 @@ pub const IO_Uring = struct {
     fn copy_cqes_ready(self: *IO_Uring, cqes: []linux.io_uring_cqe, wait_nr: u32) u32 {
         _ = wait_nr;
         const ready = self.cq_ready();
-        const count = std.math.min(cqes.len, ready);
+        const count = @min(cqes.len, ready);
         var head = self.cq.head.*;
         var tail = head +% count;
         // TODO Optimize this by using 1 or 2 memcpy's (if the tail wraps) rather than a loop.
@@ -1093,7 +1093,7 @@ pub const SubmissionQueue = struct {
     pub fn init(fd: os.fd_t, p: linux.io_uring_params) !SubmissionQueue {
         assert(fd >= 0);
         assert((p.features & linux.IORING_FEAT_SINGLE_MMAP) != 0);
-        const size = std.math.max(
+        const size = @max(
             p.sq_off.array + p.sq_entries * @sizeOf(u32),
             p.cq_off.cqes + p.cq_entries * @sizeOf(linux.io_uring_cqe),
         );
diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig
index e559e48915..389c4bea12 100644
--- a/lib/std/os/windows.zig
+++ b/lib/std/os/windows.zig
@@ -272,7 +272,7 @@ pub fn RtlGenRandom(output: []u8) RtlGenRandomError!void {
     const max_read_size: ULONG = maxInt(ULONG);
 
     while (total_read < output.len) {
-        const to_read: ULONG = math.min(buff.len, max_read_size);
+        const to_read: ULONG = @min(buff.len, max_read_size);
 
         if (advapi32.RtlGenRandom(buff.ptr, to_read) == 0) {
             return unexpectedError(kernel32.GetLastError());
@@ -501,7 +501,7 @@ pub fn ReadFile(in_hFile: HANDLE, buffer: []u8, offset: ?u64, io_mode: std.io.Mo
         return @as(usize, bytes_transferred);
     } else {
         while (true) {
-            const want_read_count = @intCast(DWORD, math.min(@as(DWORD, maxInt(DWORD)), buffer.len));
+            const want_read_count: DWORD = @min(@as(DWORD, maxInt(DWORD)), buffer.len);
             var amt_read: DWORD = undefined;
             var overlapped_data: OVERLAPPED = undefined;
             const overlapped: ?*OVERLAPPED = if (offset) |off| blk: {
diff --git a/lib/std/pdb.zig b/lib/std/pdb.zig
index 5bc836b08e..180507ba71 100644
--- a/lib/std/pdb.zig
+++ b/lib/std/pdb.zig
@@ -1049,7 +1049,7 @@ const MsfStream = struct {
         var size: usize = 0;
         var rem_buffer = buffer;
         while (size < buffer.len) {
-            const size_to_read = math.min(self.block_size - offset, rem_buffer.len);
+            const size_to_read = @min(self.block_size - offset, rem_buffer.len);
             size += try in.read(rem_buffer[0..size_to_read]);
             rem_buffer = buffer[size..];
             offset += size_to_read;
diff --git a/lib/std/rand.zig b/lib/std/rand.zig
index 1e9f4051e9..f07562c911 100644
--- a/lib/std/rand.zig
+++ b/lib/std/rand.zig
@@ -410,7 +410,7 @@ pub const Random = struct {
             r.uintLessThan(T, sum)
         else if (comptime std.meta.trait.isFloat(T))
             // take care that imprecision doesn't lead to a value slightly greater than sum
-            std.math.min(r.float(T) * sum, sum - std.math.floatEps(T))
+            @min(r.float(T) * sum, sum - std.math.floatEps(T))
         else
             @compileError("weightedIndex does not support proportions of type " ++ @typeName(T));
 
diff --git a/lib/std/sort/block.zig b/lib/std/sort/block.zig
index 6c1be9c6c2..518d148a73 100644
--- a/lib/std/sort/block.zig
+++ b/lib/std/sort/block.zig
@@ -590,7 +590,7 @@ pub fn block(
                     // whenever we leave an A block behind, we'll need to merge the previous A block with any B blocks that follow it, so track that information as well
                     var lastA = firstA;
                     var lastB = Range.init(0, 0);
-                    var blockB = Range.init(B.start, B.start + math.min(block_size, B.length()));
+                    var blockB = Range.init(B.start, B.start + @min(block_size, B.length()));
                     blockA.start += firstA.length();
                     indexA = buffer1.start;
 
@@ -849,7 +849,7 @@ fn findFirstForward(
     comptime lessThan: fn (@TypeOf(context), lhs: T, rhs: T) bool,
 ) usize {
     if (range.length() == 0) return range.start;
-    const skip = math.max(range.length() / unique, @as(usize, 1));
+    const skip = @max(range.length() / unique, @as(usize, 1));
 
     var index = range.start + skip;
     while (lessThan(context, items[index - 1], value)) : (index += skip) {
@@ -871,7 +871,7 @@ fn findFirstBackward(
     comptime lessThan: fn (@TypeOf(context), lhs: T, rhs: T) bool,
 ) usize {
     if (range.length() == 0) return range.start;
-    const skip = math.max(range.length() / unique, @as(usize, 1));
+    const skip = @max(range.length() / unique, @as(usize, 1));
 
     var index = range.end - skip;
     while (index > range.start and !lessThan(context, items[index - 1], value)) : (index -= skip) {
@@ -893,7 +893,7 @@ fn findLastForward(
     comptime lessThan: fn (@TypeOf(context), lhs: T, rhs: T) bool,
 ) usize {
     if (range.length() == 0) return range.start;
-    const skip = math.max(range.length() / unique, @as(usize, 1));
+    const skip = @max(range.length() / unique, @as(usize, 1));
 
     var index = range.start + skip;
     while (!lessThan(context, value, items[index - 1])) : (index += skip) {
@@ -915,7 +915,7 @@ fn findLastBackward(
     comptime lessThan: fn (@TypeOf(context), lhs: T, rhs: T) bool,
 ) usize {
     if (range.length() == 0) return range.start;
-    const skip = math.max(range.length() / unique, @as(usize, 1));
+    const skip = @max(range.length() / unique, @as(usize, 1));
 
     var index = range.end - skip;
     while (index > range.start and lessThan(context, value, items[index - 1])) : (index -= skip) {
diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig
index 83fa68567f..3930c9714a 100644
--- a/lib/std/zig/render.zig
+++ b/lib/std/zig/render.zig
@@ -1960,7 +1960,7 @@ fn renderArrayInit(
 
                 if (!this_contains_newline) {
                     const column = column_counter % row_size;
-                    column_widths[column] = std.math.max(column_widths[column], width);
+                    column_widths[column] = @max(column_widths[column], width);
 
                     const expr_last_token = tree.lastToken(expr) + 1;
                     const next_expr = section_exprs[i + 1];
@@ -1980,7 +1980,7 @@ fn renderArrayInit(
 
                 if (!contains_newline) {
                     const column = column_counter % row_size;
-                    column_widths[column] = std.math.max(column_widths[column], width);
+                    column_widths[column] = @max(column_widths[column], width);
                 }
             }
         }
diff --git a/lib/std/zig/system/NativeTargetInfo.zig b/lib/std/zig/system/NativeTargetInfo.zig
index f17356fdcd..cddaea2295 100644
--- a/lib/std/zig/system/NativeTargetInfo.zig
+++ b/lib/std/zig/system/NativeTargetInfo.zig
@@ -503,7 +503,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.builtin.Version {
     const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset);
     const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);
     var strtab_buf: [4096:0]u8 = undefined;
-    const shstrtab_len = std.math.min(shstrtab_size, strtab_buf.len);
+    const shstrtab_len = @min(shstrtab_size, strtab_buf.len);
     const shstrtab_read_len = try preadMin(file, &strtab_buf, shstrtab_off, shstrtab_len);
     const shstrtab = strtab_buf[0..shstrtab_read_len];
     const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum);
@@ -757,7 +757,7 @@ pub fn abiAndDynamicLinkerFromFile(
         const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset);
         const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);
         var strtab_buf: [4096:0]u8 = undefined;
-        const shstrtab_len = std.math.min(shstrtab_size, strtab_buf.len);
+        const shstrtab_len = @min(shstrtab_size, strtab_buf.len);
         const shstrtab_read_len = try preadMin(file, &strtab_buf, shstrtab_off, shstrtab_len);
         const shstrtab = strtab_buf[0..shstrtab_read_len];
 
@@ -806,7 +806,7 @@ pub fn abiAndDynamicLinkerFromFile(
                 const rpoff_file = ds.offset + rpoff_usize;
                 const rp_max_size = ds.size - rpoff_usize;
 
-                const strtab_len = std.math.min(rp_max_size, strtab_buf.len);
+                const strtab_len = @min(rp_max_size, strtab_buf.len);
                 const strtab_read_len = try preadMin(file, &strtab_buf, rpoff_file, strtab_len);
                 const strtab = strtab_buf[0..strtab_read_len];
 
diff --git a/src/Sema.zig b/src/Sema.zig
index 99ebd044f9..36fe5a6ee8 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -22367,9 +22367,9 @@ fn analyzeShuffle(
     // to it up to the length of the longer vector. This recursion terminates
     // in 1 call because these calls to analyzeShuffle guarantee a_len == b_len.
     if (a_len != b_len) {
-        const min_len = std.math.min(a_len, b_len);
+        const min_len = @min(a_len, b_len);
         const max_src = if (a_len > b_len) a_src else b_src;
-        const max_len = try sema.usizeCast(block, max_src, std.math.max(a_len, b_len));
+        const max_len = try sema.usizeCast(block, max_src, @max(a_len, b_len));
 
         const expand_mask_values = try sema.arena.alloc(InternPool.Index, max_len);
         for (@intCast(usize, 0)..@intCast(usize, min_len)) |i| {
@@ -31301,7 +31301,7 @@ fn cmpNumeric(
     }
 
     const dest_ty = if (dest_float_type) |ft| ft else blk: {
-        const max_bits = std.math.max(lhs_bits, rhs_bits);
+        const max_bits = @max(lhs_bits, rhs_bits);
         const casted_bits = std.math.cast(u16, max_bits) orelse return sema.fail(block, src, "{d} exceeds maximum integer bit count", .{max_bits});
         const signedness: std.builtin.Signedness = if (dest_int_is_signed) .signed else .unsigned;
         break :blk try mod.intType(signedness, casted_bits);
@@ -35828,7 +35828,7 @@ fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value {
     const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema);
     const limbs = try sema.arena.alloc(
         std.math.big.Limb,
-        std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
+        @max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
     );
     var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
     result_bigint.add(lhs_bigint, rhs_bigint);
@@ -35918,7 +35918,7 @@ fn intSubScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value {
     const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema);
     const limbs = try sema.arena.alloc(
         std.math.big.Limb,
-        std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
+        @max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
     );
     var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
     result_bigint.sub(lhs_bigint, rhs_bigint);
diff --git a/src/TypedValue.zig b/src/TypedValue.zig
index 9d3fb67d1f..93454710dc 100644
--- a/src/TypedValue.zig
+++ b/src/TypedValue.zig
@@ -111,7 +111,7 @@ pub fn print(
                     .val = val.castTag(.repeated).?.data,
                 };
                 const len = ty.arrayLen(mod);
-                const max_len = std.math.min(len, max_aggregate_items);
+                const max_len = @min(len, max_aggregate_items);
                 while (i < max_len) : (i += 1) {
                     if (i != 0) try writer.writeAll(", ");
                     try print(elem_tv, writer, level - 1, mod);
@@ -130,7 +130,7 @@ pub fn print(
                 const len = payload.len.toUnsignedInt(mod);
 
                 if (elem_ty.eql(Type.u8, mod)) str: {
-                    const max_len = @intCast(usize, std.math.min(len, max_string_len));
+                    const max_len: usize = @min(len, max_string_len);
                     var buf: [max_string_len]u8 = undefined;
 
                     var i: u32 = 0;
@@ -149,7 +149,7 @@ pub fn print(
 
                 try writer.writeAll(".{ ");
 
-                const max_len = std.math.min(len, max_aggregate_items);
+                const max_len = @min(len, max_aggregate_items);
                 var i: u32 = 0;
                 while (i < max_len) : (i += 1) {
                     if (i != 0) try writer.writeAll(", ");
@@ -455,7 +455,7 @@ fn printAggregate(
         const len = ty.arrayLen(mod);
 
         if (elem_ty.eql(Type.u8, mod)) str: {
-            const max_len = @intCast(usize, std.math.min(len, max_string_len));
+            const max_len: usize = @min(len, max_string_len);
             var buf: [max_string_len]u8 = undefined;
 
             var i: u32 = 0;
@@ -471,7 +471,7 @@ fn printAggregate(
 
         try writer.writeAll(".{ ");
 
-        const max_len = std.math.min(len, max_aggregate_items);
+        const max_len = @min(len, max_aggregate_items);
         var i: u32 = 0;
         while (i < max_len) : (i += 1) {
             if (i != 0) try writer.writeAll(", ");
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index a1b57516ee..6d98ecce4f 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -2907,7 +2907,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
         const dst_info = dst_ty.intInfo(mod);
         const src_ty = try mod.intType(dst_info.signedness, switch (tag) {
             else => unreachable,
-            .mul, .mulwrap => math.max3(
+            .mul, .mulwrap => @max(
                 self.activeIntBits(bin_op.lhs),
                 self.activeIntBits(bin_op.rhs),
                 dst_info.bits / 2,
@@ -3349,7 +3349,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
 
             const lhs_active_bits = self.activeIntBits(bin_op.lhs);
             const rhs_active_bits = self.activeIntBits(bin_op.rhs);
-            const src_bits = math.max3(lhs_active_bits, rhs_active_bits, dst_info.bits / 2);
+            const src_bits = @max(lhs_active_bits, rhs_active_bits, dst_info.bits / 2);
             const src_ty = try mod.intType(dst_info.signedness, src_bits);
 
             const lhs = try self.resolveInst(bin_op.lhs);
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index 409eca6e7a..0863a22fac 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -2326,7 +2326,7 @@ fn allocateAtom(self: *Elf, atom_index: Atom.Index, new_block_size: u64, alignme
             self.debug_aranges_section_dirty = true;
         }
     }
-    shdr.sh_addralign = math.max(shdr.sh_addralign, alignment);
+    shdr.sh_addralign = @max(shdr.sh_addralign, alignment);
 
     // This function can also reallocate an atom.
     // In this case we need to "unplug" it from its previous location before
diff --git a/src/link/MachO/CodeSignature.zig b/src/link/MachO/CodeSignature.zig
index 59b3e50b07..4709560ba7 100644
--- a/src/link/MachO/CodeSignature.zig
+++ b/src/link/MachO/CodeSignature.zig
@@ -99,7 +99,7 @@ const CodeDirectory = struct {
 
     fn addSpecialHash(self: *CodeDirectory, index: u32, hash: [hash_size]u8) void {
         assert(index > 0);
-        self.inner.nSpecialSlots = std.math.max(self.inner.nSpecialSlots, index);
+        self.inner.nSpecialSlots = @max(self.inner.nSpecialSlots, index);
         self.special_slots[index - 1] = hash;
     }
 
@@ -426,11 +426,11 @@ pub fn estimateSize(self: CodeSignature, file_size: u64) u32 {
     var n_special_slots: u32 = 0;
     if (self.requirements) |req| {
         ssize += @sizeOf(macho.BlobIndex) + req.size();
-        n_special_slots = std.math.max(n_special_slots, req.slotType());
+        n_special_slots = @max(n_special_slots, req.slotType());
     }
     if (self.entitlements) |ent| {
         ssize += @sizeOf(macho.BlobIndex) + ent.size() + hash_size;
-        n_special_slots = std.math.max(n_special_slots, ent.slotType());
+        n_special_slots = @max(n_special_slots, ent.slotType());
     }
     if (self.signature) |sig| {
         ssize += @sizeOf(macho.BlobIndex) + sig.size();
diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig
index b218fdbd2d..105a806075 100644
--- a/src/link/MachO/Object.zig
+++ b/src/link/MachO/Object.zig
@@ -530,7 +530,7 @@ pub fn splitRegularSections(self: *Object, zld: *Zld, object_id: u32) !void {
                     sect.addr + sect.size - addr;
 
                 const atom_align = if (addr > 0)
-                    math.min(@ctz(addr), sect.@"align")
+                    @min(@ctz(addr), sect.@"align")
                 else
                     sect.@"align";
 
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
index fdac7dfa63..5126033995 100644
--- a/src/link/Wasm.zig
+++ b/src/link/Wasm.zig
@@ -2027,7 +2027,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void {
     };
 
     const segment: *Segment = &wasm.segments.items[final_index];
-    segment.alignment = std.math.max(segment.alignment, atom.alignment);
+    segment.alignment = @max(segment.alignment, atom.alignment);
 
     try wasm.appendAtomAtIndex(final_index, atom_index);
 }
diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig
index 363648971a..33f54dece5 100644
--- a/src/link/Wasm/Object.zig
+++ b/src/link/Wasm/Object.zig
@@ -979,7 +979,7 @@ pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_b
 
         const segment: *Wasm.Segment = &wasm_bin.segments.items[final_index];
         if (relocatable_data.type == .data) { //code section and debug sections are 1-byte aligned
-            segment.alignment = std.math.max(segment.alignment, atom.alignment);
+            segment.alignment = @max(segment.alignment, atom.alignment);
         }
 
         try wasm_bin.appendAtomAtIndex(final_index, atom_index);
diff --git a/src/main.zig b/src/main.zig
index 5d666840c0..aedca80d26 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -5391,7 +5391,7 @@ fn gimmeMoreOfThoseSweetSweetFileDescriptors() void {
         //   setrlimit() now returns with errno set to EINVAL in places that historically succeeded.
         //   It no longer accepts "rlim_cur = RLIM.INFINITY" for RLIM.NOFILE.
         //   Use "rlim_cur = min(OPEN_MAX, rlim_max)".
-        lim.max = std.math.min(std.os.darwin.OPEN_MAX, lim.max);
+        lim.max = @min(std.os.darwin.OPEN_MAX, lim.max);
     }
     if (lim.cur == lim.max) return;
 
diff --git a/src/translate_c.zig b/src/translate_c.zig
index 8cc2d1856c..67176ff74b 100644
--- a/src/translate_c.zig
+++ b/src/translate_c.zig
@@ -2400,7 +2400,7 @@ fn transStringLiteralInitializer(
 
     if (array_size == 0) return Tag.empty_array.create(c.arena, elem_type);
 
-    const num_inits = math.min(str_length, array_size);
+    const num_inits = @min(str_length, array_size);
     const init_node = if (num_inits > 0) blk: {
         if (is_narrow) {
             // "string literal".* or string literal"[0..num_inits].*
diff --git a/src/translate_c/ast.zig b/src/translate_c/ast.zig
index 6c6bbf28bd..443c56a84a 100644
--- a/src/translate_c/ast.zig
+++ b/src/translate_c/ast.zig
@@ -1824,7 +1824,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
         },
         .switch_prong => {
             const payload = node.castTag(.switch_prong).?.data;
-            var items = try c.gpa.alloc(NodeIndex, std.math.max(payload.cases.len, 1));
+            var items = try c.gpa.alloc(NodeIndex, @max(payload.cases.len, 1));
             defer c.gpa.free(items);
             items[0] = 0;
             for (payload.cases, 0..) |item, i| {
@@ -1973,7 +1973,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
             const payload = node.castTag(.tuple).?.data;
             _ = try c.addToken(.period, ".");
             const l_brace = try c.addToken(.l_brace, "{");
-            var inits = try c.gpa.alloc(NodeIndex, std.math.max(payload.len, 2));
+            var inits = try c.gpa.alloc(NodeIndex, @max(payload.len, 2));
             defer c.gpa.free(inits);
             inits[0] = 0;
             inits[1] = 0;
@@ -2007,7 +2007,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
             const payload = node.castTag(.container_init_dot).?.data;
             _ = try c.addToken(.period, ".");
             const l_brace = try c.addToken(.l_brace, "{");
-            var inits = try c.gpa.alloc(NodeIndex, std.math.max(payload.len, 2));
+            var inits = try c.gpa.alloc(NodeIndex, @max(payload.len, 2));
             defer c.gpa.free(inits);
             inits[0] = 0;
             inits[1] = 0;
@@ -2046,7 +2046,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
             const lhs = try renderNode(c, payload.lhs);
 
             const l_brace = try c.addToken(.l_brace, "{");
-            var inits = try c.gpa.alloc(NodeIndex, std.math.max(payload.inits.len, 1));
+            var inits = try c.gpa.alloc(NodeIndex, @max(payload.inits.len, 1));
             defer c.gpa.free(inits);
             inits[0] = 0;
             for (payload.inits, 0..) |init, i| {
@@ -2102,7 +2102,7 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex {
     const num_vars = payload.variables.len;
     const num_funcs = payload.functions.len;
     const total_members = payload.fields.len + num_vars + num_funcs;
-    const members = try c.gpa.alloc(NodeIndex, std.math.max(total_members, 2));
+    const members = try c.gpa.alloc(NodeIndex, @max(total_members, 2));
     defer c.gpa.free(members);
     members[0] = 0;
     members[1] = 0;
@@ -2195,7 +2195,7 @@ fn renderFieldAccess(c: *Context, lhs: NodeIndex, field_name: []const u8) !NodeI
 
 fn renderArrayInit(c: *Context, lhs: NodeIndex, inits: []const Node) !NodeIndex {
     const l_brace = try c.addToken(.l_brace, "{");
-    var rendered = try c.gpa.alloc(NodeIndex, std.math.max(inits.len, 1));
+    var rendered = try c.gpa.alloc(NodeIndex, @max(inits.len, 1));
     defer c.gpa.free(rendered);
     rendered[0] = 0;
     for (inits, 0..) |init, i| {
@@ -2904,7 +2904,7 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex {
 
 fn renderParams(c: *Context, params: []Payload.Param, is_var_args: bool) !std.ArrayList(NodeIndex) {
     _ = try c.addToken(.l_paren, "(");
-    var rendered = try std.ArrayList(NodeIndex).initCapacity(c.gpa, std.math.max(params.len, 1));
+    var rendered = try std.ArrayList(NodeIndex).initCapacity(c.gpa, @max(params.len, 1));
     errdefer rendered.deinit();
 
     for (params, 0..) |param, i| {
diff --git a/src/type.zig b/src/type.zig
index 22523a7141..bb82a50682 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -1633,7 +1633,7 @@ pub const Type = struct {
                 const len = array_type.len + @boolToInt(array_type.sentinel != .none);
                 if (len == 0) return 0;
                 const elem_ty = array_type.child.toType();
-                const elem_size = std.math.max(elem_ty.abiAlignment(mod), elem_ty.abiSize(mod));
+                const elem_size = @max(elem_ty.abiAlignment(mod), elem_ty.abiSize(mod));
                 if (elem_size == 0) return 0;
                 const elem_bit_size = try bitSizeAdvanced(elem_ty, mod, opt_sema);
                 return (len - 1) * 8 * elem_size + elem_bit_size;
diff --git a/src/value.zig b/src/value.zig
index 85204e2b10..8590aa8872 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -2458,7 +2458,7 @@ pub const Value = struct {
         const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
         const limbs = try arena.alloc(
             std.math.big.Limb,
-            std.math.max(
+            @max(
                 // For the saturate
                 std.math.big.int.calcTwosCompLimbCount(info.bits),
                 lhs_bigint.limbs.len + rhs_bigint.limbs.len,
@@ -2572,7 +2572,7 @@ pub const Value = struct {
         const limbs = try arena.alloc(
             std.math.big.Limb,
             // + 1 for negatives
-            std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
+            @max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
         );
         var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
         result_bigint.bitAnd(lhs_bigint, rhs_bigint);
@@ -2638,7 +2638,7 @@ pub const Value = struct {
         const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
         const limbs = try arena.alloc(
             std.math.big.Limb,
-            std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
+            @max(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
         );
         var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
         result_bigint.bitOr(lhs_bigint, rhs_bigint);
@@ -2677,7 +2677,7 @@ pub const Value = struct {
         const limbs = try arena.alloc(
             std.math.big.Limb,
             // + 1 for negatives
-            std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
+            @max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
         );
         var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
         result_bigint.bitXor(lhs_bigint, rhs_bigint);
-- 
cgit v1.2.3


From 0f5aff34414bcb024443540fe905039f3783803a Mon Sep 17 00:00:00 2001
From: Veikka Tuominen 
Date: Fri, 9 Jun 2023 19:15:32 -0700
Subject: zig build: add option to only print failed steps

The motivating case for this is that currently when a test fails
the CI log will include ~5k lines of listing steps that succeeded.
---
 lib/build_runner.zig | 63 +++++++++++++++++++++++++++++++++++++---------------
 src/main.zig         | 42 ++++++++++++++++++-----------------
 2 files changed, 67 insertions(+), 38 deletions(-)

(limited to 'src/main.zig')

diff --git a/lib/build_runner.zig b/lib/build_runner.zig
index a09ec2cf1f..a5abbebe16 100644
--- a/lib/build_runner.zig
+++ b/lib/build_runner.zig
@@ -90,7 +90,7 @@ pub fn main() !void {
 
     var install_prefix: ?[]const u8 = null;
     var dir_list = std.Build.DirList{};
-    var enable_summary: ?bool = null;
+    var summary: ?Summary = null;
     var max_rss: usize = 0;
     var color: Color = .auto;
 
@@ -178,6 +178,15 @@ pub fn main() !void {
                     std.debug.print("Expected [auto|on|off] after {s}, found '{s}'\n\n", .{ arg, next_arg });
                     usageAndErr(builder, false, stderr_stream);
                 };
+            } else if (mem.eql(u8, arg, "--summary")) {
+                const next_arg = nextArg(args, &arg_idx) orelse {
+                    std.debug.print("Expected [all|failures|none] after {s}\n\n", .{arg});
+                    usageAndErr(builder, false, stderr_stream);
+                };
+                summary = std.meta.stringToEnum(Summary, next_arg) orelse {
+                    std.debug.print("Expected [all|failures|none] after {s}, found '{s}'\n\n", .{ arg, next_arg });
+                    usageAndErr(builder, false, stderr_stream);
+                };
             } else if (mem.eql(u8, arg, "--zig-lib-dir")) {
                 builder.zig_lib_dir = nextArg(args, &arg_idx) orelse {
                     std.debug.print("Expected argument after {s}\n\n", .{arg});
@@ -234,10 +243,6 @@ pub fn main() !void {
                 builder.enable_darling = true;
             } else if (mem.eql(u8, arg, "-fno-darling")) {
                 builder.enable_darling = false;
-            } else if (mem.eql(u8, arg, "-fsummary")) {
-                enable_summary = true;
-            } else if (mem.eql(u8, arg, "-fno-summary")) {
-                enable_summary = false;
             } else if (mem.eql(u8, arg, "-freference-trace")) {
                 builder.reference_trace = 256;
             } else if (mem.startsWith(u8, arg, "-freference-trace=")) {
@@ -302,7 +307,7 @@ pub fn main() !void {
         .memory_blocked_steps = std.ArrayList(*Step).init(arena),
 
         .claimed_rss = 0,
-        .enable_summary = enable_summary,
+        .summary = summary,
         .ttyconf = ttyconf,
         .stderr = stderr,
     };
@@ -332,7 +337,7 @@ const Run = struct {
     memory_blocked_steps: std.ArrayList(*Step),
 
     claimed_rss: usize,
-    enable_summary: ?bool,
+    summary: ?Summary,
     ttyconf: std.io.tty.Config,
     stderr: std.fs.File,
 };
@@ -469,12 +474,12 @@ fn runStepNames(
 
     // A proper command line application defaults to silently succeeding.
     // The user may request verbose mode if they have a different preference.
-    if (failure_count == 0 and run.enable_summary != true) return cleanExit();
+    if (failure_count == 0 and run.summary != Summary.all) return cleanExit();
 
     const ttyconf = run.ttyconf;
     const stderr = run.stderr;
 
-    if (run.enable_summary != false) {
+    if (run.summary != Summary.none) {
         const total_count = success_count + failure_count + pending_count + skipped_count;
         ttyconf.setColor(stderr, .cyan) catch {};
         stderr.writeAll("Build Summary:") catch {};
@@ -488,23 +493,32 @@ fn runStepNames(
         if (test_fail_count > 0) stderr.writer().print("; {d} failed", .{test_fail_count}) catch {};
         if (test_leak_count > 0) stderr.writer().print("; {d} leaked", .{test_leak_count}) catch {};
 
-        if (run.enable_summary == null) {
+        if (run.summary == null) {
             ttyconf.setColor(stderr, .dim) catch {};
-            stderr.writeAll(" (disable with -fno-summary)") catch {};
+            stderr.writeAll(" (disable with --summary none)") catch {};
             ttyconf.setColor(stderr, .reset) catch {};
         }
         stderr.writeAll("\n") catch {};
+        const failures_only = run.summary != Summary.all;
 
         // Print a fancy tree with build results.
         var print_node: PrintNode = .{ .parent = null };
         if (step_names.len == 0) {
             print_node.last = true;
-            printTreeStep(b, b.default_step, stderr, ttyconf, &print_node, &step_stack) catch {};
+            printTreeStep(b, b.default_step, stderr, ttyconf, &print_node, &step_stack, failures_only) catch {};
         } else {
+            const last_index = if (!failures_only) b.top_level_steps.count() else blk: {
+                var i: usize = step_names.len;
+                while (i > 0) {
+                    i -= 1;
+                    if (b.top_level_steps.get(step_names[i]).?.step.state != .success) break :blk i;
+                }
+                break :blk b.top_level_steps.count();
+            };
             for (step_names, 0..) |step_name, i| {
                 const tls = b.top_level_steps.get(step_name).?;
-                print_node.last = i + 1 == b.top_level_steps.count();
-                printTreeStep(b, &tls.step, stderr, ttyconf, &print_node, &step_stack) catch {};
+                print_node.last = i + 1 == last_index;
+                printTreeStep(b, &tls.step, stderr, ttyconf, &print_node, &step_stack, failures_only) catch {};
             }
         }
     }
@@ -556,8 +570,10 @@ fn printTreeStep(
     ttyconf: std.io.tty.Config,
     parent_node: *PrintNode,
     step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void),
+    failures_only: bool,
 ) !void {
     const first = step_stack.swapRemove(s);
+    if (failures_only and s.state == .success) return;
     try printPrefix(parent_node, stderr, ttyconf);
 
     if (!first) try ttyconf.setColor(stderr, .dim);
@@ -688,12 +704,20 @@ fn printTreeStep(
             },
         }
 
+        const last_index = if (!failures_only) s.dependencies.items.len -| 1 else blk: {
+            var i: usize = s.dependencies.items.len;
+            while (i > 0) {
+                i -= 1;
+                if (s.dependencies.items[i].state != .success) break :blk i;
+            }
+            break :blk s.dependencies.items.len -| 1;
+        };
         for (s.dependencies.items, 0..) |dep, i| {
             var print_node: PrintNode = .{
                 .parent = parent_node,
-                .last = i == s.dependencies.items.len - 1,
+                .last = i == last_index,
             };
-            try printTreeStep(b, dep, stderr, ttyconf, &print_node, step_stack);
+            try printTreeStep(b, dep, stderr, ttyconf, &print_node, step_stack, failures_only);
         }
     } else {
         if (s.dependencies.items.len == 0) {
@@ -948,8 +972,10 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi
         \\  -l, --list-steps             Print available steps
         \\  --verbose                    Print commands before executing them
         \\  --color [auto|off|on]        Enable or disable colored error messages
-        \\  -fsummary                    Print the build summary, even on success
-        \\  -fno-summary                 Omit the build summary, even on failure
+        \\  --summary [mode]             Control the printing of the build summary
+        \\    all                        Print the build summary in its entirety
+        \\    failures                   (Default) Only print failed steps
+        \\    none                       Do not print the build summary
         \\  -j                        Limit concurrent jobs (default is to use all CPU cores)
         \\  --maxrss              Limit memory usage (default is to use available memory)
         \\
@@ -1025,6 +1051,7 @@ fn cleanExit() void {
 }
 
 const Color = enum { auto, off, on };
+const Summary = enum { all, failures, none };
 
 fn get_tty_conf(color: Color, stderr: std.fs.File) std.io.tty.Config {
     return switch (color) {
diff --git a/src/main.zig b/src/main.zig
index aedca80d26..b245b357ca 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -4000,8 +4000,8 @@ pub const usage_libc =
     \\    Parse a libc installation text file and validate it.
     \\
     \\Options:
-    \\    -h, --help             Print this help and exit
-    \\    -target [name]         -- see the targets command
+    \\  -h, --help             Print this help and exit
+    \\  -target [name]         -- see the targets command
     \\
 ;
 
@@ -4068,7 +4068,7 @@ pub const usage_init =
     \\   directory.
     \\
     \\Options:
-    \\   -h, --help             Print this help and exit
+    \\  -h, --help             Print this help and exit
     \\
     \\
 ;
@@ -4166,16 +4166,18 @@ pub const usage_build =
     \\   Build a project from build.zig.
     \\
     \\Options:
-    \\   -freference-trace[=num]       How many lines of reference trace should be shown per compile error
-    \\   -fno-reference-trace          Disable reference trace
-    \\   -fsummary                     Print the build summary, even on success
-    \\   -fno-summary                  Omit the build summary, even on failure
-    \\   --build-file [file]           Override path to build.zig
-    \\   --cache-dir [path]            Override path to local Zig cache directory
-    \\   --global-cache-dir [path]     Override path to global Zig cache directory
-    \\   --zig-lib-dir [arg]           Override path to Zig lib directory
-    \\   --build-runner [file]         Override path to build runner
-    \\   -h, --help                    Print this help and exit
+    \\  -freference-trace[=num]       How many lines of reference trace should be shown per compile error
+    \\  -fno-reference-trace          Disable reference trace
+    \\  --summary [mode]              Control the printing of the build summary
+    \\    all                         Print the build summary in its entirety
+    \\    failures                    (Default) Only print failed steps
+    \\    none                        Do not print the build summary
+    \\  --build-file [file]           Override path to build.zig
+    \\  --cache-dir [path]            Override path to local Zig cache directory
+    \\  --global-cache-dir [path]     Override path to global Zig cache directory
+    \\  --zig-lib-dir [arg]           Override path to Zig lib directory
+    \\  --build-runner [file]         Override path to build runner
+    \\  -h, --help                    Print this help and exit
     \\
 ;
 
@@ -4576,13 +4578,13 @@ pub const usage_fmt =
     \\   recursively.
     \\
     \\Options:
-    \\   -h, --help             Print this help and exit
-    \\   --color [auto|off|on]  Enable or disable colored error messages
-    \\   --stdin                Format code from stdin; output to stdout
-    \\   --check                List non-conforming files and exit with an error
-    \\                          if the list is non-empty
-    \\   --ast-check            Run zig ast-check on every file
-    \\   --exclude [file]       Exclude file or directory from formatting
+    \\  -h, --help             Print this help and exit
+    \\  --color [auto|off|on]  Enable or disable colored error messages
+    \\  --stdin                Format code from stdin; output to stdout
+    \\  --check                List non-conforming files and exit with an error
+    \\                         if the list is non-empty
+    \\  --ast-check            Run zig ast-check on every file
+    \\  --exclude [file]       Exclude file or directory from formatting
     \\
     \\
 ;
-- 
cgit v1.2.3


From 6e84f469904a24615a6721265a88ad8dcb4ed83a Mon Sep 17 00:00:00 2001
From: r00ster91 
Date: Tue, 21 Feb 2023 18:39:22 +0100
Subject: std: replace builtin.Version with SemanticVersion

---
 build.zig                                      |   4 +-
 lib/std/Build.zig                              |   8 +-
 lib/std/Build/Cache.zig                        |   2 +-
 lib/std/Build/Step/Compile.zig                 |   4 +-
 lib/std/Build/Step/Options.zig                 |  23 -----
 lib/std/Build/Step/TranslateC.zig              |   2 +-
 lib/std/SemanticVersion.zig                    |  24 ++++-
 lib/std/builtin.zig                            | 133 -------------------------
 lib/std/c.zig                                  |   2 +-
 lib/std/crypto/tlcsprng.zig                    |   1 +
 lib/std/os.zig                                 |  18 ++--
 lib/std/os/test.zig                            |   2 +-
 lib/std/target.zig                             |  36 +++----
 lib/std/zig.zig                                |   2 +-
 lib/std/zig/CrossTarget.zig                    |  65 +++++++++---
 lib/std/zig/system/NativeTargetInfo.zig        |  22 ++--
 lib/std/zig/system/darwin.zig                  |   3 +-
 lib/std/zig/system/darwin/macos.zig            |  47 +++++----
 src/Compilation.zig                            |   4 +-
 src/codegen/spirv/spec.zig                     |   2 +-
 src/glibc.zig                                  |   4 +-
 src/link.zig                                   |   4 +-
 src/link/Elf.zig                               |   2 +-
 src/link/MachO/load_commands.zig               |  12 +--
 src/main.zig                                   |  13 ++-
 src/target.zig                                 |  14 +--
 test/link/macho/dylib/build.zig                |   2 +-
 test/link/macho/needed_library/build.zig       |   2 +-
 test/link/macho/search_strategy/build.zig      |   2 +-
 test/link/macho/tls/build.zig                  |   2 +-
 test/link/macho/uuid/build.zig                 |   2 +-
 test/standalone/load_dynamic_library/build.zig |   2 +-
 test/standalone/shared_library/build.zig       |   2 +-
 tools/gen_spirv_spec.zig                       |   2 +-
 34 files changed, 189 insertions(+), 280 deletions(-)

(limited to 'src/main.zig')

diff --git a/build.zig b/build.zig
index 9cfebebc56..28bc528772 100644
--- a/build.zig
+++ b/build.zig
@@ -9,7 +9,7 @@ const fs = std.fs;
 const InstallDirectoryOptions = std.Build.InstallDirectoryOptions;
 const assert = std.debug.assert;
 
-const zig_version = std.builtin.Version{ .major = 0, .minor = 11, .patch = 0 };
+const zig_version = std.SemanticVersion{ .major = 0, .minor = 11, .patch = 0 };
 const stack_size = 32 * 1024 * 1024;
 
 pub fn build(b: *std.Build) !void {
@@ -242,7 +242,7 @@ pub fn build(b: *std.Build) !void {
                 const commit_height = it.next().?;
                 const commit_id = it.next().?;
 
-                const ancestor_ver = try std.builtin.Version.parse(tagged_ancestor);
+                const ancestor_ver = try std.SemanticVersion.parse(tagged_ancestor);
                 if (zig_version.order(ancestor_ver) != .gt) {
                     std.debug.print("Zig version '{}' must be greater than tagged ancestor '{}'\n", .{ zig_version, ancestor_ver });
                     std.process.exit(1);
diff --git a/lib/std/Build.zig b/lib/std/Build.zig
index 6ea7153c0d..c569e0074a 100644
--- a/lib/std/Build.zig
+++ b/lib/std/Build.zig
@@ -472,7 +472,7 @@ pub fn addOptions(self: *Build) *Step.Options {
 pub const ExecutableOptions = struct {
     name: []const u8,
     root_source_file: ?FileSource = null,
-    version: ?std.builtin.Version = null,
+    version: ?std.SemanticVersion = null,
     target: CrossTarget = .{},
     optimize: std.builtin.Mode = .Debug,
     linkage: ?Step.Compile.Linkage = null,
@@ -530,7 +530,7 @@ pub fn addObject(b: *Build, options: ObjectOptions) *Step.Compile {
 pub const SharedLibraryOptions = struct {
     name: []const u8,
     root_source_file: ?FileSource = null,
-    version: ?std.builtin.Version = null,
+    version: ?std.SemanticVersion = null,
     target: CrossTarget,
     optimize: std.builtin.Mode,
     max_rss: usize = 0,
@@ -562,7 +562,7 @@ pub const StaticLibraryOptions = struct {
     root_source_file: ?FileSource = null,
     target: CrossTarget,
     optimize: std.builtin.Mode,
-    version: ?std.builtin.Version = null,
+    version: ?std.SemanticVersion = null,
     max_rss: usize = 0,
     link_libc: ?bool = null,
     single_threaded: ?bool = null,
@@ -592,7 +592,7 @@ pub const TestOptions = struct {
     root_source_file: FileSource,
     target: CrossTarget = .{},
     optimize: std.builtin.Mode = .Debug,
-    version: ?std.builtin.Version = null,
+    version: ?std.SemanticVersion = null,
     max_rss: usize = 0,
     filter: ?[]const u8 = null,
     test_runner: ?[]const u8 = null,
diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig
index a1518f7c6a..3b7f180ae8 100644
--- a/lib/std/Build/Cache.zig
+++ b/lib/std/Build/Cache.zig
@@ -212,7 +212,7 @@ pub const HashHelper = struct {
     /// Convert the input value into bytes and record it as a dependency of the process being cached.
     pub fn add(hh: *HashHelper, x: anytype) void {
         switch (@TypeOf(x)) {
-            std.builtin.Version => {
+            std.SemanticVersion => {
                 hh.add(x.major);
                 hh.add(x.minor);
                 hh.add(x.patch);
diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig
index 092fdf7e63..89576c15fa 100644
--- a/lib/std/Build/Step/Compile.zig
+++ b/lib/std/Build/Step/Compile.zig
@@ -32,7 +32,7 @@ linker_script: ?FileSource = null,
 version_script: ?[]const u8 = null,
 out_filename: []const u8,
 linkage: ?Linkage = null,
-version: ?std.builtin.Version,
+version: ?std.SemanticVersion,
 kind: Kind,
 major_only_filename: ?[]const u8,
 name_only_filename: ?[]const u8,
@@ -278,7 +278,7 @@ pub const Options = struct {
     optimize: std.builtin.Mode,
     kind: Kind,
     linkage: ?Linkage = null,
-    version: ?std.builtin.Version = null,
+    version: ?std.SemanticVersion = null,
     max_rss: usize = 0,
     filter: ?[]const u8 = null,
     test_runner: ?[]const u8 = null,
diff --git a/lib/std/Build/Step/Options.zig b/lib/std/Build/Step/Options.zig
index cc7152a81e..52821a5951 100644
--- a/lib/std/Build/Step/Options.zig
+++ b/lib/std/Build/Step/Options.zig
@@ -76,23 +76,6 @@ fn addOptionFallible(self: *Options, comptime T: type, name: []const u8, value:
             }
             return;
         },
-        std.builtin.Version => {
-            try out.print(
-                \\pub const {}: @import("std").builtin.Version = .{{
-                \\    .major = {d},
-                \\    .minor = {d},
-                \\    .patch = {d},
-                \\}};
-                \\
-            , .{
-                std.zig.fmtId(name),
-
-                value.major,
-                value.minor,
-                value.patch,
-            });
-            return;
-        },
         std.SemanticVersion => {
             try out.print(
                 \\pub const {}: @import("std").SemanticVersion = .{{
@@ -367,7 +350,6 @@ test Options {
     options.addOption([2][2]u16, "nested_array", nested_array);
     options.addOption([]const []const u16, "nested_slice", nested_slice);
     //options.addOption(KeywordEnum, "keyword_enum", .@"0.8.1");
-    options.addOption(std.builtin.Version, "version", try std.builtin.Version.parse("0.1.2"));
     options.addOption(std.SemanticVersion, "semantic_version", try std.SemanticVersion.parse("0.1.2-foo+bar"));
 
     try std.testing.expectEqualStrings(
@@ -401,11 +383,6 @@ test Options {
         //\\    @"0.8.1",
         //\\};
         //\\pub const keyword_enum: KeywordEnum = KeywordEnum.@"0.8.1";
-        \\pub const version: @import("std").builtin.Version = .{
-        \\    .major = 0,
-        \\    .minor = 1,
-        \\    .patch = 2,
-        \\};
         \\pub const semantic_version: @import("std").SemanticVersion = .{
         \\    .major = 0,
         \\    .minor = 1,
diff --git a/lib/std/Build/Step/TranslateC.zig b/lib/std/Build/Step/TranslateC.zig
index 0c7ddc4720..ced249b3f2 100644
--- a/lib/std/Build/Step/TranslateC.zig
+++ b/lib/std/Build/Step/TranslateC.zig
@@ -47,7 +47,7 @@ pub fn create(owner: *std.Build, options: Options) *TranslateC {
 
 pub const AddExecutableOptions = struct {
     name: ?[]const u8 = null,
-    version: ?std.builtin.Version = null,
+    version: ?std.SemanticVersion = null,
     target: ?CrossTarget = null,
     optimize: ?std.builtin.Mode = null,
     linkage: ?Step.Compile.Linkage = null,
diff --git a/lib/std/SemanticVersion.zig b/lib/std/SemanticVersion.zig
index 4d505b4e30..4fa1d47c40 100644
--- a/lib/std/SemanticVersion.zig
+++ b/lib/std/SemanticVersion.zig
@@ -1,4 +1,4 @@
-//! A software version formatted according to the Semantic Version 2 specification.
+//! A software version formatted according to the Semantic Versioning 2.0.0 specification.
 //!
 //! See: https://semver.org
 
@@ -167,7 +167,7 @@ const expect = std.testing.expect;
 const expectError = std.testing.expectError;
 
 test "SemanticVersion format" {
-    // Test vectors are from https://github.com/semver/semver.org/issues/59#issuecomment-390854010.
+    // Many of these test strings are from https://github.com/semver/semver.org/issues/59#issuecomment-390854010.
 
     // Valid version strings should be accepted.
     for ([_][]const u8{
@@ -200,6 +200,8 @@ test "SemanticVersion format" {
         "1.2.3----R-S.12.9.1--.12+meta",
         "1.2.3----RC-SNAPSHOT.12.9.1--.12",
         "1.0.0+0.build.1-rc.10000aaa-kk-0.1",
+        "5.4.0-1018-raspi",
+        "5.7.123",
     }) |valid| try std.testing.expectFmt(valid, "{}", .{try parse(valid)});
 
     // Invalid version strings should be rejected.
@@ -244,6 +246,24 @@ test "SemanticVersion format" {
         "+justmeta",
         "9.8.7+meta+meta",
         "9.8.7-whatever+meta+meta",
+        "2.6.32.11-svn21605",
+        "2.11.2(0.329/5/3)",
+        "2.13-DEVELOPMENT",
+        "2.3-35",
+        "1a.4",
+        "3.b1.0",
+        "1.4beta",
+        "2.7.pre",
+        "0..3",
+        "8.008.",
+        "01...",
+        "55",
+        "foobar",
+        "",
+        "-1",
+        "+4",
+        ".",
+        "....3",
     }) |invalid| try expectError(error.InvalidVersion, parse(invalid));
 
     // Valid version string that may overflow.
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
index b449080e86..54781e4465 100644
--- a/lib/std/builtin.zig
+++ b/lib/std/builtin.zig
@@ -483,139 +483,6 @@ pub const WasiExecModel = enum {
     reactor,
 };
 
-/// This data structure is used by the Zig language code generation and
-/// therefore must be kept in sync with the compiler implementation.
-pub const Version = struct {
-    major: u32,
-    minor: u32,
-    patch: u32 = 0,
-
-    pub const Range = struct {
-        min: Version,
-        max: Version,
-
-        pub fn includesVersion(self: Range, ver: Version) bool {
-            if (self.min.order(ver) == .gt) return false;
-            if (self.max.order(ver) == .lt) return false;
-            return true;
-        }
-
-        /// Checks if system is guaranteed to be at least `version` or older than `version`.
-        /// Returns `null` if a runtime check is required.
-        pub fn isAtLeast(self: Range, ver: Version) ?bool {
-            if (self.min.order(ver) != .lt) return true;
-            if (self.max.order(ver) == .lt) return false;
-            return null;
-        }
-    };
-
-    pub fn order(lhs: Version, rhs: Version) std.math.Order {
-        if (lhs.major < rhs.major) return .lt;
-        if (lhs.major > rhs.major) return .gt;
-        if (lhs.minor < rhs.minor) return .lt;
-        if (lhs.minor > rhs.minor) return .gt;
-        if (lhs.patch < rhs.patch) return .lt;
-        if (lhs.patch > rhs.patch) return .gt;
-        return .eq;
-    }
-
-    pub fn parse(text: []const u8) !Version {
-        var end: usize = 0;
-        while (end < text.len) : (end += 1) {
-            const c = text[end];
-            if (!std.ascii.isDigit(c) and c != '.') break;
-        }
-        // found no digits or '.' before unexpected character
-        if (end == 0) return error.InvalidVersion;
-
-        var it = std.mem.splitScalar(u8, text[0..end], '.');
-        // substring is not empty, first call will succeed
-        const major = it.first();
-        if (major.len == 0) return error.InvalidVersion;
-        const minor = it.next() orelse "0";
-        // ignore 'patch' if 'minor' is invalid
-        const patch = if (minor.len == 0) "0" else (it.next() orelse "0");
-
-        return Version{
-            .major = try std.fmt.parseUnsigned(u32, major, 10),
-            .minor = try std.fmt.parseUnsigned(u32, if (minor.len == 0) "0" else minor, 10),
-            .patch = try std.fmt.parseUnsigned(u32, if (patch.len == 0) "0" else patch, 10),
-        };
-    }
-
-    pub fn format(
-        self: Version,
-        comptime fmt: []const u8,
-        options: std.fmt.FormatOptions,
-        out_stream: anytype,
-    ) !void {
-        _ = options;
-        if (fmt.len == 0) {
-            if (self.patch == 0) {
-                if (self.minor == 0) {
-                    return std.fmt.format(out_stream, "{d}", .{self.major});
-                } else {
-                    return std.fmt.format(out_stream, "{d}.{d}", .{ self.major, self.minor });
-                }
-            } else {
-                return std.fmt.format(out_stream, "{d}.{d}.{d}", .{ self.major, self.minor, self.patch });
-            }
-        } else {
-            std.fmt.invalidFmtError(fmt, self);
-        }
-    }
-};
-
-test "Version.parse" {
-    @setEvalBranchQuota(3000);
-    try testVersionParse();
-    comptime (try testVersionParse());
-}
-
-fn testVersionParse() !void {
-    const f = struct {
-        fn eql(text: []const u8, v1: u32, v2: u32, v3: u32) !void {
-            const v = try Version.parse(text);
-            try std.testing.expect(v.major == v1 and v.minor == v2 and v.patch == v3);
-        }
-
-        fn err(text: []const u8, expected_err: anyerror) !void {
-            _ = Version.parse(text) catch |actual_err| {
-                if (actual_err == expected_err) return;
-                return actual_err;
-            };
-            return error.Unreachable;
-        }
-    };
-
-    try f.eql("2.6.32.11-svn21605", 2, 6, 32); // Debian PPC
-    try f.eql("2.11.2(0.329/5/3)", 2, 11, 2); // MinGW
-    try f.eql("5.4.0-1018-raspi", 5, 4, 0); // Ubuntu
-    try f.eql("5.7.12_3", 5, 7, 12); // Void
-    try f.eql("2.13-DEVELOPMENT", 2, 13, 0); // DragonFly
-    try f.eql("2.3-35", 2, 3, 0);
-    try f.eql("1a.4", 1, 0, 0);
-    try f.eql("3.b1.0", 3, 0, 0);
-    try f.eql("1.4beta", 1, 4, 0);
-    try f.eql("2.7.pre", 2, 7, 0);
-    try f.eql("0..3", 0, 0, 0);
-    try f.eql("8.008.", 8, 8, 0);
-    try f.eql("01...", 1, 0, 0);
-    try f.eql("55", 55, 0, 0);
-    try f.eql("4294967295.0.1", 4294967295, 0, 1);
-    try f.eql("429496729_6", 429496729, 0, 0);
-
-    try f.err("foobar", error.InvalidVersion);
-    try f.err("", error.InvalidVersion);
-    try f.err("-1", error.InvalidVersion);
-    try f.err("+4", error.InvalidVersion);
-    try f.err(".", error.InvalidVersion);
-    try f.err("....3", error.InvalidVersion);
-    try f.err("4294967296", error.Overflow);
-    try f.err("5000877755", error.Overflow);
-    // error.InvalidCharacter is not possible anymore
-}
-
 /// This data structure is used by the Zig language code generation and
 /// therefore must be kept in sync with the compiler implementation.
 pub const CallModifier = enum {
diff --git a/lib/std/c.zig b/lib/std/c.zig
index 7cc4adf815..c0ee29445a 100644
--- a/lib/std/c.zig
+++ b/lib/std/c.zig
@@ -20,7 +20,7 @@ pub const Tokenizer = tokenizer.Tokenizer;
 /// If linking gnu libc (glibc), the `ok` value will be true if the target
 /// version is greater than or equal to `glibc_version`.
 /// If linking a libc other than these, returns `false`.
-pub fn versionCheck(comptime glibc_version: std.builtin.Version) type {
+pub fn versionCheck(comptime glibc_version: std.SemanticVersion) type {
     return struct {
         pub const ok = blk: {
             if (!builtin.link_libc) break :blk false;
diff --git a/lib/std/crypto/tlcsprng.zig b/lib/std/crypto/tlcsprng.zig
index ac706e5f6a..54a30cfaba 100644
--- a/lib/std/crypto/tlcsprng.zig
+++ b/lib/std/crypto/tlcsprng.zig
@@ -38,6 +38,7 @@ const want_fork_safety = os_has_fork and !os_has_arc4random and
 const maybe_have_wipe_on_fork = builtin.os.isAtLeast(.linux, .{
     .major = 4,
     .minor = 14,
+    .patch = 0,
 }) orelse true;
 const is_haiku = builtin.os.tag == .haiku;
 
diff --git a/lib/std/os.zig b/lib/std/os.zig
index 4699d0186c..802bb1d8df 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -488,7 +488,7 @@ pub fn getrandom(buffer: []u8) GetRandomError!void {
     if (builtin.os.tag == .linux or builtin.os.tag == .freebsd) {
         var buf = buffer;
         const use_c = builtin.os.tag != .linux or
-            std.c.versionCheck(std.builtin.Version{ .major = 2, .minor = 25, .patch = 0 }).ok;
+            std.c.versionCheck(std.SemanticVersion{ .major = 2, .minor = 25, .patch = 0 }).ok;
 
         while (buf.len != 0) {
             const res = if (use_c) blk: {
@@ -5272,7 +5272,7 @@ pub fn getFdPath(fd: fd_t, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
             return target;
         },
         .freebsd => {
-            if (comptime builtin.os.version_range.semver.max.order(.{ .major = 13, .minor = 0 }) == .gt) {
+            if (comptime builtin.os.version_range.semver.max.order(.{ .major = 13, .minor = 0, .patch = 0 }) == .gt) {
                 var kfile: system.kinfo_file = undefined;
                 kfile.structsize = system.KINFO_FILE_SIZE;
                 switch (errno(system.fcntl(fd, system.F.KINFO, @ptrToInt(&kfile)))) {
@@ -5325,7 +5325,7 @@ pub fn getFdPath(fd: fd_t, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
             }
         },
         .dragonfly => {
-            if (comptime builtin.os.version_range.semver.max.order(.{ .major = 6, .minor = 0 }) == .lt) {
+            if (comptime builtin.os.version_range.semver.max.order(.{ .major = 6, .minor = 0, .patch = 0 }) == .lt) {
                 @compileError("querying for canonical path of a handle is unsupported on this host");
             }
             @memset(out_buffer[0..MAX_PATH_BYTES], 0);
@@ -5339,7 +5339,7 @@ pub fn getFdPath(fd: fd_t, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
             return out_buffer[0..len];
         },
         .netbsd => {
-            if (comptime builtin.os.version_range.semver.max.order(.{ .major = 10, .minor = 0 }) == .lt) {
+            if (comptime builtin.os.version_range.semver.max.order(.{ .major = 10, .minor = 0, .patch = 0 }) == .lt) {
                 @compileError("querying for canonical path of a handle is unsupported on this host");
             }
             @memset(out_buffer[0..MAX_PATH_BYTES], 0);
@@ -6152,9 +6152,9 @@ pub fn sendfile(
         .linux => sf: {
             // sendfile() first appeared in Linux 2.2, glibc 2.1.
             const call_sf = comptime if (builtin.link_libc)
-                std.c.versionCheck(.{ .major = 2, .minor = 1 }).ok
+                std.c.versionCheck(.{ .major = 2, .minor = 1, .patch = 0 }).ok
             else
-                builtin.os.version_range.linux.range.max.order(.{ .major = 2, .minor = 2 }) != .lt;
+                builtin.os.version_range.linux.range.max.order(.{ .major = 2, .minor = 2, .patch = 0 }) != .lt;
             if (!call_sf) break :sf;
 
             if (headers.len != 0) {
@@ -6453,8 +6453,8 @@ var has_copy_file_range_syscall = std.atomic.Atomic(bool).init(true);
 ///
 /// Maximum offsets on Linux and FreeBSD are `math.maxInt(i64)`.
 pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len: usize, flags: u32) CopyFileRangeError!usize {
-    if ((comptime builtin.os.isAtLeast(.freebsd, .{ .major = 13, .minor = 0 }) orelse false) or
-        ((comptime builtin.os.isAtLeast(.linux, .{ .major = 4, .minor = 5 }) orelse false and
+    if ((comptime builtin.os.isAtLeast(.freebsd, .{ .major = 13, .minor = 0, .patch = 0 }) orelse false) or
+        ((comptime builtin.os.isAtLeast(.linux, .{ .major = 4, .minor = 5, .patch = 0 }) orelse false and
         std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok) and
         has_copy_file_range_syscall.load(.Monotonic)))
     {
@@ -6787,7 +6787,7 @@ pub fn memfd_createZ(name: [*:0]const u8, flags: u32) MemFdCreateError!fd_t {
             }
         },
         .freebsd => {
-            if (comptime builtin.os.version_range.semver.max.order(.{ .major = 13, .minor = 0 }) == .lt)
+            if (comptime builtin.os.version_range.semver.max.order(.{ .major = 13, .minor = 0, .patch = 0 }) == .lt)
                 @compileError("memfd_create is unavailable on FreeBSD < 13.0");
             const rc = system.memfd_create(name, flags);
             switch (errno(rc)) {
diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig
index e7b66c0d55..59575e0109 100644
--- a/lib/std/os/test.zig
+++ b/lib/std/os/test.zig
@@ -541,7 +541,7 @@ test "memfd_create" {
     switch (native_os) {
         .linux => {},
         .freebsd => {
-            if (comptime builtin.os.version_range.semver.max.order(.{ .major = 13, .minor = 0 }) == .lt)
+            if (comptime builtin.os.version_range.semver.max.order(.{ .major = 13, .minor = 0, .patch = 0 }) == .lt)
                 return error.SkipZigTest;
         },
         else => return error.SkipZigTest,
diff --git a/lib/std/target.zig b/lib/std/target.zig
index 4c7bcfc37a..995edd02f7 100644
--- a/lib/std/target.zig
+++ b/lib/std/target.zig
@@ -1,7 +1,7 @@
 const std = @import("std.zig");
 const builtin = @import("builtin");
 const mem = std.mem;
-const Version = std.builtin.Version;
+const Version = std.SemanticVersion;
 
 /// TODO Nearly all the functions in this namespace would be
 /// better off if https://github.com/ziglang/zig/issues/425
@@ -272,75 +272,75 @@ pub const Target = struct {
 
                     .freebsd => return .{
                         .semver = Version.Range{
-                            .min = .{ .major = 12, .minor = 0 },
-                            .max = .{ .major = 13, .minor = 1 },
+                            .min = .{ .major = 12, .minor = 0, .patch = 0 },
+                            .max = .{ .major = 13, .minor = 1, .patch = 0 },
                         },
                     },
                     .macos => return switch (arch) {
                         .aarch64 => VersionRange{
                             .semver = .{
                                 .min = .{ .major = 11, .minor = 7, .patch = 1 },
-                                .max = .{ .major = 13, .minor = 3 },
+                                .max = .{ .major = 13, .minor = 3, .patch = 0 },
                             },
                         },
                         .x86_64 => VersionRange{
                             .semver = .{
                                 .min = .{ .major = 11, .minor = 7, .patch = 1 },
-                                .max = .{ .major = 13, .minor = 3 },
+                                .max = .{ .major = 13, .minor = 3, .patch = 0 },
                             },
                         },
                         else => unreachable,
                     },
                     .ios => return .{
                         .semver = .{
-                            .min = .{ .major = 12, .minor = 0 },
+                            .min = .{ .major = 12, .minor = 0, .patch = 0 },
                             .max = .{ .major = 13, .minor = 4, .patch = 0 },
                         },
                     },
                     .watchos => return .{
                         .semver = .{
-                            .min = .{ .major = 6, .minor = 0 },
+                            .min = .{ .major = 6, .minor = 0, .patch = 0 },
                             .max = .{ .major = 6, .minor = 2, .patch = 0 },
                         },
                     },
                     .tvos => return .{
                         .semver = .{
-                            .min = .{ .major = 13, .minor = 0 },
+                            .min = .{ .major = 13, .minor = 0, .patch = 0 },
                             .max = .{ .major = 13, .minor = 4, .patch = 0 },
                         },
                     },
                     .netbsd => return .{
                         .semver = .{
-                            .min = .{ .major = 8, .minor = 0 },
-                            .max = .{ .major = 10, .minor = 0 },
+                            .min = .{ .major = 8, .minor = 0, .patch = 0 },
+                            .max = .{ .major = 10, .minor = 0, .patch = 0 },
                         },
                     },
                     .openbsd => return .{
                         .semver = .{
-                            .min = .{ .major = 6, .minor = 8 },
-                            .max = .{ .major = 7, .minor = 2 },
+                            .min = .{ .major = 6, .minor = 8, .patch = 0 },
+                            .max = .{ .major = 7, .minor = 2, .patch = 0 },
                         },
                     },
                     .dragonfly => return .{
                         .semver = .{
-                            .min = .{ .major = 5, .minor = 8 },
-                            .max = .{ .major = 6, .minor = 4 },
+                            .min = .{ .major = 5, .minor = 8, .patch = 0 },
+                            .max = .{ .major = 6, .minor = 4, .patch = 0 },
                         },
                     },
                     .solaris => return .{
                         .semver = .{
-                            .min = .{ .major = 5, .minor = 11 },
-                            .max = .{ .major = 5, .minor = 11 },
+                            .min = .{ .major = 5, .minor = 11, .patch = 0 },
+                            .max = .{ .major = 5, .minor = 11, .patch = 0 },
                         },
                     },
 
                     .linux => return .{
                         .linux = .{
                             .range = .{
-                                .min = .{ .major = 3, .minor = 16 },
+                                .min = .{ .major = 3, .minor = 16, .patch = 0 },
                                 .max = .{ .major = 5, .minor = 10, .patch = 81 },
                             },
-                            .glibc = .{ .major = 2, .minor = 19 },
+                            .glibc = .{ .major = 2, .minor = 19, .patch = 0 },
                         },
                     },
 
diff --git a/lib/std/zig.zig b/lib/std/zig.zig
index 98edeabd10..fe6d2ec120 100644
--- a/lib/std/zig.zig
+++ b/lib/std/zig.zig
@@ -108,7 +108,7 @@ pub const BinNameOptions = struct {
     target: std.Target,
     output_mode: std.builtin.OutputMode,
     link_mode: ?std.builtin.LinkMode = null,
-    version: ?std.builtin.Version = null,
+    version: ?std.SemanticVersion = null,
 };
 
 /// Returns the standard file system basename of a binary generated by the Zig compiler.
diff --git a/lib/std/zig/CrossTarget.zig b/lib/std/zig/CrossTarget.zig
index 6432c733c6..13219888b2 100644
--- a/lib/std/zig/CrossTarget.zig
+++ b/lib/std/zig/CrossTarget.zig
@@ -33,7 +33,7 @@ os_version_max: ?OsVersion = null,
 
 /// `null` means default when cross compiling, or native when os_tag is native.
 /// If `isGnuLibC()` is `false`, this must be `null` and is ignored.
-glibc_version: ?SemVer = null,
+glibc_version: ?SemanticVersion = null,
 
 /// `null` means the native C ABI, if `os_tag` is native, otherwise it means the default C ABI.
 abi: ?Target.Abi = null,
@@ -61,11 +61,11 @@ pub const CpuModel = union(enum) {
 
 pub const OsVersion = union(enum) {
     none: void,
-    semver: SemVer,
+    semver: SemanticVersion,
     windows: Target.Os.WindowsVersion,
 };
 
-pub const SemVer = std.builtin.Version;
+pub const SemanticVersion = std.SemanticVersion;
 
 pub const DynamicLinker = Target.DynamicLinker;
 
@@ -266,9 +266,8 @@ pub fn parse(args: ParseOptions) !CrossTarget {
         const abi_ver_text = abi_it.rest();
         if (abi_it.next() != null) {
             if (result.isGnuLibC()) {
-                result.glibc_version = SemVer.parse(abi_ver_text) catch |err| switch (err) {
+                result.glibc_version = parseVersion(abi_ver_text) catch |err| switch (err) {
                     error.Overflow => return error.InvalidAbiVersion,
-                    error.InvalidCharacter => return error.InvalidAbiVersion,
                     error.InvalidVersion => return error.InvalidAbiVersion,
                 };
             } else {
@@ -353,6 +352,31 @@ pub fn parseCpuArch(args: ParseOptions) ?Target.Cpu.Arch {
     }
 }
 
+/// Parses a version with an omitted patch component, such as "1.0",
+/// which SemanticVersion.parse is not capable of.
+fn parseVersion(ver: []const u8) !SemanticVersion {
+    const parseVersionComponent = struct {
+        fn parseVersionComponent(component: []const u8) !usize {
+            return std.fmt.parseUnsigned(usize, component, 10) catch |err| {
+                switch (err) {
+                    error.InvalidCharacter => return error.InvalidVersion,
+                    error.Overflow => return error.Overflow,
+                }
+            };
+        }
+    }.parseVersionComponent;
+    var version_components = mem.split(u8, ver, ".");
+    const major = version_components.first();
+    const minor = version_components.next() orelse return error.InvalidVersion;
+    const patch = version_components.next() orelse "0";
+    if (version_components.next() != null) return error.InvalidVersion;
+    return .{
+        .major = try parseVersionComponent(major),
+        .minor = try parseVersionComponent(minor),
+        .patch = try parseVersionComponent(patch),
+    };
+}
+
 /// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
 pub fn getCpu(self: CrossTarget) Target.Cpu {
     switch (self.cpu_model) {
@@ -534,6 +558,16 @@ pub fn isNative(self: CrossTarget) bool {
     return self.isNativeCpu() and self.isNativeOs() and self.isNativeAbi();
 }
 
+/// Formats a version with the patch component omitted if it is zero,
+/// unlike SemanticVersion.format which formats all its version components regardless.
+fn formatVersion(version: SemanticVersion, writer: anytype) !void {
+    if (version.patch == 0) {
+        try writer.print("{d}.{d}", .{ version.major, version.minor });
+    } else {
+        try writer.print("{d}.{d}.{d}", .{ version.major, version.minor, version.patch });
+    }
+}
+
 pub fn zigTriple(self: CrossTarget, allocator: mem.Allocator) error{OutOfMemory}![]u8 {
     if (self.isNative()) {
         return allocator.dupe(u8, "native");
@@ -552,20 +586,27 @@ pub fn zigTriple(self: CrossTarget, allocator: mem.Allocator) error{OutOfMemory}
     if (self.os_version_min != null or self.os_version_max != null) {
         switch (self.getOsVersionMin()) {
             .none => {},
-            .semver => |v| try result.writer().print(".{}", .{v}),
+            .semver => |v| {
+                try result.writer().writeAll(".");
+                try formatVersion(v, result.writer());
+            },
             .windows => |v| try result.writer().print("{s}", .{v}),
         }
     }
     if (self.os_version_max) |max| {
         switch (max) {
             .none => {},
-            .semver => |v| try result.writer().print("...{}", .{v}),
+            .semver => |v| {
+                try result.writer().writeAll("...");
+                try formatVersion(v, result.writer());
+            },
             .windows => |v| try result.writer().print("..{s}", .{v}),
         }
     }
 
     if (self.glibc_version) |v| {
-        try result.writer().print("-{s}.{}", .{ @tagName(self.getAbi()), v });
+        try result.writer().print("-{s}.", .{@tagName(self.getAbi())});
+        try formatVersion(v, result.writer());
     } else if (self.abi) |abi| {
         try result.writer().print("-{s}", .{@tagName(abi)});
     }
@@ -630,7 +671,7 @@ pub fn isGnuLibC(self: CrossTarget) bool {
 
 pub fn setGnuLibCVersion(self: *CrossTarget, major: u32, minor: u32, patch: u32) void {
     assert(self.isGnuLibC());
-    self.glibc_version = SemVer{ .major = major, .minor = minor, .patch = patch };
+    self.glibc_version = SemanticVersion{ .major = major, .minor = minor, .patch = patch };
 }
 
 pub fn getObjectFormat(self: CrossTarget) Target.ObjectFormat {
@@ -709,17 +750,15 @@ fn parseOs(result: *CrossTarget, diags: *ParseOptions.Diagnostics, text: []const
             var range_it = mem.splitSequence(u8, version_text, "...");
 
             const min_text = range_it.next().?;
-            const min_ver = SemVer.parse(min_text) catch |err| switch (err) {
+            const min_ver = parseVersion(min_text) catch |err| switch (err) {
                 error.Overflow => return error.InvalidOperatingSystemVersion,
-                error.InvalidCharacter => return error.InvalidOperatingSystemVersion,
                 error.InvalidVersion => return error.InvalidOperatingSystemVersion,
             };
             result.os_version_min = .{ .semver = min_ver };
 
             const max_text = range_it.next() orelse return;
-            const max_ver = SemVer.parse(max_text) catch |err| switch (err) {
+            const max_ver = parseVersion(max_text) catch |err| switch (err) {
                 error.Overflow => return error.InvalidOperatingSystemVersion,
-                error.InvalidCharacter => return error.InvalidOperatingSystemVersion,
                 error.InvalidVersion => return error.InvalidOperatingSystemVersion,
             };
             result.os_version_max = .{ .semver = max_ver };
diff --git a/lib/std/zig/system/NativeTargetInfo.zig b/lib/std/zig/system/NativeTargetInfo.zig
index cddaea2295..2daac4881d 100644
--- a/lib/std/zig/system/NativeTargetInfo.zig
+++ b/lib/std/zig/system/NativeTargetInfo.zig
@@ -43,24 +43,22 @@ pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo {
                 const release = mem.sliceTo(&uts.release, 0);
                 // The release field sometimes has a weird format,
                 // `Version.parse` will attempt to find some meaningful interpretation.
-                if (std.builtin.Version.parse(release)) |ver| {
+                if (std.SemanticVersion.parse(release)) |ver| {
                     os.version_range.linux.range.min = ver;
                     os.version_range.linux.range.max = ver;
                 } else |err| switch (err) {
                     error.Overflow => {},
-                    error.InvalidCharacter => {},
                     error.InvalidVersion => {},
                 }
             },
             .solaris => {
                 const uts = std.os.uname();
                 const release = mem.sliceTo(&uts.release, 0);
-                if (std.builtin.Version.parse(release)) |ver| {
+                if (std.SemanticVersion.parse(release)) |ver| {
                     os.version_range.semver.min = ver;
                     os.version_range.semver.max = ver;
                 } else |err| switch (err) {
                     error.Overflow => {},
-                    error.InvalidCharacter => {},
                     error.InvalidVersion => {},
                 }
             },
@@ -144,7 +142,7 @@ pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo {
                     error.Unexpected => return error.OSVersionDetectionFail,
                 };
 
-                if (std.builtin.Version.parse(buf[0 .. len - 1])) |ver| {
+                if (std.SemanticVersion.parse(buf[0 .. len - 1])) |ver| {
                     os.version_range.semver.min = ver;
                     os.version_range.semver.max = ver;
                 } else |_| {
@@ -390,7 +388,7 @@ fn detectAbiAndDynamicLinker(
     };
 }
 
-fn glibcVerFromRPath(rpath: []const u8) !std.builtin.Version {
+fn glibcVerFromRPath(rpath: []const u8) !std.SemanticVersion {
     var dir = fs.cwd().openDir(rpath, .{}) catch |err| switch (err) {
         error.NameTooLong => unreachable,
         error.InvalidUtf8 => unreachable,
@@ -471,7 +469,7 @@ fn glibcVerFromRPath(rpath: []const u8) !std.builtin.Version {
     };
 }
 
-fn glibcVerFromSoFile(file: fs.File) !std.builtin.Version {
+fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
     var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;
     _ = try preadMin(file, &hdr_buf, 0, hdr_buf.len);
     const hdr32 = @ptrCast(*elf.Elf32_Ehdr, &hdr_buf);
@@ -557,13 +555,12 @@ fn glibcVerFromSoFile(file: fs.File) !std.builtin.Version {
     const dynstr_bytes = buf[0..dynstr_size];
     _ = try preadMin(file, dynstr_bytes, dynstr.offset, dynstr_bytes.len);
     var it = mem.splitScalar(u8, dynstr_bytes, 0);
-    var max_ver: std.builtin.Version = .{ .major = 2, .minor = 2, .patch = 5 };
+    var max_ver: std.SemanticVersion = .{ .major = 2, .minor = 2, .patch = 5 };
     while (it.next()) |s| {
         if (mem.startsWith(u8, s, "GLIBC_2.")) {
             const chopped = s["GLIBC_".len..];
-            const ver = std.builtin.Version.parse(chopped) catch |err| switch (err) {
+            const ver = std.SemanticVersion.parse(chopped) catch |err| switch (err) {
                 error.Overflow => return error.InvalidGnuLibCVersion,
-                error.InvalidCharacter => return error.InvalidGnuLibCVersion,
                 error.InvalidVersion => return error.InvalidGnuLibCVersion,
             };
             switch (ver.order(max_ver)) {
@@ -575,7 +572,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.builtin.Version {
     return max_ver;
 }
 
-fn glibcVerFromLinkName(link_name: []const u8, prefix: []const u8) !std.builtin.Version {
+fn glibcVerFromLinkName(link_name: []const u8, prefix: []const u8) !std.SemanticVersion {
     // example: "libc-2.3.4.so"
     // example: "libc-2.27.so"
     // example: "ld-2.33.so"
@@ -585,9 +582,8 @@ fn glibcVerFromLinkName(link_name: []const u8, prefix: []const u8) !std.builtin.
     }
     // chop off "libc-" and ".so"
     const link_name_chopped = link_name[prefix.len .. link_name.len - suffix.len];
-    return std.builtin.Version.parse(link_name_chopped) catch |err| switch (err) {
+    return std.SemanticVersion.parse(link_name_chopped) catch |err| switch (err) {
         error.Overflow => return error.InvalidGnuLibCVersion,
-        error.InvalidCharacter => return error.InvalidGnuLibCVersion,
         error.InvalidVersion => return error.InvalidGnuLibCVersion,
     };
 }
diff --git a/lib/std/zig/system/darwin.zig b/lib/std/zig/system/darwin.zig
index fbddaa799a..05762ffc54 100644
--- a/lib/std/zig/system/darwin.zig
+++ b/lib/std/zig/system/darwin.zig
@@ -2,7 +2,7 @@ const std = @import("std");
 const mem = std.mem;
 const Allocator = mem.Allocator;
 const Target = std.Target;
-const Version = std.builtin.Version;
+const Version = std.SemanticVersion;
 
 pub const macos = @import("darwin/macos.zig");
 
@@ -69,6 +69,7 @@ pub fn getDarwinSDK(allocator: Allocator, target: Target) ?DarwinSDK {
         const version = Version.parse(raw_version) catch Version{
             .major = 0,
             .minor = 0,
+            .patch = 0,
         };
         break :version version;
     };
diff --git a/lib/std/zig/system/darwin/macos.zig b/lib/std/zig/system/darwin/macos.zig
index eef2f77a62..6717b1319f 100644
--- a/lib/std/zig/system/darwin/macos.zig
+++ b/lib/std/zig/system/darwin/macos.zig
@@ -74,20 +74,39 @@ pub fn detect(target_os: *Target.Os) !void {
     return error.OSVersionDetectionFail;
 }
 
-fn parseSystemVersion(buf: []const u8) !std.builtin.Version {
+fn parseSystemVersion(buf: []const u8) !std.SemanticVersion {
     var svt = SystemVersionTokenizer{ .bytes = buf };
     try svt.skipUntilTag(.start, "dict");
     while (true) {
         try svt.skipUntilTag(.start, "key");
         const content = try svt.expectContent();
         try svt.skipUntilTag(.end, "key");
-        if (std.mem.eql(u8, content, "ProductVersion")) break;
+        if (mem.eql(u8, content, "ProductVersion")) break;
     }
     try svt.skipUntilTag(.start, "string");
     const ver = try svt.expectContent();
     try svt.skipUntilTag(.end, "string");
 
-    return std.builtin.Version.parse(ver);
+    const parseVersionComponent = struct {
+        fn parseVersionComponent(component: []const u8) !usize {
+            return std.fmt.parseUnsigned(usize, component, 10) catch |err| {
+                switch (err) {
+                    error.InvalidCharacter => return error.InvalidVersion,
+                    error.Overflow => return error.Overflow,
+                }
+            };
+        }
+    }.parseVersionComponent;
+    var version_components = mem.split(u8, ver, ".");
+    const major = version_components.first();
+    const minor = version_components.next() orelse return error.InvalidVersion;
+    const patch = version_components.next() orelse "0";
+    if (version_components.next() != null) return error.InvalidVersion;
+    return .{
+        .major = try parseVersionComponent(major),
+        .minor = try parseVersionComponent(minor),
+        .patch = try parseVersionComponent(patch),
+    };
 }
 
 const SystemVersionTokenizer = struct {
@@ -246,7 +265,7 @@ const SystemVersionTokenizer = struct {
         while (try self.next()) |tok| {
             switch (tok) {
                 .tag => |tag| {
-                    if (tag.kind == kind and std.mem.eql(u8, tag.name, name)) return;
+                    if (tag.kind == kind and mem.eql(u8, tag.name, name)) return;
                 },
                 else => {},
             }
@@ -297,7 +316,7 @@ test "detect" {
             \\
             \\
             ,
-            .{ .major = 10, .minor = 3 },
+            .{ .major = 10, .minor = 3, .patch = 0 },
         },
         .{
             \\
@@ -361,7 +380,7 @@ test "detect" {
             \\
             \\
             ,
-            .{ .major = 11, .minor = 0 },
+            .{ .major = 11, .minor = 0, .patch = 0 },
         },
         .{
             \\
@@ -383,27 +402,17 @@ test "detect" {
             \\
             \\
             ,
-            .{ .major = 11, .minor = 1 },
+            .{ .major = 11, .minor = 1, .patch = 0 },
         },
     };
 
     inline for (cases) |case| {
         const ver0 = try parseSystemVersion(case[0]);
-        const ver1: std.builtin.Version = case[1];
-        try testVersionEquality(ver1, ver0);
+        const ver1: std.SemanticVersion = case[1];
+        try testing.expectEqual(@as(std.math.Order, .eq), ver0.order(ver1));
     }
 }
 
-fn testVersionEquality(expected: std.builtin.Version, got: std.builtin.Version) !void {
-    var b_expected: [64]u8 = undefined;
-    const s_expected: []const u8 = try std.fmt.bufPrint(b_expected[0..], "{}", .{expected});
-
-    var b_got: [64]u8 = undefined;
-    const s_got: []const u8 = try std.fmt.bufPrint(b_got[0..], "{}", .{got});
-
-    try testing.expectEqualStrings(s_expected, s_got);
-}
-
 pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
     var cpu_family: std.c.CPUFAMILY = undefined;
     var len: usize = @sizeOf(std.c.CPUFAMILY);
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 662dcdc408..739b747e32 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -615,8 +615,8 @@ pub const InitOptions = struct {
     stack_size_override: ?u64 = null,
     image_base_override: ?u64 = null,
     self_exe_path: ?[]const u8 = null,
-    version: ?std.builtin.Version = null,
-    compatibility_version: ?std.builtin.Version = null,
+    version: ?std.SemanticVersion = null,
+    compatibility_version: ?std.SemanticVersion = null,
     libc_installation: ?*const LibCInstallation = null,
     machine_code_model: std.builtin.CodeModel = .default,
     clang_preprocessor_mode: ClangPreprocessorMode = .no,
diff --git a/src/codegen/spirv/spec.zig b/src/codegen/spirv/spec.zig
index 60d16461cb..f73487f41f 100644
--- a/src/codegen/spirv/spec.zig
+++ b/src/codegen/spirv/spec.zig
@@ -1,6 +1,6 @@
 //! This file is auto-generated by tools/gen_spirv_spec.zig.
 
-const Version = @import("std").builtin.Version;
+const Version = @import("std").SemanticVersion;
 
 pub const Word = u32;
 pub const IdResult = struct {
diff --git a/src/glibc.zig b/src/glibc.zig
index 4ab00eeed9..bb38c2c987 100644
--- a/src/glibc.zig
+++ b/src/glibc.zig
@@ -5,7 +5,7 @@ const log = std.log;
 const fs = std.fs;
 const path = fs.path;
 const assert = std.debug.assert;
-const Version = std.builtin.Version;
+const Version = std.SemanticVersion;
 
 const target_util = @import("target.zig");
 const Compilation = @import("Compilation.zig");
@@ -172,7 +172,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr
 
     const target = comp.getTarget();
     const target_ver = target.os.version_range.linux.glibc;
-    const start_old_init_fini = target_ver.order(.{ .major = 2, .minor = 33 }) != .gt;
+    const start_old_init_fini = target_ver.order(.{ .major = 2, .minor = 33, .patch = 0 }) != .gt;
 
     // In all cases in this function, we add the C compiler flags to
     // cache_exempt_flags rather than extra_flags, because these arguments
diff --git a/src/link.zig b/src/link.zig
index c184f7ed7c..9458bd6c0a 100644
--- a/src/link.zig
+++ b/src/link.zig
@@ -197,8 +197,8 @@ pub const Options = struct {
     /// __real_symbol.
     symbol_wrap_set: std.StringArrayHashMapUnmanaged(void),
 
-    version: ?std.builtin.Version,
-    compatibility_version: ?std.builtin.Version,
+    version: ?std.SemanticVersion,
+    compatibility_version: ?std.SemanticVersion,
     libc_installation: ?*const LibCInstallation,
 
     dwarf_format: ?std.dwarf.Format,
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index e0d0dfc75f..b2e7f57211 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -3414,7 +3414,7 @@ const CsuObjects = struct {
                     if (result.crtn) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* });
 
                     var gccv: []const u8 = undefined;
-                    if (link_options.target.os.version_range.semver.isAtLeast(.{ .major = 5, .minor = 4 }) orelse true) {
+                    if (link_options.target.os.version_range.semver.isAtLeast(.{ .major = 5, .minor = 4, .patch = 0 }) orelse true) {
                         gccv = "gcc80";
                     } else {
                         gccv = "gcc54";
diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig
index 5111f53f2a..eb582e2222 100644
--- a/src/link/MachO/load_commands.zig
+++ b/src/link/MachO/load_commands.zig
@@ -204,12 +204,12 @@ pub fn writeDylibIdLC(gpa: Allocator, options: *const link.Options, lc_writer: a
     const emit = options.emit.?;
     const install_name = options.install_name orelse try emit.directory.join(gpa, &.{emit.sub_path});
     defer if (options.install_name == null) gpa.free(install_name);
-    const curr = options.version orelse std.builtin.Version{
+    const curr = options.version orelse std.SemanticVersion{
         .major = 1,
         .minor = 0,
         .patch = 0,
     };
-    const compat = options.compatibility_version orelse std.builtin.Version{
+    const compat = options.compatibility_version orelse std.SemanticVersion{
         .major = 1,
         .minor = 0,
         .patch = 0,
@@ -217,8 +217,8 @@ pub fn writeDylibIdLC(gpa: Allocator, options: *const link.Options, lc_writer: a
     try writeDylibLC(.{
         .cmd = .ID_DYLIB,
         .name = install_name,
-        .current_version = curr.major << 16 | curr.minor << 8 | curr.patch,
-        .compatibility_version = compat.major << 16 | compat.minor << 8 | compat.patch,
+        .current_version = @intCast(u32, curr.major << 16 | curr.minor << 8 | curr.patch),
+        .compatibility_version = @intCast(u32, compat.major << 16 | compat.minor << 8 | compat.patch),
     }, lc_writer);
 }
 
@@ -275,12 +275,12 @@ pub fn writeBuildVersionLC(options: *const link.Options, lc_writer: anytype) !vo
     const cmdsize = @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version);
     const platform_version = blk: {
         const ver = options.target.os.version_range.semver.min;
-        const platform_version = ver.major << 16 | ver.minor << 8;
+        const platform_version = @intCast(u32, ver.major << 16 | ver.minor << 8);
         break :blk platform_version;
     };
     const sdk_version = if (options.native_darwin_sdk) |sdk| blk: {
         const ver = sdk.version;
-        const sdk_version = ver.major << 16 | ver.minor << 8;
+        const sdk_version = @intCast(u32, ver.major << 16 | ver.minor << 8);
         break :blk sdk_version;
     } else platform_version;
     const is_simulator_abi = options.target.abi == .simulator;
diff --git a/src/main.zig b/src/main.zig
index b245b357ca..2f56cad133 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -724,9 +724,9 @@ fn buildOutputType(
     var dll_export_fns: ?bool = null;
     var single_threaded: ?bool = null;
     var root_src_file: ?[]const u8 = null;
-    var version: std.builtin.Version = .{ .major = 0, .minor = 0, .patch = 0 };
+    var version: std.SemanticVersion = .{ .major = 0, .minor = 0, .patch = 0 };
     var have_version = false;
-    var compatibility_version: ?std.builtin.Version = null;
+    var compatibility_version: ?std.SemanticVersion = null;
     var strip: ?bool = null;
     var formatted_panics: ?bool = null;
     var function_sections = false;
@@ -1121,7 +1121,7 @@ fn buildOutputType(
                         try cssan.addIncludePath(.iframework, arg, args_iter.nextOrFatal(), false);
                     } else if (mem.eql(u8, arg, "--version")) {
                         const next_arg = args_iter.nextOrFatal();
-                        version = std.builtin.Version.parse(next_arg) catch |err| {
+                        version = std.SemanticVersion.parse(next_arg) catch |err| {
                             fatal("unable to parse --version '{s}': {s}", .{ next_arg, @errorName(err) });
                         };
                         have_version = true;
@@ -2152,12 +2152,12 @@ fn buildOutputType(
                     try system_libs.put(linker_args_it.nextOrFatal(), .{ .weak = true });
                 } else if (mem.eql(u8, arg, "-compatibility_version")) {
                     const compat_version = linker_args_it.nextOrFatal();
-                    compatibility_version = std.builtin.Version.parse(compat_version) catch |err| {
+                    compatibility_version = std.SemanticVersion.parse(compat_version) catch |err| {
                         fatal("unable to parse -compatibility_version '{s}': {s}", .{ compat_version, @errorName(err) });
                     };
                 } else if (mem.eql(u8, arg, "-current_version")) {
                     const curr_version = linker_args_it.nextOrFatal();
-                    version = std.builtin.Version.parse(curr_version) catch |err| {
+                    version = std.SemanticVersion.parse(curr_version) catch |err| {
                         fatal("unable to parse -current_version '{s}': {s}", .{ curr_version, @errorName(err) });
                     };
                     have_version = true;
@@ -2207,10 +2207,9 @@ fn buildOutputType(
                 } else if (mem.startsWith(u8, arg, "/version:")) {
                     var split_it = mem.splitBackwardsScalar(u8, arg, ':');
                     const version_arg = split_it.first();
-                    version = std.builtin.Version.parse(version_arg) catch |err| {
+                    version = std.SemanticVersion.parse(version_arg) catch |err| {
                         fatal("unable to parse /version '{s}': {s}", .{ arg, @errorName(err) });
                     };
-
                     have_version = true;
                 } else {
                     fatal("unsupported linker arg: {s}", .{arg});
diff --git a/src/target.zig b/src/target.zig
index ac78d27c1a..2d27869cf6 100644
--- a/src/target.zig
+++ b/src/target.zig
@@ -6,7 +6,7 @@ pub const ArchOsAbi = struct {
     arch: std.Target.Cpu.Arch,
     os: std.Target.Os.Tag,
     abi: std.Target.Abi,
-    os_ver: ?std.builtin.Version = null,
+    os_ver: ?std.SemanticVersion = null,
 };
 
 pub const available_libcs = [_]ArchOsAbi{
@@ -16,9 +16,9 @@ pub const available_libcs = [_]ArchOsAbi{
     .{ .arch = .aarch64, .os = .linux, .abi = .gnu },
     .{ .arch = .aarch64, .os = .linux, .abi = .musl },
     .{ .arch = .aarch64, .os = .windows, .abi = .gnu },
-    .{ .arch = .aarch64, .os = .macos, .abi = .none, .os_ver = .{ .major = 11, .minor = 0 } },
-    .{ .arch = .aarch64, .os = .macos, .abi = .none, .os_ver = .{ .major = 12, .minor = 0 } },
-    .{ .arch = .aarch64, .os = .macos, .abi = .none, .os_ver = .{ .major = 13, .minor = 0 } },
+    .{ .arch = .aarch64, .os = .macos, .abi = .none, .os_ver = .{ .major = 11, .minor = 0, .patch = 0 } },
+    .{ .arch = .aarch64, .os = .macos, .abi = .none, .os_ver = .{ .major = 12, .minor = 0, .patch = 0 } },
+    .{ .arch = .aarch64, .os = .macos, .abi = .none, .os_ver = .{ .major = 13, .minor = 0, .patch = 0 } },
     .{ .arch = .armeb, .os = .linux, .abi = .gnueabi },
     .{ .arch = .armeb, .os = .linux, .abi = .gnueabihf },
     .{ .arch = .armeb, .os = .linux, .abi = .musleabi },
@@ -71,9 +71,9 @@ pub const available_libcs = [_]ArchOsAbi{
     .{ .arch = .x86_64, .os = .linux, .abi = .gnux32 },
     .{ .arch = .x86_64, .os = .linux, .abi = .musl },
     .{ .arch = .x86_64, .os = .windows, .abi = .gnu },
-    .{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 11, .minor = 0 } },
-    .{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 12, .minor = 0 } },
-    .{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 13, .minor = 0 } },
+    .{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 11, .minor = 0, .patch = 0 } },
+    .{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 12, .minor = 0, .patch = 0 } },
+    .{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 13, .minor = 0, .patch = 0 } },
 };
 
 pub fn libCGenericName(target: std.Target) [:0]const u8 {
diff --git a/test/link/macho/dylib/build.zig b/test/link/macho/dylib/build.zig
index fe294f3333..5fbf73dd1b 100644
--- a/test/link/macho/dylib/build.zig
+++ b/test/link/macho/dylib/build.zig
@@ -17,7 +17,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
 
     const dylib = b.addSharedLibrary(.{
         .name = "a",
-        .version = .{ .major = 1, .minor = 0 },
+        .version = .{ .major = 1, .minor = 0, .patch = 0 },
         .optimize = optimize,
         .target = target,
     });
diff --git a/test/link/macho/needed_library/build.zig b/test/link/macho/needed_library/build.zig
index 7b56572cc3..d39166c18b 100644
--- a/test/link/macho/needed_library/build.zig
+++ b/test/link/macho/needed_library/build.zig
@@ -17,7 +17,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
 
     const dylib = b.addSharedLibrary(.{
         .name = "a",
-        .version = .{ .major = 1, .minor = 0 },
+        .version = .{ .major = 1, .minor = 0, .patch = 0 },
         .optimize = optimize,
         .target = target,
     });
diff --git a/test/link/macho/search_strategy/build.zig b/test/link/macho/search_strategy/build.zig
index 4b52d9aa0a..336ca593b1 100644
--- a/test/link/macho/search_strategy/build.zig
+++ b/test/link/macho/search_strategy/build.zig
@@ -61,7 +61,7 @@ fn createScenario(
 
     const dylib = b.addSharedLibrary(.{
         .name = name,
-        .version = .{ .major = 1, .minor = 0 },
+        .version = .{ .major = 1, .minor = 0, .patch = 0 },
         .optimize = optimize,
         .target = target,
     });
diff --git a/test/link/macho/tls/build.zig b/test/link/macho/tls/build.zig
index f155f514f8..555fe207c5 100644
--- a/test/link/macho/tls/build.zig
+++ b/test/link/macho/tls/build.zig
@@ -17,7 +17,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
 
     const lib = b.addSharedLibrary(.{
         .name = "a",
-        .version = .{ .major = 1, .minor = 0 },
+        .version = .{ .major = 1, .minor = 0, .patch = 0 },
         .optimize = optimize,
         .target = target,
     });
diff --git a/test/link/macho/uuid/build.zig b/test/link/macho/uuid/build.zig
index 0072825f46..f2ef6b33ec 100644
--- a/test/link/macho/uuid/build.zig
+++ b/test/link/macho/uuid/build.zig
@@ -62,7 +62,7 @@ fn simpleDylib(
 ) *std.Build.Step.Compile {
     const dylib = b.addSharedLibrary(.{
         .name = "test",
-        .version = .{ .major = 1, .minor = 0 },
+        .version = .{ .major = 1, .minor = 0, .patch = 0 },
         .optimize = optimize,
         .target = target,
     });
diff --git a/test/standalone/load_dynamic_library/build.zig b/test/standalone/load_dynamic_library/build.zig
index 6dec8de7ae..a711704e46 100644
--- a/test/standalone/load_dynamic_library/build.zig
+++ b/test/standalone/load_dynamic_library/build.zig
@@ -13,7 +13,7 @@ pub fn build(b: *std.Build) void {
     const lib = b.addSharedLibrary(.{
         .name = "add",
         .root_source_file = .{ .path = "add.zig" },
-        .version = .{ .major = 1, .minor = 0 },
+        .version = .{ .major = 1, .minor = 0, .patch = 0 },
         .optimize = optimize,
         .target = target,
     });
diff --git a/test/standalone/shared_library/build.zig b/test/standalone/shared_library/build.zig
index 377bf81862..3034d89017 100644
--- a/test/standalone/shared_library/build.zig
+++ b/test/standalone/shared_library/build.zig
@@ -9,7 +9,7 @@ pub fn build(b: *std.Build) void {
     const lib = b.addSharedLibrary(.{
         .name = "mathtest",
         .root_source_file = .{ .path = "mathtest.zig" },
-        .version = .{ .major = 1, .minor = 0 },
+        .version = .{ .major = 1, .minor = 0, .patch = 0 },
         .target = target,
         .optimize = optimize,
     });
diff --git a/tools/gen_spirv_spec.zig b/tools/gen_spirv_spec.zig
index 28a5ed7ded..b48e3834a2 100644
--- a/tools/gen_spirv_spec.zig
+++ b/tools/gen_spirv_spec.zig
@@ -76,7 +76,7 @@ fn render(writer: anytype, allocator: Allocator, registry: g.CoreRegistry) !void
     try writer.writeAll(
         \\//! This file is auto-generated by tools/gen_spirv_spec.zig.
         \\
-        \\const Version = @import("std").builtin.Version;
+        \\const Version = @import("std").SemanticVersion;
         \\
         \\pub const Word = u32;
         \\pub const IdResult = struct{
-- 
cgit v1.2.3