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.
This commit is contained in:
Andrew Kelley 2021-01-11 22:01:16 -07:00
parent 8932c2d745
commit 5b2a79848c
16 changed files with 114 additions and 62 deletions

View File

@ -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");

View File

@ -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,

View File

@ -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"),

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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 {

View File

@ -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,

View File

@ -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,

View File

@ -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;

View File

@ -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");
}

View File

@ -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;

View File

@ -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;

View File

@ -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,
};
}

View File

@ -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.