authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-01-23 01:38:20+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-01-23 23:22:38+00:00
logef4d7f01a5c26d8ed6fa8236d1b64e4091a51be3
tree80da7b2ae3a66a5e394d31ccd62421529a14929b
parentb46a40ff1db6c4d467925a9a0d72436cdb3a6a74
signaturelock-open Commit is signed but in an unrecognized format.

compiler: Fix computation of Compilation.Config.any_unwind_tables.

This moves the default value logic to Package.Module.create() instead and makes it so that Compilation.Config.any_unwind_tables is computed similarly to any_sanitize_thread, any_fuzz, etc. It turns out that for any_unwind_tables, we only actually care if unwind tables are enabled at all, not at what level.

7 files changed, 36 insertions(+), 43 deletions(-)

src/Compilation.zig+4-5
...@@ -1274,15 +1274,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1274,15 +1274,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1274 // The "any" values provided by resolved config only account for1274 // The "any" values provided by resolved config only account for
1275 // explicitly-provided settings. We now make them additionally account1275 // explicitly-provided settings. We now make them additionally account
1276 // for default setting resolution.1276 // for default setting resolution.
1277 const any_unwind_tables = switch (options.config.any_unwind_tables) {1277 const any_unwind_tables = options.config.any_unwind_tables or options.root_mod.unwind_tables != .none;
1278 .none => options.root_mod.unwind_tables,
1279 .sync, .@"async" => |uwt| uwt,
1280 };
1281 const any_non_single_threaded = options.config.any_non_single_threaded or !options.root_mod.single_threaded;1278 const any_non_single_threaded = options.config.any_non_single_threaded or !options.root_mod.single_threaded;
1282 const any_sanitize_thread = options.config.any_sanitize_thread or options.root_mod.sanitize_thread;1279 const any_sanitize_thread = options.config.any_sanitize_thread or options.root_mod.sanitize_thread;
1283 const any_fuzz = options.config.any_fuzz or options.root_mod.fuzz;1280 const any_fuzz = options.config.any_fuzz or options.root_mod.fuzz;
12841281
1285 const link_eh_frame_hdr = options.link_eh_frame_hdr or any_unwind_tables != .none;1282 const link_eh_frame_hdr = options.link_eh_frame_hdr or any_unwind_tables;
1286 const build_id = options.build_id orelse .none;1283 const build_id = options.build_id orelse .none;
12871284
1288 const link_libc = options.config.link_libc;1285 const link_libc = options.config.link_libc;
...@@ -6459,6 +6456,7 @@ fn buildOutputFromZig(...@@ -6459,6 +6456,7 @@ fn buildOutputFromZig(
6459 .root_optimize_mode = optimize_mode,6456 .root_optimize_mode = optimize_mode,
6460 .root_strip = strip,6457 .root_strip = strip,
6461 .link_libc = comp.config.link_libc,6458 .link_libc = comp.config.link_libc,
6459 .any_unwind_tables = comp.root_mod.unwind_tables != .none,
6462 });6460 });
64636461
6464 const root_mod = try Package.Module.create(arena, .{6462 const root_mod = try Package.Module.create(arena, .{
...@@ -6595,6 +6593,7 @@ pub fn build_crt_file(...@@ -6595,6 +6593,7 @@ pub fn build_crt_file(
6595 .root_optimize_mode = comp.compilerRtOptMode(),6593 .root_optimize_mode = comp.compilerRtOptMode(),
6596 .root_strip = comp.compilerRtStrip(),6594 .root_strip = comp.compilerRtStrip(),
6597 .link_libc = false,6595 .link_libc = false,
6596 .any_unwind_tables = options.unwind_tables != .none,
6598 .lto = switch (output_mode) {6597 .lto = switch (output_mode) {
6599 .Lib => comp.config.lto,6598 .Lib => comp.config.lto,
6600 .Obj, .Exe => .none,6599 .Obj, .Exe => .none,
src/Compilation/Config.zig+6-13
...@@ -12,14 +12,13 @@ link_libunwind: bool,...@@ -12,14 +12,13 @@ link_libunwind: bool,
12/// True if and only if the c_source_files field will have nonzero length when12/// True if and only if the c_source_files field will have nonzero length when
13/// calling Compilation.create.13/// calling Compilation.create.
14any_c_source_files: bool,14any_c_source_files: bool,
15/// This is not `.none` if any `Module` has `unwind_tables` set explicitly to a15/// This is `true` if any `Module` has `unwind_tables` set explicitly to a
16/// value other than `.none`. Until `Compilation.create()` is called, it is16/// value other than `.none`. Until `Compilation.create()` is called, it is
17/// possible for this to be `.none` while in fact all `Module` instances have17/// possible for this to be `false` while in fact all `Module` instances have
18/// `unwind_tables != .none` due to the default. After `Compilation.create()` is18/// `unwind_tables != .none` due to the default. After `Compilation.create()` is
19/// called, this will also take into account the default setting, making this19/// called, this will also take into account the default setting, making this
20/// value `.sync` or `.@"async"` if and only if any `Module` has20/// value `true` if and only if any `Module` has `unwind_tables != .none`.
21/// `unwind_tables != .none`.21any_unwind_tables: bool,
22any_unwind_tables: std.builtin.UnwindTables,
23/// This is true if any Module has single_threaded set explicitly to false. Until22/// This is true if any Module has single_threaded set explicitly to false. Until
24/// Compilation.create is called, it is possible for this to be false while in23/// Compilation.create is called, it is possible for this to be false while in
25/// fact all Module instances have single_threaded=false due to the default24/// fact all Module instances have single_threaded=false due to the default
...@@ -88,7 +87,7 @@ pub const Options = struct {...@@ -88,7 +87,7 @@ pub const Options = struct {
88 any_non_single_threaded: bool = false,87 any_non_single_threaded: bool = false,
89 any_sanitize_thread: bool = false,88 any_sanitize_thread: bool = false,
90 any_fuzz: bool = false,89 any_fuzz: bool = false,
91 any_unwind_tables: std.builtin.UnwindTables = .none,90 any_unwind_tables: bool = false,
92 any_dyn_libs: bool = false,91 any_dyn_libs: bool = false,
93 any_c_source_files: bool = false,92 any_c_source_files: bool = false,
94 any_non_stripped: bool = false,93 any_non_stripped: bool = false,
...@@ -359,12 +358,6 @@ pub fn resolve(options: Options) ResolveError!Config {...@@ -359,12 +358,6 @@ pub fn resolve(options: Options) ResolveError!Config {
359 break :b false;358 break :b false;
360 };359 };
361360
362 const any_unwind_tables = b: {
363 if (options.any_unwind_tables != .none) break :b options.any_unwind_tables;
364
365 break :b target_util.needUnwindTables(target, link_libunwind, options.any_sanitize_thread);
366 };
367
368 const link_mode = b: {361 const link_mode = b: {
369 const explicitly_exe_or_dyn_lib = switch (options.output_mode) {362 const explicitly_exe_or_dyn_lib = switch (options.output_mode) {
370 .Obj => false,363 .Obj => false,
...@@ -496,7 +489,7 @@ pub fn resolve(options: Options) ResolveError!Config {...@@ -496,7 +489,7 @@ pub fn resolve(options: Options) ResolveError!Config {
496 .link_libc = link_libc,489 .link_libc = link_libc,
497 .link_libcpp = link_libcpp,490 .link_libcpp = link_libcpp,
498 .link_libunwind = link_libunwind,491 .link_libunwind = link_libunwind,
499 .any_unwind_tables = any_unwind_tables,492 .any_unwind_tables = options.any_unwind_tables,
500 .any_c_source_files = options.any_c_source_files,493 .any_c_source_files = options.any_c_source_files,
501 .any_non_single_threaded = options.any_non_single_threaded,494 .any_non_single_threaded = options.any_non_single_threaded,
502 .any_error_tracing = any_error_tracing,495 .any_error_tracing = any_error_tracing,
src/Package/Module.zig+12-4
...@@ -112,7 +112,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {...@@ -112,7 +112,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
112 if (options.inherited.sanitize_thread == true) assert(options.global.any_sanitize_thread);112 if (options.inherited.sanitize_thread == true) assert(options.global.any_sanitize_thread);
113 if (options.inherited.fuzz == true) assert(options.global.any_fuzz);113 if (options.inherited.fuzz == true) assert(options.global.any_fuzz);
114 if (options.inherited.single_threaded == false) assert(options.global.any_non_single_threaded);114 if (options.inherited.single_threaded == false) assert(options.global.any_non_single_threaded);
115 if (options.inherited.unwind_tables) |uwt| if (uwt != .none) assert(options.global.any_unwind_tables != .none);115 if (options.inherited.unwind_tables) |uwt| if (uwt != .none) assert(options.global.any_unwind_tables);
116 if (options.inherited.error_tracing == true) assert(options.global.any_error_tracing);116 if (options.inherited.error_tracing == true) assert(options.global.any_error_tracing);
117117
118 const resolved_target = options.inherited.resolved_target orelse options.parent.?.resolved_target;118 const resolved_target = options.inherited.resolved_target orelse options.parent.?.resolved_target;
...@@ -121,9 +121,6 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {...@@ -121,9 +121,6 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
121 const optimize_mode = options.inherited.optimize_mode orelse121 const optimize_mode = options.inherited.optimize_mode orelse
122 if (options.parent) |p| p.optimize_mode else .Debug;122 if (options.parent) |p| p.optimize_mode else .Debug;
123123
124 const unwind_tables = options.inherited.unwind_tables orelse
125 if (options.parent) |p| p.unwind_tables else options.global.any_unwind_tables;
126
127 const strip = b: {124 const strip = b: {
128 if (options.inherited.strip) |x| break :b x;125 if (options.inherited.strip) |x| break :b x;
129 if (options.parent) |p| break :b p.strip;126 if (options.parent) |p| break :b p.strip;
...@@ -220,6 +217,17 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {...@@ -220,6 +217,17 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
220 break :b false;217 break :b false;
221 };218 };
222219
220 const unwind_tables = b: {
221 if (options.inherited.unwind_tables) |x| break :b x;
222 if (options.parent) |p| break :b p.unwind_tables;
223
224 break :b target_util.defaultUnwindTables(
225 target,
226 options.global.link_libunwind,
227 sanitize_thread or options.global.any_sanitize_thread,
228 );
229 };
230
223 const fuzz = b: {231 const fuzz = b: {
224 if (options.inherited.fuzz) |x| break :b x;232 if (options.inherited.fuzz) |x| break :b x;
225 if (options.parent) |p| break :b p.fuzz;233 if (options.parent) |p| break :b p.fuzz;
src/libcxx.zig+6-6
...@@ -397,6 +397,10 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -397,6 +397,10 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
397397
398 const optimize_mode = comp.compilerRtOptMode();398 const optimize_mode = comp.compilerRtOptMode();
399 const strip = comp.compilerRtStrip();399 const strip = comp.compilerRtStrip();
400 // See the `-fno-exceptions` logic for WASI.
401 // The old 32-bit x86 variant of SEH doesn't use tables.
402 const unwind_tables: std.builtin.UnwindTables =
403 if (target.os.tag == .wasi or (target.cpu.arch == .x86 and target.os.tag == .windows)) .none else .@"async";
400404
401 const config = Compilation.Config.resolve(.{405 const config = Compilation.Config.resolve(.{
402 .output_mode = output_mode,406 .output_mode = output_mode,
...@@ -408,6 +412,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -408,6 +412,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
408 .root_optimize_mode = optimize_mode,412 .root_optimize_mode = optimize_mode,
409 .root_strip = strip,413 .root_strip = strip,
410 .link_libc = true,414 .link_libc = true,
415 .any_unwind_tables = unwind_tables != .none,
411 .lto = comp.config.lto,416 .lto = comp.config.lto,
412 .any_sanitize_thread = comp.config.any_sanitize_thread,417 .any_sanitize_thread = comp.config.any_sanitize_thread,
413 }) catch |err| {418 }) catch |err| {
...@@ -438,12 +443,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -438,12 +443,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
438 .valgrind = false,443 .valgrind = false,
439 .optimize_mode = optimize_mode,444 .optimize_mode = optimize_mode,
440 .structured_cfg = comp.root_mod.structured_cfg,445 .structured_cfg = comp.root_mod.structured_cfg,
441 // See the `-fno-exceptions` logic for WASI.446 .unwind_tables = unwind_tables,
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",
447 .pic = comp.root_mod.pic,447 .pic = comp.root_mod.pic,
448 },448 },
449 .global = config,449 .global = config,
src/libunwind.zig+5-2
...@@ -27,6 +27,9 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -27,6 +27,9 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
27 const arena = arena_allocator.allocator();27 const arena = arena_allocator.allocator();
2828
29 const output_mode = .Lib;29 const output_mode = .Lib;
30 const target = comp.root_mod.resolved_target.result;
31 const unwind_tables: std.builtin.UnwindTables =
32 if (target.cpu.arch == .x86 and target.os.tag == .windows) .none else .@"async";
30 const config = Compilation.Config.resolve(.{33 const config = Compilation.Config.resolve(.{
31 .output_mode = .Lib,34 .output_mode = .Lib,
32 .resolved_target = comp.root_mod.resolved_target,35 .resolved_target = comp.root_mod.resolved_target,
...@@ -36,6 +39,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -36,6 +39,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
36 .root_optimize_mode = comp.compilerRtOptMode(),39 .root_optimize_mode = comp.compilerRtOptMode(),
37 .root_strip = comp.compilerRtStrip(),40 .root_strip = comp.compilerRtStrip(),
38 .link_libc = true,41 .link_libc = true,
42 .any_unwind_tables = unwind_tables != .none,
39 .lto = comp.config.lto,43 .lto = comp.config.lto,
40 }) catch |err| {44 }) catch |err| {
41 comp.setMiscFailure(45 comp.setMiscFailure(
...@@ -45,7 +49,6 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -45,7 +49,6 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
45 );49 );
46 return error.SubCompilationFailed;50 return error.SubCompilationFailed;
47 };51 };
48 const target = comp.root_mod.resolved_target.result;
49 const root_mod = Module.create(arena, .{52 const root_mod = Module.create(arena, .{
50 .global_cache_directory = comp.global_cache_directory,53 .global_cache_directory = comp.global_cache_directory,
51 .paths = .{54 .paths = .{
...@@ -65,7 +68,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -65,7 +68,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
65 .sanitize_thread = false,68 .sanitize_thread = false,
66 // necessary so that libunwind can unwind through its own stack frames69 // necessary so that libunwind can unwind through its own stack frames
67 // The old 32-bit x86 variant of SEH doesn't use tables.70 // The old 32-bit x86 variant of SEH doesn't use tables.
68 .unwind_tables = if (target.cpu.arch == .x86 and target.os.tag == .windows) .none else .@"async",71 .unwind_tables = unwind_tables,
69 .pic = if (target_util.supports_fpic(target)) true else null,72 .pic = if (target_util.supports_fpic(target)) true else null,
70 .optimize_mode = comp.compilerRtOptMode(),73 .optimize_mode = comp.compilerRtOptMode(),
71 },74 },
src/main.zig+2-12
...@@ -2849,12 +2849,7 @@ fn buildOutputType(...@@ -2849,12 +2849,7 @@ fn buildOutputType(
2849 create_module.opts.any_fuzz = true;2849 create_module.opts.any_fuzz = true;
2850 if (mod_opts.unwind_tables) |uwt| switch (uwt) {2850 if (mod_opts.unwind_tables) |uwt| switch (uwt) {
2851 .none => {},2851 .none => {},
2852 .sync => if (create_module.opts.any_unwind_tables == .none) {2852 .sync, .@"async" => create_module.opts.any_unwind_tables = true,
2853 create_module.opts.any_unwind_tables = .sync;
2854 },
2855 .@"async" => {
2856 create_module.opts.any_unwind_tables = .@"async";
2857 },
2858 };2853 };
2859 if (mod_opts.strip == false)2854 if (mod_opts.strip == false)
2860 create_module.opts.any_non_stripped = true;2855 create_module.opts.any_non_stripped = true;
...@@ -7566,12 +7561,7 @@ fn handleModArg(...@@ -7566,12 +7561,7 @@ fn handleModArg(
7566 create_module.opts.any_fuzz = true;7561 create_module.opts.any_fuzz = true;
7567 if (mod_opts.unwind_tables) |uwt| switch (uwt) {7562 if (mod_opts.unwind_tables) |uwt| switch (uwt) {
7568 .none => {},7563 .none => {},
7569 .sync => if (create_module.opts.any_unwind_tables == .none) {7564 .sync, .@"async" => create_module.opts.any_unwind_tables = true,
7570 create_module.opts.any_unwind_tables = .sync;
7571 },
7572 .@"async" => {
7573 create_module.opts.any_unwind_tables = .@"async";
7574 },
7575 };7565 };
7576 if (mod_opts.strip == false)7566 if (mod_opts.strip == false)
7577 create_module.opts.any_non_stripped = true;7567 create_module.opts.any_non_stripped = true;
src/target.zig+1-1
...@@ -407,7 +407,7 @@ pub fn clangSupportsNoImplicitFloatArg(target: std.Target) bool {...@@ -407,7 +407,7 @@ pub fn clangSupportsNoImplicitFloatArg(target: std.Target) bool {
407 };407 };
408}408}
409409
410pub fn needUnwindTables(target: std.Target, libunwind: bool, libtsan: bool) std.builtin.UnwindTables {410pub fn defaultUnwindTables(target: std.Target, libunwind: bool, libtsan: bool) std.builtin.UnwindTables {
411 if (target.os.tag == .windows) {411 if (target.os.tag == .windows) {
412 // The old 32-bit x86 variant of SEH doesn't use tables.412 // The old 32-bit x86 variant of SEH doesn't use tables.
413 return if (target.cpu.arch != .x86) .@"async" else .none;413 return if (target.cpu.arch != .x86) .@"async" else .none;