diff --git a/src/Compilation.zig b/src/Compilation.zig index b7cf3c5276..4d4eafba65 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1871,7 +1871,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { try comp.work_queue.writeItem(.libtsan); } - if (comp.getTarget().isMinGW() and !comp.bin_file.options.single_threaded) { + if (comp.getTarget().isMinGW() and comp.config.any_non_single_threaded) { // LLD might drop some symbols as unused during LTO and GCing, therefore, // we force mark them for resolution here. @@ -2418,10 +2418,8 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes try addModuleTableToCacheHash(gpa, arena, &man.hash, mod.main_mod, .{ .files = man }); // Synchronize with other matching comments: ZigOnlyHashStuff - man.hash.add(comp.bin_file.options.valgrind); - man.hash.add(comp.bin_file.options.single_threaded); - man.hash.add(comp.bin_file.options.use_llvm); - man.hash.add(comp.bin_file.options.use_lib_llvm); + man.hash.add(comp.config.use_llvm); + man.hash.add(comp.config.use_lib_llvm); man.hash.add(comp.bin_file.options.dll_export_fns); man.hash.add(comp.bin_file.options.is_test); man.hash.add(comp.test_evented_io); @@ -4922,7 +4920,7 @@ pub fn addCCArgs( try argv.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS"); try argv.append("-D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS"); - if (comp.bin_file.options.single_threaded) { + if (!comp.config.any_non_single_threaded) { try argv.append("-D_LIBCPP_HAS_NO_THREADS"); } diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 33b9bab40b..0e379212cc 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -7,6 +7,8 @@ link_libc: bool, link_libcpp: bool, link_libunwind: bool, any_unwind_tables: bool, +any_c_source_files: bool, +any_non_single_threaded: bool, pie: bool, /// If this is true then linker code is responsible for making an LLVM IR /// Module, outputting it to an object file, and then linking that together @@ -31,7 +33,6 @@ shared_memory: bool, is_test: bool, test_evented_io: bool, entry: ?[]const u8, -any_c_source_files: bool, pub const CFrontend = enum { clang, aro }; @@ -374,6 +375,8 @@ pub fn resolve(options: Options) !Config { .link_libcpp = link_libcpp, .link_libunwind = link_libunwind, .any_unwind_tables = any_unwind_tables, + .any_c_source_files = options.any_c_source_files, + .any_non_single_threaded = options.any_non_single_threaded, .pie = pie, .lto = lto, .import_memory = import_memory, @@ -385,7 +388,6 @@ pub fn resolve(options: Options) !Config { .use_lld = use_lld, .entry = entry, .wasi_exec_model = wasi_exec_model, - .any_c_source_files = options.any_c_source_files, }; } diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index aa6c2dea79..e0be273c26 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -7724,10 +7724,13 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airFence(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { + const zcu = func.bin_file.base.comp.module.?; // Only when the atomic feature is enabled, and we're not building // for a single-threaded build, can we emit the `fence` instruction. // In all other cases, we emit no instructions for a fence. - if (func.useAtomicFeature() and !func.bin_file.base.options.single_threaded) { + const func_namespace = zcu.namespacePtr(zcu.declPtr(func.decl).namespace); + const single_threaded = func_namespace.file_scope.mod.single_threaded; + if (func.useAtomicFeature() and !single_threaded) { try func.addAtomicTag(.atomic_fence); } diff --git a/src/codegen.zig b/src/codegen.zig index b464a9f365..5efde3985c 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -942,7 +942,9 @@ fn genDeclRef( try mod.markDeclAlive(decl); - const is_threadlocal = tv.val.isPtrToThreadLocal(mod) and !bin_file.options.single_threaded; + const decl_namespace = mod.namespacePtr(decl.namespace_index); + const single_threaded = decl_namespace.file_scope.mod.single_threaded; + const is_threadlocal = tv.val.isPtrToThreadLocal(mod) and !single_threaded; const is_extern = decl.isExtern(mod); if (bin_file.cast(link.File.Elf)) |elf_file| { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 57e5770d89..a072c6a069 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1591,8 +1591,10 @@ pub const Object = struct { var di_file: ?if (build_options.have_llvm) *llvm.DIFile else noreturn = null; var di_scope: ?if (build_options.have_llvm) *llvm.DIScope else noreturn = null; + const namespace = mod.namespacePtr(decl.src_namespace); + if (o.di_builder) |dib| { - di_file = try o.getDIFile(gpa, mod.namespacePtr(decl.src_namespace).file_scope); + di_file = try o.getDIFile(gpa, namespace.file_scope); const line_number = decl.src_line + 1; const is_internal_linkage = decl.val.getExternFunc(mod) == null and @@ -1623,6 +1625,8 @@ pub const Object = struct { di_scope = subprogram.toScope(); } + const single_threaded = namespace.file_scope.mod.single_threaded; + var fg: FuncGen = .{ .gpa = gpa, .air = air, @@ -1634,7 +1638,7 @@ pub const Object = struct { .arg_index = 0, .func_inst_table = .{}, .blocks = .{}, - .sync_scope = if (mod.comp.bin_file.options.single_threaded) .singlethread else .system, + .sync_scope = if (single_threaded) .singlethread else .system, .di_scope = di_scope, .di_file = di_file, .base_line = dg.decl.src_line, @@ -1788,8 +1792,10 @@ pub const Object = struct { if (mod.wantDllExports()) global_index.setDllStorageClass(.default, &self.builder); global_index.setUnnamedAddr(.unnamed_addr, &self.builder); if (decl.val.getVariable(mod)) |decl_var| { + const decl_namespace = mod.namespacePtr(decl.namespace_index); + const single_threaded = decl_namespace.file_scope.mod.single_threaded; global_index.ptrConst(&self.builder).kind.variable.setThreadLocal( - if (decl_var.is_threadlocal and !mod.comp.bin_file.options.single_threaded) + if (decl_var.is_threadlocal and !single_threaded) .generaldynamic else .default, @@ -3176,7 +3182,8 @@ pub const Object = struct { variable_index.setLinkage(.external, &o.builder); variable_index.setUnnamedAddr(.default, &o.builder); if (decl.val.getVariable(mod)) |decl_var| { - const single_threaded = mod.comp.bin_file.options.single_threaded; + const decl_namespace = mod.namespacePtr(decl.namespace_index); + const single_threaded = decl_namespace.file_scope.mod.single_threaded; variable_index.setThreadLocal( if (decl_var.is_threadlocal and !single_threaded) .generaldynamic else .default, &o.builder, diff --git a/src/libcxx.zig b/src/libcxx.zig index 19c1d25b8c..8ae7db80f1 100644 --- a/src/libcxx.zig +++ b/src/libcxx.zig @@ -154,7 +154,7 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: *std.Progress.Node) !void { continue; if (std.mem.startsWith(u8, cxx_src, "src/support/ibm/") and target.os.tag != .zos) continue; - if (comp.bin_file.options.single_threaded) { + if (!comp.config.any_non_single_threaded) { if (std.mem.startsWith(u8, cxx_src, "src/support/win32/thread_win32.cpp")) { continue; } @@ -332,7 +332,7 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: *std.Progress.Node) !void { } // WASM targets are single threaded. - if (comp.bin_file.options.single_threaded) { + if (!comp.config.any_non_single_threaded) { if (std.mem.startsWith(u8, cxxabi_src, "src/cxa_thread_atexit.cpp")) { continue; } diff --git a/src/libunwind.zig b/src/libunwind.zig index f0330a4e51..876bd7a31f 100644 --- a/src/libunwind.zig +++ b/src/libunwind.zig @@ -67,7 +67,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { if (comp.bin_file.options.optimize_mode == .Debug) { try cflags.append("-D_DEBUG"); } - if (comp.bin_file.options.single_threaded) { + if (!comp.config.any_non_single_threaded) { try cflags.append("-D_LIBUNWIND_HAS_NO_THREADS"); } if (target.cpu.arch.isARM() and target.abi.floatAbi() == .hard) { diff --git a/src/link/MachO.zig b/src/link/MachO.zig index c1d7eef652..3da076ba56 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -267,7 +267,10 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO { }); try self.strtab.buffer.append(gpa, 0); - try self.populateMissingMetadata(); + try self.populateMissingMetadata(.{ + .symbol_count_hint = options.symbol_count_hint, + .program_code_size_hint = options.program_code_size_hint, + }); if (self.d_sym) |*d_sym| { try d_sym.populateMissingMetadata(self); @@ -1704,7 +1707,8 @@ pub fn createDsoHandleSymbol(self: *MachO) !void { } pub fn resolveSymbols(self: *MachO) !void { - const output_mode = self.base.comp.config.output_mode; + const comp = self.base.comp; + const output_mode = comp.config.output_mode; // We add the specified entrypoint as the first unresolved symbols so that // we search for it in libraries should there be no object files specified // on the linker line. @@ -1729,7 +1733,7 @@ pub fn resolveSymbols(self: *MachO) !void { if (self.unresolved.count() > 0 and self.dyld_stub_binder_index == null) { self.dyld_stub_binder_index = try self.addUndefined("dyld_stub_binder", .{ .add_got = true }); } - if (!self.base.options.single_threaded and self.mode == .incremental) { + if (comp.config.any_non_single_threaded and self.mode == .incremental) { _ = try self.addUndefined("__tlv_bootstrap", .{}); } @@ -2436,7 +2440,8 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex) const tracy = trace(@src()); defer tracy.end(); - const gpa = self.base.comp.gpa; + const comp = self.base.comp; + const gpa = comp.gpa; const decl = mod.declPtr(decl_index); if (decl.val.getExternFunc(mod)) |_| { @@ -2453,7 +2458,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex) } const is_threadlocal = if (decl.val.getVariable(mod)) |variable| - variable.is_threadlocal and !self.base.options.single_threaded + variable.is_threadlocal and comp.config.any_non_single_threaded else false; if (is_threadlocal) return self.updateThreadlocalVariable(mod, decl_index); @@ -3129,11 +3134,17 @@ pub fn getAnonDeclVAddr(self: *MachO, decl_val: InternPool.Index, reloc_info: li return 0; } -fn populateMissingMetadata(self: *MachO) !void { +const PopulateMissingMetadataOptions = struct { + symbol_count_hint: u64, + program_code_size_hint: u64, +}; + +fn populateMissingMetadata(self: *MachO, options: PopulateMissingMetadataOptions) !void { assert(self.mode == .incremental); - const gpa = self.base.comp.gpa; - const target = self.base.comp.root_mod.resolved_target.result; + const comp = self.base.comp; + const gpa = comp.gpa; + const target = comp.root_mod.resolved_target.result; const cpu_arch = target.cpu.arch; const pagezero_vmsize = self.calcPagezeroSize(); @@ -3171,7 +3182,7 @@ fn populateMissingMetadata(self: *MachO) !void { if (self.text_section_index == null) { // Sadly, segments need unique string identfiers for some reason. self.text_section_index = try self.allocateSection("__TEXT1", "__text", .{ - .size = self.base.options.program_code_size_hint, + .size = options.program_code_size_hint, .alignment = switch (cpu_arch) { .x86_64 => 1, .aarch64 => @sizeOf(u32), @@ -3207,7 +3218,7 @@ fn populateMissingMetadata(self: *MachO) !void { if (self.got_section_index == null) { self.got_section_index = try self.allocateSection("__DATA_CONST", "__got", .{ - .size = @sizeOf(u64) * self.base.options.symbol_count_hint, + .size = @sizeOf(u64) * options.symbol_count_hint, .alignment = @alignOf(u64), .flags = macho.S_NON_LAZY_SYMBOL_POINTERS, .prot = macho.PROT.READ | macho.PROT.WRITE, @@ -3245,7 +3256,7 @@ fn populateMissingMetadata(self: *MachO) !void { self.segment_table_dirty = true; } - if (!self.base.options.single_threaded) { + if (comp.config.any_non_single_threaded) { if (self.thread_vars_section_index == null) { self.thread_vars_section_index = try self.allocateSection("__DATA2", "__thread_vars", .{ .size = @sizeOf(u64) * 3,