Commit a9b18023a4

Andrew Kelley <andrew@ziglang.org>
2020-09-18 08:27:24
stage2: implement --show-builtin
This takes the place of `zig builtin`. This is an improvement over the command because now the generated source will correctly show LinkMode and OutputMode, whereas before it was always stuck as Static and Obj, respectively.
1 parent dc47868
src/all_types.hpp
@@ -2161,11 +2161,9 @@ struct CodeGen {
     bool have_err_ret_tracing;
     bool verbose_tokenize;
     bool verbose_ast;
-    bool verbose_link;
     bool verbose_ir;
     bool verbose_llvm_ir;
     bool verbose_cimport;
-    bool verbose_cc;
     bool verbose_llvm_cpu_features;
     bool error_during_imports;
     bool generate_error_name_table;
src/stage1.cpp
@@ -104,11 +104,9 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {
 
     g->verbose_tokenize = stage1->verbose_tokenize;
     g->verbose_ast = stage1->verbose_ast;
-    g->verbose_link = stage1->verbose_link;
     g->verbose_ir = stage1->verbose_ir;
     g->verbose_llvm_ir = stage1->verbose_llvm_ir;
     g->verbose_cimport = stage1->verbose_cimport;
-    g->verbose_cc = stage1->verbose_cc;
     g->verbose_llvm_cpu_features = stage1->verbose_llvm_cpu_features;
 
     g->err_color = stage1->err_color;
src/stage1.h
@@ -194,11 +194,9 @@ struct ZigStage1 {
     bool test_is_evented;
     bool verbose_tokenize;
     bool verbose_ast;
-    bool verbose_link;
     bool verbose_ir;
     bool verbose_llvm_ir;
     bool verbose_cimport;
-    bool verbose_cc;
     bool verbose_llvm_cpu_features;
 };
 
src/zig0.cpp
@@ -44,11 +44,9 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
         "  -mcpu [cpu]                  specify target CPU and feature set\n"
         "  --verbose-tokenize           enable compiler debug output for tokenization\n"
         "  --verbose-ast                enable compiler debug output for AST parsing\n"
-        "  --verbose-link               enable compiler debug output for linking\n"
         "  --verbose-ir                 enable compiler debug output for Zig IR\n"
         "  --verbose-llvm-ir            enable compiler debug output for LLVM IR\n"
         "  --verbose-cimport            enable compiler debug output for C imports\n"
-        "  --verbose-cc                 enable compiler debug output for C compilation\n"
         "  --verbose-llvm-cpu-features  enable compiler debug output for LLVM CPU features\n"
         "\n"
     , arg0);
@@ -82,11 +80,9 @@ int main(int argc, char **argv) {
     const char *out_name = nullptr;
     bool verbose_tokenize = false;
     bool verbose_ast = false;
-    bool verbose_link = false;
     bool verbose_ir = false;
     bool verbose_llvm_ir = false;
     bool verbose_cimport = false;
-    bool verbose_cc = false;
     bool verbose_llvm_cpu_features = false;
     ErrColor color = ErrColorAuto;
     const char *dynamic_linker = nullptr;
@@ -120,16 +116,12 @@ int main(int argc, char **argv) {
                 verbose_tokenize = true;
             } else if (strcmp(arg, "--verbose-ast") == 0) {
                 verbose_ast = true;
-            } else if (strcmp(arg, "--verbose-link") == 0) {
-                verbose_link = true;
             } else if (strcmp(arg, "--verbose-ir") == 0) {
                 verbose_ir = true;
             } else if (strcmp(arg, "--verbose-llvm-ir") == 0) {
                 verbose_llvm_ir = true;
             } else if (strcmp(arg, "--verbose-cimport") == 0) {
                 verbose_cimport = true;
-            } else if (strcmp(arg, "--verbose-cc") == 0) {
-                verbose_cc = true;
             } else if (strcmp(arg, "--verbose-llvm-cpu-features") == 0) {
                 verbose_llvm_cpu_features = true;
             } else if (arg[1] == 'l' && arg[2] != 0) {
@@ -283,11 +275,9 @@ int main(int argc, char **argv) {
     stage1->strip = strip;
     stage1->verbose_tokenize = verbose_tokenize;
     stage1->verbose_ast = verbose_ast;
-    stage1->verbose_link = verbose_link;
     stage1->verbose_ir = verbose_ir;
     stage1->verbose_llvm_ir = verbose_llvm_ir;
     stage1->verbose_cimport = verbose_cimport;
-    stage1->verbose_cc = verbose_cc;
     stage1->verbose_llvm_cpu_features = verbose_llvm_cpu_features;
     stage1->output_dir_ptr = output_dir;
     stage1->output_dir_len = strlen(output_dir);
src-self-hosted/link/Elf.zig
@@ -1569,7 +1569,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
         try argv.append("-Bsymbolic");
     }
 
-    if (self.base.options.debug_link) {
+    if (self.base.options.verbose_link) {
         for (argv.items[0 .. argv.items.len - 1]) |arg| {
             std.debug.print("{} ", .{arg});
         }
src-self-hosted/Compilation.zig
@@ -29,7 +29,7 @@ c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},
 
 link_error_flags: link.File.ErrorFlags = .{},
 
-work_queue: std.fifo.LinearFifo(WorkItem, .Dynamic),
+work_queue: std.fifo.LinearFifo(Job, .Dynamic),
 
 /// The ErrorMsg memory is owned by the `CObject`, using Compilation's general purpose allocator.
 failed_c_objects: std.AutoArrayHashMapUnmanaged(*CObject, *ErrorMsg) = .{},
@@ -43,8 +43,9 @@ sanitize_c: bool,
 /// This is `true` for `zig cc`, `zig c++`, and `zig translate-c`.
 clang_passthrough_mode: bool,
 /// Whether to print clang argvs to stdout.
-debug_cc: bool,
+verbose_cc: bool,
 disable_c_depfile: bool,
+is_test: bool,
 
 c_source_files: []const CSourceFile,
 clang_argv: []const []const u8,
@@ -56,16 +57,16 @@ zig_cache_directory: Directory,
 libc_include_dir_list: []const []const u8,
 rand: *std.rand.Random,
 
-/// Populated when we build libc++.a. A WorkItem to build this is placed in the queue
+/// Populated when we build libc++.a. A Job to build this is placed in the queue
 /// and resolved before calling linker.flush().
 libcxx_static_lib: ?[]const u8 = null,
-/// Populated when we build libc++abi.a. A WorkItem to build this is placed in the queue
+/// Populated when we build libc++abi.a. A Job to build this is placed in the queue
 /// and resolved before calling linker.flush().
 libcxxabi_static_lib: ?[]const u8 = null,
-/// Populated when we build libunwind.a. A WorkItem to build this is placed in the queue
+/// Populated when we build libunwind.a. A Job to build this is placed in the queue
 /// and resolved before calling linker.flush().
 libunwind_static_lib: ?CRTFile = null,
-/// Populated when we build c.a. A WorkItem to build this is placed in the queue
+/// Populated when we build c.a. A Job to build this is placed in the queue
 /// and resolved before calling linker.flush().
 libc_static_lib: ?[]const u8 = null,
 
@@ -98,7 +99,7 @@ pub const CSourceFile = struct {
     extra_flags: []const []const u8 = &[0][]const u8{},
 };
 
-const WorkItem = union(enum) {
+const Job = union(enum) {
     /// Write the machine code for a Decl to the output file.
     codegen_decl: *Module.Decl,
     /// The Decl needs to be analyzed and possibly export itself.
@@ -116,8 +117,11 @@ const WorkItem = union(enum) {
     glibc_crt_file: glibc.CRTFile,
     /// all of the glibc shared objects
     glibc_shared_objects,
-
+    /// libunwind.a, usually needed when linking libc
     libunwind: void,
+
+    /// Generate builtin.zig source code and write it into the correct place.
+    generate_builtin_zig: void,
 };
 
 pub const CObject = struct {
@@ -282,8 +286,9 @@ pub const InitOptions = struct {
     linker_z_nodelete: bool = false,
     linker_z_defs: bool = false,
     clang_passthrough_mode: bool = false,
-    debug_cc: bool = false,
-    debug_link: bool = false,
+    verbose_cc: bool = false,
+    verbose_link: bool = false,
+    is_test: bool = false,
     stack_size_override: ?u64 = null,
     self_exe_path: ?[]const u8 = null,
     version: ?std.builtin.Version = null,
@@ -570,6 +575,11 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
             break :blk link_artifact_directory;
         };
 
+        const error_return_tracing = !options.strip and switch (options.optimize_mode) {
+            .Debug, .ReleaseSafe => true,
+            .ReleaseFast, .ReleaseSmall => false,
+        };
+
         const bin_file = try link.File.openPath(gpa, .{
             .directory = bin_directory,
             .sub_path = emit_bin.basename,
@@ -612,9 +622,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
             .valgrind = valgrind,
             .stack_check = stack_check,
             .single_threaded = single_threaded,
-            .debug_link = options.debug_link,
+            .verbose_link = options.verbose_link,
             .machine_code_model = options.machine_code_model,
             .dll_export_fns = dll_export_fns,
+            .error_return_tracing = error_return_tracing,
         });
         errdefer bin_file.destroy();
 
@@ -624,7 +635,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
             .zig_lib_directory = options.zig_lib_directory,
             .zig_cache_directory = options.zig_cache_directory,
             .bin_file = bin_file,
-            .work_queue = std.fifo.LinearFifo(WorkItem, .Dynamic).init(gpa),
+            .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa),
             .keep_source_files_loaded = options.keep_source_files_loaded,
             .use_clang = use_clang,
             .clang_argv = options.clang_argv,
@@ -635,14 +646,19 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
             .sanitize_c = sanitize_c,
             .rand = options.rand,
             .clang_passthrough_mode = options.clang_passthrough_mode,
-            .debug_cc = options.debug_cc,
+            .verbose_cc = options.verbose_cc,
             .disable_c_depfile = options.disable_c_depfile,
             .owned_link_dir = owned_link_dir,
+            .is_test = options.is_test,
         };
         break :comp comp;
     };
     errdefer comp.destroy();
 
+    if (comp.bin_file.options.module) |mod| {
+        try comp.work_queue.writeItem(.{ .generate_builtin_zig = {} });
+    }
+
     // Add a `CObject` for each `c_source_files`.
     try comp.c_object_table.ensureCapacity(gpa, options.c_source_files.len);
     for (options.c_source_files) |c_source_file| {
@@ -659,7 +675,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
     // If we need to build glibc for the target, add work items for it.
     // We go through the work queue so that building can be done in parallel.
     if (comp.wantBuildGLibCFromSource()) {
-        try comp.addBuildingGLibCWorkItems();
+        try comp.addBuildingGLibCJobs();
     }
     if (comp.wantBuildLibUnwindFromSource()) {
         try comp.work_queue.writeItem(.{ .libunwind = {} });
@@ -715,7 +731,7 @@ pub fn update(self: *Compilation) !void {
     defer tracy.end();
 
     // For compiling C objects, we rely on the cache hash system to avoid duplicating work.
-    // Add a WorkItem for each C object.
+    // Add a Job for each C object.
     try self.work_queue.ensureUnusedCapacity(self.c_object_table.items().len);
     for (self.c_object_table.items()) |entry| {
         self.work_queue.writeItemAssumeCapacity(.{ .c_object = entry.key });
@@ -974,6 +990,13 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void {
                 fatal("unable to build libunwind: {}", .{@errorName(err)});
             };
         },
+        .generate_builtin_zig => {
+            // This Job is only queued up if there is a zig module.
+            self.updateBuiltinZigFile(self.bin_file.options.module.?) catch |err| {
+                // TODO Expose this as a normal compile error rather than crashing here.
+                fatal("unable to update builtin.zig file: {}", .{@errorName(err)});
+            };
+        },
     };
 }
 
@@ -1057,7 +1080,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
         try argv.append(c_object.src.src_path);
         try argv.appendSlice(c_object.src.extra_flags);
 
-        if (comp.debug_cc) {
+        if (comp.verbose_cc) {
             for (argv.items[0 .. argv.items.len - 1]) |arg| {
                 std.debug.print("{} ", .{arg});
             }
@@ -1616,8 +1639,8 @@ pub fn get_libc_crt_file(comp: *Compilation, arena: *Allocator, basename: []cons
     return full_path;
 }
 
-fn addBuildingGLibCWorkItems(comp: *Compilation) !void {
-    try comp.work_queue.write(&[_]WorkItem{
+fn addBuildingGLibCJobs(comp: *Compilation) !void {
+    try comp.work_queue.write(&[_]Job{
         .{ .glibc_crt_file = .crti_o },
         .{ .glibc_crt_file = .crtn_o },
         .{ .glibc_crt_file = .scrt1_o },
@@ -1646,3 +1669,163 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {
     return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and
         comp.bin_file.options.libc_installation == null;
 }
+
+fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) !void {
+    const source = try comp.generateBuiltinZigSource();
+    defer comp.gpa.free(source);
+    try mod.zig_cache_artifact_directory.handle.writeFile("builtin.zig", source);
+}
+
+pub fn generateBuiltinZigSource(comp: *Compilation) ![]u8 {
+    var buffer = std.ArrayList(u8).init(comp.gpa);
+    defer buffer.deinit();
+
+    const target = comp.getTarget();
+    const generic_arch_name = target.cpu.arch.genericName();
+
+    @setEvalBranchQuota(4000);
+    try buffer.writer().print(
+        \\usingnamespace @import("std").builtin;
+        \\/// Deprecated
+        \\pub const arch = std.Target.current.cpu.arch;
+        \\/// Deprecated
+        \\pub const endian = std.Target.current.cpu.arch.endian();
+        \\pub const output_mode = OutputMode.{};
+        \\pub const link_mode = LinkMode.{};
+        \\pub const is_test = {};
+        \\pub const single_threaded = {};
+        \\pub const abi = Abi.{};
+        \\pub const cpu: Cpu = Cpu{{
+        \\    .arch = .{},
+        \\    .model = &Target.{}.cpu.{},
+        \\    .features = Target.{}.featureSet(&[_]Target.{}.Feature{{
+        \\
+    , .{
+        @tagName(comp.bin_file.options.output_mode),
+        @tagName(comp.bin_file.options.link_mode),
+        comp.is_test,
+        comp.bin_file.options.single_threaded,
+        @tagName(target.abi),
+        @tagName(target.cpu.arch),
+        generic_arch_name,
+        target.cpu.model.name,
+        generic_arch_name,
+        generic_arch_name,
+    });
+
+    for (target.cpu.arch.allFeaturesList()) |feature, index_usize| {
+        const index = @intCast(std.Target.Cpu.Feature.Set.Index, index_usize);
+        const is_enabled = target.cpu.features.isEnabled(index);
+        if (is_enabled) {
+            // TODO some kind of "zig identifier escape" function rather than
+            // unconditionally using @"" syntax
+            try buffer.appendSlice("        .@\"");
+            try buffer.appendSlice(feature.name);
+            try buffer.appendSlice("\",\n");
+        }
+    }
+
+    try buffer.writer().print(
+        \\    }}),
+        \\}};
+        \\pub const os = Os{{
+        \\    .tag = .{},
+        \\    .version_range = .{{
+        ,
+        .{@tagName(target.os.tag)},
+    );
+
+    switch (target.os.getVersionRange()) {
+        .none => try buffer.appendSlice(" .none = {} }\n"),
+        .semver => |semver| try buffer.outStream().print(
+            \\ .semver = .{{
+            \\        .min = .{{
+            \\            .major = {},
+            \\            .minor = {},
+            \\            .patch = {},
+            \\        }},
+            \\        .max = .{{
+            \\            .major = {},
+            \\            .minor = {},
+            \\            .patch = {},
+            \\        }},
+            \\    }}}},
+            \\
+        , .{
+            semver.min.major,
+            semver.min.minor,
+            semver.min.patch,
+
+            semver.max.major,
+            semver.max.minor,
+            semver.max.patch,
+        }),
+        .linux => |linux| try buffer.outStream().print(
+            \\ .linux = .{{
+            \\        .range = .{{
+            \\            .min = .{{
+            \\                .major = {},
+            \\                .minor = {},
+            \\                .patch = {},
+            \\            }},
+            \\            .max = .{{
+            \\                .major = {},
+            \\                .minor = {},
+            \\                .patch = {},
+            \\            }},
+            \\        }},
+            \\        .glibc = .{{
+            \\            .major = {},
+            \\            .minor = {},
+            \\            .patch = {},
+            \\        }},
+            \\    }}}},
+            \\
+        , .{
+            linux.range.min.major,
+            linux.range.min.minor,
+            linux.range.min.patch,
+
+            linux.range.max.major,
+            linux.range.max.minor,
+            linux.range.max.patch,
+
+            linux.glibc.major,
+            linux.glibc.minor,
+            linux.glibc.patch,
+        }),
+        .windows => |windows| try buffer.outStream().print(
+            \\ .windows = .{{
+            \\        .min = {s},
+            \\        .max = {s},
+            \\    }}}},
+            \\
+            ,
+            .{ windows.min, windows.max },
+        ),
+    }
+    try buffer.appendSlice("};\n");
+    try buffer.writer().print(
+        \\pub const object_format = ObjectFormat.{};
+        \\pub const mode = Mode.{};
+        \\pub const link_libc = {};
+        \\pub const link_libcpp = {};
+        \\pub const have_error_return_tracing = {};
+        \\pub const valgrind_support = {};
+        \\pub const position_independent_code = {};
+        \\pub const strip_debug_info = {};
+        \\pub const code_model = CodeModel.{};
+        \\
+    , .{
+        @tagName(comp.bin_file.options.object_format),
+        @tagName(comp.bin_file.options.optimize_mode),
+        comp.bin_file.options.link_libc,
+        comp.bin_file.options.link_libcpp,
+        comp.bin_file.options.error_return_tracing,
+        comp.bin_file.options.valgrind,
+        comp.bin_file.options.pic,
+        comp.bin_file.options.strip,
+        @tagName(comp.bin_file.options.machine_code_model),
+    });
+    return buffer.toOwnedSlice();
+}
src-self-hosted/glibc.zig
@@ -711,8 +711,8 @@ fn build_crt_file(
         .is_native_os = comp.bin_file.options.is_native_os,
         .self_exe_path = comp.self_exe_path,
         .c_source_files = c_source_files,
-        .debug_cc = comp.debug_cc,
-        .debug_link = comp.bin_file.options.debug_link,
+        .verbose_cc = comp.verbose_cc,
+        .verbose_link = comp.bin_file.options.verbose_link,
         .clang_passthrough_mode = comp.clang_passthrough_mode,
     });
     defer sub_compilation.destroy();
@@ -987,8 +987,8 @@ fn buildSharedLib(
         .strip = comp.bin_file.options.strip,
         .is_native_os = false,
         .self_exe_path = comp.self_exe_path,
-        .debug_cc = comp.debug_cc,
-        .debug_link = comp.bin_file.options.debug_link,
+        .verbose_cc = comp.verbose_cc,
+        .verbose_link = comp.bin_file.options.verbose_link,
         .clang_passthrough_mode = comp.clang_passthrough_mode,
         .version = version,
         .version_script = map_file_path,
src-self-hosted/libunwind.zig
@@ -107,8 +107,8 @@ pub fn buildStaticLib(comp: *Compilation) !void {
         .is_native_os = comp.bin_file.options.is_native_os,
         .self_exe_path = comp.self_exe_path,
         .c_source_files = &c_source_files,
-        .debug_cc = comp.debug_cc,
-        .debug_link = comp.bin_file.options.debug_link,
+        .verbose_cc = comp.verbose_cc,
+        .verbose_link = comp.bin_file.options.verbose_link,
         .clang_passthrough_mode = comp.clang_passthrough_mode,
         .link_libc = true,
     });
src-self-hosted/link.zig
@@ -61,8 +61,9 @@ pub const Options = struct {
     valgrind: bool,
     stack_check: bool,
     single_threaded: bool,
-    debug_link: bool = false,
+    verbose_link: bool = false,
     dll_export_fns: bool,
+    error_return_tracing: bool,
     gc_sections: ?bool = null,
     allow_shlib_undefined: ?bool = null,
     linker_script: ?[]const u8 = null,
@@ -441,7 +442,7 @@ pub const File = struct {
             base.options.sub_path;
         const full_out_path_z = try arena.dupeZ(u8, full_out_path);
 
-        if (base.options.debug_link) {
+        if (base.options.verbose_link) {
             std.debug.print("ar rcs {}", .{full_out_path_z});
             for (object_files.items) |arg| {
                 std.debug.print(" {}", .{arg});
src-self-hosted/main.zig
@@ -179,6 +179,7 @@ const usage_build_generic =
     \\  --color [auto|off|on]     Enable or disable colored error messages
     \\  -femit-bin[=path]         (default) output machine code
     \\  -fno-emit-bin             Do not output machine code
+    \\  --show-builtin            Output the source of @import("builtin") then exit
     \\
     \\Compile Options:
     \\  -target [name]            <arch><sub>-<os>-<abi> see the targets command
@@ -233,8 +234,8 @@ const usage_build_generic =
     \\
     \\Debug Options (Zig Compiler Development):
     \\  -ftime-report             Print timing diagnostics
-    \\  --debug-link              Verbose linker invocation
-    \\  --debug-cc                Verbose C compiler invocation
+    \\  --verbose-link            Display linker invocations
+    \\  --verbose-cc              Display C compiler invocations
     \\
 ;
 
@@ -274,9 +275,10 @@ pub fn buildOutputType(
     var strip = false;
     var single_threaded = false;
     var watch = false;
-    var debug_link = false;
-    var debug_cc = false;
+    var verbose_link = false;
+    var verbose_cc = false;
     var time_report = false;
+    var show_builtin = false;
     var emit_bin: Emit = .yes_default_path;
     var emit_zir: Emit = .no;
     var target_arch_os_abi: []const u8 = "native";
@@ -531,6 +533,8 @@ pub fn buildOutputType(
                     dll_export_fns = true;
                 } else if (mem.eql(u8, arg, "-fno-dll-export-fns")) {
                     dll_export_fns = false;
+                } else if (mem.eql(u8, arg, "--show-builtin")) {
+                    show_builtin = true;
                 } else if (mem.eql(u8, arg, "--strip")) {
                     strip = true;
                 } else if (mem.eql(u8, arg, "--single-threaded")) {
@@ -539,10 +543,10 @@ pub fn buildOutputType(
                     link_eh_frame_hdr = true;
                 } else if (mem.eql(u8, arg, "-Bsymbolic")) {
                     linker_bind_global_refs_locally = true;
-                } else if (mem.eql(u8, arg, "--debug-link")) {
-                    debug_link = true;
-                } else if (mem.eql(u8, arg, "--debug-cc")) {
-                    debug_cc = true;
+                } else if (mem.eql(u8, arg, "--verbose-link")) {
+                    verbose_link = true;
+                } else if (mem.eql(u8, arg, "--verbose-cc")) {
+                    verbose_cc = true;
                 } else if (mem.startsWith(u8, arg, "-T")) {
                     linker_script = arg[2..];
                 } else if (mem.startsWith(u8, arg, "-L")) {
@@ -680,8 +684,8 @@ pub fn buildOutputType(
                 },
                 .linker_script => linker_script = it.only_arg,
                 .verbose_cmds => {
-                    debug_cc = true;
-                    debug_link = true;
+                    verbose_cc = true;
+                    verbose_link = true;
                 },
                 .for_linker => try linker_args.append(it.only_arg),
                 .linker_input_z => {
@@ -873,6 +877,8 @@ pub fn buildOutputType(
         } else if (emit_bin == .yes) {
             const basename = fs.path.basename(emit_bin.yes);
             break :blk mem.split(basename, ".").next().?;
+        } else if (show_builtin) {
+            break :blk "builtin";
         } else {
             fatal("--name [name] not provided and unable to infer", .{});
         }
@@ -1160,17 +1166,20 @@ pub fn buildOutputType(
         .clang_passthrough_mode = arg_mode != .build,
         .version = if (have_version) version else null,
         .libc_installation = if (libc_installation) |*lci| lci else null,
-        .debug_cc = debug_cc,
-        .debug_link = debug_link,
+        .verbose_cc = verbose_cc,
+        .verbose_link = verbose_link,
         .machine_code_model = machine_code_model,
     }) catch |err| {
         fatal("unable to create compilation: {}", .{@errorName(err)});
     };
     defer comp.destroy();
 
-    const stdin = std.io.getStdIn().inStream();
-    const stderr = std.io.getStdErr().outStream();
-    var repl_buf: [1024]u8 = undefined;
+    if (show_builtin) {
+        const source = try comp.generateBuiltinZigSource();
+        defer comp.gpa.free(source);
+        try std.io.getStdOut().writeAll(source);
+        return;
+    }
 
     try updateModule(gpa, comp, zir_out_path);
 
@@ -1179,6 +1188,10 @@ pub fn buildOutputType(
         fatal("TODO: implement `zig cc` when using it as a preprocessor", .{});
     }
 
+    const stdin = std.io.getStdIn().inStream();
+    const stderr = std.io.getStdErr().outStream();
+    var repl_buf: [1024]u8 = undefined;
+
     while (watch) {
         try stderr.print("🦎 ", .{});
         if (output_mode == .Exe) {
BRANCH_TODO
@@ -1,9 +1,5 @@
- * `zig builtin`
  * `zig translate-c`
  * `zig test`
- * `zig run`
- * `zig init-lib`
- * `zig init-exe`
  * `zig build`
  * `-ftime-report`
  *  -fstack-report               print stack size diagnostics\n"
@@ -15,14 +11,14 @@
  *  -femit-llvm-ir               produce a .ll file with LLVM IR\n"
  *  -fno-emit-llvm-ir            (default) do not produce a .ll file with LLVM IR\n"
  *  --cache-dir [path]           override the local cache directory\n"
- * move main.cpp to stage2
  * make sure zig cc works
    - using it as a preprocessor (-E)
    - try building some software
  * support rpaths in ELF linker code
  * build & link against compiler-rt
    - stage1 C++ code integration
- * build & link againstn freestanding libc
+ * repair @cImport
+ * build & link against freestanding libc
  * add CLI support for a way to pass extra flags to c source files
  * capture lld stdout/stderr better
  * musl
@@ -41,6 +37,9 @@
  * implement -fno-emit-bin
  * audit the base cache hash
  * audit the CLI options for stage2
+ * `zig init-lib`
+ * `zig init-exe`
+ * `zig run`
 
  * implement serialization/deserialization of incremental compilation metadata
  * incremental compilation - implement detection of which source files changed
@@ -69,3 +68,6 @@
  * rename src-self-hosted/ to src/
  * improve Directory.join to only use 1 allocation in a clean way.
  * tracy builds with lc++
+ * some kind of "zig identifier escape" function rather than unconditionally using @"" syntax
+   in builtin.zig
+ * rename Mode to OptimizeMode