Commit 264969a8c3

Andrew Kelley <andrew@ziglang.org>
2021-06-10 20:25:33
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
1 parent e3a7469
src/stage1/all_types.hpp
@@ -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;
src/stage1/codegen.cpp
@@ -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");
     }
 }
src/stage1/stage1.cpp
@@ -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;
src/stage1/stage1.h
@@ -182,6 +182,7 @@ struct ZigStage1 {
     bool pic;
     bool pie;
     bool lto;
+    bool unwind_tables;
     bool link_libc;
     bool link_libcpp;
     bool strip;
src/clang_options_data.zig
@@ -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"),
src/Compilation.zig
@@ -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,
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,
src/stage1.zig
@@ -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,
src/target.zig
@@ -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;
+}
tools/update_clang_options.zig
@@ -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",