authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-11-13 06:04:04+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-12-11 00:10:15+01:00
log8af82621d75f9f0d96ebf734f5ea862d06a5f1fa
treee004815ccdc1ae57557d69a2e42270edd81ca469
parent0b67463b9285158d818d6cd196c5f2ba9961a05e
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

compiler: Improve the handling of unwind table levels.

The goal here is to support both levels of unwind tables (sync and async) in zig cc and zig build. Previously, the LLVM backend always used async tables while zig cc was partially influenced by whatever was Clang's default.

16 files changed, 174 insertions(+), 53 deletions(-)

lib/std/Build.zig+5-5
......@@ -706,7 +706,7 @@ pub const ExecutableOptions = struct {
706706 single_threaded: ?bool = null,
707707 pic: ?bool = null,
708708 strip: ?bool = null,
709 unwind_tables: ?bool = null,
709 unwind_tables: ?std.builtin.UnwindTables = null,
710710 omit_frame_pointer: ?bool = null,
711711 sanitize_thread: ?bool = null,
712712 error_tracing: ?bool = null,
......@@ -762,7 +762,7 @@ pub const ObjectOptions = struct {
762762 single_threaded: ?bool = null,
763763 pic: ?bool = null,
764764 strip: ?bool = null,
765 unwind_tables: ?bool = null,
765 unwind_tables: ?std.builtin.UnwindTables = null,
766766 omit_frame_pointer: ?bool = null,
767767 sanitize_thread: ?bool = null,
768768 error_tracing: ?bool = null,
......@@ -810,7 +810,7 @@ pub const SharedLibraryOptions = struct {
810810 single_threaded: ?bool = null,
811811 pic: ?bool = null,
812812 strip: ?bool = null,
813 unwind_tables: ?bool = null,
813 unwind_tables: ?std.builtin.UnwindTables = null,
814814 omit_frame_pointer: ?bool = null,
815815 sanitize_thread: ?bool = null,
816816 error_tracing: ?bool = null,
......@@ -867,7 +867,7 @@ pub const StaticLibraryOptions = struct {
867867 single_threaded: ?bool = null,
868868 pic: ?bool = null,
869869 strip: ?bool = null,
870 unwind_tables: ?bool = null,
870 unwind_tables: ?std.builtin.UnwindTables = null,
871871 omit_frame_pointer: ?bool = null,
872872 sanitize_thread: ?bool = null,
873873 error_tracing: ?bool = null,
......@@ -919,7 +919,7 @@ pub const TestOptions = struct {
919919 single_threaded: ?bool = null,
920920 pic: ?bool = null,
921921 strip: ?bool = null,
922 unwind_tables: ?bool = null,
922 unwind_tables: ?std.builtin.UnwindTables = null,
923923 omit_frame_pointer: ?bool = null,
924924 sanitize_thread: ?bool = null,
925925 error_tracing: ?bool = null,
lib/std/Build/Module.zig+10-3
......@@ -22,7 +22,7 @@ frameworks: std.StringArrayHashMapUnmanaged(LinkFrameworkOptions),
2222link_objects: std.ArrayListUnmanaged(LinkObject),
2323
2424strip: ?bool,
25unwind_tables: ?bool,
25unwind_tables: ?std.builtin.UnwindTables,
2626single_threaded: ?bool,
2727stack_protector: ?bool,
2828stack_check: ?bool,
......@@ -218,7 +218,7 @@ pub const CreateOptions = struct {
218218 link_libcpp: ?bool = null,
219219 single_threaded: ?bool = null,
220220 strip: ?bool = null,
221 unwind_tables: ?bool = null,
221 unwind_tables: ?std.builtin.UnwindTables = null,
222222 dwarf_format: ?std.dwarf.Format = null,
223223 code_model: std.builtin.CodeModel = .default,
224224 stack_protector: ?bool = null,
......@@ -675,7 +675,6 @@ pub fn appendZigProcessFlags(
675675 const b = m.owner;
676676
677677 try addFlag(zig_args, m.strip, "-fstrip", "-fno-strip");
678 try addFlag(zig_args, m.unwind_tables, "-funwind-tables", "-fno-unwind-tables");
679678 try addFlag(zig_args, m.single_threaded, "-fsingle-threaded", "-fno-single-threaded");
680679 try addFlag(zig_args, m.stack_check, "-fstack-check", "-fno-stack-check");
681680 try addFlag(zig_args, m.stack_protector, "-fstack-protector", "-fno-stack-protector");
......@@ -695,6 +694,14 @@ pub fn appendZigProcessFlags(
695694 });
696695 }
697696
697 if (m.unwind_tables) |unwind_tables| {
698 try zig_args.append(switch (unwind_tables) {
699 .none => "-fno-unwind-tables",
700 .sync => "-funwind-tables",
701 .@"async" => "-fasync-unwind-tables",
702 });
703 }
704
698705 try zig_args.ensureUnusedCapacity(1);
699706 if (m.optimize) |optimize| switch (optimize) {
700707 .Debug => zig_args.appendAssumeCapacity("-ODebug"),
lib/std/builtin.zig+8
......@@ -804,6 +804,14 @@ pub const LinkMode = enum {
804804 dynamic,
805805};
806806
807/// This data structure is used by the Zig language code generation and
808/// therefore must be kept in sync with the compiler implementation.
809pub const UnwindTables = enum {
810 none,
811 sync,
812 @"async",
813};
814
807815/// This data structure is used by the Zig language code generation and
808816/// therefore must be kept in sync with the compiler implementation.
809817pub const WasiExecModel = enum {
src/Builtin.zig+3
......@@ -2,6 +2,7 @@ target: std.Target,
22zig_backend: std.builtin.CompilerBackend,
33output_mode: std.builtin.OutputMode,
44link_mode: std.builtin.LinkMode,
5unwind_tables: std.builtin.UnwindTables,
56is_test: bool,
67single_threaded: bool,
78link_libc: bool,
......@@ -40,6 +41,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
4041 \\
4142 \\pub const output_mode: std.builtin.OutputMode = .{p_};
4243 \\pub const link_mode: std.builtin.LinkMode = .{p_};
44 \\pub const unwind_tables: std.builtin.UnwindTables = .{p_};
4345 \\pub const is_test = {};
4446 \\pub const single_threaded = {};
4547 \\pub const abi: std.Target.Abi = .{p_};
......@@ -53,6 +55,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
5355 std.zig.fmtId(@tagName(zig_backend)),
5456 std.zig.fmtId(@tagName(opts.output_mode)),
5557 std.zig.fmtId(@tagName(opts.link_mode)),
58 std.zig.fmtId(@tagName(opts.unwind_tables)),
5659 opts.is_test,
5760 opts.single_threaded,
5861 std.zig.fmtId(@tagName(target.abi)),
src/Compilation.zig+20-7
......@@ -1261,12 +1261,15 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
12611261 // The "any" values provided by resolved config only account for
12621262 // explicitly-provided settings. We now make them additionally account
12631263 // for default setting resolution.
1264 const any_unwind_tables = options.config.any_unwind_tables or options.root_mod.unwind_tables;
1264 const any_unwind_tables = switch (options.config.any_unwind_tables) {
1265 .none => options.root_mod.unwind_tables,
1266 .sync, .@"async" => |uwt| uwt,
1267 };
12651268 const any_non_single_threaded = options.config.any_non_single_threaded or !options.root_mod.single_threaded;
12661269 const any_sanitize_thread = options.config.any_sanitize_thread or options.root_mod.sanitize_thread;
12671270 const any_fuzz = options.config.any_fuzz or options.root_mod.fuzz;
12681271
1269 const link_eh_frame_hdr = options.link_eh_frame_hdr or any_unwind_tables;
1272 const link_eh_frame_hdr = options.link_eh_frame_hdr or any_unwind_tables != .none;
12701273 const build_id = options.build_id orelse .none;
12711274
12721275 const link_libc = options.config.link_libc;
......@@ -1354,6 +1357,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
13541357 cache.hash.add(options.config.pie);
13551358 cache.hash.add(options.config.lto);
13561359 cache.hash.add(options.config.link_mode);
1360 cache.hash.add(options.config.any_unwind_tables);
13571361 cache.hash.add(options.function_sections);
13581362 cache.hash.add(options.data_sections);
13591363 cache.hash.add(link_libc);
......@@ -5538,10 +5542,17 @@ pub fn addCCArgs(
55385542 try argv.append("-Werror=date-time");
55395543 }
55405544
5541 if (mod.unwind_tables) {
5542 try argv.append("-funwind-tables");
5543 } else {
5544 try argv.append("-fno-unwind-tables");
5545 switch (mod.unwind_tables) {
5546 .none => {
5547 try argv.append("-fno-unwind-tables");
5548 try argv.append("-fno-asynchronous-unwind-tables");
5549 },
5550 .sync => {
5551 // Need to override Clang's convoluted default logic.
5552 try argv.append("-fno-asynchronous-unwind-tables");
5553 try argv.append("-funwind-tables");
5554 },
5555 .@"async" => try argv.append("-fasynchronous-unwind-tables"),
55455556 }
55465557 },
55475558 .shared_library, .ll, .bc, .unknown, .static_library, .object, .def, .zig, .res, .manifest => {},
......@@ -6273,6 +6284,7 @@ pub const CrtFileOptions = struct {
62736284 function_sections: ?bool = null,
62746285 data_sections: ?bool = null,
62756286 omit_frame_pointer: ?bool = null,
6287 unwind_tables: ?std.builtin.UnwindTables = null,
62766288 pic: ?bool = null,
62776289 no_builtin: ?bool = null,
62786290};
......@@ -6334,7 +6346,8 @@ pub fn build_crt_file(
63346346 // Some libcs (e.g. musl) are opinionated about -fomit-frame-pointer.
63356347 .omit_frame_pointer = options.omit_frame_pointer orelse comp.root_mod.omit_frame_pointer,
63366348 .valgrind = false,
6337 .unwind_tables = false,
6349 // Some libcs (e.g. MinGW) are opinionated about -funwind-tables.
6350 .unwind_tables = options.unwind_tables orelse .none,
63386351 // Some CRT objects (e.g. musl's rcrt1.o and Scrt1.o) are opinionated about PIC.
63396352 .pic = options.pic orelse comp.root_mod.pic,
63406353 .optimize_mode = comp.compilerRtOptMode(),
src/Compilation/Config.zig+14-10
......@@ -12,13 +12,14 @@ link_libunwind: bool,
1212/// True if and only if the c_source_files field will have nonzero length when
1313/// calling Compilation.create.
1414any_c_source_files: bool,
15/// This is true if any Module has unwind_tables set explicitly to true. Until
16/// Compilation.create is called, it is possible for this to be false while in
17/// fact all Module instances have unwind_tables=true due to the default
18/// being unwind_tables=true. After Compilation.create is called this will
19/// also take into account the default setting, making this value true if and
20/// only if any Module has unwind_tables set to true.
21any_unwind_tables: bool,
15/// This is not `.none` if any `Module` has `unwind_tables` set explicitly to a
16/// value other than `.none`. Until `Compilation.create()` is called, it is
17/// possible for this to be `.none` while in fact all `Module` instances have
18/// `unwind_tables != .none` due to the default. After `Compilation.create()` is
19/// called, this will also take into account the default setting, making this
20/// value `.sync` or `.@"async"` if and only if any `Module` has
21/// `unwind_tables != .none`.
22any_unwind_tables: std.builtin.UnwindTables,
2223/// This is true if any Module has single_threaded set explicitly to false. Until
2324/// Compilation.create is called, it is possible for this to be false while in
2425/// fact all Module instances have single_threaded=false due to the default
......@@ -85,7 +86,7 @@ pub const Options = struct {
8586 any_non_single_threaded: bool = false,
8687 any_sanitize_thread: bool = false,
8788 any_fuzz: bool = false,
88 any_unwind_tables: bool = false,
89 any_unwind_tables: std.builtin.UnwindTables = .none,
8990 any_dyn_libs: bool = false,
9091 any_c_source_files: bool = false,
9192 any_non_stripped: bool = false,
......@@ -356,8 +357,11 @@ pub fn resolve(options: Options) ResolveError!Config {
356357 break :b false;
357358 };
358359
359 const any_unwind_tables = options.any_unwind_tables or
360 link_libunwind or target_util.needUnwindTables(target);
360 const any_unwind_tables = b: {
361 if (options.any_unwind_tables != .none) break :b options.any_unwind_tables;
362
363 break :b target_util.needUnwindTables(target, link_libunwind, options.any_sanitize_thread);
364 };
361365
362366 const link_mode = b: {
363367 const explicitly_exe_or_dyn_lib = switch (options.output_mode) {
src/Package/Module.zig+4-3
......@@ -27,7 +27,7 @@ red_zone: bool,
2727sanitize_c: bool,
2828sanitize_thread: bool,
2929fuzz: bool,
30unwind_tables: bool,
30unwind_tables: std.builtin.UnwindTables,
3131cc_argv: []const []const u8,
3232/// (SPIR-V) whether to generate a structured control flow graph or not
3333structured_cfg: bool,
......@@ -91,7 +91,7 @@ pub const CreateOptions = struct {
9191 /// other number means stack protection with that buffer size.
9292 stack_protector: ?u32 = null,
9393 red_zone: ?bool = null,
94 unwind_tables: ?bool = null,
94 unwind_tables: ?std.builtin.UnwindTables = null,
9595 sanitize_c: ?bool = null,
9696 sanitize_thread: ?bool = null,
9797 fuzz: ?bool = null,
......@@ -112,7 +112,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
112112 if (options.inherited.sanitize_thread == true) assert(options.global.any_sanitize_thread);
113113 if (options.inherited.fuzz == true) assert(options.global.any_fuzz);
114114 if (options.inherited.single_threaded == false) assert(options.global.any_non_single_threaded);
115 if (options.inherited.unwind_tables == true) assert(options.global.any_unwind_tables);
115 if (options.inherited.unwind_tables) |uwt| if (uwt != .none) assert(options.global.any_unwind_tables != .none);
116116 if (options.inherited.error_tracing == true) assert(options.global.any_error_tracing);
117117
118118 const resolved_target = options.inherited.resolved_target orelse options.parent.?.resolved_target;
......@@ -382,6 +382,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
382382 .zig_backend = zig_backend,
383383 .output_mode = options.global.output_mode,
384384 .link_mode = options.global.link_mode,
385 .unwind_tables = options.global.any_unwind_tables,
385386 .is_test = options.global.is_test,
386387 .single_threaded = single_threaded,
387388 .link_libc = options.global.link_libc,
src/clang_options_data.zig+16-2
......@@ -2757,7 +2757,14 @@ flagpd1("fast"),
27572757flagpd1("fastcp"),
27582758flagpd1("fastf"),
27592759flagpd1("fasync-exceptions"),
2760flagpd1("fasynchronous-unwind-tables"),
2760.{
2761 .name = "fasynchronous-unwind-tables",
2762 .syntax = .flag,
2763 .zig_equivalent = .asynchronous_unwind_tables,
2764 .pd1 = true,
2765 .pd2 = false,
2766 .psl = false,
2767},
27612768flagpd1("fauto-import"),
27622769flagpd1("fauto-profile"),
27632770flagpd1("fauto-profile-accurate"),
......@@ -3247,7 +3254,14 @@ flagpd1("fno-assume-sane-operator-new"),
32473254flagpd1("fno-assume-unique-vtables"),
32483255flagpd1("fno-assumptions"),
32493256flagpd1("fno-async-exceptions"),
3250flagpd1("fno-asynchronous-unwind-tables"),
3257.{
3258 .name = "fno-asynchronous-unwind-tables",
3259 .syntax = .flag,
3260 .zig_equivalent = .no_asynchronous_unwind_tables,
3261 .pd1 = true,
3262 .pd2 = false,
3263 .psl = false,
3264},
32513265flagpd1("fno-auto-import"),
32523266flagpd1("fno-auto-profile"),
32533267flagpd1("fno-auto-profile-accurate"),
src/codegen/llvm.zig+5-2
......@@ -3141,8 +3141,11 @@ pub const Object = struct {
31413141 } }, &o.builder);
31423142 }
31433143 try attributes.addFnAttr(.nounwind, &o.builder);
3144 if (owner_mod.unwind_tables) {
3145 try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder);
3144 if (owner_mod.unwind_tables != .none) {
3145 try attributes.addFnAttr(
3146 .{ .uwtable = if (owner_mod.unwind_tables == .@"async") .@"async" else .sync },
3147 &o.builder,
3148 );
31463149 }
31473150 if (owner_mod.no_builtin) {
31483151 // The intent here is for compiler-rt and libc functions to not generate
src/libcxx.zig+6-3
......@@ -397,7 +397,6 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
397397
398398 const optimize_mode = comp.compilerRtOptMode();
399399 const strip = comp.compilerRtStrip();
400 const unwind_tables = true;
401400
402401 const config = Compilation.Config.resolve(.{
403402 .output_mode = output_mode,
......@@ -409,7 +408,6 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
409408 .root_optimize_mode = optimize_mode,
410409 .root_strip = strip,
411410 .link_libc = true,
412 .any_unwind_tables = unwind_tables,
413411 .lto = comp.config.lto,
414412 .any_sanitize_thread = comp.config.any_sanitize_thread,
415413 }) catch |err| {
......@@ -440,7 +438,12 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
440438 .valgrind = false,
441439 .optimize_mode = optimize_mode,
442440 .structured_cfg = comp.root_mod.structured_cfg,
443 .unwind_tables = unwind_tables,
441 // See the `-fno-exceptions` logic for WASI.
442 // The old 32-bit x86 variant of SEH doesn't use tables.
443 .unwind_tables = if (target.os.tag == .wasi or (target.cpu.arch == .x86 and target.os.tag == .windows))
444 .none
445 else
446 .@"async",
444447 .pic = comp.root_mod.pic,
445448 },
446449 .global = config,
src/libunwind.zig+2-1
......@@ -65,7 +65,8 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
6565 .sanitize_c = false,
6666 .sanitize_thread = false,
6767 // necessary so that libunwind can unwind through its own stack frames
68 .unwind_tables = true,
68 // The old 32-bit x86 variant of SEH doesn't use tables.
69 .unwind_tables = if (target.cpu.arch == .x86 and target.os.tag == .windows) .none else .@"async",
6970 .pic = if (target_util.supports_fpic(target)) true else null,
7071 .optimize_mode = comp.compilerRtOptMode(),
7172 },
src/main.zig+46-8
......@@ -510,6 +510,7 @@ const usage_build_generic =
510510 \\ -ffuzz Enable fuzz testing instrumentation
511511 \\ -fno-fuzz Disable fuzz testing instrumentation
512512 \\ -funwind-tables Always produce unwind table entries for all functions
513 \\ -fasync-unwind-tables Always produce asynchronous unwind table entries for all functions
513514 \\ -fno-unwind-tables Never produce unwind table entries
514515 \\ -ferror-tracing Enable error tracing in ReleaseFast mode
515516 \\ -fno-error-tracing Disable error tracing in Debug and ReleaseSafe mode
......@@ -1385,9 +1386,11 @@ fn buildOutputType(
13851386 } else if (mem.eql(u8, arg, "-fno-lto")) {
13861387 create_module.opts.lto = false;
13871388 } else if (mem.eql(u8, arg, "-funwind-tables")) {
1388 mod_opts.unwind_tables = true;
1389 mod_opts.unwind_tables = .sync;
1390 } else if (mem.eql(u8, arg, "-fasync-unwind-tables")) {
1391 mod_opts.unwind_tables = .@"async";
13891392 } else if (mem.eql(u8, arg, "-fno-unwind-tables")) {
1390 mod_opts.unwind_tables = false;
1393 mod_opts.unwind_tables = .none;
13911394 } else if (mem.eql(u8, arg, "-fstack-check")) {
13921395 mod_opts.stack_check = true;
13931396 } else if (mem.eql(u8, arg, "-fno-stack-check")) {
......@@ -1973,8 +1976,27 @@ fn buildOutputType(
19731976 }
19741977 },
19751978 .no_stack_protector => mod_opts.stack_protector = 0,
1976 .unwind_tables => mod_opts.unwind_tables = true,
1977 .no_unwind_tables => mod_opts.unwind_tables = false,
1979 // The way these unwind table options are processed in GCC and Clang is crazy
1980 // convoluted, and we also don't know the target triple here, so this is all
1981 // best-effort.
1982 .unwind_tables => if (mod_opts.unwind_tables) |uwt| switch (uwt) {
1983 .none => {
1984 mod_opts.unwind_tables = .sync;
1985 },
1986 .sync, .@"async" => {},
1987 } else {
1988 mod_opts.unwind_tables = .sync;
1989 },
1990 .no_unwind_tables => mod_opts.unwind_tables = .none,
1991 .asynchronous_unwind_tables => mod_opts.unwind_tables = .@"async",
1992 .no_asynchronous_unwind_tables => if (mod_opts.unwind_tables) |uwt| switch (uwt) {
1993 .none, .sync => {},
1994 .@"async" => {
1995 mod_opts.unwind_tables = .sync;
1996 },
1997 } else {
1998 mod_opts.unwind_tables = .sync;
1999 },
19782000 .nostdlib => {
19792001 create_module.opts.ensure_libc_on_non_freestanding = false;
19802002 create_module.opts.ensure_libcpp_on_non_freestanding = false;
......@@ -2788,8 +2810,15 @@ fn buildOutputType(
27882810 create_module.opts.any_sanitize_thread = true;
27892811 if (mod_opts.fuzz == true)
27902812 create_module.opts.any_fuzz = true;
2791 if (mod_opts.unwind_tables == true)
2792 create_module.opts.any_unwind_tables = true;
2813 if (mod_opts.unwind_tables) |uwt| switch (uwt) {
2814 .none => {},
2815 .sync => if (create_module.opts.any_unwind_tables == .none) {
2816 create_module.opts.any_unwind_tables = .sync;
2817 },
2818 .@"async" => {
2819 create_module.opts.any_unwind_tables = .@"async";
2820 },
2821 };
27932822 if (mod_opts.strip == false)
27942823 create_module.opts.any_non_stripped = true;
27952824 if (mod_opts.error_tracing == true)
......@@ -5713,6 +5742,8 @@ pub const ClangArgIterator = struct {
57135742 no_lto,
57145743 unwind_tables,
57155744 no_unwind_tables,
5745 asynchronous_unwind_tables,
5746 no_asynchronous_unwind_tables,
57165747 nostdlib,
57175748 nostdlib_cpp,
57185749 shared,
......@@ -7435,8 +7466,15 @@ fn handleModArg(
74357466 create_module.opts.any_sanitize_thread = true;
74367467 if (mod_opts.fuzz == true)
74377468 create_module.opts.any_fuzz = true;
7438 if (mod_opts.unwind_tables == true)
7439 create_module.opts.any_unwind_tables = true;
7469 if (mod_opts.unwind_tables) |uwt| switch (uwt) {
7470 .none => {},
7471 .sync => if (create_module.opts.any_unwind_tables == .none) {
7472 create_module.opts.any_unwind_tables = .sync;
7473 },
7474 .@"async" => {
7475 create_module.opts.any_unwind_tables = .@"async";
7476 },
7477 };
74407478 if (mod_opts.strip == false)
74417479 create_module.opts.any_non_stripped = true;
74427480 if (mod_opts.error_tracing == true)
src/mingw.zig+13-4
......@@ -24,6 +24,10 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
2424 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
2525 defer arena_allocator.deinit();
2626 const arena = arena_allocator.allocator();
27 const target = comp.getTarget();
28
29 // The old 32-bit x86 variant of SEH doesn't use tables.
30 const unwind_tables: std.builtin.UnwindTables = if (target.cpu.arch != .x86) .@"async" else .none;
2731
2832 switch (crt_file) {
2933 .crt2_o => {
......@@ -41,7 +45,9 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
4145 .owner = undefined,
4246 },
4347 };
44 return comp.build_crt_file("crt2", .Obj, .@"mingw-w64 crt2.o", prog_node, &files, .{});
48 return comp.build_crt_file("crt2", .Obj, .@"mingw-w64 crt2.o", prog_node, &files, .{
49 .unwind_tables = unwind_tables,
50 });
4551 },
4652
4753 .dllcrt2_o => {
......@@ -56,7 +62,9 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
5662 .owner = undefined,
5763 },
5864 };
59 return comp.build_crt_file("dllcrt2", .Obj, .@"mingw-w64 dllcrt2.o", prog_node, &files, .{});
65 return comp.build_crt_file("dllcrt2", .Obj, .@"mingw-w64 dllcrt2.o", prog_node, &files, .{
66 .unwind_tables = unwind_tables,
67 });
6068 },
6169
6270 .mingw32_lib => {
......@@ -73,7 +81,6 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
7381 .owner = undefined,
7482 });
7583 }
76 const target = comp.getTarget();
7784 if (target.cpu.arch == .x86 or target.cpu.arch == .x86_64) {
7885 for (mingw32_x86_src) |dep| {
7986 try c_source_files.append(.{
......@@ -118,7 +125,9 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
118125 } else {
119126 @panic("unsupported arch");
120127 }
121 return comp.build_crt_file("mingw32", .Lib, .@"mingw-w64 mingw32.lib", prog_node, c_source_files.items, .{});
128 return comp.build_crt_file("mingw32", .Lib, .@"mingw-w64 mingw32.lib", prog_node, c_source_files.items, .{
129 .unwind_tables = unwind_tables,
130 });
122131 },
123132 }
124133}
src/target.zig+11-2
......@@ -4,6 +4,7 @@ const assert = std.debug.assert;
44const Type = @import("Type.zig");
55const AddressSpace = std.builtin.AddressSpace;
66const Alignment = @import("InternPool.zig").Alignment;
7const Compilation = @import("Compilation.zig");
78const Feature = @import("Zcu.zig").Feature;
89
910pub const default_stack_protector_buffer_size = 4;
......@@ -408,8 +409,16 @@ pub fn clangSupportsNoImplicitFloatArg(target: std.Target) bool {
408409 };
409410}
410411
411pub fn needUnwindTables(target: std.Target) bool {
412 return target.os.tag == .windows or target.isDarwin() or std.debug.Dwarf.abi.supportsUnwinding(target);
412pub fn needUnwindTables(target: std.Target, libunwind: bool, libtsan: bool) std.builtin.UnwindTables {
413 if (target.os.tag == .windows) {
414 // The old 32-bit x86 variant of SEH doesn't use tables.
415 return if (target.cpu.arch != .x86) .@"async" else .none;
416 }
417 if (target.os.tag.isDarwin()) return .@"async";
418 if (libunwind) return .@"async";
419 if (libtsan) return .@"async";
420 if (std.debug.Dwarf.abi.supportsUnwinding(target)) return .@"async";
421 return .none;
413422}
414423
415424pub fn defaultAddressSpace(
test/standalone/stack_iterator/build.zig+3-3
......@@ -23,7 +23,7 @@ pub fn build(b: *std.Build) void {
2323 .root_source_file = b.path("unwind.zig"),
2424 .target = target,
2525 .optimize = optimize,
26 .unwind_tables = if (target.result.isDarwin()) true else null,
26 .unwind_tables = if (target.result.isDarwin()) .@"async" else null,
2727 .omit_frame_pointer = false,
2828 });
2929
......@@ -46,7 +46,7 @@ pub fn build(b: *std.Build) void {
4646 .root_source_file = b.path("unwind.zig"),
4747 .target = target,
4848 .optimize = optimize,
49 .unwind_tables = true,
49 .unwind_tables = .@"async",
5050 .omit_frame_pointer = true,
5151 });
5252
......@@ -85,7 +85,7 @@ pub fn build(b: *std.Build) void {
8585 .root_source_file = b.path("shared_lib_unwind.zig"),
8686 .target = target,
8787 .optimize = optimize,
88 .unwind_tables = if (target.result.isDarwin()) true else null,
88 .unwind_tables = if (target.result.isDarwin()) .@"async" else null,
8989 .omit_frame_pointer = true,
9090 });
9191
tools/update_clang_options.zig+8
......@@ -110,6 +110,14 @@ const known_options = [_]KnownOpt{
110110 .name = "fno-unwind-tables",
111111 .ident = "no_unwind_tables",
112112 },
113 .{
114 .name = "fasynchronous-unwind-tables",
115 .ident = "asynchronous_unwind_tables",
116 },
117 .{
118 .name = "fno-asynchronous-unwind-tables",
119 .ident = "no_asynchronous_unwind_tables",
120 },
113121 .{
114122 .name = "nolibc",
115123 .ident = "nostdlib",