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 10:31:48-07:00
log264969a8c3f84212a71fc43f9239b0dc7684994c
tree7348dc01f191bae3b331519986ea51f23c197212
parente3a74697f0317e1e6185262b477c0bfcad06d788

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,
...@@ -659,6 +660,7 @@ pub const InitOptions = struct {...@@ -659,6 +660,7 @@ pub const InitOptions = struct {
659 want_tsan: ?bool = null,660 want_tsan: ?bool = null,
660 want_compiler_rt: ?bool = null,661 want_compiler_rt: ?bool = null,
661 want_lto: ?bool = null,662 want_lto: ?bool = null,
663 want_unwind_tables: ?bool = null,
662 use_llvm: ?bool = null,664 use_llvm: ?bool = null,
663 use_lld: ?bool = null,665 use_lld: ?bool = null,
664 use_clang: ?bool = null,666 use_clang: ?bool = null,
...@@ -815,8 +817,20 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -815,8 +817,20 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
815 return error.MachineCodeModelNotSupported;817 return error.MachineCodeModelNotSupported;
816 }818 }
817819
820 const tsan = options.want_tsan orelse false;
821 // TSAN is implemented in C++ so it requires linking libc++.
822 const link_libcpp = options.link_libcpp or tsan;
823 const link_libc = link_libcpp or options.link_libc or
824 target_util.osRequiresLibC(options.target);
825
826 const link_libunwind = options.link_libunwind or
827 (link_libcpp and target_util.libcNeedsLibUnwind(options.target));
828 const unwind_tables = options.want_unwind_tables orelse
829 (link_libunwind or target_util.needUnwindTables(options.target));
830 const link_eh_frame_hdr = options.link_eh_frame_hdr or unwind_tables;
831
818 // Make a decision on whether to use LLD or our own linker.832 // Make a decision on whether to use LLD or our own linker.
819 const use_lld = if (options.use_lld) |explicit| explicit else blk: {833 const use_lld = options.use_lld orelse blk: {
820 if (!build_options.have_llvm)834 if (!build_options.have_llvm)
821 break :blk false;835 break :blk false;
822836
...@@ -835,7 +849,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -835,7 +849,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
835 options.frameworks.len != 0 or849 options.frameworks.len != 0 or
836 options.system_libs.len != 0 or850 options.system_libs.len != 0 or
837 options.link_libc or options.link_libcpp or851 options.link_libc or options.link_libcpp or
838 options.link_eh_frame_hdr or852 link_eh_frame_hdr or
839 options.link_emit_relocs or853 options.link_emit_relocs or
840 options.output_mode == .Lib or854 options.output_mode == .Lib or
841 options.lld_argv.len != 0 or855 options.lld_argv.len != 0 or
...@@ -894,15 +908,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -894,15 +908,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
894 }908 }
895 };909 };
896910
897 const tsan = options.want_tsan orelse false;
898 // TSAN is implemented in C++ so it requires linking libc++.
899 const link_libcpp = options.link_libcpp or tsan;
900 const link_libc = link_libcpp or options.link_libc or
901 target_util.osRequiresLibC(options.target);
902
903 const link_libunwind = options.link_libunwind or
904 (link_libcpp and target_util.libcNeedsLibUnwind(options.target));
905
906 const must_dynamic_link = dl: {911 const must_dynamic_link = dl: {
907 if (target_util.cannotDynamicLink(options.target))912 if (target_util.cannotDynamicLink(options.target))
908 break :dl false;913 break :dl false;
...@@ -1072,6 +1077,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1072,6 +1077,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1072 cache.hash.add(pic);1077 cache.hash.add(pic);
1073 cache.hash.add(pie);1078 cache.hash.add(pie);
1074 cache.hash.add(lto);1079 cache.hash.add(lto);
1080 cache.hash.add(unwind_tables);
1075 cache.hash.add(tsan);1081 cache.hash.add(tsan);
1076 cache.hash.add(stack_check);1082 cache.hash.add(stack_check);
1077 cache.hash.add(red_zone);1083 cache.hash.add(red_zone);
...@@ -1303,7 +1309,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1303,7 +1309,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1303 .linker_script = options.linker_script,1309 .linker_script = options.linker_script,
1304 .version_script = options.version_script,1310 .version_script = options.version_script,
1305 .gc_sections = options.linker_gc_sections,1311 .gc_sections = options.linker_gc_sections,
1306 .eh_frame_hdr = options.link_eh_frame_hdr,1312 .eh_frame_hdr = link_eh_frame_hdr,
1307 .emit_relocs = options.link_emit_relocs,1313 .emit_relocs = options.link_emit_relocs,
1308 .rdynamic = options.rdynamic,1314 .rdynamic = options.rdynamic,
1309 .extra_lld_args = options.lld_argv,1315 .extra_lld_args = options.lld_argv,
...@@ -1366,6 +1372,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1366,6 +1372,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1366 .color = options.color,1372 .color = options.color,
1367 .time_report = options.time_report,1373 .time_report = options.time_report,
1368 .stack_report = options.stack_report,1374 .stack_report = options.stack_report,
1375 .unwind_tables = unwind_tables,
1369 .test_filter = options.test_filter,1376 .test_filter = options.test_filter,
1370 .test_name_prefix = options.test_name_prefix,1377 .test_name_prefix = options.test_name_prefix,
1371 .test_evented_io = options.test_evented_io,1378 .test_evented_io = options.test_evented_io,
...@@ -2963,6 +2970,12 @@ pub fn addCCArgs(...@@ -2963,6 +2970,12 @@ pub fn addCCArgs(
2963 if (target_util.supports_fpic(target) and comp.bin_file.options.pic) {2970 if (target_util.supports_fpic(target) and comp.bin_file.options.pic) {
2964 try argv.append("-fPIC");2971 try argv.append("-fPIC");
2965 }2972 }
2973
2974 if (comp.unwind_tables) {
2975 try argv.append("-funwind-tables");
2976 } else {
2977 try argv.append("-fno-unwind-tables");
2978 }
2966 },2979 },
2967 .shared_library, .ll, .bc, .unknown, .static_library, .object, .zig => {},2980 .shared_library, .ll, .bc, .unknown, .static_library, .object, .zig => {},
2968 .assembly => {2981 .assembly => {
...@@ -3927,6 +3940,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node...@@ -3927,6 +3940,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
3927 .pic = comp.bin_file.options.pic,3940 .pic = comp.bin_file.options.pic,
3928 .pie = comp.bin_file.options.pie,3941 .pie = comp.bin_file.options.pie,
3929 .lto = comp.bin_file.options.lto,3942 .lto = comp.bin_file.options.lto,
3943 .unwind_tables = comp.unwind_tables,
3930 .link_libc = comp.bin_file.options.link_libc,3944 .link_libc = comp.bin_file.options.link_libc,
3931 .link_libcpp = comp.bin_file.options.link_libcpp,3945 .link_libcpp = comp.bin_file.options.link_libcpp,
3932 .strip = comp.bin_file.options.strip,3946 .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
...@@ -263,22 +263,26 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v...@@ -263,22 +263,26 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
263}263}
264264
265const usage_build_generic =265const usage_build_generic =
266 \\Usage: zig build-exe <options> [files]266 \\Usage: zig build-exe <options> [files]
267 \\ zig build-lib <options> [files]267 \\ zig build-lib <options> [files]
268 \\ zig build-obj <options> [files]268 \\ zig build-obj <options> [files]
269 \\ zig test <options> [files]269 \\ zig test <options> [files]
270 \\ zig run <options> [file] [-- [args]]270 \\ zig run <options> [file] [-- [args]]
271 \\ zig translate-c <options> [file]
271 \\272 \\
272 \\Supported file types:273 \\Supported file types:
273 \\ .zig Zig source code274 \\ .zig Zig source code
274 \\ .o ELF object file275 \\ .o ELF object file
275 \\ .o MACH-O (macOS) object file276 \\ .o Mach-O (macOS) object file
277 \\ .o WebAssembly object file
276 \\ .obj COFF (Windows) object file278 \\ .obj COFF (Windows) object file
277 \\ .lib COFF (Windows) static library279 \\ .lib COFF (Windows) static library
278 \\ .a ELF static library280 \\ .a ELF static library
281 \\ .a Mach-O (macOS) static library
282 \\ .a WebAssembly static library
279 \\ .so ELF shared object (dynamic link)283 \\ .so ELF shared object (dynamic link)
280 \\ .dll Windows Dynamic Link Library284 \\ .dll Windows Dynamic Link Library
281 \\ .dylib MACH-O (macOS) dynamic library285 \\ .dylib Mach-O (macOS) dynamic library
282 \\ .tbd (macOS) text-based dylib definition286 \\ .tbd (macOS) text-based dylib definition
283 \\ .s Target-specific assembly source code287 \\ .s Target-specific assembly source code
284 \\ .S Assembly with C preprocessor (requires LLVM extensions)288 \\ .S Assembly with C preprocessor (requires LLVM extensions)
...@@ -341,6 +345,8 @@ const usage_build_generic =...@@ -341,6 +345,8 @@ const usage_build_generic =
341 \\ -fno-sanitize-thread Disable Thread Sanitizer345 \\ -fno-sanitize-thread Disable Thread Sanitizer
342 \\ -fdll-export-fns Mark exported functions as DLL exports (Windows)346 \\ -fdll-export-fns Mark exported functions as DLL exports (Windows)
343 \\ -fno-dll-export-fns Force-disable marking exported functions as DLL exports347 \\ -fno-dll-export-fns Force-disable marking exported functions as DLL exports
348 \\ -funwind-tables Always produce unwind table entries for all functions
349 \\ -fno-unwind-tables Never produce unwind table entries
344 \\ -fLLVM Force using LLVM as the codegen backend350 \\ -fLLVM Force using LLVM as the codegen backend
345 \\ -fno-LLVM Prevent using LLVM as a codegen backend351 \\ -fno-LLVM Prevent using LLVM as a codegen backend
346 \\ -fClang Force using Clang as the C/C++ compilation backend352 \\ -fClang Force using Clang as the C/C++ compilation backend
...@@ -568,6 +574,7 @@ fn buildOutputType(...@@ -568,6 +574,7 @@ fn buildOutputType(
568 var want_pic: ?bool = null;574 var want_pic: ?bool = null;
569 var want_pie: ?bool = null;575 var want_pie: ?bool = null;
570 var want_lto: ?bool = null;576 var want_lto: ?bool = null;
577 var want_unwind_tables: ?bool = null;
571 var want_sanitize_c: ?bool = null;578 var want_sanitize_c: ?bool = null;
572 var want_stack_check: ?bool = null;579 var want_stack_check: ?bool = null;
573 var want_red_zone: ?bool = null;580 var want_red_zone: ?bool = null;
...@@ -920,6 +927,10 @@ fn buildOutputType(...@@ -920,6 +927,10 @@ fn buildOutputType(
920 want_lto = true;927 want_lto = true;
921 } else if (mem.eql(u8, arg, "-fno-lto")) {928 } else if (mem.eql(u8, arg, "-fno-lto")) {
922 want_lto = false;929 want_lto = false;
930 } else if (mem.eql(u8, arg, "-funwind-tables")) {
931 want_unwind_tables = true;
932 } else if (mem.eql(u8, arg, "-fno-unwind-tables")) {
933 want_unwind_tables = false;
923 } else if (mem.eql(u8, arg, "-fstack-check")) {934 } else if (mem.eql(u8, arg, "-fstack-check")) {
924 want_stack_check = true;935 want_stack_check = true;
925 } else if (mem.eql(u8, arg, "-fno-stack-check")) {936 } else if (mem.eql(u8, arg, "-fno-stack-check")) {
...@@ -1151,6 +1162,8 @@ fn buildOutputType(...@@ -1151,6 +1162,8 @@ fn buildOutputType(
1151 .no_lto => want_lto = false,1162 .no_lto => want_lto = false,
1152 .red_zone => want_red_zone = true,1163 .red_zone => want_red_zone = true,
1153 .no_red_zone => want_red_zone = false,1164 .no_red_zone => want_red_zone = false,
1165 .unwind_tables => want_unwind_tables = true,
1166 .no_unwind_tables => want_unwind_tables = false,
1154 .nostdlib => ensure_libc_on_non_freestanding = false,1167 .nostdlib => ensure_libc_on_non_freestanding = false,
1155 .nostdlib_cpp => ensure_libcpp_on_non_freestanding = false,1168 .nostdlib_cpp => ensure_libcpp_on_non_freestanding = false,
1156 .shared => {1169 .shared => {
...@@ -1893,6 +1906,7 @@ fn buildOutputType(...@@ -1893,6 +1906,7 @@ fn buildOutputType(
1893 .want_pic = want_pic,1906 .want_pic = want_pic,
1894 .want_pie = want_pie,1907 .want_pie = want_pie,
1895 .want_lto = want_lto,1908 .want_lto = want_lto,
1909 .want_unwind_tables = want_unwind_tables,
1896 .want_sanitize_c = want_sanitize_c,1910 .want_sanitize_c = want_sanitize_c,
1897 .want_stack_check = want_stack_check,1911 .want_stack_check = want_stack_check,
1898 .want_red_zone = want_red_zone,1912 .want_red_zone = want_red_zone,
...@@ -3294,6 +3308,8 @@ pub const ClangArgIterator = struct {...@@ -3294,6 +3308,8 @@ pub const ClangArgIterator = struct {
3294 no_pie,3308 no_pie,
3295 lto,3309 lto,
3296 no_lto,3310 no_lto,
3311 unwind_tables,
3312 no_unwind_tables,
3297 nostdlib,3313 nostdlib,
3298 nostdlib_cpp,3314 nostdlib_cpp,
3299 shared,3315 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",