Commit 5b2a79848c

Andrew Kelley <andrew@ziglang.org>
2021-01-12 06:01:16
stage2: cleanups regarding red zone CLI flags
* CLI: change to -mred-zone and -mno-red-zone to match gcc/clang. * build.zig: remove the double negative and make it an optional bool. This follows precedent from other flags, allowing the compiler CLI to be the decider of what is default instead of duplicating the default value into the build system code. * Compilation: make it an optional `want_red_zone` instead of a `no_red_zone` bool. The default is decided by a call to `target_util.hasRedZone`. * When creating a Clang command line, put -mred-zone on the command line if we are forcing it to be enabled. * Update update_clang_options.zig with respect to the recent {s}/{} format changes. * `zig cc` integration with red zone preference.
1 parent 8932c2d
lib/std/build.zig
@@ -1262,7 +1262,6 @@ pub const LibExeObjStep = struct {
     disable_stack_probing: bool,
     disable_sanitize_c: bool,
     sanitize_thread: bool,
-    no_red_zone: bool = false,
     rdynamic: bool,
     c_std: Builder.CStd,
     override_lib_dir: ?[]const u8,
@@ -1333,6 +1332,8 @@ pub const LibExeObjStep = struct {
     /// Position Independent Executable
     pie: ?bool = null,
 
+    red_zone: ?bool = null,
+
     subsystem: ?builtin.SubSystem = null,
 
     /// Overrides the default stack size
@@ -2261,8 +2262,12 @@ pub const LibExeObjStep = struct {
         if (self.disable_stack_probing) {
             try zig_args.append("-fno-stack-check");
         }
-        if (self.no_red_zone) {
-            try zig_args.append("-fno-red-zone");
+        if (self.red_zone) |red_zone| {
+            if (red_zone) {
+                try zig_args.append("-mred-zone");
+            } else {
+                try zig_args.append("-mno-red-zone");
+            }
         }
         if (self.disable_sanitize_c) {
             try zig_args.append("-fno-sanitize-c");
src/stage1/all_types.hpp
@@ -2195,7 +2195,7 @@ struct CodeGen {
     bool link_mode_dynamic;
     bool dll_export_fns;
     bool have_stack_probing;
-    bool no_red_zone;
+    bool red_zone;
     bool function_sections;
     bool test_is_evented;
     bool valgrind_enabled;
src/stage1/codegen.cpp
@@ -513,8 +513,8 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
     } else {
         maybe_import_dll(g, llvm_fn, linkage);
     }
-    
-    if (g->no_red_zone) {
+
+    if (!g->red_zone) {
         addLLVMFnAttr(llvm_fn, "noredzone");
     }
 
src/stage1/stage1.cpp
@@ -91,7 +91,7 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {
     g->have_pic = stage1->pic;
     g->have_pie = stage1->pie;
     g->have_stack_probing = stage1->enable_stack_probing;
-    g->no_red_zone = stage1->no_red_zone;
+    g->red_zone = stage1->red_zone;
     g->is_single_threaded = stage1->is_single_threaded;
     g->valgrind_enabled = stage1->valgrind_enabled;
     g->tsan_enabled = stage1->tsan_enabled;
src/stage1/stage1.h
@@ -188,7 +188,7 @@ struct ZigStage1 {
     bool tsan_enabled;
     bool function_sections;
     bool enable_stack_probing;
-    bool no_red_zone;
+    bool red_zone;
     bool enable_time_report;
     bool enable_stack_report;
     bool test_is_evented;
src/clang_options_data.zig
@@ -3803,7 +3803,14 @@ flagpd1("mno-qpx"),
 flagpd1("mno-rdpid"),
 flagpd1("mno-rdrnd"),
 flagpd1("mno-rdseed"),
-flagpd1("mno-red-zone"),
+.{
+    .name = "mno-red-zone",
+    .syntax = .flag,
+    .zig_equivalent = .no_red_zone,
+    .pd1 = true,
+    .pd2 = false,
+    .psl = false,
+},
 flagpd1("mno-reference-types"),
 flagpd1("mno-relax"),
 flagpd1("mno-relax-all"),
@@ -3901,7 +3908,14 @@ flagpd1("mrdseed"),
 flagpd1("mreassociate"),
 flagpd1("mrecip"),
 flagpd1("mrecord-mcount"),
-flagpd1("mred-zone"),
+.{
+    .name = "mred-zone",
+    .syntax = .flag,
+    .zig_equivalent = .red_zone,
+    .pd1 = true,
+    .pd2 = false,
+    .psl = false,
+},
 flagpd1("mreference-types"),
 sepd1("mregparm"),
 flagpd1("mrelax"),
src/Compilation.zig
@@ -392,7 +392,7 @@ pub const InitOptions = struct {
     want_pie: ?bool = null,
     want_sanitize_c: ?bool = null,
     want_stack_check: ?bool = null,
-    no_red_zone: bool = false,
+    want_red_zone: ?bool = null,
     want_valgrind: ?bool = null,
     want_tsan: ?bool = null,
     want_compiler_rt: ?bool = null,
@@ -744,6 +744,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
         } else null;
 
         const strip = options.strip or !target_util.hasDebugInfo(options.target);
+        const red_zone = options.want_red_zone orelse target_util.hasRedZone(options.target);
 
         // We put everything into the cache hash that *cannot be modified during an incremental update*.
         // For example, one cannot change the target between updates, but one can change source files,
@@ -774,7 +775,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
         cache.hash.add(pie);
         cache.hash.add(tsan);
         cache.hash.add(stack_check);
-        cache.hash.add(options.no_red_zone);
+        cache.hash.add(red_zone);
         cache.hash.add(link_mode);
         cache.hash.add(options.function_sections);
         cache.hash.add(strip);
@@ -984,7 +985,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
             .valgrind = valgrind,
             .tsan = tsan,
             .stack_check = stack_check,
-            .no_red_zone = options.no_red_zone,
+            .red_zone = red_zone,
             .single_threaded = single_threaded,
             .verbose_link = options.verbose_link,
             .machine_code_model = options.machine_code_model,
@@ -2258,11 +2259,13 @@ pub fn addCCArgs(
             } else if (!comp.sanitize_c and comp.bin_file.options.tsan) {
                 try argv.append("-fsanitize=thread");
             }
-            
-            if (comp.bin_file.options.no_red_zone) {
+
+            if (comp.bin_file.options.red_zone) {
+                try argv.append("-mred-zone");
+            } else if (target_util.hasRedZone(target)) {
                 try argv.append("-mno-red-zone");
             }
-            
+
             switch (comp.bin_file.options.optimize_mode) {
                 .Debug => {
                     // windows c runtime requires -D_DEBUG if using debug libraries
@@ -2967,7 +2970,7 @@ fn buildOutputFromZig(
         .function_sections = true,
         .want_sanitize_c = false,
         .want_stack_check = false,
-        .no_red_zone = comp.bin_file.options.no_red_zone,
+        .want_red_zone = comp.bin_file.options.red_zone,
         .want_valgrind = false,
         .want_tsan = false,
         .want_pic = comp.bin_file.options.pic,
@@ -3206,7 +3209,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
         .tsan_enabled = comp.bin_file.options.tsan,
         .function_sections = comp.bin_file.options.function_sections,
         .enable_stack_probing = comp.bin_file.options.stack_check,
-        .no_red_zone = comp.bin_file.options.no_red_zone,
+        .red_zone = comp.bin_file.options.red_zone,
         .enable_time_report = comp.time_report,
         .enable_stack_report = comp.stack_report,
         .test_is_evented = comp.test_evented_io,
@@ -3351,7 +3354,7 @@ pub fn build_crt_file(
         .optimize_mode = comp.compilerRtOptMode(),
         .want_sanitize_c = false,
         .want_stack_check = false,
-        .no_red_zone = comp.bin_file.options.no_red_zone,
+        .want_red_zone = comp.bin_file.options.red_zone,
         .want_valgrind = false,
         .want_tsan = false,
         .want_pic = comp.bin_file.options.pic,
src/glibc.zig
@@ -934,7 +934,7 @@ fn buildSharedLib(
         .optimize_mode = comp.compilerRtOptMode(),
         .want_sanitize_c = false,
         .want_stack_check = false,
-        .no_red_zone = comp.bin_file.options.no_red_zone,
+        .want_red_zone = comp.bin_file.options.red_zone,
         .want_valgrind = false,
         .want_tsan = false,
         .emit_h = null,
src/libcxx.zig
@@ -167,7 +167,7 @@ pub fn buildLibCXX(comp: *Compilation) !void {
         .link_mode = link_mode,
         .want_sanitize_c = false,
         .want_stack_check = false,
-        .no_red_zone = comp.bin_file.options.no_red_zone,
+        .want_red_zone = comp.bin_file.options.red_zone,
         .want_valgrind = false,
         .want_tsan = comp.bin_file.options.tsan,
         .want_pic = comp.bin_file.options.pic,
@@ -285,7 +285,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {
         .link_mode = link_mode,
         .want_sanitize_c = false,
         .want_stack_check = false,
-        .no_red_zone = comp.bin_file.options.no_red_zone,
+        .want_red_zone = comp.bin_file.options.red_zone,
         .want_valgrind = false,
         .want_tsan = comp.bin_file.options.tsan,
         .want_pic = comp.bin_file.options.pic,
src/libunwind.zig
@@ -108,7 +108,7 @@ pub fn buildStaticLib(comp: *Compilation) !void {
         .link_mode = link_mode,
         .want_sanitize_c = false,
         .want_stack_check = false,
-        .no_red_zone = comp.bin_file.options.no_red_zone,
+        .want_red_zone = comp.bin_file.options.red_zone,
         .want_valgrind = false,
         .want_tsan = false,
         .want_pic = comp.bin_file.options.pic,
src/link.zig
@@ -77,7 +77,7 @@ pub const Options = struct {
     valgrind: bool,
     tsan: bool,
     stack_check: bool,
-    no_red_zone: bool,
+    red_zone: bool,
     single_threaded: bool,
     verbose_link: bool,
     dll_export_fns: bool,
src/main.zig
@@ -267,6 +267,8 @@ const usage_build_generic =
     \\  -mcmodel=[default|tiny|   Limit range of code and data virtual addresses
     \\            small|kernel|
     \\            medium|large]
+    \\  -mred-zone                Force-enable the "red-zone"
+    \\  -mno-red-zone             Force-disable the "red-zone"
     \\  --name [name]             Override root name (not a file path)
     \\  -O [mode]                 Choose what to optimize for
     \\    Debug                   (default) Optimizations off, safety on
@@ -282,8 +284,6 @@ const usage_build_generic =
     \\  -fno-PIE                  Force-disable Position Independent Executable
     \\  -fstack-check             Enable stack probing in unsafe builds
     \\  -fno-stack-check          Disable stack probing in safe builds
-    \\  -fred-zone                Enable the "red-zone"
-    \\  -fno-red-zone             Disable the "red-zone"
     \\  -fsanitize-c              Enable C undefined behavior detection in unsafe builds
     \\  -fno-sanitize-c           Disable C undefined behavior detection in safe builds
     \\  -fvalgrind                Include valgrind client requests in release builds
@@ -507,7 +507,7 @@ fn buildOutputType(
     var want_pie: ?bool = null;
     var want_sanitize_c: ?bool = null;
     var want_stack_check: ?bool = null;
-    var no_red_zone: bool = false;
+    var want_red_zone: ?bool = null;
     var want_valgrind: ?bool = null;
     var want_tsan: ?bool = null;
     var want_compiler_rt: ?bool = null;
@@ -846,10 +846,10 @@ fn buildOutputType(
                         want_stack_check = true;
                     } else if (mem.eql(u8, arg, "-fno-stack-check")) {
                         want_stack_check = false;
-                    } else if (mem.eql(u8, arg, "-fred-zone")) {
-                        no_red_zone = false;
-                    } else if (mem.eql(u8, arg, "-fno-red-zone")) {
-                        no_red_zone = true;
+                    } else if (mem.eql(u8, arg, "-mred-zone")) {
+                        want_red_zone = true;
+                    } else if (mem.eql(u8, arg, "-mno-red-zone")) {
+                        want_red_zone = false;
                     } else if (mem.eql(u8, arg, "-fsanitize-c")) {
                         want_sanitize_c = true;
                     } else if (mem.eql(u8, arg, "-fno-sanitize-c")) {
@@ -1075,6 +1075,8 @@ fn buildOutputType(
                     .no_pic => want_pic = false,
                     .pie => want_pie = true,
                     .no_pie => want_pie = false,
+                    .red_zone => want_red_zone = true,
+                    .no_red_zone => want_red_zone = false,
                     .nostdlib => ensure_libc_on_non_freestanding = false,
                     .nostdlib_cpp => ensure_libcpp_on_non_freestanding = false,
                     .shared => {
@@ -1767,7 +1769,7 @@ fn buildOutputType(
         .want_pie = want_pie,
         .want_sanitize_c = want_sanitize_c,
         .want_stack_check = want_stack_check,
-        .no_red_zone = no_red_zone,
+        .want_red_zone = want_red_zone,
         .want_valgrind = want_valgrind,
         .want_tsan = want_tsan,
         .want_compiler_rt = want_compiler_rt,
@@ -2977,6 +2979,8 @@ pub const ClangArgIterator = struct {
         framework_dir,
         framework,
         nostdlibinc,
+        red_zone,
+        no_red_zone,
     };
 
     const Args = struct {
src/musl.zig
@@ -206,7 +206,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
                 .optimize_mode = comp.compilerRtOptMode(),
                 .want_sanitize_c = false,
                 .want_stack_check = false,
-                .no_red_zone = comp.bin_file.options.no_red_zone,
+                .want_red_zone = comp.bin_file.options.red_zone,
                 .want_valgrind = false,
                 .want_tsan = false,
                 .emit_h = null,
src/stage1.zig
@@ -119,7 +119,7 @@ pub const Module = extern struct {
     tsan_enabled: bool,
     function_sections: bool,
     enable_stack_probing: bool,
-    no_red_zone: bool,
+    red_zone: bool,
     enable_time_report: bool,
     enable_stack_report: bool,
     test_is_evented: bool,
src/target.zig
@@ -349,3 +349,21 @@ pub fn defaultCompilerRtOptimizeMode(target: std.Target) std.builtin.Mode {
         return .ReleaseFast;
     }
 }
+
+pub fn hasRedZone(target: std.Target) bool {
+    return switch (target.cpu.arch) {
+        .x86_64,
+        .i386,
+        .wasm32,
+        .wasm64,
+        .powerpc,
+        .powerpc64,
+        .powerpc64le,
+        .aarch64,
+        .aarch64_be,
+        .aarch64_32,
+        => true,
+
+        else => false,
+    };
+}
tools/update_clang_options.zig
@@ -248,6 +248,14 @@ const known_options = [_]KnownOpt{
         .name = "mtune",
         .ident = "mcpu",
     },
+    .{
+        .name = "mred-zone",
+        .ident = "red_zone",
+    },
+    .{
+        .name = "mno-red-zone",
+        .ident = "no_red_zone",
+    },
     .{
         .name = "MD",
         .ident = "dep_file",
@@ -340,9 +348,9 @@ pub fn main() anyerror!void {
     const child_args = [_][]const u8{
         llvm_tblgen_exe,
         "--dump-json",
-        try std.fmt.allocPrint(allocator, "{}/clang/include/clang/Driver/Options.td", .{llvm_src_root}),
-        try std.fmt.allocPrint(allocator, "-I={}/llvm/include", .{llvm_src_root}),
-        try std.fmt.allocPrint(allocator, "-I={}/clang/include/clang/Driver", .{llvm_src_root}),
+        try std.fmt.allocPrint(allocator, "{s}/clang/include/clang/Driver/Options.td", .{llvm_src_root}),
+        try std.fmt.allocPrint(allocator, "-I={s}/llvm/include", .{llvm_src_root}),
+        try std.fmt.allocPrint(allocator, "-I={s}/clang/include/clang/Driver", .{llvm_src_root}),
     };
 
     const child_result = try std.ChildProcess.exec(.{
@@ -351,11 +359,11 @@ pub fn main() anyerror!void {
         .max_output_bytes = 100 * 1024 * 1024,
     });
 
-    std.debug.warn("{}\n", .{child_result.stderr});
+    std.debug.warn("{s}\n", .{child_result.stderr});
 
     const json_text = switch (child_result.term) {
         .Exited => |code| if (code == 0) child_result.stdout else {
-            std.debug.warn("llvm-tblgen exited with code {}\n", .{code});
+            std.debug.warn("llvm-tblgen exited with code {d}\n", .{code});
             std.process.exit(1);
         },
         else => {
@@ -412,7 +420,7 @@ pub fn main() anyerror!void {
             } else if (std.mem.eql(u8, prefix, "/")) {
                 pslash = true;
             } else {
-                std.debug.warn("{} has unrecognized prefix '{}'\n", .{ name, prefix });
+                std.debug.warn("{s} has unrecognized prefix '{s}'\n", .{ name, prefix });
                 std.process.exit(1);
             }
         }
@@ -422,7 +430,7 @@ pub fn main() anyerror!void {
             // `-MT foo` is ambiguous because there is also an -MT flag
             // The canonical way to specify the flag is with `/MT` and so we make this
             // the only way.
-            try stdout.print("flagpsl(\"{}\"),\n", .{name});
+            try stdout.print("flagpsl(\"{s}\"),\n", .{name});
         } else if (knownOption(name)) |ident| {
 
             // Workaround the fact that in 'Options.td'  -Ofast is listed as 'joined'
@@ -430,34 +438,34 @@ pub fn main() anyerror!void {
 
             try stdout.print(
                 \\.{{
-                \\    .name = "{}",
-                \\    .syntax = {},
-                \\    .zig_equivalent = .{},
-                \\    .pd1 = {},
-                \\    .pd2 = {},
-                \\    .psl = {},
+                \\    .name = "{s}",
+                \\    .syntax = {s},
+                \\    .zig_equivalent = .{s},
+                \\    .pd1 = {s},
+                \\    .pd2 = {s},
+                \\    .psl = {s},
                 \\}},
                 \\
             , .{ name, final_syntax, ident, pd1, pd2, pslash });
         } else if (pd1 and !pd2 and !pslash and syntax == .flag) {
-            try stdout.print("flagpd1(\"{}\"),\n", .{name});
+            try stdout.print("flagpd1(\"{s}\"),\n", .{name});
         } else if (!pd1 and !pd2 and pslash and syntax == .flag) {
-            try stdout.print("flagpsl(\"{}\"),\n", .{name});
+            try stdout.print("flagpsl(\"{s}\"),\n", .{name});
         } else if (pd1 and !pd2 and !pslash and syntax == .joined) {
-            try stdout.print("joinpd1(\"{}\"),\n", .{name});
+            try stdout.print("joinpd1(\"{s}\"),\n", .{name});
         } else if (pd1 and !pd2 and !pslash and syntax == .joined_or_separate) {
-            try stdout.print("jspd1(\"{}\"),\n", .{name});
+            try stdout.print("jspd1(\"{s}\"),\n", .{name});
         } else if (pd1 and !pd2 and !pslash and syntax == .separate) {
-            try stdout.print("sepd1(\"{}\"),\n", .{name});
+            try stdout.print("sepd1(\"{s}\"),\n", .{name});
         } else {
             try stdout.print(
                 \\.{{
-                \\    .name = "{}",
-                \\    .syntax = {},
+                \\    .name = "{s}",
+                \\    .syntax = {s},
                 \\    .zig_equivalent = .other,
-                \\    .pd1 = {},
-                \\    .pd2 = {},
-                \\    .psl = {},
+                \\    .pd1 = {s},
+                \\    .pd2 = {s},
+                \\    .psl = {s},
                 \\}},
                 \\
             , .{ name, syntax, pd1, pd2, pslash });
@@ -506,8 +514,8 @@ const Syntax = union(enum) {
         out_stream: anytype,
     ) !void {
         switch (self) {
-            .multi_arg => |n| return out_stream.print(".{{.{}={}}}", .{ @tagName(self), n }),
-            else => return out_stream.print(".{}", .{@tagName(self)}),
+            .multi_arg => |n| return out_stream.print(".{{.{s}={}}}", .{ @tagName(self), n }),
+            else => return out_stream.print(".{s}", .{@tagName(self)}),
         }
     }
 };
@@ -559,9 +567,9 @@ fn objSyntax(obj: *json.ObjectMap) Syntax {
         return .flag;
     }
     const key = obj.get("!name").?.String;
-    std.debug.warn("{} (key {}) has unrecognized superclasses:\n", .{ name, key });
+    std.debug.warn("{s} (key {s}) has unrecognized superclasses:\n", .{ name, key });
     for (obj.get("!superclasses").?.Array.items) |superclass_json| {
-        std.debug.warn(" {}\n", .{superclass_json.String});
+        std.debug.warn(" {s}\n", .{superclass_json.String});
     }
     std.process.exit(1);
 }
@@ -612,7 +620,7 @@ fn objectLessThan(context: void, a: *json.ObjectMap, b: *json.ObjectMap) bool {
 
 fn usageAndExit(file: fs.File, arg0: []const u8, code: u8) noreturn {
     file.writer().print(
-        \\Usage: {} /path/to/llvm-tblgen /path/to/git/llvm/llvm-project
+        \\Usage: {s} /path/to/llvm-tblgen /path/to/git/llvm/llvm-project
         \\Alternative Usage: zig run /path/to/git/zig/tools/update_clang_options.zig -- /path/to/llvm-tblgen /path/to/git/llvm/llvm-project
         \\
         \\Prints to stdout Zig code which you can use to replace the file src/clang_options_data.zig.