authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-12-14 16:41:20-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-01 17:51:19-07:00
logf54471b54c471bb6f8e51a1383be09d01c24d0c3
tree63b869ef277027fc0f21e4789b953d9d2e421e68
parent769dea6e37ffef32f0972a0b958ff2ea38db6854

compiler: miscellaneous branch progress

implement builtin.zig file population for all modules rather than assuming there is only one global builtin.zig module. move some fields from link.File to Compilation move some fields from Module to Compilation compute debug_format in global Compilation config resolution wire up C compilation to the concept of owner modules make whole cache mode call link.File.createEmpty() instead of link.File.open()

21 files changed, 457 insertions(+), 336 deletions(-)

src/Builtin.zig+60-2
......@@ -20,8 +20,11 @@ wasi_exec_model: std.builtin.WasiExecModel,
2020
2121pub fn generate(opts: @This(), allocator: Allocator) Allocator.Error![:0]u8 {
2222 var buffer = std.ArrayList(u8).init(allocator);
23 defer buffer.deinit();
23 try append(opts, &buffer);
24 return buffer.toOwnedSliceSentinel(0);
25}
2426
27pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
2528 const target = opts.target;
2629 const generic_arch_name = target.cpu.arch.genericName();
2730 const zig_backend = opts.zig_backend;
......@@ -231,10 +234,65 @@ pub fn generate(opts: @This(), allocator: Allocator) Allocator.Error![:0]u8 {
231234 );
232235 }
233236 }
237}
234238
235 return buffer.toOwnedSliceSentinel(0);
239pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void {
240 assert(file.source_loaded == true);
241
242 if (mod.root.statFile(mod.root_src_path)) |stat| {
243 if (stat.size != file.source.len) {
244 std.log.warn(
245 "the cached file '{}{s}' had the wrong size. Expected {d}, found {d}. " ++
246 "Overwriting with correct file contents now",
247 .{ mod.root, mod.root_src_path, file.source.len, stat.size },
248 );
249
250 try writeFile(file, mod);
251 } else {
252 file.stat = .{
253 .size = stat.size,
254 .inode = stat.inode,
255 .mtime = stat.mtime,
256 };
257 }
258 } else |err| switch (err) {
259 error.BadPathName => unreachable, // it's always "builtin.zig"
260 error.NameTooLong => unreachable, // it's always "builtin.zig"
261 error.PipeBusy => unreachable, // it's not a pipe
262 error.WouldBlock => unreachable, // not asking for non-blocking I/O
263
264 error.FileNotFound => try writeFile(file, mod),
265
266 else => |e| return e,
267 }
268
269 file.tree = try std.zig.Ast.parse(comp.gpa, file.source, .zig);
270 file.tree_loaded = true;
271 assert(file.tree.errors.len == 0); // builtin.zig must parse
272
273 file.zir = try AstGen.generate(comp.gpa, file.tree);
274 file.zir_loaded = true;
275 file.status = .success_zir;
276}
277
278fn writeFile(file: *File, mod: *Module) !void {
279 var af = try mod.root.atomicFile(mod.root_src_path, .{});
280 defer af.deinit();
281 try af.file.writeAll(file.source);
282 try af.finish();
283
284 file.stat = .{
285 .size = file.source.len,
286 .inode = 0, // dummy value
287 .mtime = 0, // dummy value
288 };
236289}
237290
238291const std = @import("std");
239292const Allocator = std.mem.Allocator;
240293const build_options = @import("build_options");
294const Module = @import("Package/Module.zig");
295const assert = std.debug.assert;
296const AstGen = @import("AstGen.zig");
297const File = @import("Module.zig").File;
298const Compilation = @import("Compilation.zig");
src/Compilation.zig+103-80
......@@ -37,6 +37,7 @@ const Zir = @import("Zir.zig");
3737const Autodoc = @import("Autodoc.zig");
3838const Color = @import("main.zig").Color;
3939const resinator = @import("resinator.zig");
40const Builtin = @import("Builtin.zig");
4041
4142pub const Config = @import("Compilation/Config.zig");
4243
......@@ -59,7 +60,10 @@ root_mod: *Package.Module,
5960/// User-specified settings that have all the defaults resolved into concrete values.
6061config: Config,
6162
62/// This is `null` when `-fno-emit-bin` is used.
63/// The main output file.
64/// In whole cache mode, this is null except for during the body of the update
65/// function. In incremental cache mode, this is a long-lived object.
66/// In both cases, this is `null` when `-fno-emit-bin` is used.
6367bin_file: ?*link.File,
6468
6569/// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin)
......@@ -80,6 +84,8 @@ version: ?std.SemanticVersion,
8084libc_installation: ?*const LibCInstallation,
8185skip_linker_dependencies: bool,
8286no_builtin: bool,
87function_sections: bool,
88data_sections: bool,
8389
8490c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},
8591win32_resource_table: if (build_options.only_core_functionality) void else std.AutoArrayHashMapUnmanaged(*Win32Resource, void) =
......@@ -120,7 +126,6 @@ failed_win32_resources: if (build_options.only_core_functionality) void else std
120126/// Miscellaneous things that can fail.
121127misc_failures: std.AutoArrayHashMapUnmanaged(MiscTask, MiscError) = .{},
122128
123keep_source_files_loaded: bool,
124129/// When this is `true` it means invoking clang as a sub-process is expected to inherit
125130/// stdin, stdout, stderr, and if it returns non success, to forward the exit code.
126131/// Otherwise we attempt to parse the error messages and expose them via the Compilation API.
......@@ -144,6 +149,7 @@ debug_compiler_runtime_libs: bool,
144149debug_compile_errors: bool,
145150job_queued_compiler_rt_lib: bool = false,
146151job_queued_compiler_rt_obj: bool = false,
152job_queued_update_builtin_zig: bool,
147153alloc_failure_occurred: bool = false,
148154formatted_panics: bool = false,
149155last_update_was_cache_hit: bool = false,
......@@ -814,13 +820,13 @@ pub const cache_helpers = struct {
814820 addEmitLoc(hh, optional_emit_loc orelse return);
815821 }
816822
817 pub fn addOptionalDebugFormat(hh: *Cache.HashHelper, x: ?link.File.DebugFormat) void {
823 pub fn addOptionalDebugFormat(hh: *Cache.HashHelper, x: ?Config.DebugFormat) void {
818824 hh.add(x != null);
819825 addDebugFormat(hh, x orelse return);
820826 }
821827
822 pub fn addDebugFormat(hh: *Cache.HashHelper, x: link.File.DebugFormat) void {
823 const tag: @typeInfo(link.File.DebugFormat).Union.tag_type.? = x;
828 pub fn addDebugFormat(hh: *Cache.HashHelper, x: Config.DebugFormat) void {
829 const tag: @typeInfo(Config.DebugFormat).Union.tag_type.? = x;
824830 hh.add(tag);
825831 switch (x) {
826832 .strip, .code_view => {},
......@@ -860,11 +866,11 @@ pub const SystemLib = link.SystemLib;
860866
861867pub const CacheMode = enum { incremental, whole };
862868
863pub const CacheUse = union(CacheMode) {
869const CacheUse = union(CacheMode) {
864870 incremental: *Incremental,
865871 whole: *Whole,
866872
867 pub const Whole = struct {
873 const Whole = struct {
868874 /// This is a pointer to a local variable inside `update()`.
869875 cache_manifest: ?*Cache.Manifest = null,
870876 cache_manifest_mutex: std.Thread.Mutex = .{},
......@@ -873,12 +879,14 @@ pub const CacheUse = union(CacheMode) {
873879 /// of exactly the correct size for "o/[digest]/[basename]".
874880 /// The basename is of the outputted binary file in case we don't know the directory yet.
875881 bin_sub_path: ?[]u8,
876 /// Same as `whole_bin_sub_path` but for implibs.
882 /// Same as `bin_sub_path` but for implibs.
877883 implib_sub_path: ?[]u8,
878884 docs_sub_path: ?[]u8,
885 lf_open_opts: link.File.OpenOptions,
886 tmp_artifact_directory: ?Cache.Directory,
879887 };
880888
881 pub const Incremental = struct {
889 const Incremental = struct {
882890 /// Where build artifacts and incremental compilation metadata serialization go.
883891 artifact_directory: Compilation.Directory,
884892 };
......@@ -937,7 +945,6 @@ pub const InitOptions = struct {
937945 /// this flag would be set to disable this machinery to avoid false positives.
938946 disable_lld_caching: bool = false,
939947 cache_mode: CacheMode = .incremental,
940 keep_source_files_loaded: bool = false,
941948 lib_dirs: []const []const u8 = &[0][]const u8{},
942949 rpath_list: []const []const u8 = &[0][]const u8{},
943950 symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{},
......@@ -1040,7 +1047,6 @@ pub const InitOptions = struct {
10401047 test_name_prefix: ?[]const u8 = null,
10411048 test_runner_path: ?[]const u8 = null,
10421049 subsystem: ?std.Target.SubSystem = null,
1043 debug_format: ?link.File.DebugFormat = null,
10441050 /// (Zig compiler development) Enable dumping linker's state as JSON.
10451051 enable_link_snapshots: bool = false,
10461052 /// (Darwin) Install name of the dylib
......@@ -1327,7 +1333,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
13271333 cache.hash.add(options.config.link_libcpp);
13281334 cache.hash.add(options.config.link_libunwind);
13291335 cache.hash.add(output_mode);
1330 cache_helpers.addOptionalDebugFormat(&cache.hash, options.debug_format);
1336 cache_helpers.addDebugFormat(&cache.hash, comp.config.debug_format);
13311337 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_bin);
13321338 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_implib);
13331339 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs);
......@@ -1380,7 +1386,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
13801386 };
13811387 errdefer if (opt_zcu) |zcu| zcu.deinit();
13821388
1383 const system_libs = try std.StringArrayHashMapUnmanaged(SystemLib).init(
1389 var system_libs = try std.StringArrayHashMapUnmanaged(SystemLib).init(
13841390 gpa,
13851391 options.system_lib_names,
13861392 options.system_lib_infos,
......@@ -1409,7 +1415,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
14091415 .win32_resource_work_queue = if (build_options.only_core_functionality) {} else std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa),
14101416 .astgen_work_queue = std.fifo.LinearFifo(*Module.File, .Dynamic).init(gpa),
14111417 .embed_file_work_queue = std.fifo.LinearFifo(*Module.EmbedFile, .Dynamic).init(gpa),
1412 .keep_source_files_loaded = options.keep_source_files_loaded,
14131418 .c_source_files = options.c_source_files,
14141419 .rc_source_files = options.rc_source_files,
14151420 .cache_parent = cache,
......@@ -1451,10 +1456,12 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
14511456 .llvm_opt_bisect_limit = options.llvm_opt_bisect_limit,
14521457 .skip_linker_dependencies = options.skip_linker_dependencies,
14531458 .no_builtin = options.no_builtin,
1459 .job_queued_update_builtin_zig = have_zcu,
1460 .function_sections = options.function_sections,
1461 .data_sections = options.data_sections,
14541462 };
14551463
14561464 const lf_open_opts: link.File.OpenOptions = .{
1457 .comp = comp,
14581465 .linker_script = options.linker_script,
14591466 .z_nodelete = options.linker_z_nodelete,
14601467 .z_notext = options.linker_z_notext,
......@@ -1471,8 +1478,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
14711478 .lib_dirs = options.lib_dirs,
14721479 .rpath_list = options.rpath_list,
14731480 .symbol_wrap_set = options.symbol_wrap_set,
1474 .function_sections = options.function_sections,
1475 .data_sections = options.data_sections,
14761481 .allow_shlib_undefined = options.linker_allow_shlib_undefined,
14771482 .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,
14781483 .compress_debug_sections = options.linker_compress_debug_sections orelse .none,
......@@ -1507,7 +1512,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
15071512 .build_id = build_id,
15081513 .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole,
15091514 .subsystem = options.subsystem,
1510 .debug_format = options.debug_format,
15111515 .hash_style = options.hash_style,
15121516 .enable_link_snapshots = options.enable_link_snapshots,
15131517 .install_name = options.install_name,
......@@ -1572,17 +1576,17 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
15721576 .directory = emit_bin.directory orelse artifact_directory,
15731577 .sub_path = emit_bin.basename,
15741578 };
1575 comp.bin_file = try link.File.open(arena, emit, lf_open_opts);
1579 comp.bin_file = try link.File.open(arena, comp, emit, lf_open_opts);
15761580 }
15771581
1578 if (options.implib_emit) |emit_implib| {
1582 if (options.emit_implib) |emit_implib| {
15791583 comp.implib_emit = .{
15801584 .directory = emit_implib.directory orelse artifact_directory,
15811585 .sub_path = emit_implib.basename,
15821586 };
15831587 }
15841588
1585 if (options.docs_emit) |emit_docs| {
1589 if (options.emit_docs) |emit_docs| {
15861590 comp.docs_emit = .{
15871591 .directory = emit_docs.directory orelse artifact_directory,
15881592 .sub_path = emit_docs.basename,
......@@ -1610,6 +1614,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
16101614 .bin_sub_path = try prepareWholeEmitSubPath(arena, options.emit_bin),
16111615 .implib_sub_path = try prepareWholeEmitSubPath(arena, options.emit_implib),
16121616 .docs_sub_path = try prepareWholeEmitSubPath(arena, options.emit_docs),
1617 .tmp_artifact_directory = null,
16131618 };
16141619 comp.cache_use = .{ .whole = whole };
16151620 },
......@@ -1662,7 +1667,10 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
16621667 }
16631668 }
16641669
1665 const have_bin_emit = comp.bin_file != null or comp.whole_bin_sub_path != null;
1670 const have_bin_emit = switch (comp.cache_use) {
1671 .whole => |whole| whole.bin_sub_path != null,
1672 .incremental => comp.bin_file != null,
1673 };
16661674
16671675 if (have_bin_emit and !comp.skip_linker_dependencies and target.ofmt != .c) {
16681676 if (target.isDarwin()) {
......@@ -1814,8 +1822,13 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
18141822pub fn destroy(self: *Compilation) void {
18151823 if (self.bin_file) |lf| lf.destroy();
18161824 if (self.module) |zcu| zcu.deinit();
1825 switch (self.cache_use) {
1826 .incremental => |incremental| {
1827 incremental.artifact_directory.handle.close();
1828 },
1829 .whole => {},
1830 }
18171831
1818 const gpa = self.gpa;
18191832 self.work_queue.deinit();
18201833 self.anon_work_queue.deinit();
18211834 self.c_object_work_queue.deinit();
......@@ -1825,6 +1838,9 @@ pub fn destroy(self: *Compilation) void {
18251838 self.astgen_work_queue.deinit();
18261839 self.embed_file_work_queue.deinit();
18271840
1841 const gpa = self.gpa;
1842 self.system_libs.deinit(gpa);
1843
18281844 {
18291845 var it = self.crt_files.iterator();
18301846 while (it.next()) |entry| {
......@@ -1914,7 +1930,7 @@ pub fn hotCodeSwap(comp: *Compilation, prog_node: *std.Progress.Node, pid: std.C
19141930}
19151931
19161932fn cleanupAfterUpdate(comp: *Compilation) void {
1917 switch (comp) {
1933 switch (comp.cache_use) {
19181934 .incremental => return,
19191935 .whole => |whole| {
19201936 if (whole.cache_manifest) |man| {
......@@ -1971,7 +1987,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
19711987 log.debug("CacheMode.whole cache hit for {s}", .{comp.root_name});
19721988 const digest = man.final();
19731989
1974 comp.wholeCacheModeSetBinFilePath(&digest);
1990 comp.wholeCacheModeSetBinFilePath(whole, &digest);
19751991
19761992 assert(comp.bin_file.lock == null);
19771993 comp.bin_file.lock = man.toOwnedLock();
......@@ -2001,21 +2017,21 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
20012017 // Now that the directory is known, it is time to create the Emit
20022018 // objects and call link.File.open.
20032019
2004 if (comp.whole_implib_sub_path) |sub_path| {
2020 if (whole.implib_sub_path) |sub_path| {
20052021 comp.implib_emit = .{
20062022 .directory = tmp_artifact_directory,
20072023 .sub_path = std.fs.path.basename(sub_path),
20082024 };
20092025 }
20102026
2011 if (comp.whole_docs_sub_path) |sub_path| {
2027 if (whole.docs_sub_path) |sub_path| {
20122028 comp.docs_emit = .{
20132029 .directory = tmp_artifact_directory,
20142030 .sub_path = std.fs.path.basename(sub_path),
20152031 };
20162032 }
20172033
2018 if (comp.whole_bin_sub_path) |sub_path| {
2034 if (whole.bin_sub_path) |sub_path| {
20192035 const emit: Emit = .{
20202036 .directory = tmp_artifact_directory,
20212037 .sub_path = std.fs.path.basename(sub_path),
......@@ -2024,7 +2040,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
20242040 // but in practice it won't leak much and usually whole cache mode
20252041 // will be combined with exactly one call to update().
20262042 const arena = comp.arena.allocator();
2027 comp.bin_file = try link.File.open(arena, emit, whole.lf_open_opts);
2043 comp.bin_file = try link.File.createEmpty(arena, comp, emit, whole.lf_open_opts);
20282044 }
20292045 },
20302046 .incremental => {},
......@@ -2158,7 +2174,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
21582174 const o_sub_path = "o" ++ s ++ digest;
21592175
21602176 try renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path);
2161 comp.wholeCacheModeSetBinFilePath(&digest);
2177 comp.wholeCacheModeSetBinFilePath(whole, &digest);
21622178
21632179 // Failure here only means an unnecessary cache miss.
21642180 man.writeManifest() catch |err| {
......@@ -2170,19 +2186,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
21702186 },
21712187 .incremental => {},
21722188 }
2173
2174 // Unload all source files to save memory.
2175 // The ZIR needs to stay loaded in memory because (1) Decl objects contain references
2176 // to it, and (2) generic instantiations, comptime calls, inline calls will need
2177 // to reference the ZIR.
2178 if (!comp.keep_source_files_loaded) {
2179 if (comp.module) |module| {
2180 for (module.import_table.values()) |file| {
2181 file.unloadTree(comp.gpa);
2182 file.unloadSource(comp.gpa);
2183 }
2184 }
2185 }
21862189}
21872190
21882191/// This function is called by the frontend before flush(). It communicates that
......@@ -2274,10 +2277,14 @@ fn flush(comp: *Compilation, prog_node: *std.Progress.Node) !void {
22742277}
22752278
22762279/// Communicate the output binary location to parent Compilations.
2277fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_digest_len]u8) void {
2280fn wholeCacheModeSetBinFilePath(
2281 comp: *Compilation,
2282 whole: *CacheUse.Whole,
2283 digest: *const [Cache.hex_digest_len]u8,
2284) void {
22782285 const digest_start = 2; // "o/[digest]/[basename]"
22792286
2280 if (comp.whole_bin_sub_path) |sub_path| {
2287 if (whole.bin_sub_path) |sub_path| {
22812288 @memcpy(sub_path[digest_start..][0..digest.len], digest);
22822289
22832290 comp.bin_file.?.emit = .{
......@@ -2286,7 +2293,7 @@ fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_di
22862293 };
22872294 }
22882295
2289 if (comp.whole_implib_sub_path) |sub_path| {
2296 if (whole.implib_sub_path) |sub_path| {
22902297 @memcpy(sub_path[digest_start..][0..digest.len], digest);
22912298
22922299 comp.implib_emit = .{
......@@ -2295,7 +2302,7 @@ fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_di
22952302 };
22962303 }
22972304
2298 if (comp.whole_docs_sub_path) |sub_path| {
2305 if (whole.docs_sub_path) |sub_path| {
22992306 @memcpy(sub_path[digest_start..][0..digest.len], digest);
23002307
23012308 comp.docs_emit = .{
......@@ -3232,13 +3239,25 @@ pub fn performAllTheWork(
32323239 // 1. to avoid race condition of zig processes truncating each other's builtin.zig files
32333240 // 2. optimization; in the hot path it only incurs a stat() syscall, which happens
32343241 // in the `astgen_wait_group`.
3235 if (comp.module) |mod| {
3236 if (mod.job_queued_update_builtin_zig) {
3237 mod.job_queued_update_builtin_zig = false;
3242 if (comp.job_queued_update_builtin_zig) b: {
3243 comp.job_queued_update_builtin_zig = false;
3244 const zcu = comp.module orelse break :b;
3245 _ = zcu;
3246 // TODO put all the modules in a flat array to make them easy to iterate.
3247 var seen: std.AutoArrayHashMapUnmanaged(*Package.Module, void) = .{};
3248 defer seen.deinit(comp.gpa);
3249 try seen.put(comp.gpa, comp.root_mod);
3250 var i: usize = 0;
3251 while (i < seen.count()) : (i += 1) {
3252 const mod = seen.keys()[i];
3253 for (mod.deps.values()) |dep|
3254 try seen.put(comp.gpa, dep);
3255
3256 const file = mod.builtin_file orelse continue;
32383257
32393258 comp.astgen_wait_group.start();
32403259 try comp.thread_pool.spawn(workerUpdateBuiltinZigFile, .{
3241 comp, mod, &comp.astgen_wait_group,
3260 comp, mod, file, &comp.astgen_wait_group,
32423261 });
32433262 }
32443263 }
......@@ -3702,19 +3721,17 @@ fn workerAstGenFile(
37023721
37033722fn workerUpdateBuiltinZigFile(
37043723 comp: *Compilation,
3705 mod: *Module,
3724 mod: *Package.Module,
3725 file: *Module.File,
37063726 wg: *WaitGroup,
37073727) void {
37083728 defer wg.finish();
3709
3710 mod.populateBuiltinFile() catch |err| {
3711 const dir_path: []const u8 = mod.zig_cache_artifact_directory.path orelse ".";
3712
3729 Builtin.populateFile(comp, mod, file) catch |err| {
37133730 comp.mutex.lock();
37143731 defer comp.mutex.unlock();
37153732
3716 comp.setMiscFailure(.write_builtin_zig, "unable to write builtin.zig to {s}: {s}", .{
3717 dir_path, @errorName(err),
3733 comp.setMiscFailure(.write_builtin_zig, "unable to write '{}{s}': {s}", .{
3734 mod.root, mod.root_src_path, @errorName(err),
37183735 });
37193736 };
37203737}
......@@ -3755,14 +3772,17 @@ fn detectEmbedFileUpdate(comp: *Compilation, embed_file: *Module.EmbedFile) !voi
37553772 @panic("TODO: handle embed file incremental update");
37563773}
37573774
3758pub fn obtainCObjectCacheManifest(comp: *const Compilation) Cache.Manifest {
3775pub fn obtainCObjectCacheManifest(
3776 comp: *const Compilation,
3777 owner_mod: *Package.Module,
3778) Cache.Manifest {
37593779 var man = comp.cache_parent.obtain();
37603780
37613781 // Only things that need to be added on top of the base hash, and only things
37623782 // that apply both to @cImport and compiling C objects. No linking stuff here!
37633783 // Also nothing that applies only to compiling .zig code.
3764 man.hash.add(comp.sanitize_c);
3765 man.hash.addListOfBytes(comp.clang_argv);
3784 man.hash.add(owner_mod.sanitize_c);
3785 man.hash.addListOfBytes(owner_mod.clang_argv);
37663786 man.hash.add(comp.config.link_libcpp);
37673787
37683788 // When libc_installation is null it means that Zig generated this dir list
......@@ -3797,19 +3817,19 @@ pub const CImportResult = struct {
37973817/// Caller owns returned memory.
37983818/// This API is currently coupled pretty tightly to stage1's needs; it will need to be reworked
37993819/// a bit when we want to start using it from self-hosted.
3800pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
3820pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module) !CImportResult {
38013821 if (build_options.only_core_functionality) @panic("@cImport is not available in a zig2.c build");
38023822 const tracy_trace = trace(@src());
38033823 defer tracy_trace.end();
38043824
38053825 const cimport_zig_basename = "cimport.zig";
38063826
3807 var man = comp.obtainCObjectCacheManifest();
3827 var man = comp.obtainCObjectCacheManifest(owner_mod);
38083828 defer man.deinit();
38093829
38103830 man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects
38113831 man.hash.addBytes(c_src);
3812 man.hash.add(comp.c_frontend);
3832 man.hash.add(comp.config.c_frontend);
38133833
38143834 // If the previous invocation resulted in clang errors, we will see a hit
38153835 // here with 0 files in the manifest, in which case it is actually a miss.
......@@ -3846,15 +3866,15 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
38463866 var argv = std.ArrayList([]const u8).init(comp.gpa);
38473867 defer argv.deinit();
38483868
3849 try argv.append(@tagName(comp.c_frontend)); // argv[0] is program name, actual args start at [1]
3850 try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path);
3869 try argv.append(@tagName(comp.config.c_frontend)); // argv[0] is program name, actual args start at [1]
3870 try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path, owner_mod);
38513871
38523872 try argv.append(out_h_path);
38533873
38543874 if (comp.verbose_cc) {
38553875 dump_argv(argv.items);
38563876 }
3857 var tree = switch (comp.c_frontend) {
3877 var tree = switch (comp.config.c_frontend) {
38583878 .aro => tree: {
38593879 const translate_c = @import("aro_translate_c.zig");
38603880 _ = translate_c;
......@@ -4119,7 +4139,7 @@ fn reportRetryableEmbedFileError(
41194139}
41204140
41214141fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.Progress.Node) !void {
4122 if (comp.c_frontend == .aro) {
4142 if (comp.config.c_frontend == .aro) {
41234143 return comp.failCObj(c_object, "aro does not support compiling C objects yet", .{});
41244144 }
41254145 if (!build_options.have_llvm) {
......@@ -4142,7 +4162,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
41424162 _ = comp.failed_c_objects.swapRemove(c_object);
41434163 }
41444164
4145 var man = comp.obtainCObjectCacheManifest();
4165 var man = comp.obtainCObjectCacheManifest(c_object.src.owner);
41464166 defer man.deinit();
41474167
41484168 man.hash.add(comp.clang_preprocessor_mode);
......@@ -4219,7 +4239,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
42194239 if (std.process.can_execv and direct_o and
42204240 comp.disable_c_depfile and comp.clang_passthrough_mode)
42214241 {
4222 try comp.addCCArgs(arena, &argv, ext, null);
4242 try comp.addCCArgs(arena, &argv, ext, null, c_object.src.owner);
42234243 try argv.appendSlice(c_object.src.extra_flags);
42244244 try argv.appendSlice(c_object.src.cache_exempt_flags);
42254245
......@@ -4262,7 +4282,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
42624282 null
42634283 else
42644284 try std.fmt.allocPrint(arena, "{s}.d", .{out_obj_path});
4265 try comp.addCCArgs(arena, &argv, ext, out_dep_path);
4285 try comp.addCCArgs(arena, &argv, ext, out_dep_path, c_object.src.owner);
42664286 try argv.appendSlice(c_object.src.extra_flags);
42674287 try argv.appendSlice(c_object.src.cache_exempt_flags);
42684288
......@@ -4610,7 +4630,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
46104630 // mode. While these defines are not normally present when calling rc.exe directly,
46114631 // them being defined matches the behavior of how MSVC calls rc.exe which is the more
46124632 // relevant behavior in this case.
4613 try comp.addCCArgs(arena, &argv, .rc, out_dep_path);
4633 try comp.addCCArgs(arena, &argv, .rc, out_dep_path, rc_src.owner);
46144634
46154635 if (comp.verbose_cc) {
46164636 dump_argv(argv.items);
......@@ -4788,11 +4808,12 @@ pub fn addTranslateCCArgs(
47884808 argv: *std.ArrayList([]const u8),
47894809 ext: FileExt,
47904810 out_dep_path: ?[]const u8,
4811 owner_mod: *Package.Module,
47914812) !void {
4792 try argv.appendSlice(&[_][]const u8{ "-x", "c" });
4793 try comp.addCCArgs(arena, argv, ext, out_dep_path);
4813 try argv.appendSlice(&.{ "-x", "c" });
4814 try comp.addCCArgs(arena, argv, ext, out_dep_path, owner_mod);
47944815 // This gives us access to preprocessing entities, presumably at the cost of performance.
4795 try argv.appendSlice(&[_][]const u8{ "-Xclang", "-detailed-preprocessing-record" });
4816 try argv.appendSlice(&.{ "-Xclang", "-detailed-preprocessing-record" });
47964817}
47974818
47984819/// Add common C compiler args between translate-c and C object compilation.
......@@ -4825,11 +4846,11 @@ pub fn addCCArgs(
48254846 try argv.append("-fno-caret-diagnostics");
48264847 }
48274848
4828 if (comp.bin_file.function_sections) {
4849 if (comp.function_sections) {
48294850 try argv.append("-ffunction-sections");
48304851 }
48314852
4832 if (comp.bin_file.data_sections) {
4853 if (comp.data_sections) {
48334854 try argv.append("-fdata-sections");
48344855 }
48354856
......@@ -5088,7 +5109,7 @@ pub fn addCCArgs(
50885109 try argv.append("-fPIC");
50895110 }
50905111
5091 if (comp.unwind_tables) {
5112 if (mod.unwind_tables) {
50925113 try argv.append("-funwind-tables");
50935114 } else {
50945115 try argv.append("-fno-unwind-tables");
......@@ -5174,7 +5195,7 @@ pub fn addCCArgs(
51745195 }
51755196
51765197 try argv.ensureUnusedCapacity(2);
5177 switch (comp.bin_file.debug_format) {
5198 switch (comp.config.debug_format) {
51785199 .strip => {},
51795200 .code_view => {
51805201 // -g is required here because -gcodeview doesn't trigger debug info
......@@ -5210,7 +5231,7 @@ pub fn addCCArgs(
52105231 try argv.append("-ffreestanding");
52115232 }
52125233
5213 try argv.appendSlice(comp.clang_argv);
5234 try argv.appendSlice(mod.cc_argv);
52145235}
52155236
52165237fn failCObj(
......@@ -6094,6 +6115,7 @@ fn buildOutputFromZig(
60946115 .have_zcu = true,
60956116 .emit_bin = true,
60966117 .root_optimize_mode = comp.compilerRtOptMode(),
6118 .root_strip = comp.compilerRtStrip(),
60976119 .link_libc = comp.config.link_libc,
60986120 .any_unwind_tables = unwind_tables,
60996121 });
......@@ -6198,6 +6220,7 @@ pub fn build_crt_file(
61986220 .have_zcu = false,
61996221 .emit_bin = true,
62006222 .root_optimize_mode = comp.compilerRtOptMode(),
6223 .root_strip = comp.compilerRtStrip(),
62016224 .link_libc = false,
62026225 .lto = switch (output_mode) {
62036226 .Lib => comp.config.lto,
src/Compilation/Config.zig+31
......@@ -33,9 +33,16 @@ shared_memory: bool,
3333is_test: bool,
3434test_evented_io: bool,
3535entry: ?[]const u8,
36debug_format: DebugFormat,
3637
3738pub const CFrontend = enum { clang, aro };
3839
40pub const DebugFormat = union(enum) {
41 strip,
42 dwarf: std.dwarf.Format,
43 code_view,
44};
45
3946pub const Options = struct {
4047 output_mode: std.builtin.OutputMode,
4148 resolved_target: Module.ResolvedTarget,
......@@ -43,6 +50,7 @@ pub const Options = struct {
4350 have_zcu: bool,
4451 emit_bin: bool,
4552 root_optimize_mode: ?std.builtin.OptimizeMode = null,
53 root_strip: ?bool = null,
4654 link_mode: ?std.builtin.LinkMode = null,
4755 ensure_libc_on_non_freestanding: bool = false,
4856 ensure_libcpp_on_non_freestanding: bool = false,
......@@ -51,6 +59,7 @@ pub const Options = struct {
5159 any_unwind_tables: bool = false,
5260 any_dyn_libs: bool = false,
5361 any_c_source_files: bool = false,
62 any_non_stripped: bool = false,
5463 emit_llvm_ir: bool = false,
5564 emit_llvm_bc: bool = false,
5665 link_libc: ?bool = null,
......@@ -74,6 +83,7 @@ pub const Options = struct {
7483 export_memory: ?bool = null,
7584 shared_memory: ?bool = null,
7685 test_evented_io: bool = false,
86 debug_format: ?Config.DebugFormat = null,
7787};
7888
7989pub fn resolve(options: Options) !Config {
......@@ -365,6 +375,26 @@ pub fn resolve(options: Options) !Config {
365375 break :b false;
366376 };
367377
378 const root_strip = b: {
379 if (options.root_strip) |x| break :b x;
380 if (root_optimize_mode == .ReleaseSmall) break :b true;
381 if (!target_util.hasDebugInfo(target)) break :b true;
382 break :b false;
383 };
384
385 const debug_format: DebugFormat = b: {
386 if (root_strip and !options.any_non_stripped) break :b .strip;
387 break :b switch (target.ofmt) {
388 .elf, .macho, .wasm => .{ .dwarf = .@"32" },
389 .coff => .code_view,
390 .c => switch (target.os.tag) {
391 .windows, .uefi => .code_view,
392 else => .{ .dwarf = .@"32" },
393 },
394 .spirv, .nvptx, .dxcontainer, .hex, .raw, .plan9 => .strip,
395 };
396 };
397
368398 return .{
369399 .output_mode = options.output_mode,
370400 .have_zcu = options.have_zcu,
......@@ -388,6 +418,7 @@ pub fn resolve(options: Options) !Config {
388418 .use_lld = use_lld,
389419 .entry = entry,
390420 .wasi_exec_model = wasi_exec_model,
421 .debug_format = debug_format,
391422 };
392423}
393424
src/Module.zig-69
......@@ -152,8 +152,6 @@ stage1_flags: packed struct {
152152 reserved: u2 = 0,
153153} = .{},
154154
155job_queued_update_builtin_zig: bool = true,
156
157155compile_log_text: ArrayListUnmanaged(u8) = .{},
158156
159157emit_h: ?*GlobalEmitH,
......@@ -2490,7 +2488,6 @@ pub fn deinit(mod: *Module) void {
24902488
24912489 mod.compile_log_text.deinit(gpa);
24922490
2493 mod.zig_cache_artifact_directory.handle.close();
24942491 mod.local_zir_cache.handle.close();
24952492 mod.global_zir_cache.handle.close();
24962493
......@@ -3075,72 +3072,6 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
30753072 }
30763073}
30773074
3078pub fn populateBuiltinFile(mod: *Module) !void {
3079 const tracy = trace(@src());
3080 defer tracy.end();
3081
3082 const comp = mod.comp;
3083 const builtin_mod, const file = blk: {
3084 comp.mutex.lock();
3085 defer comp.mutex.unlock();
3086
3087 const builtin_mod = mod.main_mod.deps.get("builtin").?;
3088 const result = try mod.importPkg(builtin_mod);
3089 break :blk .{ builtin_mod, result.file };
3090 };
3091 const gpa = mod.gpa;
3092 file.source = try comp.generateBuiltinZigSource(gpa);
3093 file.source_loaded = true;
3094
3095 if (builtin_mod.root.statFile(builtin_mod.root_src_path)) |stat| {
3096 if (stat.size != file.source.len) {
3097 log.warn(
3098 "the cached file '{}{s}' had the wrong size. Expected {d}, found {d}. " ++
3099 "Overwriting with correct file contents now",
3100 .{ builtin_mod.root, builtin_mod.root_src_path, file.source.len, stat.size },
3101 );
3102
3103 try writeBuiltinFile(file, builtin_mod);
3104 } else {
3105 file.stat = .{
3106 .size = stat.size,
3107 .inode = stat.inode,
3108 .mtime = stat.mtime,
3109 };
3110 }
3111 } else |err| switch (err) {
3112 error.BadPathName => unreachable, // it's always "builtin.zig"
3113 error.NameTooLong => unreachable, // it's always "builtin.zig"
3114 error.PipeBusy => unreachable, // it's not a pipe
3115 error.WouldBlock => unreachable, // not asking for non-blocking I/O
3116
3117 error.FileNotFound => try writeBuiltinFile(file, builtin_mod),
3118
3119 else => |e| return e,
3120 }
3121
3122 file.tree = try Ast.parse(gpa, file.source, .zig);
3123 file.tree_loaded = true;
3124 assert(file.tree.errors.len == 0); // builtin.zig must parse
3125
3126 file.zir = try AstGen.generate(gpa, file.tree);
3127 file.zir_loaded = true;
3128 file.status = .success_zir;
3129}
3130
3131fn writeBuiltinFile(file: *File, builtin_mod: *Package.Module) !void {
3132 var af = try builtin_mod.root.atomicFile(builtin_mod.root_src_path, .{});
3133 defer af.deinit();
3134 try af.file.writeAll(file.source);
3135 try af.finish();
3136
3137 file.stat = .{
3138 .size = file.source.len,
3139 .inode = 0, // dummy value
3140 .mtime = 0, // dummy value
3141 };
3142}
3143
31443075pub fn mapOldZirToNew(
31453076 gpa: Allocator,
31463077 old_zir: Zir,
src/Package/Module.zig+26-5
......@@ -33,11 +33,16 @@ cc_argv: []const []const u8,
3333/// (SPIR-V) whether to generate a structured control flow graph or not
3434structured_cfg: bool,
3535
36/// The contents of `@import("builtin")` for this module.
37generated_builtin_source: []const u8,
36/// If the module is an `@import("builtin")` module, this is the `File` that
37/// is preallocated for it. Otherwise this field is null.
38builtin_file: ?*File,
3839
3940pub const Deps = std.StringArrayHashMapUnmanaged(*Module);
4041
42pub fn isBuiltin(m: Module) bool {
43 return m.file != null;
44}
45
4146pub const Tree = struct {
4247 /// Each `Package` exposes a `Module` with build.zig as its root source file.
4348 build_module_table: std.AutoArrayHashMapUnmanaged(MultiHashHexDigest, *Module),
......@@ -329,6 +334,8 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
329334 .wasi_exec_model = options.global.wasi_exec_model,
330335 }, arena);
331336
337 const new_file = try arena.create(File);
338
332339 const digest = Cache.HashHelper.oneShot(generated_builtin_source);
333340 const builtin_sub_path = try arena.dupe(u8, "b" ++ std.fs.path.sep_str ++ digest);
334341 const new = try arena.create(Module);
......@@ -359,12 +366,25 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
359366 .stack_protector = stack_protector,
360367 .code_model = code_model,
361368 .red_zone = red_zone,
362 .generated_builtin_source = generated_builtin_source,
363369 .sanitize_c = sanitize_c,
364370 .sanitize_thread = sanitize_thread,
365371 .unwind_tables = unwind_tables,
366372 .cc_argv = &.{},
367373 .structured_cfg = structured_cfg,
374 .builtin_file = new_file,
375 };
376 new_file.* = .{
377 .sub_file_path = "builtin.zig",
378 .source = generated_builtin_source,
379 .source_loaded = true,
380 .tree_loaded = false,
381 .zir_loaded = false,
382 .stat = undefined,
383 .tree = undefined,
384 .zir = undefined,
385 .status = .never_loaded,
386 .mod = new,
387 .root_decl = .none,
368388 };
369389 break :b new;
370390 };
......@@ -391,12 +411,12 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
391411 .stack_protector = stack_protector,
392412 .code_model = code_model,
393413 .red_zone = red_zone,
394 .generated_builtin_source = builtin_mod.generated_builtin_source,
395414 .sanitize_c = sanitize_c,
396415 .sanitize_thread = sanitize_thread,
397416 .unwind_tables = unwind_tables,
398417 .cc_argv = options.cc_argv,
399418 .structured_cfg = structured_cfg,
419 .builtin_file = null,
400420 };
401421
402422 try mod.deps.ensureUnusedCapacity(arena, 1);
......@@ -437,8 +457,8 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*P
437457 .sanitize_thread = undefined,
438458 .unwind_tables = undefined,
439459 .cc_argv = undefined,
440 .generated_builtin_source = undefined,
441460 .structured_cfg = undefined,
461 .builtin_file = null,
442462 };
443463 return mod;
444464}
......@@ -457,3 +477,4 @@ const Cache = std.Build.Cache;
457477const Builtin = @import("../Builtin.zig");
458478const assert = std.debug.assert;
459479const Compilation = @import("../Compilation.zig");
480const File = @import("../Module.zig").File;
src/Sema.zig+6-1
......@@ -784,6 +784,11 @@ pub const Block = struct {
784784 }
785785 }
786786
787 pub fn ownerModule(block: Block) *Package.Module {
788 const zcu = block.sema.mod;
789 return zcu.namespacePtr(block.namespace).file_scope.mod;
790 }
791
787792 pub fn startAnonDecl(block: *Block) !WipAnonDecl {
788793 return WipAnonDecl{
789794 .block = block,
......@@ -5733,7 +5738,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
57335738 // Ignore the result, all the relevant operations have written to c_import_buf already.
57345739 _ = try sema.analyzeBodyBreak(&child_block, body);
57355740
5736 var c_import_res = comp.cImport(c_import_buf.items) catch |err|
5741 var c_import_res = comp.cImport(c_import_buf.items, parent_block.ownerModule()) catch |err|
57375742 return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)});
57385743 defer c_import_res.deinit(gpa);
57395744
src/codegen/llvm.zig+4-12
......@@ -854,9 +854,8 @@ pub const Object = struct {
854854 /// want to iterate over it while adding entries to it.
855855 pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr);
856856
857 pub fn create(arena: Allocator, options: link.File.OpenOptions) !*Object {
857 pub fn create(arena: Allocator, comp: *Compilation) !*Object {
858858 if (build_options.only_c) unreachable;
859 const comp = options.comp;
860859 const gpa = comp.gpa;
861860 const target = comp.root_mod.resolved_target.result;
862861 const llvm_target_triple = try targetTriple(arena, target);
......@@ -878,14 +877,7 @@ pub const Object = struct {
878877 var target_data: if (build_options.have_llvm) *llvm.TargetData else void = undefined;
879878 if (builder.useLibLlvm()) {
880879 debug_info: {
881 const debug_format = options.debug_format orelse b: {
882 if (strip) break :b .strip;
883 break :b switch (target.ofmt) {
884 .coff => .code_view,
885 else => .{ .dwarf = .@"32" },
886 };
887 };
888 switch (debug_format) {
880 switch (comp.config.debug_format) {
889881 .strip => break :debug_info,
890882 .code_view => builder.llvm.module.?.addModuleCodeViewFlag(),
891883 .dwarf => |f| builder.llvm.module.?.addModuleDebugInfoFlag(f == .@"64"),
......@@ -961,8 +953,8 @@ pub const Object = struct {
961953 opt_level,
962954 reloc_mode,
963955 code_model,
964 options.function_sections orelse false,
965 options.data_sections orelse false,
956 comp.function_sections,
957 comp.data_sections,
966958 float_abi,
967959 if (target_util.llvmMachineAbi(target)) |s| s.ptr else null,
968960 );
src/libunwind.zig+2-1
......@@ -28,6 +28,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void {
2828 .have_zcu = false,
2929 .emit_bin = true,
3030 .root_optimize_mode = comp.compilerRtOptMode(),
31 .root_strip = comp.compilerRtStrip(),
3132 .link_libc = true,
3233 // Disable LTO to avoid https://github.com/llvm/llvm-project/issues/56825
3334 .lto = false,
......@@ -131,7 +132,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void {
131132 .libc_installation = comp.libc_installation,
132133 .emit_bin = emit_bin,
133134 .link_mode = link_mode,
134 .function_sections = comp.bin_file.function_sections,
135 .function_sections = comp.function_sections,
135136 .c_source_files = &c_source_files,
136137 .verbose_cc = comp.verbose_cc,
137138 .verbose_link = comp.verbose_link,
src/link.zig+22-19
......@@ -68,9 +68,6 @@ pub const File = struct {
6868 force_undefined_symbols: std.StringArrayHashMapUnmanaged(void),
6969 allow_shlib_undefined: bool,
7070 stack_size: u64,
71 debug_format: DebugFormat,
72 function_sections: bool,
73 data_sections: bool,
7471
7572 /// Prevents other processes from clobbering files in the output directory
7673 /// of this linking operation.
......@@ -78,16 +75,7 @@ pub const File = struct {
7875
7976 child_pid: ?std.ChildProcess.Id = null,
8077
81 pub const DebugFormat = union(enum) {
82 strip,
83 dwarf: std.dwarf.Format,
84 code_view,
85 };
86
8778 pub const OpenOptions = struct {
88 comp: *Compilation,
89 emit: Compilation.Emit,
90
9179 symbol_count_hint: u64 = 32,
9280 program_code_size_hint: u64 = 256 * 1024,
9381
......@@ -95,8 +83,6 @@ pub const File = struct {
9583 entry_addr: ?u64,
9684 stack_size: ?u64,
9785 image_base: ?u64,
98 function_sections: bool,
99 data_sections: bool,
10086 eh_frame_hdr: bool,
10187 emit_relocs: bool,
10288 rdynamic: bool,
......@@ -150,8 +136,6 @@ pub const File = struct {
150136
151137 compatibility_version: ?std.SemanticVersion,
152138
153 debug_format: ?DebugFormat,
154
155139 // TODO: remove this. libraries are resolved by the frontend.
156140 lib_dirs: []const []const u8,
157141 rpath_list: []const []const u8,
......@@ -190,10 +174,29 @@ pub const File = struct {
190174 /// rewriting it. A malicious file is detected as incremental link failure
191175 /// and does not cause Illegal Behavior. This operation is not atomic.
192176 /// `arena` is used for allocations with the same lifetime as the created File.
193 pub fn open(arena: Allocator, options: OpenOptions) !*File {
194 switch (Tag.fromObjectFormat(options.comp.root_mod.resolved_target.result.ofmt)) {
177 pub fn open(
178 arena: Allocator,
179 comp: *Compilation,
180 emit: Compilation.Emit,
181 options: OpenOptions,
182 ) !*File {
183 switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) {
184 inline else => |tag| {
185 const ptr = try tag.Type().open(arena, comp, emit, options);
186 return &ptr.base;
187 },
188 }
189 }
190
191 pub fn createEmpty(
192 arena: Allocator,
193 comp: *Compilation,
194 emit: Compilation.Emit,
195 options: OpenOptions,
196 ) !*File {
197 switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) {
195198 inline else => |tag| {
196 const ptr = try tag.Type().open(arena, options);
199 const ptr = try tag.Type().createEmpty(arena, comp, emit, options);
197200 return &ptr.base;
198201 },
199202 }
src/link/C.zig+13-13
......@@ -92,21 +92,24 @@ pub fn addString(this: *C, s: []const u8) Allocator.Error!String {
9292 };
9393}
9494
95pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {
96 const target = options.comp.root_mod.resolved_target.result;
95pub fn open(
96 arena: Allocator,
97 comp: *Compilation,
98 emit: Compilation.Emit,
99 options: link.File.OpenOptions,
100) !*C {
101 const target = comp.root_mod.resolved_target.result;
97102 assert(target.ofmt == .c);
98 const optimize_mode = options.comp.root_mod.optimize_mode;
99 const use_lld = build_options.have_llvm and options.comp.config.use_lld;
100 const use_llvm = options.comp.config.use_llvm;
101 const output_mode = options.comp.config.output_mode;
102 const link_mode = options.comp.config.link_mode;
103 const optimize_mode = comp.root_mod.optimize_mode;
104 const use_lld = build_options.have_llvm and comp.config.use_lld;
105 const use_llvm = comp.config.use_llvm;
106 const output_mode = comp.config.output_mode;
107 const link_mode = comp.config.link_mode;
103108
104109 // These are caught by `Compilation.Config.resolve`.
105110 assert(!use_lld);
106111 assert(!use_llvm);
107112
108 const emit = options.emit;
109
110113 const file = try emit.directory.handle.createFile(emit.sub_path, .{
111114 // Truncation is done on `flush`.
112115 .truncate = false,
......@@ -119,7 +122,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {
119122 c_file.* = .{
120123 .base = .{
121124 .tag = .c,
122 .comp = options.comp,
125 .comp = comp,
123126 .emit = emit,
124127 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
125128 .stack_size = options.stack_size orelse 16777216,
......@@ -129,9 +132,6 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {
129132 .build_id = options.build_id,
130133 .rpath_list = options.rpath_list,
131134 .force_undefined_symbols = options.force_undefined_symbols,
132 .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
133 .function_sections = options.function_sections,
134 .data_sections = options.data_sections,
135135 },
136136 };
137137
src/link/Coff.zig+24-18
......@@ -234,44 +234,49 @@ const ideal_factor = 3;
234234const minimum_text_block_size = 64;
235235pub const min_text_capacity = padToIdeal(minimum_text_block_size);
236236
237pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Coff {
237pub fn open(
238 arena: Allocator,
239 comp: *Compilation,
240 emit: Compilation.Emit,
241 options: link.File.OpenOptions,
242) !*Coff {
238243 if (build_options.only_c) unreachable;
239 const target = options.comp.root_mod.resolved_target.result;
244 const target = comp.root_mod.resolved_target.result;
240245 assert(target.ofmt == .coff);
241246
242 const self = try createEmpty(arena, options);
247 const self = try createEmpty(arena, comp, emit, options);
243248 errdefer self.base.destroy();
244249
245 const use_lld = build_options.have_llvm and options.comp.config.use_lld;
246 const use_llvm = options.comp.config.use_llvm;
250 const use_lld = build_options.have_llvm and comp.config.use_lld;
251 const use_llvm = comp.config.use_llvm;
247252
248253 if (use_lld and use_llvm) {
249254 // LLVM emits the object file; LLD links it into the final product.
250255 return self;
251256 }
252257
253 const sub_path = if (!use_lld) options.emit.sub_path else p: {
258 const sub_path = if (!use_lld) emit.sub_path else p: {
254259 // Open a temporary object file, not the final output file because we
255260 // want to link with LLD.
256261 const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{
257 options.emit.sub_path, target.ofmt.fileExt(target.cpu.arch),
262 emit.sub_path, target.ofmt.fileExt(target.cpu.arch),
258263 });
259264 self.base.intermediary_basename = o_file_path;
260265 break :p o_file_path;
261266 };
262267
263 self.base.file = try options.emit.directory.handle.createFile(sub_path, .{
268 self.base.file = try emit.directory.handle.createFile(sub_path, .{
264269 .truncate = false,
265270 .read = true,
266271 .mode = link.File.determineMode(
267272 use_lld,
268 options.comp.config.output_mode,
269 options.comp.config.link_mode,
273 comp.config.output_mode,
274 comp.config.link_mode,
270275 ),
271276 });
272277
273278 assert(self.llvm_object == null);
274 const gpa = self.base.comp.gpa;
279 const gpa = comp.gpa;
275280
276281 try self.strtab.buffer.ensureUnusedCapacity(gpa, @sizeOf(u32));
277282 self.strtab.buffer.appendNTimesAssumeCapacity(0, @sizeOf(u32));
......@@ -362,8 +367,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Coff {
362367 return self;
363368}
364369
365pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {
366 const comp = options.comp;
370pub fn createEmpty(
371 arena: Allocator,
372 comp: *Compilation,
373 emit: Compilation.Emit,
374 options: link.File.OpenOptions,
375) !*Coff {
367376 const target = comp.root_mod.resolved_target.result;
368377 const optimize_mode = comp.root_mod.optimize_mode;
369378 const output_mode = comp.config.output_mode;
......@@ -380,7 +389,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {
380389 .base = .{
381390 .tag = .coff,
382391 .comp = comp,
383 .emit = options.emit,
392 .emit = emit,
384393 .stack_size = options.stack_size orelse 16777216,
385394 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug),
386395 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
......@@ -389,9 +398,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {
389398 .build_id = options.build_id,
390399 .rpath_list = options.rpath_list,
391400 .force_undefined_symbols = options.force_undefined_symbols,
392 .debug_format = options.debug_format orelse .code_view,
393 .function_sections = options.function_sections,
394 .data_sections = options.data_sections,
395401 },
396402 .ptr_width = ptr_width,
397403 .page_size = page_size,
......@@ -423,7 +429,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {
423429
424430 const use_llvm = comp.config.use_llvm;
425431 if (use_llvm and comp.config.have_zcu) {
426 self.llvm_object = try LlvmObject.create(arena, options);
432 self.llvm_object = try LlvmObject.create(arena, comp);
427433 }
428434 return self;
429435}
src/link/Coff/lld.zig+1-1
......@@ -171,7 +171,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
171171
172172 try argv.append("-ERRORLIMIT:0");
173173 try argv.append("-NOLOGO");
174 if (self.base.debug_format != .strip) {
174 if (comp.config.debug_format != .strip) {
175175 try argv.append("-DEBUG");
176176
177177 const out_ext = std.fs.path.extension(full_out_path);
src/link/Elf.zig+27-21
......@@ -228,18 +228,23 @@ pub const HashStyle = enum { sysv, gnu, both };
228228pub const CompressDebugSections = enum { none, zlib, zstd };
229229pub const SortSection = enum { name, alignment };
230230
231pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {
231pub fn open(
232 arena: Allocator,
233 comp: *Compilation,
234 emit: Compilation.Emit,
235 options: link.File.OpenOptions,
236) !*Elf {
232237 if (build_options.only_c) unreachable;
233 const target = options.comp.root_mod.resolved_target.result;
238 const target = comp.root_mod.resolved_target.result;
234239 assert(target.ofmt == .elf);
235240
236 const use_lld = build_options.have_llvm and options.comp.config.use_lld;
237 const use_llvm = options.comp.config.use_llvm;
238 const opt_zcu = options.comp.module;
239 const output_mode = options.comp.config.output_mode;
240 const link_mode = options.comp.config.link_mode;
241 const use_lld = build_options.have_llvm and comp.config.use_lld;
242 const use_llvm = comp.config.use_llvm;
243 const opt_zcu = comp.module;
244 const output_mode = comp.config.output_mode;
245 const link_mode = comp.config.link_mode;
241246
242 const self = try createEmpty(arena, options);
247 const self = try createEmpty(arena, comp, emit, options);
243248 errdefer self.base.destroy();
244249
245250 if (use_lld and use_llvm) {
......@@ -250,23 +255,23 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {
250255 const is_obj = output_mode == .Obj;
251256 const is_obj_or_ar = is_obj or (output_mode == .Lib and link_mode == .Static);
252257
253 const sub_path = if (!use_lld) options.emit.sub_path else p: {
258 const sub_path = if (!use_lld) emit.sub_path else p: {
254259 // Open a temporary object file, not the final output file because we
255260 // want to link with LLD.
256261 const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{
257 options.emit.sub_path, target.ofmt.fileExt(target.cpu.arch),
262 emit.sub_path, target.ofmt.fileExt(target.cpu.arch),
258263 });
259264 self.base.intermediary_basename = o_file_path;
260265 break :p o_file_path;
261266 };
262267
263 self.base.file = try options.emit.directory.handle.createFile(sub_path, .{
268 self.base.file = try emit.directory.handle.createFile(sub_path, .{
264269 .truncate = false,
265270 .read = true,
266271 .mode = link.File.determineMode(use_lld, output_mode, link_mode),
267272 });
268273
269 const gpa = options.comp.gpa;
274 const gpa = comp.gpa;
270275
271276 // Index 0 is always a null symbol.
272277 try self.symbols.append(gpa, .{});
......@@ -343,8 +348,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {
343348 return self;
344349}
345350
346pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {
347 const comp = options.comp;
351pub fn createEmpty(
352 arena: Allocator,
353 comp: *Compilation,
354 emit: Compilation.Emit,
355 options: link.File.OpenOptions,
356) !*Elf {
348357 const use_llvm = comp.config.use_llvm;
349358 const optimize_mode = comp.root_mod.optimize_mode;
350359 const target = comp.root_mod.resolved_target.result;
......@@ -373,7 +382,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {
373382 .base = .{
374383 .tag = .elf,
375384 .comp = comp,
376 .emit = options.emit,
385 .emit = emit,
377386 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
378387 .stack_size = options.stack_size orelse 16777216,
379388 .allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os,
......@@ -382,9 +391,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {
382391 .build_id = options.build_id,
383392 .rpath_list = options.rpath_list,
384393 .force_undefined_symbols = options.force_undefined_symbols,
385 .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
386 .function_sections = options.function_sections,
387 .data_sections = options.data_sections,
388394 },
389395 .ptr_width = ptr_width,
390396 .page_size = page_size,
......@@ -423,7 +429,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {
423429 .version_script = options.version_script,
424430 };
425431 if (use_llvm and comp.config.have_zcu) {
426 self.llvm_object = try LlvmObject.create(arena, options);
432 self.llvm_object = try LlvmObject.create(arena, comp);
427433 }
428434
429435 return self;
......@@ -1753,7 +1759,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
17531759 try argv.append("-pie");
17541760 }
17551761
1756 if (self.base.debug_format == .strip) {
1762 if (comp.config.debug_format == .strip) {
17571763 try argv.append("-s");
17581764 }
17591765
......@@ -2640,7 +2646,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
26402646 try argv.append("--export-dynamic");
26412647 }
26422648
2643 if (self.base.debug_format == .strip) {
2649 if (comp.config.debug_format == .strip) {
26442650 try argv.append("-s");
26452651 }
26462652
src/link/Elf/Object.zig+2-1
......@@ -293,13 +293,14 @@ fn initOutputSection(self: Object, elf_file: *Elf, shdr: ElfShdr) error{OutOfMem
293293}
294294
295295fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool {
296 const comp = elf_file.base.comp;
296297 const shdr = self.shdrs.items[index];
297298 const name = self.getString(shdr.sh_name);
298299 const ignore = blk: {
299300 if (mem.startsWith(u8, name, ".note")) break :blk true;
300301 if (mem.startsWith(u8, name, ".comment")) break :blk true;
301302 if (mem.startsWith(u8, name, ".llvm_addrsig")) break :blk true;
302 if (elf_file.base.debug_format == .strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and
303 if (comp.config.debug_format == .strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and
303304 mem.startsWith(u8, name, ".debug")) break :blk true;
304305 break :blk false;
305306 };
src/link/Elf/ZigObject.zig+9-3
......@@ -76,7 +76,8 @@ pub const symbol_mask: u32 = 0x7fffffff;
7676pub const SHN_ATOM: u16 = 0x100;
7777
7878pub fn init(self: *ZigObject, elf_file: *Elf) !void {
79 const gpa = elf_file.base.comp.gpa;
79 const comp = elf_file.base.comp;
80 const gpa = comp.gpa;
8081
8182 try self.atoms.append(gpa, 0); // null input section
8283 try self.relocs.append(gpa, .{}); // null relocs section
......@@ -96,8 +97,13 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {
9697 esym.st_shndx = elf.SHN_ABS;
9798 symbol_ptr.esym_index = esym_index;
9899
99 if (elf_file.base.debug_format != .strip) {
100 self.dwarf = Dwarf.init(&elf_file.base, .dwarf32);
100 switch (comp.config.debug_format) {
101 .strip => {},
102 .dwarf => |v| {
103 assert(v == .@"32");
104 self.dwarf = Dwarf.init(&elf_file.base, .dwarf32);
105 },
106 .code_view => unreachable,
101107 }
102108}
103109
src/link/MachO.zig+22-17
......@@ -182,18 +182,21 @@ pub const SdkLayout = enum {
182182 vendored,
183183};
184184
185pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {
185pub fn open(
186 arena: Allocator,
187 comp: *Compilation,
188 emit: Compilation.Emit,
189 options: link.File.OpenOptions,
190) !*MachO {
186191 if (build_options.only_c) unreachable;
187 const comp = options.comp;
188192 const target = comp.root_mod.resolved_target.result;
189193 const use_lld = build_options.have_llvm and comp.config.use_lld;
190194 const use_llvm = comp.config.use_llvm;
191195 assert(target.ofmt == .macho);
192196
193197 const gpa = comp.gpa;
194 const emit = options.emit;
195198 const mode: Mode = mode: {
196 if (use_llvm or comp.module == null or comp.cache_mode == .whole)
199 if (use_llvm or comp.module == null or comp.cache_use == .whole)
197200 break :mode .zld;
198201 break :mode .incremental;
199202 };
......@@ -201,7 +204,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {
201204 if (comp.module == null) {
202205 // No point in opening a file, we would not write anything to it.
203206 // Initialize with empty.
204 return createEmpty(arena, options);
207 return createEmpty(arena, comp, emit, options);
205208 }
206209 // Open a temporary object file, not the final output file because we
207210 // want to link with LLD.
......@@ -210,7 +213,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {
210213 });
211214 } else emit.sub_path;
212215
213 const self = try createEmpty(arena, options);
216 const self = try createEmpty(arena, comp, emit, options);
214217 errdefer self.base.destroy();
215218
216219 if (mode == .zld) {
......@@ -232,7 +235,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {
232235 });
233236 self.base.file = file;
234237
235 if (self.base.debug_format != .strip and comp.module != null) {
238 if (comp.config.debug_format != .strip and comp.module != null) {
236239 // Create dSYM bundle.
237240 log.debug("creating {s}.dSYM bundle", .{sub_path});
238241
......@@ -279,8 +282,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {
279282 return self;
280283}
281284
282pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO {
283 const comp = options.comp;
285pub fn createEmpty(
286 arena: Allocator,
287 comp: *Compilation,
288 emit: Compilation.Emit,
289 options: link.File.OpenOptions,
290) !*MachO {
284291 const optimize_mode = comp.root_mod.optimize_mode;
285292 const use_llvm = comp.config.use_llvm;
286293
......@@ -289,7 +296,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO {
289296 .base = .{
290297 .tag = .macho,
291298 .comp = comp,
292 .emit = options.emit,
299 .emit = emit,
293300 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug),
294301 .stack_size = options.stack_size orelse 16777216,
295302 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
......@@ -298,11 +305,8 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO {
298305 .build_id = options.build_id,
299306 .rpath_list = options.rpath_list,
300307 .force_undefined_symbols = options.force_undefined_symbols,
301 .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
302 .function_sections = options.function_sections,
303 .data_sections = options.data_sections,
304308 },
305 .mode = if (use_llvm or comp.module == null or comp.cache_mode == .whole)
309 .mode = if (use_llvm or comp.module == null or comp.cache_use == .whole)
306310 .zld
307311 else
308312 .incremental,
......@@ -317,7 +321,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO {
317321 };
318322
319323 if (use_llvm and comp.module != null) {
320 self.llvm_object = try LlvmObject.create(arena, options);
324 self.llvm_object = try LlvmObject.create(arena, comp);
321325 }
322326
323327 log.debug("selected linker mode '{s}'", .{@tagName(self.mode)});
......@@ -4313,7 +4317,8 @@ fn addLocalToSymtab(self: *MachO, sym_loc: SymbolWithLoc, locals: *std.ArrayList
43134317}
43144318
43154319fn writeSymtab(self: *MachO) !SymtabCtx {
4316 const gpa = self.base.comp.gpa;
4320 const comp = self.base.comp;
4321 const gpa = comp.gpa;
43174322
43184323 var locals = std.ArrayList(macho.nlist_64).init(gpa);
43194324 defer locals.deinit();
......@@ -4368,7 +4373,7 @@ fn writeSymtab(self: *MachO) !SymtabCtx {
43684373
43694374 // We generate stabs last in order to ensure that the strtab always has debug info
43704375 // strings trailing
4371 if (self.base.debug_format != .strip) {
4376 if (comp.config.debug_format != .strip) {
43724377 for (self.objects.items) |object| {
43734378 assert(self.d_sym == null); // TODO
43744379 try self.generateSymbolStabs(object, &locals);
src/link/NvPtx.zig+20-13
......@@ -25,12 +25,17 @@ const LlvmObject = @import("../codegen/llvm.zig").Object;
2525base: link.File,
2626llvm_object: *LlvmObject,
2727
28pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
28pub fn createEmpty(
29 arena: Allocator,
30 comp: *Compilation,
31 emit: Compilation.Emit,
32 options: link.File.OpenOptions,
33) !*NvPtx {
2934 if (build_options.only_c) unreachable;
3035
31 const target = options.comp.root_mod.resolved_target.result;
32 const use_lld = build_options.have_llvm and options.comp.config.use_lld;
33 const use_llvm = options.comp.config.use_llvm;
36 const target = comp.root_mod.resolved_target.result;
37 const use_lld = build_options.have_llvm and comp.config.use_lld;
38 const use_llvm = comp.config.use_llvm;
3439
3540 assert(use_llvm); // Caught by Compilation.Config.resolve.
3641 assert(!use_lld); // Caught by Compilation.Config.resolve.
......@@ -42,13 +47,13 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
4247 else => return error.PtxArchNotSupported,
4348 }
4449
45 const llvm_object = try LlvmObject.create(arena, options);
50 const llvm_object = try LlvmObject.create(arena, comp);
4651 const nvptx = try arena.create(NvPtx);
4752 nvptx.* = .{
4853 .base = .{
4954 .tag = .nvptx,
50 .comp = options.comp,
51 .emit = options.emit,
55 .comp = comp,
56 .emit = emit,
5257 .gc_sections = options.gc_sections orelse false,
5358 .stack_size = options.stack_size orelse 0,
5459 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
......@@ -57,9 +62,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
5762 .build_id = options.build_id,
5863 .rpath_list = options.rpath_list,
5964 .force_undefined_symbols = options.force_undefined_symbols,
60 .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
61 .function_sections = options.function_sections,
62 .data_sections = options.data_sections,
6365 },
6466 .llvm_object = llvm_object,
6567 };
......@@ -67,10 +69,15 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
6769 return nvptx;
6870}
6971
70pub fn open(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
71 const target = options.comp.root_mod.resolved_target.result;
72pub fn open(
73 arena: Allocator,
74 comp: *Compilation,
75 emit: Compilation.Emit,
76 options: link.File.OpenOptions,
77) !*NvPtx {
78 const target = comp.root_mod.resolved_target.result;
7279 assert(target.ofmt == .nvptx);
73 return createEmpty(arena, options);
80 return createEmpty(arena, comp, emit, options);
7481}
7582
7683pub fn deinit(self: *NvPtx) void {
src/link/Plan9.zig+21-15
......@@ -294,8 +294,12 @@ pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases {
294294 };
295295}
296296
297pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {
298 const comp = options.comp;
297pub fn createEmpty(
298 arena: Allocator,
299 comp: *Compilation,
300 emit: Compilation.Emit,
301 options: link.File.OpenOptions,
302) !*Plan9 {
299303 const target = comp.root_mod.resolved_target.result;
300304 const gpa = comp.gpa;
301305 const optimize_mode = comp.root_mod.optimize_mode;
......@@ -313,7 +317,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {
313317 .base = .{
314318 .tag = .plan9,
315319 .comp = comp,
316 .emit = options.emit,
320 .emit = emit,
317321 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
318322 .stack_size = options.stack_size orelse 16777216,
319323 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
......@@ -322,9 +326,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {
322326 .build_id = options.build_id,
323327 .rpath_list = options.rpath_list,
324328 .force_undefined_symbols = options.force_undefined_symbols,
325 .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
326 .function_sections = options.function_sections,
327 .data_sections = options.data_sections,
328329 },
329330 .sixtyfour_bit = sixtyfour_bit,
330331 .bases = undefined,
......@@ -1308,26 +1309,31 @@ pub fn deinit(self: *Plan9) void {
13081309 }
13091310}
13101311
1311pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {
1312pub fn open(
1313 arena: Allocator,
1314 comp: *Compilation,
1315 emit: Compilation.Emit,
1316 options: link.File.OpenOptions,
1317) !*Plan9 {
13121318 if (build_options.only_c) unreachable;
13131319
1314 const target = options.comp.root_mod.resolved_target.result;
1315 const use_lld = build_options.have_llvm and options.comp.config.use_lld;
1316 const use_llvm = options.comp.config.use_llvm;
1320 const target = comp.root_mod.resolved_target.result;
1321 const use_lld = build_options.have_llvm and comp.config.use_lld;
1322 const use_llvm = comp.config.use_llvm;
13171323
13181324 assert(!use_llvm); // Caught by Compilation.Config.resolve.
13191325 assert(!use_lld); // Caught by Compilation.Config.resolve.
13201326 assert(target.ofmt == .plan9);
13211327
1322 const self = try createEmpty(arena, options);
1328 const self = try createEmpty(arena, comp, emit, options);
13231329 errdefer self.base.destroy();
13241330
1325 const file = try options.emit.directory.handle.createFile(options.emit.sub_path, .{
1331 const file = try emit.directory.handle.createFile(emit.sub_path, .{
13261332 .read = true,
13271333 .mode = link.File.determineMode(
13281334 use_lld,
1329 options.comp.config.output_mode,
1330 options.comp.config.link_mode,
1335 comp.config.output_mode,
1336 comp.config.link_mode,
13311337 ),
13321338 });
13331339 errdefer file.close();
......@@ -1335,7 +1341,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {
13351341
13361342 self.bases = defaultBaseAddrs(target.cpu.arch);
13371343
1338 const gpa = options.comp.gpa;
1344 const gpa = comp.gpa;
13391345
13401346 try self.syms.appendSlice(gpa, &.{
13411347 // we include the global offset table to make it easier for debugging
src/link/SpirV.zig+21-14
......@@ -49,16 +49,21 @@ object: codegen.Object,
4949
5050pub const base_tag: link.File.Tag = .spirv;
5151
52pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV {
53 const gpa = options.comp.gpa;
54 const target = options.comp.root_mod.resolved_target.result;
52pub fn createEmpty(
53 arena: Allocator,
54 comp: *Compilation,
55 emit: Compilation.Emit,
56 options: link.File.OpenOptions,
57) !*SpirV {
58 const gpa = comp.gpa;
59 const target = comp.root_mod.resolved_target.result;
5560
5661 const self = try arena.create(SpirV);
5762 self.* = .{
5863 .base = .{
5964 .tag = .spirv,
60 .comp = options.comp,
61 .emit = options.emit,
65 .comp = comp,
66 .emit = emit,
6267 .gc_sections = options.gc_sections orelse false,
6368 .stack_size = options.stack_size orelse 0,
6469 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
......@@ -67,9 +72,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV {
6772 .build_id = options.build_id,
6873 .rpath_list = options.rpath_list,
6974 .force_undefined_symbols = options.force_undefined_symbols,
70 .function_sections = options.function_sections,
71 .data_sections = options.data_sections,
72 .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
7375 },
7476 .object = codegen.Object.init(gpa),
7577 };
......@@ -90,22 +92,27 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV {
9092 return self;
9193}
9294
93pub fn open(arena: Allocator, options: link.File.OpenOptions) !*SpirV {
95pub fn open(
96 arena: Allocator,
97 comp: *Compilation,
98 emit: Compilation.Emit,
99 options: link.File.OpenOptions,
100) !*SpirV {
94101 if (build_options.only_c) unreachable;
95102
96 const target = options.comp.root_mod.resolved_target.result;
97 const use_lld = build_options.have_llvm and options.comp.config.use_lld;
98 const use_llvm = options.comp.config.use_llvm;
103 const target = comp.root_mod.resolved_target.result;
104 const use_lld = build_options.have_llvm and comp.config.use_lld;
105 const use_llvm = comp.config.use_llvm;
99106
100107 assert(!use_llvm); // Caught by Compilation.Config.resolve.
101108 assert(!use_lld); // Caught by Compilation.Config.resolve.
102109 assert(target.ofmt == .spirv); // Caught by Compilation.Config.resolve.
103110
104 const spirv = try createEmpty(arena, options);
111 const spirv = try createEmpty(arena, comp, emit, options);
105112 errdefer spirv.base.destroy();
106113
107114 // TODO: read the file and keep valid parts instead of truncating
108 const file = try options.emit.directory.handle.createFile(options.emit.sub_path, .{
115 const file = try emit.directory.handle.createFile(emit.sub_path, .{
109116 .truncate = true,
110117 .read = true,
111118 });
src/link/Wasm.zig+24-17
......@@ -373,9 +373,13 @@ pub const StringTable = struct {
373373 }
374374};
375375
376pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
376pub fn open(
377 arena: Allocator,
378 comp: *Compilation,
379 emit: Compilation.Emit,
380 options: link.File.OpenOptions,
381) !*Wasm {
377382 if (build_options.only_c) unreachable;
378 const comp = options.comp;
379383 const gpa = comp.gpa;
380384 const target = comp.root_mod.resolved_target.result;
381385 assert(target.ofmt == .wasm);
......@@ -385,7 +389,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
385389 const output_mode = comp.config.output_mode;
386390 const shared_memory = comp.config.shared_memory;
387391
388 const wasm = try createEmpty(arena, options);
392 const wasm = try createEmpty(arena, comp, emit, options);
389393 errdefer wasm.base.destroy();
390394
391395 if (use_lld and use_llvm) {
......@@ -393,18 +397,18 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
393397 return wasm;
394398 }
395399
396 const sub_path = if (!use_lld) options.emit.sub_path else p: {
400 const sub_path = if (!use_lld) emit.sub_path else p: {
397401 // Open a temporary object file, not the final output file because we
398402 // want to link with LLD.
399403 const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{
400 options.emit.sub_path, target.ofmt.fileExt(target.cpu.arch),
404 emit.sub_path, target.ofmt.fileExt(target.cpu.arch),
401405 });
402406 wasm.base.intermediary_basename = o_file_path;
403407 break :p o_file_path;
404408 };
405409
406410 // TODO: read the file and keep valid parts instead of truncating
407 const file = try options.emit.directory.handle.createFile(sub_path, .{
411 const file = try emit.directory.handle.createFile(sub_path, .{
408412 .truncate = true,
409413 .read = true,
410414 .mode = if (fs.has_executable_bit)
......@@ -530,8 +534,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
530534 return wasm;
531535}
532536
533pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
534 const comp = options.comp;
537pub fn createEmpty(
538 arena: Allocator,
539 comp: *Compilation,
540 emit: Compilation.Emit,
541 options: link.File.OpenOptions,
542) !*Wasm {
535543 const use_llvm = comp.config.use_llvm;
536544 const output_mode = comp.config.output_mode;
537545
......@@ -540,7 +548,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
540548 .base = .{
541549 .tag = .wasm,
542550 .comp = comp,
543 .emit = options.emit,
551 .emit = emit,
544552 .gc_sections = options.gc_sections orelse (output_mode != .Obj),
545553 .stack_size = options.stack_size orelse std.wasm.page_size * 16, // 1MB
546554 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
......@@ -549,9 +557,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
549557 .build_id = options.build_id,
550558 .rpath_list = options.rpath_list,
551559 .force_undefined_symbols = options.force_undefined_symbols,
552 .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
553 .function_sections = options.function_sections,
554 .data_sections = options.data_sections,
555560 },
556561 .name = undefined,
557562 .import_table = options.import_table,
......@@ -566,7 +571,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
566571 };
567572
568573 if (use_llvm) {
569 wasm.llvm_object = try LlvmObject.create(arena, options);
574 wasm.llvm_object = try LlvmObject.create(arena, comp);
570575 }
571576 return wasm;
572577}
......@@ -4205,11 +4210,11 @@ fn writeToFile(
42054210 if (data_section_index) |data_index| {
42064211 try wasm.emitDataRelocations(&binary_bytes, data_index, symbol_table);
42074212 }
4208 } else if (wasm.base.debug_format != .strip) {
4213 } else if (comp.config.debug_format != .strip) {
42094214 try wasm.emitNameSection(&binary_bytes, arena);
42104215 }
42114216
4212 if (wasm.base.debug_format != .strip) {
4217 if (comp.config.debug_format != .strip) {
42134218 // The build id must be computed on the main sections only,
42144219 // so we have to do it now, before the debug sections.
42154220 switch (wasm.base.build_id) {
......@@ -4748,7 +4753,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
47484753 try argv.append("--no-gc-sections");
47494754 }
47504755
4751 if (wasm.base.debug_format == .strip) {
4756 if (comp.config.debug_format == .strip) {
47524757 try argv.append("-s");
47534758 }
47544759
......@@ -5276,7 +5281,9 @@ pub fn storeDeclType(wasm: *Wasm, decl_index: InternPool.DeclIndex, func_type: s
52765281fn markReferences(wasm: *Wasm) !void {
52775282 const tracy = trace(@src());
52785283 defer tracy.end();
5284
52795285 const do_garbage_collect = wasm.base.gc_sections;
5286 const comp = wasm.base.comp;
52805287
52815288 for (wasm.resolved_symbols.keys()) |sym_loc| {
52825289 const sym = sym_loc.getSymbol(wasm);
......@@ -5287,7 +5294,7 @@ fn markReferences(wasm: *Wasm) !void {
52875294
52885295 // Debug sections may require to be parsed and marked when it contains
52895296 // relocations to alive symbols.
5290 if (sym.tag == .section and wasm.base.debug_format != .strip) {
5297 if (sym.tag == .section and comp.config.debug_format != .strip) {
52915298 const file = sym_loc.file orelse continue; // Incremental debug info is done independently
52925299 const object = &wasm.objects.items[file];
52935300 const atom_index = try Object.parseSymbolIntoAtom(object, file, sym_loc.index, wasm);
src/main.zig+19-14
......@@ -892,7 +892,6 @@ fn buildOutputType(
892892 var contains_res_file: bool = false;
893893 var reference_trace: ?u32 = null;
894894 var pdb_out_path: ?[]const u8 = null;
895 var debug_format: ?link.File.DebugFormat = null;
896895 var error_limit: ?Module.ErrorInt = null;
897896 // These are before resolving sysroot.
898897 var lib_dir_args: std.ArrayListUnmanaged([]const u8) = .{};
......@@ -1054,6 +1053,8 @@ fn buildOutputType(
10541053 create_module.opts.any_sanitize_thread = true;
10551054 if (mod_opts.unwind_tables == true)
10561055 create_module.opts.any_unwind_tables = true;
1056 if (mod_opts.strip == false)
1057 create_module.opts.any_non_stripped = true;
10571058
10581059 const root_src = try introspect.resolvePath(arena, root_src_orig);
10591060 try create_module.modules.put(arena, mod_name, .{
......@@ -1480,9 +1481,9 @@ fn buildOutputType(
14801481 } else if (mem.eql(u8, arg, "-fno-strip")) {
14811482 mod_opts.strip = false;
14821483 } else if (mem.eql(u8, arg, "-gdwarf32")) {
1483 debug_format = .{ .dwarf = .@"32" };
1484 create_module.opts.debug_format = .{ .dwarf = .@"32" };
14841485 } else if (mem.eql(u8, arg, "-gdwarf64")) {
1485 debug_format = .{ .dwarf = .@"64" };
1486 create_module.opts.debug_format = .{ .dwarf = .@"64" };
14861487 } else if (mem.eql(u8, arg, "-fformatted-panics")) {
14871488 formatted_panics = true;
14881489 } else if (mem.eql(u8, arg, "-fno-formatted-panics")) {
......@@ -1989,11 +1990,11 @@ fn buildOutputType(
19891990 },
19901991 .gdwarf32 => {
19911992 mod_opts.strip = false;
1992 debug_format = .{ .dwarf = .@"32" };
1993 create_module.opts.debug_format = .{ .dwarf = .@"32" };
19931994 },
19941995 .gdwarf64 => {
19951996 mod_opts.strip = false;
1996 debug_format = .{ .dwarf = .@"64" };
1997 create_module.opts.debug_format = .{ .dwarf = .@"64" };
19971998 },
19981999 .sanitize => {
19992000 if (mem.eql(u8, it.only_arg, "undefined")) {
......@@ -2532,6 +2533,8 @@ fn buildOutputType(
25322533 create_module.opts.any_sanitize_thread = true;
25332534 if (mod_opts.unwind_tables == true)
25342535 create_module.opts.any_unwind_tables = true;
2536 if (mod_opts.strip == false)
2537 create_module.opts.any_non_stripped = true;
25352538
25362539 const src_path = try introspect.resolvePath(arena, unresolved_src_path);
25372540 try create_module.modules.put(arena, "main", .{
......@@ -3359,7 +3362,6 @@ fn buildOutputType(
33593362 .emit_docs = emit_docs_resolved.data,
33603363 .emit_implib = emit_implib_resolved.data,
33613364 .dll_export_fns = dll_export_fns,
3362 .keep_source_files_loaded = false,
33633365 .lib_dirs = lib_dirs.items,
33643366 .rpath_list = rpath_list.items,
33653367 .symbol_wrap_set = symbol_wrap_set,
......@@ -3443,7 +3445,6 @@ fn buildOutputType(
34433445 .test_runner_path = test_runner_path,
34443446 .disable_lld_caching = !output_to_cache,
34453447 .subsystem = subsystem,
3446 .debug_format = debug_format,
34473448 .debug_compile_errors = debug_compile_errors,
34483449 .enable_link_snapshots = enable_link_snapshots,
34493450 .install_name = install_name,
......@@ -3484,7 +3485,9 @@ fn buildOutputType(
34843485 defer if (!comp_destroyed) comp.destroy();
34853486
34863487 if (show_builtin) {
3487 return std.io.getStdOut().writeAll(try comp.generateBuiltinZigSource(arena));
3488 const builtin_mod = comp.root_mod.deps.get("builtin").?;
3489 const source = builtin_mod.builtin_file.?.source;
3490 return std.io.getStdOut().writeAll(source);
34883491 }
34893492 switch (listen) {
34903493 .none => {},
......@@ -3737,6 +3740,7 @@ fn createModule(
37373740 const resolved_target = cli_mod.inherited.resolved_target.?;
37383741 create_module.opts.resolved_target = resolved_target;
37393742 create_module.opts.root_optimize_mode = cli_mod.inherited.optimize_mode;
3743 create_module.opts.root_strip = cli_mod.inherited.strip;
37403744 const target = resolved_target.result;
37413745
37423746 // First, remove libc, libc++, and compiler_rt libraries from the system libraries list.
......@@ -4366,12 +4370,12 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati
43664370
43674371 const translated_zig_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{comp.root_name});
43684372
4369 var man: Cache.Manifest = comp.obtainCObjectCacheManifest();
4373 var man: Cache.Manifest = comp.obtainCObjectCacheManifest(comp.root_mod);
43704374 man.want_shared_lock = false;
43714375 defer man.deinit();
43724376
43734377 man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects
4374 man.hash.add(comp.c_frontend);
4378 man.hash.add(comp.config.c_frontend);
43754379 Compilation.cache_helpers.hashCSource(&man, c_source_file) catch |err| {
43764380 fatal("unable to process '{s}': {s}", .{ c_source_file.src_path, @errorName(err) });
43774381 };
......@@ -4380,14 +4384,14 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati
43804384 const digest = if (try man.hit()) man.final() else digest: {
43814385 if (fancy_output) |p| p.cache_hit = false;
43824386 var argv = std.ArrayList([]const u8).init(arena);
4383 try argv.append(@tagName(comp.c_frontend)); // argv[0] is program name, actual args start at [1]
4387 try argv.append(@tagName(comp.config.c_frontend)); // argv[0] is program name, actual args start at [1]
43844388
43854389 var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{});
43864390 defer zig_cache_tmp_dir.close();
43874391
43884392 const ext = Compilation.classifyFileExt(c_source_file.src_path);
43894393 const out_dep_path: ?[]const u8 = blk: {
4390 if (comp.c_frontend == .aro or comp.disable_c_depfile or !ext.clangSupportsDepFile())
4394 if (comp.config.c_frontend == .aro or comp.disable_c_depfile or !ext.clangSupportsDepFile())
43914395 break :blk null;
43924396
43934397 const c_src_basename = fs.path.basename(c_source_file.src_path);
......@@ -4397,14 +4401,15 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati
43974401 };
43984402
43994403 // TODO
4400 if (comp.c_frontend != .aro) try comp.addTranslateCCArgs(arena, &argv, ext, out_dep_path);
4404 if (comp.config.c_frontend != .aro)
4405 try comp.addTranslateCCArgs(arena, &argv, ext, out_dep_path, comp.root_mod);
44014406 try argv.append(c_source_file.src_path);
44024407
44034408 if (comp.verbose_cc) {
44044409 Compilation.dump_argv(argv.items);
44054410 }
44064411
4407 var tree = switch (comp.c_frontend) {
4412 var tree = switch (comp.config.c_frontend) {
44084413 .aro => tree: {
44094414 const aro = @import("aro");
44104415 const translate_c = @import("aro_translate_c.zig");