From 8932c2d7456fc86b9e92c7976cedcce798caef1a Mon Sep 17 00:00:00 2001 From: Lee Cannon Date: Sun, 20 Dec 2020 21:41:00 +0000 Subject: Added support for no red zone --- src/stage1/codegen.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/stage1/codegen.cpp') diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 386bc43086..fbc13f2638 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -513,6 +513,10 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { } else { maybe_import_dll(g, llvm_fn, linkage); } + + if (g->no_red_zone) { + addLLVMFnAttr(llvm_fn, "noredzone"); + } if (fn->alignstack_value != 0) { addLLVMFnAttrInt(llvm_fn, "alignstack", fn->alignstack_value); -- cgit v1.2.3 From 5b2a79848ced20db80f3f4ce46b3ef7f4a051d53 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 11 Jan 2021 22:01:16 -0700 Subject: 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. --- lib/std/build.zig | 11 ++++++-- src/Compilation.zig | 21 ++++++++------ src/clang_options_data.zig | 18 ++++++++++-- src/glibc.zig | 2 +- src/libcxx.zig | 4 +-- src/libunwind.zig | 2 +- src/link.zig | 2 +- src/main.zig | 20 +++++++------ src/musl.zig | 2 +- src/stage1.zig | 2 +- src/stage1/all_types.hpp | 2 +- src/stage1/codegen.cpp | 4 +-- src/stage1/stage1.cpp | 2 +- src/stage1/stage1.h | 2 +- src/target.zig | 18 ++++++++++++ tools/update_clang_options.zig | 64 ++++++++++++++++++++++++------------------ 16 files changed, 114 insertions(+), 62 deletions(-) (limited to 'src/stage1/codegen.cpp') diff --git a/lib/std/build.zig b/lib/std/build.zig index 869671c785..381488d800 100644 --- a/lib/std/build.zig +++ b/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"); diff --git a/src/Compilation.zig b/src/Compilation.zig index 1588544010..0efad3362d 100644 --- a/src/Compilation.zig +++ b/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, diff --git a/src/clang_options_data.zig b/src/clang_options_data.zig index 52dc8c0280..c901c6045f 100644 --- a/src/clang_options_data.zig +++ b/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"), diff --git a/src/glibc.zig b/src/glibc.zig index 28ed31f7bb..b154bd530d 100644 --- a/src/glibc.zig +++ b/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, diff --git a/src/libcxx.zig b/src/libcxx.zig index dc9fdc15e7..11989998e9 100644 --- a/src/libcxx.zig +++ b/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, diff --git a/src/libunwind.zig b/src/libunwind.zig index cfc0cb00aa..c2d0475d6f 100644 --- a/src/libunwind.zig +++ b/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, diff --git a/src/link.zig b/src/link.zig index 04cfce99ab..6914131bea 100644 --- a/src/link.zig +++ b/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, diff --git a/src/main.zig b/src/main.zig index a7a23c2b2d..867aa348b1 100644 --- a/src/main.zig +++ b/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 { diff --git a/src/musl.zig b/src/musl.zig index d9060307d0..0cb6983e28 100644 --- a/src/musl.zig +++ b/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, diff --git a/src/stage1.zig b/src/stage1.zig index 721ab93fcd..44fd8e109e 100644 --- a/src/stage1.zig +++ b/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, diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index af8305d4b0..c235bb362d 100644 --- a/src/stage1/all_types.hpp +++ b/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; diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index fbc13f2638..10943483f4 100644 --- a/src/stage1/codegen.cpp +++ b/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"); } diff --git a/src/stage1/stage1.cpp b/src/stage1/stage1.cpp index 7cf34c9a47..d680121577 100644 --- a/src/stage1/stage1.cpp +++ b/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; diff --git a/src/stage1/stage1.h b/src/stage1/stage1.h index 66e0effbf6..6db3621cf5 100644 --- a/src/stage1/stage1.h +++ b/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; diff --git a/src/target.zig b/src/target.zig index daac577c7b..c3df682ce0 100644 --- a/src/target.zig +++ b/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, + }; +} diff --git a/tools/update_clang_options.zig b/tools/update_clang_options.zig index ad380e0139..189a2ed7fa 100644 --- a/tools/update_clang_options.zig +++ b/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. -- cgit v1.2.3