Merge 'Add support for no red zone'

Merges #7511
This commit is contained in:
Andrew Kelley 2021-01-11 22:07:47 -07:00
commit 0edde40c25
16 changed files with 118 additions and 30 deletions

View File

@ -1332,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
@ -2260,6 +2262,13 @@ pub const LibExeObjStep = struct {
if (self.disable_stack_probing) {
try zig_args.append("-fno-stack-check");
}
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,6 +392,7 @@ pub const InitOptions = struct {
want_pie: ?bool = null,
want_sanitize_c: ?bool = null,
want_stack_check: ?bool = null,
want_red_zone: ?bool = null,
want_valgrind: ?bool = null,
want_tsan: ?bool = null,
want_compiler_rt: ?bool = null,
@ -743,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,
@ -773,6 +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(red_zone);
cache.hash.add(link_mode);
cache.hash.add(options.function_sections);
cache.hash.add(strip);
@ -982,6 +985,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
.valgrind = valgrind,
.tsan = tsan,
.stack_check = stack_check,
.red_zone = red_zone,
.single_threaded = single_threaded,
.verbose_link = options.verbose_link,
.machine_code_model = options.machine_code_model,
@ -2256,6 +2260,12 @@ pub fn addCCArgs(
try argv.append("-fsanitize=thread");
}
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
@ -2960,6 +2970,7 @@ fn buildOutputFromZig(
.function_sections = true,
.want_sanitize_c = false,
.want_stack_check = false,
.want_red_zone = comp.bin_file.options.red_zone,
.want_valgrind = false,
.want_tsan = false,
.want_pic = comp.bin_file.options.pic,
@ -3198,6 +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,
.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,
@ -3342,6 +3354,7 @@ pub fn build_crt_file(
.optimize_mode = comp.compilerRtOptMode(),
.want_sanitize_c = false,
.want_stack_check = false,
.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,6 +934,7 @@ fn buildSharedLib(
.optimize_mode = comp.compilerRtOptMode(),
.want_sanitize_c = false,
.want_stack_check = false,
.want_red_zone = comp.bin_file.options.red_zone,
.want_valgrind = false,
.want_tsan = false,
.emit_h = null,

View File

@ -167,6 +167,7 @@ pub fn buildLibCXX(comp: *Compilation) !void {
.link_mode = link_mode,
.want_sanitize_c = false,
.want_stack_check = false,
.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,
@ -284,6 +285,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {
.link_mode = link_mode,
.want_sanitize_c = false,
.want_stack_check = false,
.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,6 +108,7 @@ pub fn buildStaticLib(comp: *Compilation) !void {
.link_mode = link_mode,
.want_sanitize_c = false,
.want_stack_check = false,
.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,6 +77,7 @@ pub const Options = struct {
valgrind: bool,
tsan: bool,
stack_check: 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
@ -505,6 +507,7 @@ fn buildOutputType(
var want_pie: ?bool = null;
var want_sanitize_c: ?bool = null;
var want_stack_check: ?bool = null;
var want_red_zone: ?bool = null;
var want_valgrind: ?bool = null;
var want_tsan: ?bool = null;
var want_compiler_rt: ?bool = null;
@ -843,6 +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, "-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")) {
@ -1068,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 => {
@ -1760,6 +1769,7 @@ fn buildOutputType(
.want_pie = want_pie,
.want_sanitize_c = want_sanitize_c,
.want_stack_check = want_stack_check,
.want_red_zone = want_red_zone,
.want_valgrind = want_valgrind,
.want_tsan = want_tsan,
.want_compiler_rt = want_compiler_rt,
@ -2969,6 +2979,8 @@ pub const ClangArgIterator = struct {
framework_dir,
framework,
nostdlibinc,
red_zone,
no_red_zone,
};
const Args = struct {

View File

@ -206,6 +206,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
.optimize_mode = comp.compilerRtOptMode(),
.want_sanitize_c = false,
.want_stack_check = false,
.want_red_zone = comp.bin_file.options.red_zone,
.want_valgrind = false,
.want_tsan = false,
.emit_h = null,

View File

@ -119,6 +119,7 @@ pub const Module = extern struct {
tsan_enabled: bool,
function_sections: bool,
enable_stack_probing: bool,
red_zone: bool,
enable_time_report: bool,
enable_stack_report: bool,
test_is_evented: bool,

View File

@ -2195,6 +2195,7 @@ struct CodeGen {
bool link_mode_dynamic;
bool dll_export_fns;
bool have_stack_probing;
bool red_zone;
bool function_sections;
bool test_is_evented;
bool valgrind_enabled;

View File

@ -514,6 +514,10 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
maybe_import_dll(g, llvm_fn, linkage);
}
if (!g->red_zone) {
addLLVMFnAttr(llvm_fn, "noredzone");
}
if (fn->alignstack_value != 0) {
addLLVMFnAttrInt(llvm_fn, "alignstack", fn->alignstack_value);
}

View File

@ -91,6 +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->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,6 +188,7 @@ struct ZigStage1 {
bool tsan_enabled;
bool function_sections;
bool enable_stack_probing;
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.