better awareness of unwind tables
* stage1 backend allows configuring the uwtables function attr via a flag rather than its own logic. * stage2 defaults to enabling uwtable attr when linking libunwind, or always on windows * stage2 makes link_eh_frame_hdr true automatically if uwtable attr is set to be on for zig functions * CLI: add -funwind-tables and -fno-unwind-tables to allow the user to override the defaults. * hook it up to `zig cc` closes #9046
This commit is contained in:
@@ -81,6 +81,7 @@ verbose_llvm_cpu_features: bool,
|
||||
disable_c_depfile: bool,
|
||||
time_report: bool,
|
||||
stack_report: bool,
|
||||
unwind_tables: bool,
|
||||
|
||||
c_source_files: []const CSourceFile,
|
||||
clang_argv: []const []const u8,
|
||||
@@ -659,6 +660,7 @@ pub const InitOptions = struct {
|
||||
want_tsan: ?bool = null,
|
||||
want_compiler_rt: ?bool = null,
|
||||
want_lto: ?bool = null,
|
||||
want_unwind_tables: ?bool = null,
|
||||
use_llvm: ?bool = null,
|
||||
use_lld: ?bool = null,
|
||||
use_clang: ?bool = null,
|
||||
@@ -815,8 +817,20 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
||||
return error.MachineCodeModelNotSupported;
|
||||
}
|
||||
|
||||
const tsan = options.want_tsan orelse false;
|
||||
// TSAN is implemented in C++ so it requires linking libc++.
|
||||
const link_libcpp = options.link_libcpp or tsan;
|
||||
const link_libc = link_libcpp or options.link_libc or
|
||||
target_util.osRequiresLibC(options.target);
|
||||
|
||||
const link_libunwind = options.link_libunwind or
|
||||
(link_libcpp and target_util.libcNeedsLibUnwind(options.target));
|
||||
const unwind_tables = options.want_unwind_tables orelse
|
||||
(link_libunwind or target_util.needUnwindTables(options.target));
|
||||
const link_eh_frame_hdr = options.link_eh_frame_hdr or unwind_tables;
|
||||
|
||||
// Make a decision on whether to use LLD or our own linker.
|
||||
const use_lld = if (options.use_lld) |explicit| explicit else blk: {
|
||||
const use_lld = options.use_lld orelse blk: {
|
||||
if (!build_options.have_llvm)
|
||||
break :blk false;
|
||||
|
||||
@@ -835,7 +849,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
||||
options.frameworks.len != 0 or
|
||||
options.system_libs.len != 0 or
|
||||
options.link_libc or options.link_libcpp or
|
||||
options.link_eh_frame_hdr or
|
||||
link_eh_frame_hdr or
|
||||
options.link_emit_relocs or
|
||||
options.output_mode == .Lib or
|
||||
options.lld_argv.len != 0 or
|
||||
@@ -894,15 +908,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
||||
}
|
||||
};
|
||||
|
||||
const tsan = options.want_tsan orelse false;
|
||||
// TSAN is implemented in C++ so it requires linking libc++.
|
||||
const link_libcpp = options.link_libcpp or tsan;
|
||||
const link_libc = link_libcpp or options.link_libc or
|
||||
target_util.osRequiresLibC(options.target);
|
||||
|
||||
const link_libunwind = options.link_libunwind or
|
||||
(link_libcpp and target_util.libcNeedsLibUnwind(options.target));
|
||||
|
||||
const must_dynamic_link = dl: {
|
||||
if (target_util.cannotDynamicLink(options.target))
|
||||
break :dl false;
|
||||
@@ -1072,6 +1077,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
||||
cache.hash.add(pic);
|
||||
cache.hash.add(pie);
|
||||
cache.hash.add(lto);
|
||||
cache.hash.add(unwind_tables);
|
||||
cache.hash.add(tsan);
|
||||
cache.hash.add(stack_check);
|
||||
cache.hash.add(red_zone);
|
||||
@@ -1303,7 +1309,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
||||
.linker_script = options.linker_script,
|
||||
.version_script = options.version_script,
|
||||
.gc_sections = options.linker_gc_sections,
|
||||
.eh_frame_hdr = options.link_eh_frame_hdr,
|
||||
.eh_frame_hdr = link_eh_frame_hdr,
|
||||
.emit_relocs = options.link_emit_relocs,
|
||||
.rdynamic = options.rdynamic,
|
||||
.extra_lld_args = options.lld_argv,
|
||||
@@ -1366,6 +1372,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
||||
.color = options.color,
|
||||
.time_report = options.time_report,
|
||||
.stack_report = options.stack_report,
|
||||
.unwind_tables = unwind_tables,
|
||||
.test_filter = options.test_filter,
|
||||
.test_name_prefix = options.test_name_prefix,
|
||||
.test_evented_io = options.test_evented_io,
|
||||
@@ -2963,6 +2970,12 @@ pub fn addCCArgs(
|
||||
if (target_util.supports_fpic(target) and comp.bin_file.options.pic) {
|
||||
try argv.append("-fPIC");
|
||||
}
|
||||
|
||||
if (comp.unwind_tables) {
|
||||
try argv.append("-funwind-tables");
|
||||
} else {
|
||||
try argv.append("-fno-unwind-tables");
|
||||
}
|
||||
},
|
||||
.shared_library, .ll, .bc, .unknown, .static_library, .object, .zig => {},
|
||||
.assembly => {
|
||||
@@ -3927,6 +3940,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
|
||||
.pic = comp.bin_file.options.pic,
|
||||
.pie = comp.bin_file.options.pie,
|
||||
.lto = comp.bin_file.options.lto,
|
||||
.unwind_tables = comp.unwind_tables,
|
||||
.link_libc = comp.bin_file.options.link_libc,
|
||||
.link_libcpp = comp.bin_file.options.link_libcpp,
|
||||
.strip = comp.bin_file.options.strip,
|
||||
|
||||
@@ -3151,7 +3151,14 @@ flagpd1("fno-unsafe-loop-optimizations"),
|
||||
flagpd1("fno-unsafe-math-optimizations"),
|
||||
flagpd1("fno-unsigned-char"),
|
||||
flagpd1("fno-unswitch-loops"),
|
||||
flagpd1("fno-unwind-tables"),
|
||||
.{
|
||||
.name = "fno-unwind-tables",
|
||||
.syntax = .flag,
|
||||
.zig_equivalent = .no_unwind_tables,
|
||||
.pd1 = true,
|
||||
.pd2 = false,
|
||||
.psl = false,
|
||||
},
|
||||
flagpd1("fno-use-cxa-atexit"),
|
||||
flagpd1("fno-use-init-array"),
|
||||
flagpd1("fno-use-line-directives"),
|
||||
@@ -3410,7 +3417,14 @@ flagpd1("funsafe-math-optimizations"),
|
||||
flagpd1("funsigned-bitfields"),
|
||||
flagpd1("funsigned-char"),
|
||||
flagpd1("funswitch-loops"),
|
||||
flagpd1("funwind-tables"),
|
||||
.{
|
||||
.name = "funwind-tables",
|
||||
.syntax = .flag,
|
||||
.zig_equivalent = .unwind_tables,
|
||||
.pd1 = true,
|
||||
.pd2 = false,
|
||||
.psl = false,
|
||||
},
|
||||
flagpd1("fuse-ctor-homing"),
|
||||
flagpd1("fuse-cxa-atexit"),
|
||||
flagpd1("fuse-init-array"),
|
||||
|
||||
30
src/main.zig
30
src/main.zig
@@ -263,22 +263,26 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
|
||||
}
|
||||
|
||||
const usage_build_generic =
|
||||
\\Usage: zig build-exe <options> [files]
|
||||
\\ zig build-lib <options> [files]
|
||||
\\ zig build-obj <options> [files]
|
||||
\\ zig test <options> [files]
|
||||
\\ zig run <options> [file] [-- [args]]
|
||||
\\Usage: zig build-exe <options> [files]
|
||||
\\ zig build-lib <options> [files]
|
||||
\\ zig build-obj <options> [files]
|
||||
\\ zig test <options> [files]
|
||||
\\ zig run <options> [file] [-- [args]]
|
||||
\\ zig translate-c <options> [file]
|
||||
\\
|
||||
\\Supported file types:
|
||||
\\ .zig Zig source code
|
||||
\\ .o ELF object file
|
||||
\\ .o MACH-O (macOS) object file
|
||||
\\ .o Mach-O (macOS) object file
|
||||
\\ .o WebAssembly object file
|
||||
\\ .obj COFF (Windows) object file
|
||||
\\ .lib COFF (Windows) static library
|
||||
\\ .a ELF static library
|
||||
\\ .a Mach-O (macOS) static library
|
||||
\\ .a WebAssembly static library
|
||||
\\ .so ELF shared object (dynamic link)
|
||||
\\ .dll Windows Dynamic Link Library
|
||||
\\ .dylib MACH-O (macOS) dynamic library
|
||||
\\ .dylib Mach-O (macOS) dynamic library
|
||||
\\ .tbd (macOS) text-based dylib definition
|
||||
\\ .s Target-specific assembly source code
|
||||
\\ .S Assembly with C preprocessor (requires LLVM extensions)
|
||||
@@ -341,6 +345,8 @@ const usage_build_generic =
|
||||
\\ -fno-sanitize-thread Disable Thread Sanitizer
|
||||
\\ -fdll-export-fns Mark exported functions as DLL exports (Windows)
|
||||
\\ -fno-dll-export-fns Force-disable marking exported functions as DLL exports
|
||||
\\ -funwind-tables Always produce unwind table entries for all functions
|
||||
\\ -fno-unwind-tables Never produce unwind table entries
|
||||
\\ -fLLVM Force using LLVM as the codegen backend
|
||||
\\ -fno-LLVM Prevent using LLVM as a codegen backend
|
||||
\\ -fClang Force using Clang as the C/C++ compilation backend
|
||||
@@ -568,6 +574,7 @@ fn buildOutputType(
|
||||
var want_pic: ?bool = null;
|
||||
var want_pie: ?bool = null;
|
||||
var want_lto: ?bool = null;
|
||||
var want_unwind_tables: ?bool = null;
|
||||
var want_sanitize_c: ?bool = null;
|
||||
var want_stack_check: ?bool = null;
|
||||
var want_red_zone: ?bool = null;
|
||||
@@ -920,6 +927,10 @@ fn buildOutputType(
|
||||
want_lto = true;
|
||||
} else if (mem.eql(u8, arg, "-fno-lto")) {
|
||||
want_lto = false;
|
||||
} else if (mem.eql(u8, arg, "-funwind-tables")) {
|
||||
want_unwind_tables = true;
|
||||
} else if (mem.eql(u8, arg, "-fno-unwind-tables")) {
|
||||
want_unwind_tables = false;
|
||||
} else if (mem.eql(u8, arg, "-fstack-check")) {
|
||||
want_stack_check = true;
|
||||
} else if (mem.eql(u8, arg, "-fno-stack-check")) {
|
||||
@@ -1151,6 +1162,8 @@ fn buildOutputType(
|
||||
.no_lto => want_lto = false,
|
||||
.red_zone => want_red_zone = true,
|
||||
.no_red_zone => want_red_zone = false,
|
||||
.unwind_tables => want_unwind_tables = true,
|
||||
.no_unwind_tables => want_unwind_tables = false,
|
||||
.nostdlib => ensure_libc_on_non_freestanding = false,
|
||||
.nostdlib_cpp => ensure_libcpp_on_non_freestanding = false,
|
||||
.shared => {
|
||||
@@ -1893,6 +1906,7 @@ fn buildOutputType(
|
||||
.want_pic = want_pic,
|
||||
.want_pie = want_pie,
|
||||
.want_lto = want_lto,
|
||||
.want_unwind_tables = want_unwind_tables,
|
||||
.want_sanitize_c = want_sanitize_c,
|
||||
.want_stack_check = want_stack_check,
|
||||
.want_red_zone = want_red_zone,
|
||||
@@ -3294,6 +3308,8 @@ pub const ClangArgIterator = struct {
|
||||
no_pie,
|
||||
lto,
|
||||
no_lto,
|
||||
unwind_tables,
|
||||
no_unwind_tables,
|
||||
nostdlib,
|
||||
nostdlib_cpp,
|
||||
shared,
|
||||
|
||||
@@ -110,6 +110,7 @@ pub const Module = extern struct {
|
||||
pic: bool,
|
||||
pie: bool,
|
||||
lto: bool,
|
||||
unwind_tables: bool,
|
||||
link_libc: bool,
|
||||
link_libcpp: bool,
|
||||
strip: bool,
|
||||
|
||||
@@ -2144,6 +2144,7 @@ struct CodeGen {
|
||||
bool have_pic;
|
||||
bool have_pie;
|
||||
bool have_lto;
|
||||
bool unwind_tables;
|
||||
bool link_mode_dynamic;
|
||||
bool dll_export_fns;
|
||||
bool have_stack_probing;
|
||||
|
||||
@@ -211,7 +211,7 @@ static ZigLLVM_CallingConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
|
||||
}
|
||||
|
||||
static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) {
|
||||
if (g->zig_target->os == OsWindows) {
|
||||
if (g->unwind_tables) {
|
||||
addLLVMFnAttr(fn_val, "uwtable");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,7 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {
|
||||
g->have_pic = stage1->pic;
|
||||
g->have_pie = stage1->pie;
|
||||
g->have_lto = stage1->lto;
|
||||
g->unwind_tables = stage1->unwind_tables;
|
||||
g->have_stack_probing = stage1->enable_stack_probing;
|
||||
g->red_zone = stage1->red_zone;
|
||||
g->is_single_threaded = stage1->is_single_threaded;
|
||||
|
||||
@@ -182,6 +182,7 @@ struct ZigStage1 {
|
||||
bool pic;
|
||||
bool pie;
|
||||
bool lto;
|
||||
bool unwind_tables;
|
||||
bool link_libc;
|
||||
bool link_libcpp;
|
||||
bool strip;
|
||||
|
||||
@@ -404,3 +404,7 @@ pub fn clangAssemblerSupportsMcpuArg(target: std.Target) bool {
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn needUnwindTables(target: std.Target) bool {
|
||||
return target.os.tag == .windows;
|
||||
}
|
||||
|
||||
@@ -70,6 +70,14 @@ const known_options = [_]KnownOpt{
|
||||
.name = "fno-lto",
|
||||
.ident = "no_lto",
|
||||
},
|
||||
.{
|
||||
.name = "funwind-tables",
|
||||
.ident = "unwind_tables",
|
||||
},
|
||||
.{
|
||||
.name = "fno-unwind-tables",
|
||||
.ident = "no_unwind_tables",
|
||||
},
|
||||
.{
|
||||
.name = "nolibc",
|
||||
.ident = "nostdlib",
|
||||
|
||||
Reference in New Issue
Block a user