authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-06-10 11:25:33-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-06-11 13:23:00-04:00
logb6277a4b1c2be27701d594bc1465ac72fc226260
tree6a422059457c92c6baeaba53e6e95a2195cc0d43
parent6cc88458029759bbedcb4d949deb887d464cdd60

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

10 files changed, 82 insertions(+), 22 deletions(-)

src/Compilation.zig+26-12
...@@ -81,6 +81,7 @@ verbose_llvm_cpu_features: bool,...@@ -81,6 +81,7 @@ verbose_llvm_cpu_features: bool,
81disable_c_depfile: bool,81disable_c_depfile: bool,
82time_report: bool,82time_report: bool,
83stack_report: bool,83stack_report: bool,
84unwind_tables: bool,
8485
85c_source_files: []const CSourceFile,86c_source_files: []const CSourceFile,
86clang_argv: []const []const u8,87clang_argv: []const []const u8,
...@@ -665,6 +666,7 @@ pub const InitOptions = struct {...@@ -665,6 +666,7 @@ pub const InitOptions = struct {
665 want_tsan: ?bool = null,666 want_tsan: ?bool = null,
666 want_compiler_rt: ?bool = null,667 want_compiler_rt: ?bool = null,
667 want_lto: ?bool = null,668 want_lto: ?bool = null,
669 want_unwind_tables: ?bool = null,
668 use_llvm: ?bool = null,670 use_llvm: ?bool = null,
669 use_lld: ?bool = null,671 use_lld: ?bool = null,
670 use_clang: ?bool = null,672 use_clang: ?bool = null,
...@@ -823,8 +825,20 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -823,8 +825,20 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
823 return error.MachineCodeModelNotSupported;825 return error.MachineCodeModelNotSupported;
824 }826 }
825827
828 const tsan = options.want_tsan orelse false;
829 // TSAN is implemented in C++ so it requires linking libc++.
830 const link_libcpp = options.link_libcpp or tsan;
831 const link_libc = link_libcpp or options.link_libc or
832 target_util.osRequiresLibC(options.target);
833
834 const link_libunwind = options.link_libunwind or
835 (link_libcpp and target_util.libcNeedsLibUnwind(options.target));
836 const unwind_tables = options.want_unwind_tables orelse
837 (link_libunwind or target_util.needUnwindTables(options.target));
838 const link_eh_frame_hdr = options.link_eh_frame_hdr or unwind_tables;
839
826 // Make a decision on whether to use LLD or our own linker.840 // Make a decision on whether to use LLD or our own linker.
827 const use_lld = if (options.use_lld) |explicit| explicit else blk: {841 const use_lld = options.use_lld orelse blk: {
828 if (!build_options.have_llvm)842 if (!build_options.have_llvm)
829 break :blk false;843 break :blk false;
830844
...@@ -843,7 +857,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -843,7 +857,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
843 options.frameworks.len != 0 or857 options.frameworks.len != 0 or
844 options.system_libs.len != 0 or858 options.system_libs.len != 0 or
845 options.link_libc or options.link_libcpp or859 options.link_libc or options.link_libcpp or
846 options.link_eh_frame_hdr or860 link_eh_frame_hdr or
847 options.link_emit_relocs or861 options.link_emit_relocs or
848 options.output_mode == .Lib or862 options.output_mode == .Lib or
849 options.lld_argv.len != 0 or863 options.lld_argv.len != 0 or
...@@ -902,15 +916,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -902,15 +916,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
902 }916 }
903 };917 };
904918
905 const tsan = options.want_tsan orelse false;
906 // TSAN is implemented in C++ so it requires linking libc++.
907 const link_libcpp = options.link_libcpp or tsan;
908 const link_libc = link_libcpp or options.link_libc or
909 target_util.osRequiresLibC(options.target);
910
911 const link_libunwind = options.link_libunwind or
912 (link_libcpp and target_util.libcNeedsLibUnwind(options.target));
913
914 const must_dynamic_link = dl: {919 const must_dynamic_link = dl: {
915 if (target_util.cannotDynamicLink(options.target))920 if (target_util.cannotDynamicLink(options.target))
916 break :dl false;921 break :dl false;
...@@ -1080,6 +1085,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1080,6 +1085,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1080 cache.hash.add(pic);1085 cache.hash.add(pic);
1081 cache.hash.add(pie);1086 cache.hash.add(pie);
1082 cache.hash.add(lto);1087 cache.hash.add(lto);
1088 cache.hash.add(unwind_tables);
1083 cache.hash.add(tsan);1089 cache.hash.add(tsan);
1084 cache.hash.add(stack_check);1090 cache.hash.add(stack_check);
1085 cache.hash.add(red_zone);1091 cache.hash.add(red_zone);
...@@ -1312,7 +1318,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1312,7 +1318,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1312 .linker_script = options.linker_script,1318 .linker_script = options.linker_script,
1313 .version_script = options.version_script,1319 .version_script = options.version_script,
1314 .gc_sections = options.linker_gc_sections,1320 .gc_sections = options.linker_gc_sections,
1315 .eh_frame_hdr = options.link_eh_frame_hdr,1321 .eh_frame_hdr = link_eh_frame_hdr,
1316 .emit_relocs = options.link_emit_relocs,1322 .emit_relocs = options.link_emit_relocs,
1317 .rdynamic = options.rdynamic,1323 .rdynamic = options.rdynamic,
1318 .extra_lld_args = options.lld_argv,1324 .extra_lld_args = options.lld_argv,
...@@ -1376,6 +1382,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1376,6 +1382,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1376 .color = options.color,1382 .color = options.color,
1377 .time_report = options.time_report,1383 .time_report = options.time_report,
1378 .stack_report = options.stack_report,1384 .stack_report = options.stack_report,
1385 .unwind_tables = unwind_tables,
1379 .test_filter = options.test_filter,1386 .test_filter = options.test_filter,
1380 .test_name_prefix = options.test_name_prefix,1387 .test_name_prefix = options.test_name_prefix,
1381 .test_evented_io = options.test_evented_io,1388 .test_evented_io = options.test_evented_io,
...@@ -2983,6 +2990,12 @@ pub fn addCCArgs(...@@ -2983,6 +2990,12 @@ pub fn addCCArgs(
2983 if (target_util.supports_fpic(target) and comp.bin_file.options.pic) {2990 if (target_util.supports_fpic(target) and comp.bin_file.options.pic) {
2984 try argv.append("-fPIC");2991 try argv.append("-fPIC");
2985 }2992 }
2993
2994 if (comp.unwind_tables) {
2995 try argv.append("-funwind-tables");
2996 } else {
2997 try argv.append("-fno-unwind-tables");
2998 }
2986 },2999 },
2987 .shared_library, .ll, .bc, .unknown, .static_library, .object, .zig => {},3000 .shared_library, .ll, .bc, .unknown, .static_library, .object, .zig => {},
2988 .assembly => {3001 .assembly => {
...@@ -3948,6 +3961,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node...@@ -3948,6 +3961,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
3948 .pic = comp.bin_file.options.pic,3961 .pic = comp.bin_file.options.pic,
3949 .pie = comp.bin_file.options.pie,3962 .pie = comp.bin_file.options.pie,
3950 .lto = comp.bin_file.options.lto,3963 .lto = comp.bin_file.options.lto,
3964 .unwind_tables = comp.unwind_tables,
3951 .link_libc = comp.bin_file.options.link_libc,3965 .link_libc = comp.bin_file.options.link_libc,
3952 .link_libcpp = comp.bin_file.options.link_libcpp,3966 .link_libcpp = comp.bin_file.options.link_libcpp,
3953 .strip = comp.bin_file.options.strip,3967 .strip = comp.bin_file.options.strip,
src/clang_options_data.zig+16-2
...@@ -3151,7 +3151,14 @@ flagpd1("fno-unsafe-loop-optimizations"),...@@ -3151,7 +3151,14 @@ flagpd1("fno-unsafe-loop-optimizations"),
3151flagpd1("fno-unsafe-math-optimizations"),3151flagpd1("fno-unsafe-math-optimizations"),
3152flagpd1("fno-unsigned-char"),3152flagpd1("fno-unsigned-char"),
3153flagpd1("fno-unswitch-loops"),3153flagpd1("fno-unswitch-loops"),
3154flagpd1("fno-unwind-tables"),3154.{
3155 .name = "fno-unwind-tables",
3156 .syntax = .flag,
3157 .zig_equivalent = .no_unwind_tables,
3158 .pd1 = true,
3159 .pd2 = false,
3160 .psl = false,
3161},
3155flagpd1("fno-use-cxa-atexit"),3162flagpd1("fno-use-cxa-atexit"),
3156flagpd1("fno-use-init-array"),3163flagpd1("fno-use-init-array"),
3157flagpd1("fno-use-line-directives"),3164flagpd1("fno-use-line-directives"),
...@@ -3410,7 +3417,14 @@ flagpd1("funsafe-math-optimizations"),...@@ -3410,7 +3417,14 @@ flagpd1("funsafe-math-optimizations"),
3410flagpd1("funsigned-bitfields"),3417flagpd1("funsigned-bitfields"),
3411flagpd1("funsigned-char"),3418flagpd1("funsigned-char"),
3412flagpd1("funswitch-loops"),3419flagpd1("funswitch-loops"),
3413flagpd1("funwind-tables"),3420.{
3421 .name = "funwind-tables",
3422 .syntax = .flag,
3423 .zig_equivalent = .unwind_tables,
3424 .pd1 = true,
3425 .pd2 = false,
3426 .psl = false,
3427},
3414flagpd1("fuse-ctor-homing"),3428flagpd1("fuse-ctor-homing"),
3415flagpd1("fuse-cxa-atexit"),3429flagpd1("fuse-cxa-atexit"),
3416flagpd1("fuse-init-array"),3430flagpd1("fuse-init-array"),
src/main.zig+23-7
...@@ -264,22 +264,26 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v...@@ -264,22 +264,26 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
264}264}
265265
266const usage_build_generic =266const usage_build_generic =
267 \\Usage: zig build-exe <options> [files]267 \\Usage: zig build-exe <options> [files]
268 \\ zig build-lib <options> [files]268 \\ zig build-lib <options> [files]
269 \\ zig build-obj <options> [files]269 \\ zig build-obj <options> [files]
270 \\ zig test <options> [files]270 \\ zig test <options> [files]
271 \\ zig run <options> [file] [-- [args]]271 \\ zig run <options> [file] [-- [args]]
272 \\ zig translate-c <options> [file]
272 \\273 \\
273 \\Supported file types:274 \\Supported file types:
274 \\ .zig Zig source code275 \\ .zig Zig source code
275 \\ .o ELF object file276 \\ .o ELF object file
276 \\ .o MACH-O (macOS) object file277 \\ .o Mach-O (macOS) object file
278 \\ .o WebAssembly object file
277 \\ .obj COFF (Windows) object file279 \\ .obj COFF (Windows) object file
278 \\ .lib COFF (Windows) static library280 \\ .lib COFF (Windows) static library
279 \\ .a ELF static library281 \\ .a ELF static library
282 \\ .a Mach-O (macOS) static library
283 \\ .a WebAssembly static library
280 \\ .so ELF shared object (dynamic link)284 \\ .so ELF shared object (dynamic link)
281 \\ .dll Windows Dynamic Link Library285 \\ .dll Windows Dynamic Link Library
282 \\ .dylib MACH-O (macOS) dynamic library286 \\ .dylib Mach-O (macOS) dynamic library
283 \\ .tbd (macOS) text-based dylib definition287 \\ .tbd (macOS) text-based dylib definition
284 \\ .s Target-specific assembly source code288 \\ .s Target-specific assembly source code
285 \\ .S Assembly with C preprocessor (requires LLVM extensions)289 \\ .S Assembly with C preprocessor (requires LLVM extensions)
...@@ -342,6 +346,8 @@ const usage_build_generic =...@@ -342,6 +346,8 @@ const usage_build_generic =
342 \\ -fno-sanitize-thread Disable Thread Sanitizer346 \\ -fno-sanitize-thread Disable Thread Sanitizer
343 \\ -fdll-export-fns Mark exported functions as DLL exports (Windows)347 \\ -fdll-export-fns Mark exported functions as DLL exports (Windows)
344 \\ -fno-dll-export-fns Force-disable marking exported functions as DLL exports348 \\ -fno-dll-export-fns Force-disable marking exported functions as DLL exports
349 \\ -funwind-tables Always produce unwind table entries for all functions
350 \\ -fno-unwind-tables Never produce unwind table entries
345 \\ -fLLVM Force using LLVM as the codegen backend351 \\ -fLLVM Force using LLVM as the codegen backend
346 \\ -fno-LLVM Prevent using LLVM as a codegen backend352 \\ -fno-LLVM Prevent using LLVM as a codegen backend
347 \\ -fClang Force using Clang as the C/C++ compilation backend353 \\ -fClang Force using Clang as the C/C++ compilation backend
...@@ -569,6 +575,7 @@ fn buildOutputType(...@@ -569,6 +575,7 @@ fn buildOutputType(
569 var want_pic: ?bool = null;575 var want_pic: ?bool = null;
570 var want_pie: ?bool = null;576 var want_pie: ?bool = null;
571 var want_lto: ?bool = null;577 var want_lto: ?bool = null;
578 var want_unwind_tables: ?bool = null;
572 var want_sanitize_c: ?bool = null;579 var want_sanitize_c: ?bool = null;
573 var want_stack_check: ?bool = null;580 var want_stack_check: ?bool = null;
574 var want_red_zone: ?bool = null;581 var want_red_zone: ?bool = null;
...@@ -925,6 +932,10 @@ fn buildOutputType(...@@ -925,6 +932,10 @@ fn buildOutputType(
925 want_lto = true;932 want_lto = true;
926 } else if (mem.eql(u8, arg, "-fno-lto")) {933 } else if (mem.eql(u8, arg, "-fno-lto")) {
927 want_lto = false;934 want_lto = false;
935 } else if (mem.eql(u8, arg, "-funwind-tables")) {
936 want_unwind_tables = true;
937 } else if (mem.eql(u8, arg, "-fno-unwind-tables")) {
938 want_unwind_tables = false;
928 } else if (mem.eql(u8, arg, "-fstack-check")) {939 } else if (mem.eql(u8, arg, "-fstack-check")) {
929 want_stack_check = true;940 want_stack_check = true;
930 } else if (mem.eql(u8, arg, "-fno-stack-check")) {941 } else if (mem.eql(u8, arg, "-fno-stack-check")) {
...@@ -1156,6 +1167,8 @@ fn buildOutputType(...@@ -1156,6 +1167,8 @@ fn buildOutputType(
1156 .no_lto => want_lto = false,1167 .no_lto => want_lto = false,
1157 .red_zone => want_red_zone = true,1168 .red_zone => want_red_zone = true,
1158 .no_red_zone => want_red_zone = false,1169 .no_red_zone => want_red_zone = false,
1170 .unwind_tables => want_unwind_tables = true,
1171 .no_unwind_tables => want_unwind_tables = false,
1159 .nostdlib => ensure_libc_on_non_freestanding = false,1172 .nostdlib => ensure_libc_on_non_freestanding = false,
1160 .nostdlib_cpp => ensure_libcpp_on_non_freestanding = false,1173 .nostdlib_cpp => ensure_libcpp_on_non_freestanding = false,
1161 .shared => {1174 .shared => {
...@@ -1913,6 +1926,7 @@ fn buildOutputType(...@@ -1913,6 +1926,7 @@ fn buildOutputType(
1913 .want_pic = want_pic,1926 .want_pic = want_pic,
1914 .want_pie = want_pie,1927 .want_pie = want_pie,
1915 .want_lto = want_lto,1928 .want_lto = want_lto,
1929 .want_unwind_tables = want_unwind_tables,
1916 .want_sanitize_c = want_sanitize_c,1930 .want_sanitize_c = want_sanitize_c,
1917 .want_stack_check = want_stack_check,1931 .want_stack_check = want_stack_check,
1918 .want_red_zone = want_red_zone,1932 .want_red_zone = want_red_zone,
...@@ -3315,6 +3329,8 @@ pub const ClangArgIterator = struct {...@@ -3315,6 +3329,8 @@ pub const ClangArgIterator = struct {
3315 no_pie,3329 no_pie,
3316 lto,3330 lto,
3317 no_lto,3331 no_lto,
3332 unwind_tables,
3333 no_unwind_tables,
3318 nostdlib,3334 nostdlib,
3319 nostdlib_cpp,3335 nostdlib_cpp,
3320 shared,3336 shared,
src/stage1.zig+1
...@@ -110,6 +110,7 @@ pub const Module = extern struct {...@@ -110,6 +110,7 @@ pub const Module = extern struct {
110 pic: bool,110 pic: bool,
111 pie: bool,111 pie: bool,
112 lto: bool,112 lto: bool,
113 unwind_tables: bool,
113 link_libc: bool,114 link_libc: bool,
114 link_libcpp: bool,115 link_libcpp: bool,
115 strip: bool,116 strip: bool,
src/stage1/all_types.hpp+1
...@@ -2144,6 +2144,7 @@ struct CodeGen {...@@ -2144,6 +2144,7 @@ struct CodeGen {
2144 bool have_pic;2144 bool have_pic;
2145 bool have_pie;2145 bool have_pie;
2146 bool have_lto;2146 bool have_lto;
2147 bool unwind_tables;
2147 bool link_mode_dynamic;2148 bool link_mode_dynamic;
2148 bool dll_export_fns;2149 bool dll_export_fns;
2149 bool have_stack_probing;2150 bool have_stack_probing;
src/stage1/codegen.cpp+1-1
...@@ -211,7 +211,7 @@ static ZigLLVM_CallingConv get_llvm_cc(CodeGen *g, CallingConvention cc) {...@@ -211,7 +211,7 @@ static ZigLLVM_CallingConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
211}211}
212212
213static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) {213static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) {
214 if (g->zig_target->os == OsWindows) {214 if (g->unwind_tables) {
215 addLLVMFnAttr(fn_val, "uwtable");215 addLLVMFnAttr(fn_val, "uwtable");
216 }216 }
217}217}
src/stage1/stage1.cpp+1
...@@ -91,6 +91,7 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {...@@ -91,6 +91,7 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {
91 g->have_pic = stage1->pic;91 g->have_pic = stage1->pic;
92 g->have_pie = stage1->pie;92 g->have_pie = stage1->pie;
93 g->have_lto = stage1->lto;93 g->have_lto = stage1->lto;
94 g->unwind_tables = stage1->unwind_tables;
94 g->have_stack_probing = stage1->enable_stack_probing;95 g->have_stack_probing = stage1->enable_stack_probing;
95 g->red_zone = stage1->red_zone;96 g->red_zone = stage1->red_zone;
96 g->is_single_threaded = stage1->is_single_threaded;97 g->is_single_threaded = stage1->is_single_threaded;
src/stage1/stage1.h+1
...@@ -182,6 +182,7 @@ struct ZigStage1 {...@@ -182,6 +182,7 @@ struct ZigStage1 {
182 bool pic;182 bool pic;
183 bool pie;183 bool pie;
184 bool lto;184 bool lto;
185 bool unwind_tables;
185 bool link_libc;186 bool link_libc;
186 bool link_libcpp;187 bool link_libcpp;
187 bool strip;188 bool strip;
src/target.zig+4
...@@ -404,3 +404,7 @@ pub fn clangAssemblerSupportsMcpuArg(target: std.Target) bool {...@@ -404,3 +404,7 @@ pub fn clangAssemblerSupportsMcpuArg(target: std.Target) bool {
404 else => false,404 else => false,
405 };405 };
406}406}
407
408pub fn needUnwindTables(target: std.Target) bool {
409 return target.os.tag == .windows;
410}
tools/update_clang_options.zig+8
...@@ -70,6 +70,14 @@ const known_options = [_]KnownOpt{...@@ -70,6 +70,14 @@ const known_options = [_]KnownOpt{
70 .name = "fno-lto",70 .name = "fno-lto",
71 .ident = "no_lto",71 .ident = "no_lto",
72 },72 },
73 .{
74 .name = "funwind-tables",
75 .ident = "unwind_tables",
76 },
77 .{
78 .name = "fno-unwind-tables",
79 .ident = "no_unwind_tables",
80 },
73 .{81 .{
74 .name = "nolibc",82 .name = "nolibc",
75 .ident = "nostdlib",83 .ident = "nostdlib",