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,...@@ -20,8 +20,11 @@ wasi_exec_model: std.builtin.WasiExecModel,
2020
21pub fn generate(opts: @This(), allocator: Allocator) Allocator.Error![:0]u8 {21pub fn generate(opts: @This(), allocator: Allocator) Allocator.Error![:0]u8 {
22 var buffer = std.ArrayList(u8).init(allocator);22 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 {
25 const target = opts.target;28 const target = opts.target;
26 const generic_arch_name = target.cpu.arch.genericName();29 const generic_arch_name = target.cpu.arch.genericName();
27 const zig_backend = opts.zig_backend;30 const zig_backend = opts.zig_backend;
...@@ -231,10 +234,65 @@ pub fn generate(opts: @This(), allocator: Allocator) Allocator.Error![:0]u8 {...@@ -231,10 +234,65 @@ pub fn generate(opts: @This(), allocator: Allocator) Allocator.Error![:0]u8 {
231 );234 );
232 }235 }
233 }236 }
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 };
236}289}
237290
238const std = @import("std");291const std = @import("std");
239const Allocator = std.mem.Allocator;292const Allocator = std.mem.Allocator;
240const build_options = @import("build_options");293const 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");...@@ -37,6 +37,7 @@ const Zir = @import("Zir.zig");
37const Autodoc = @import("Autodoc.zig");37const Autodoc = @import("Autodoc.zig");
38const Color = @import("main.zig").Color;38const Color = @import("main.zig").Color;
39const resinator = @import("resinator.zig");39const resinator = @import("resinator.zig");
40const Builtin = @import("Builtin.zig");
4041
41pub const Config = @import("Compilation/Config.zig");42pub const Config = @import("Compilation/Config.zig");
4243
...@@ -59,7 +60,10 @@ root_mod: *Package.Module,...@@ -59,7 +60,10 @@ root_mod: *Package.Module,
59/// User-specified settings that have all the defaults resolved into concrete values.60/// User-specified settings that have all the defaults resolved into concrete values.
60config: Config,61config: 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.
63bin_file: ?*link.File,67bin_file: ?*link.File,
6468
65/// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin)69/// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin)
...@@ -80,6 +84,8 @@ version: ?std.SemanticVersion,...@@ -80,6 +84,8 @@ version: ?std.SemanticVersion,
80libc_installation: ?*const LibCInstallation,84libc_installation: ?*const LibCInstallation,
81skip_linker_dependencies: bool,85skip_linker_dependencies: bool,
82no_builtin: bool,86no_builtin: bool,
87function_sections: bool,
88data_sections: bool,
8389
84c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},90c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},
85win32_resource_table: if (build_options.only_core_functionality) void else std.AutoArrayHashMapUnmanaged(*Win32Resource, void) =91win32_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...@@ -120,7 +126,6 @@ failed_win32_resources: if (build_options.only_core_functionality) void else std
120/// Miscellaneous things that can fail.126/// Miscellaneous things that can fail.
121misc_failures: std.AutoArrayHashMapUnmanaged(MiscTask, MiscError) = .{},127misc_failures: std.AutoArrayHashMapUnmanaged(MiscTask, MiscError) = .{},
122128
123keep_source_files_loaded: bool,
124/// When this is `true` it means invoking clang as a sub-process is expected to inherit129/// When this is `true` it means invoking clang as a sub-process is expected to inherit
125/// stdin, stdout, stderr, and if it returns non success, to forward the exit code.130/// stdin, stdout, stderr, and if it returns non success, to forward the exit code.
126/// Otherwise we attempt to parse the error messages and expose them via the Compilation API.131/// Otherwise we attempt to parse the error messages and expose them via the Compilation API.
...@@ -144,6 +149,7 @@ debug_compiler_runtime_libs: bool,...@@ -144,6 +149,7 @@ debug_compiler_runtime_libs: bool,
144debug_compile_errors: bool,149debug_compile_errors: bool,
145job_queued_compiler_rt_lib: bool = false,150job_queued_compiler_rt_lib: bool = false,
146job_queued_compiler_rt_obj: bool = false,151job_queued_compiler_rt_obj: bool = false,
152job_queued_update_builtin_zig: bool,
147alloc_failure_occurred: bool = false,153alloc_failure_occurred: bool = false,
148formatted_panics: bool = false,154formatted_panics: bool = false,
149last_update_was_cache_hit: bool = false,155last_update_was_cache_hit: bool = false,
...@@ -814,13 +820,13 @@ pub const cache_helpers = struct {...@@ -814,13 +820,13 @@ pub const cache_helpers = struct {
814 addEmitLoc(hh, optional_emit_loc orelse return);820 addEmitLoc(hh, optional_emit_loc orelse return);
815 }821 }
816822
817 pub fn addOptionalDebugFormat(hh: *Cache.HashHelper, x: ?link.File.DebugFormat) void {823 pub fn addOptionalDebugFormat(hh: *Cache.HashHelper, x: ?Config.DebugFormat) void {
818 hh.add(x != null);824 hh.add(x != null);
819 addDebugFormat(hh, x orelse return);825 addDebugFormat(hh, x orelse return);
820 }826 }
821827
822 pub fn addDebugFormat(hh: *Cache.HashHelper, x: link.File.DebugFormat) void {828 pub fn addDebugFormat(hh: *Cache.HashHelper, x: Config.DebugFormat) void {
823 const tag: @typeInfo(link.File.DebugFormat).Union.tag_type.? = x;829 const tag: @typeInfo(Config.DebugFormat).Union.tag_type.? = x;
824 hh.add(tag);830 hh.add(tag);
825 switch (x) {831 switch (x) {
826 .strip, .code_view => {},832 .strip, .code_view => {},
...@@ -860,11 +866,11 @@ pub const SystemLib = link.SystemLib;...@@ -860,11 +866,11 @@ pub const SystemLib = link.SystemLib;
860866
861pub const CacheMode = enum { incremental, whole };867pub const CacheMode = enum { incremental, whole };
862868
863pub const CacheUse = union(CacheMode) {869const CacheUse = union(CacheMode) {
864 incremental: *Incremental,870 incremental: *Incremental,
865 whole: *Whole,871 whole: *Whole,
866872
867 pub const Whole = struct {873 const Whole = struct {
868 /// This is a pointer to a local variable inside `update()`.874 /// This is a pointer to a local variable inside `update()`.
869 cache_manifest: ?*Cache.Manifest = null,875 cache_manifest: ?*Cache.Manifest = null,
870 cache_manifest_mutex: std.Thread.Mutex = .{},876 cache_manifest_mutex: std.Thread.Mutex = .{},
...@@ -873,12 +879,14 @@ pub const CacheUse = union(CacheMode) {...@@ -873,12 +879,14 @@ pub const CacheUse = union(CacheMode) {
873 /// of exactly the correct size for "o/[digest]/[basename]".879 /// of exactly the correct size for "o/[digest]/[basename]".
874 /// The basename is of the outputted binary file in case we don't know the directory yet.880 /// The basename is of the outputted binary file in case we don't know the directory yet.
875 bin_sub_path: ?[]u8,881 bin_sub_path: ?[]u8,
876 /// Same as `whole_bin_sub_path` but for implibs.882 /// Same as `bin_sub_path` but for implibs.
877 implib_sub_path: ?[]u8,883 implib_sub_path: ?[]u8,
878 docs_sub_path: ?[]u8,884 docs_sub_path: ?[]u8,
885 lf_open_opts: link.File.OpenOptions,
886 tmp_artifact_directory: ?Cache.Directory,
879 };887 };
880888
881 pub const Incremental = struct {889 const Incremental = struct {
882 /// Where build artifacts and incremental compilation metadata serialization go.890 /// Where build artifacts and incremental compilation metadata serialization go.
883 artifact_directory: Compilation.Directory,891 artifact_directory: Compilation.Directory,
884 };892 };
...@@ -937,7 +945,6 @@ pub const InitOptions = struct {...@@ -937,7 +945,6 @@ pub const InitOptions = struct {
937 /// this flag would be set to disable this machinery to avoid false positives.945 /// this flag would be set to disable this machinery to avoid false positives.
938 disable_lld_caching: bool = false,946 disable_lld_caching: bool = false,
939 cache_mode: CacheMode = .incremental,947 cache_mode: CacheMode = .incremental,
940 keep_source_files_loaded: bool = false,
941 lib_dirs: []const []const u8 = &[0][]const u8{},948 lib_dirs: []const []const u8 = &[0][]const u8{},
942 rpath_list: []const []const u8 = &[0][]const u8{},949 rpath_list: []const []const u8 = &[0][]const u8{},
943 symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{},950 symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{},
...@@ -1040,7 +1047,6 @@ pub const InitOptions = struct {...@@ -1040,7 +1047,6 @@ pub const InitOptions = struct {
1040 test_name_prefix: ?[]const u8 = null,1047 test_name_prefix: ?[]const u8 = null,
1041 test_runner_path: ?[]const u8 = null,1048 test_runner_path: ?[]const u8 = null,
1042 subsystem: ?std.Target.SubSystem = null,1049 subsystem: ?std.Target.SubSystem = null,
1043 debug_format: ?link.File.DebugFormat = null,
1044 /// (Zig compiler development) Enable dumping linker's state as JSON.1050 /// (Zig compiler development) Enable dumping linker's state as JSON.
1045 enable_link_snapshots: bool = false,1051 enable_link_snapshots: bool = false,
1046 /// (Darwin) Install name of the dylib1052 /// (Darwin) Install name of the dylib
...@@ -1327,7 +1333,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1327,7 +1333,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1327 cache.hash.add(options.config.link_libcpp);1333 cache.hash.add(options.config.link_libcpp);
1328 cache.hash.add(options.config.link_libunwind);1334 cache.hash.add(options.config.link_libunwind);
1329 cache.hash.add(output_mode);1335 cache.hash.add(output_mode);
1330 cache_helpers.addOptionalDebugFormat(&cache.hash, options.debug_format);1336 cache_helpers.addDebugFormat(&cache.hash, comp.config.debug_format);
1331 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_bin);1337 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_bin);
1332 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_implib);1338 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_implib);
1333 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs);1339 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs);
...@@ -1380,7 +1386,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1380,7 +1386,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1380 };1386 };
1381 errdefer if (opt_zcu) |zcu| zcu.deinit();1387 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(
1384 gpa,1390 gpa,
1385 options.system_lib_names,1391 options.system_lib_names,
1386 options.system_lib_infos,1392 options.system_lib_infos,
...@@ -1409,7 +1415,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1409,7 +1415,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1409 .win32_resource_work_queue = if (build_options.only_core_functionality) {} else std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa),1415 .win32_resource_work_queue = if (build_options.only_core_functionality) {} else std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa),
1410 .astgen_work_queue = std.fifo.LinearFifo(*Module.File, .Dynamic).init(gpa),1416 .astgen_work_queue = std.fifo.LinearFifo(*Module.File, .Dynamic).init(gpa),
1411 .embed_file_work_queue = std.fifo.LinearFifo(*Module.EmbedFile, .Dynamic).init(gpa),1417 .embed_file_work_queue = std.fifo.LinearFifo(*Module.EmbedFile, .Dynamic).init(gpa),
1412 .keep_source_files_loaded = options.keep_source_files_loaded,
1413 .c_source_files = options.c_source_files,1418 .c_source_files = options.c_source_files,
1414 .rc_source_files = options.rc_source_files,1419 .rc_source_files = options.rc_source_files,
1415 .cache_parent = cache,1420 .cache_parent = cache,
...@@ -1451,10 +1456,12 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1451,10 +1456,12 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1451 .llvm_opt_bisect_limit = options.llvm_opt_bisect_limit,1456 .llvm_opt_bisect_limit = options.llvm_opt_bisect_limit,
1452 .skip_linker_dependencies = options.skip_linker_dependencies,1457 .skip_linker_dependencies = options.skip_linker_dependencies,
1453 .no_builtin = options.no_builtin,1458 .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,
1454 };1462 };
14551463
1456 const lf_open_opts: link.File.OpenOptions = .{1464 const lf_open_opts: link.File.OpenOptions = .{
1457 .comp = comp,
1458 .linker_script = options.linker_script,1465 .linker_script = options.linker_script,
1459 .z_nodelete = options.linker_z_nodelete,1466 .z_nodelete = options.linker_z_nodelete,
1460 .z_notext = options.linker_z_notext,1467 .z_notext = options.linker_z_notext,
...@@ -1471,8 +1478,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1471,8 +1478,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1471 .lib_dirs = options.lib_dirs,1478 .lib_dirs = options.lib_dirs,
1472 .rpath_list = options.rpath_list,1479 .rpath_list = options.rpath_list,
1473 .symbol_wrap_set = options.symbol_wrap_set,1480 .symbol_wrap_set = options.symbol_wrap_set,
1474 .function_sections = options.function_sections,
1475 .data_sections = options.data_sections,
1476 .allow_shlib_undefined = options.linker_allow_shlib_undefined,1481 .allow_shlib_undefined = options.linker_allow_shlib_undefined,
1477 .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,1482 .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,
1478 .compress_debug_sections = options.linker_compress_debug_sections orelse .none,1483 .compress_debug_sections = options.linker_compress_debug_sections orelse .none,
...@@ -1507,7 +1512,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1507,7 +1512,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1507 .build_id = build_id,1512 .build_id = build_id,
1508 .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole,1513 .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole,
1509 .subsystem = options.subsystem,1514 .subsystem = options.subsystem,
1510 .debug_format = options.debug_format,
1511 .hash_style = options.hash_style,1515 .hash_style = options.hash_style,
1512 .enable_link_snapshots = options.enable_link_snapshots,1516 .enable_link_snapshots = options.enable_link_snapshots,
1513 .install_name = options.install_name,1517 .install_name = options.install_name,
...@@ -1572,17 +1576,17 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1572,17 +1576,17 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1572 .directory = emit_bin.directory orelse artifact_directory,1576 .directory = emit_bin.directory orelse artifact_directory,
1573 .sub_path = emit_bin.basename,1577 .sub_path = emit_bin.basename,
1574 };1578 };
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);
1576 }1580 }
15771581
1578 if (options.implib_emit) |emit_implib| {1582 if (options.emit_implib) |emit_implib| {
1579 comp.implib_emit = .{1583 comp.implib_emit = .{
1580 .directory = emit_implib.directory orelse artifact_directory,1584 .directory = emit_implib.directory orelse artifact_directory,
1581 .sub_path = emit_implib.basename,1585 .sub_path = emit_implib.basename,
1582 };1586 };
1583 }1587 }
15841588
1585 if (options.docs_emit) |emit_docs| {1589 if (options.emit_docs) |emit_docs| {
1586 comp.docs_emit = .{1590 comp.docs_emit = .{
1587 .directory = emit_docs.directory orelse artifact_directory,1591 .directory = emit_docs.directory orelse artifact_directory,
1588 .sub_path = emit_docs.basename,1592 .sub_path = emit_docs.basename,
...@@ -1610,6 +1614,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1610,6 +1614,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1610 .bin_sub_path = try prepareWholeEmitSubPath(arena, options.emit_bin),1614 .bin_sub_path = try prepareWholeEmitSubPath(arena, options.emit_bin),
1611 .implib_sub_path = try prepareWholeEmitSubPath(arena, options.emit_implib),1615 .implib_sub_path = try prepareWholeEmitSubPath(arena, options.emit_implib),
1612 .docs_sub_path = try prepareWholeEmitSubPath(arena, options.emit_docs),1616 .docs_sub_path = try prepareWholeEmitSubPath(arena, options.emit_docs),
1617 .tmp_artifact_directory = null,
1613 };1618 };
1614 comp.cache_use = .{ .whole = whole };1619 comp.cache_use = .{ .whole = whole };
1615 },1620 },
...@@ -1662,7 +1667,10 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1662,7 +1667,10 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1662 }1667 }
1663 }1668 }
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
1667 if (have_bin_emit and !comp.skip_linker_dependencies and target.ofmt != .c) {1675 if (have_bin_emit and !comp.skip_linker_dependencies and target.ofmt != .c) {
1668 if (target.isDarwin()) {1676 if (target.isDarwin()) {
...@@ -1814,8 +1822,13 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1814,8 +1822,13 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1814pub fn destroy(self: *Compilation) void {1822pub fn destroy(self: *Compilation) void {
1815 if (self.bin_file) |lf| lf.destroy();1823 if (self.bin_file) |lf| lf.destroy();
1816 if (self.module) |zcu| zcu.deinit();1824 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;
1819 self.work_queue.deinit();1832 self.work_queue.deinit();
1820 self.anon_work_queue.deinit();1833 self.anon_work_queue.deinit();
1821 self.c_object_work_queue.deinit();1834 self.c_object_work_queue.deinit();
...@@ -1825,6 +1838,9 @@ pub fn destroy(self: *Compilation) void {...@@ -1825,6 +1838,9 @@ pub fn destroy(self: *Compilation) void {
1825 self.astgen_work_queue.deinit();1838 self.astgen_work_queue.deinit();
1826 self.embed_file_work_queue.deinit();1839 self.embed_file_work_queue.deinit();
18271840
1841 const gpa = self.gpa;
1842 self.system_libs.deinit(gpa);
1843
1828 {1844 {
1829 var it = self.crt_files.iterator();1845 var it = self.crt_files.iterator();
1830 while (it.next()) |entry| {1846 while (it.next()) |entry| {
...@@ -1914,7 +1930,7 @@ pub fn hotCodeSwap(comp: *Compilation, prog_node: *std.Progress.Node, pid: std.C...@@ -1914,7 +1930,7 @@ pub fn hotCodeSwap(comp: *Compilation, prog_node: *std.Progress.Node, pid: std.C
1914}1930}
19151931
1916fn cleanupAfterUpdate(comp: *Compilation) void {1932fn cleanupAfterUpdate(comp: *Compilation) void {
1917 switch (comp) {1933 switch (comp.cache_use) {
1918 .incremental => return,1934 .incremental => return,
1919 .whole => |whole| {1935 .whole => |whole| {
1920 if (whole.cache_manifest) |man| {1936 if (whole.cache_manifest) |man| {
...@@ -1971,7 +1987,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void...@@ -1971,7 +1987,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
1971 log.debug("CacheMode.whole cache hit for {s}", .{comp.root_name});1987 log.debug("CacheMode.whole cache hit for {s}", .{comp.root_name});
1972 const digest = man.final();1988 const digest = man.final();
19731989
1974 comp.wholeCacheModeSetBinFilePath(&digest);1990 comp.wholeCacheModeSetBinFilePath(whole, &digest);
19751991
1976 assert(comp.bin_file.lock == null);1992 assert(comp.bin_file.lock == null);
1977 comp.bin_file.lock = man.toOwnedLock();1993 comp.bin_file.lock = man.toOwnedLock();
...@@ -2001,21 +2017,21 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void...@@ -2001,21 +2017,21 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
2001 // Now that the directory is known, it is time to create the Emit2017 // Now that the directory is known, it is time to create the Emit
2002 // objects and call link.File.open.2018 // objects and call link.File.open.
20032019
2004 if (comp.whole_implib_sub_path) |sub_path| {2020 if (whole.implib_sub_path) |sub_path| {
2005 comp.implib_emit = .{2021 comp.implib_emit = .{
2006 .directory = tmp_artifact_directory,2022 .directory = tmp_artifact_directory,
2007 .sub_path = std.fs.path.basename(sub_path),2023 .sub_path = std.fs.path.basename(sub_path),
2008 };2024 };
2009 }2025 }
20102026
2011 if (comp.whole_docs_sub_path) |sub_path| {2027 if (whole.docs_sub_path) |sub_path| {
2012 comp.docs_emit = .{2028 comp.docs_emit = .{
2013 .directory = tmp_artifact_directory,2029 .directory = tmp_artifact_directory,
2014 .sub_path = std.fs.path.basename(sub_path),2030 .sub_path = std.fs.path.basename(sub_path),
2015 };2031 };
2016 }2032 }
20172033
2018 if (comp.whole_bin_sub_path) |sub_path| {2034 if (whole.bin_sub_path) |sub_path| {
2019 const emit: Emit = .{2035 const emit: Emit = .{
2020 .directory = tmp_artifact_directory,2036 .directory = tmp_artifact_directory,
2021 .sub_path = std.fs.path.basename(sub_path),2037 .sub_path = std.fs.path.basename(sub_path),
...@@ -2024,7 +2040,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void...@@ -2024,7 +2040,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
2024 // but in practice it won't leak much and usually whole cache mode2040 // but in practice it won't leak much and usually whole cache mode
2025 // will be combined with exactly one call to update().2041 // will be combined with exactly one call to update().
2026 const arena = comp.arena.allocator();2042 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);
2028 }2044 }
2029 },2045 },
2030 .incremental => {},2046 .incremental => {},
...@@ -2158,7 +2174,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void...@@ -2158,7 +2174,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
2158 const o_sub_path = "o" ++ s ++ digest;2174 const o_sub_path = "o" ++ s ++ digest;
21592175
2160 try renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path);2176 try renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path);
2161 comp.wholeCacheModeSetBinFilePath(&digest);2177 comp.wholeCacheModeSetBinFilePath(whole, &digest);
21622178
2163 // Failure here only means an unnecessary cache miss.2179 // Failure here only means an unnecessary cache miss.
2164 man.writeManifest() catch |err| {2180 man.writeManifest() catch |err| {
...@@ -2170,19 +2186,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void...@@ -2170,19 +2186,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
2170 },2186 },
2171 .incremental => {},2187 .incremental => {},
2172 }2188 }
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 }
2186}2189}
21872190
2188/// This function is called by the frontend before flush(). It communicates that2191/// 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 {...@@ -2274,10 +2277,14 @@ fn flush(comp: *Compilation, prog_node: *std.Progress.Node) !void {
2274}2277}
22752278
2276/// Communicate the output binary location to parent Compilations.2279/// 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 {
2278 const digest_start = 2; // "o/[digest]/[basename]"2285 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| {
2281 @memcpy(sub_path[digest_start..][0..digest.len], digest);2288 @memcpy(sub_path[digest_start..][0..digest.len], digest);
22822289
2283 comp.bin_file.?.emit = .{2290 comp.bin_file.?.emit = .{
...@@ -2286,7 +2293,7 @@ fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_di...@@ -2286,7 +2293,7 @@ fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_di
2286 };2293 };
2287 }2294 }
22882295
2289 if (comp.whole_implib_sub_path) |sub_path| {2296 if (whole.implib_sub_path) |sub_path| {
2290 @memcpy(sub_path[digest_start..][0..digest.len], digest);2297 @memcpy(sub_path[digest_start..][0..digest.len], digest);
22912298
2292 comp.implib_emit = .{2299 comp.implib_emit = .{
...@@ -2295,7 +2302,7 @@ fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_di...@@ -2295,7 +2302,7 @@ fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_di
2295 };2302 };
2296 }2303 }
22972304
2298 if (comp.whole_docs_sub_path) |sub_path| {2305 if (whole.docs_sub_path) |sub_path| {
2299 @memcpy(sub_path[digest_start..][0..digest.len], digest);2306 @memcpy(sub_path[digest_start..][0..digest.len], digest);
23002307
2301 comp.docs_emit = .{2308 comp.docs_emit = .{
...@@ -3232,13 +3239,25 @@ pub fn performAllTheWork(...@@ -3232,13 +3239,25 @@ pub fn performAllTheWork(
3232 // 1. to avoid race condition of zig processes truncating each other's builtin.zig files3239 // 1. to avoid race condition of zig processes truncating each other's builtin.zig files
3233 // 2. optimization; in the hot path it only incurs a stat() syscall, which happens3240 // 2. optimization; in the hot path it only incurs a stat() syscall, which happens
3234 // in the `astgen_wait_group`.3241 // in the `astgen_wait_group`.
3235 if (comp.module) |mod| {3242 if (comp.job_queued_update_builtin_zig) b: {
3236 if (mod.job_queued_update_builtin_zig) {3243 comp.job_queued_update_builtin_zig = false;
3237 mod.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
3239 comp.astgen_wait_group.start();3258 comp.astgen_wait_group.start();
3240 try comp.thread_pool.spawn(workerUpdateBuiltinZigFile, .{3259 try comp.thread_pool.spawn(workerUpdateBuiltinZigFile, .{
3241 comp, mod, &comp.astgen_wait_group,3260 comp, mod, file, &comp.astgen_wait_group,
3242 });3261 });
3243 }3262 }
3244 }3263 }
...@@ -3702,19 +3721,17 @@ fn workerAstGenFile(...@@ -3702,19 +3721,17 @@ fn workerAstGenFile(
37023721
3703fn workerUpdateBuiltinZigFile(3722fn workerUpdateBuiltinZigFile(
3704 comp: *Compilation,3723 comp: *Compilation,
3705 mod: *Module,3724 mod: *Package.Module,
3725 file: *Module.File,
3706 wg: *WaitGroup,3726 wg: *WaitGroup,
3707) void {3727) void {
3708 defer wg.finish();3728 defer wg.finish();
37093729 Builtin.populateFile(comp, mod, file) catch |err| {
3710 mod.populateBuiltinFile() catch |err| {
3711 const dir_path: []const u8 = mod.zig_cache_artifact_directory.path orelse ".";
3712
3713 comp.mutex.lock();3730 comp.mutex.lock();
3714 defer comp.mutex.unlock();3731 defer comp.mutex.unlock();
37153732
3716 comp.setMiscFailure(.write_builtin_zig, "unable to write builtin.zig to {s}: {s}", .{3733 comp.setMiscFailure(.write_builtin_zig, "unable to write '{}{s}': {s}", .{
3717 dir_path, @errorName(err),3734 mod.root, mod.root_src_path, @errorName(err),
3718 });3735 });
3719 };3736 };
3720}3737}
...@@ -3755,14 +3772,17 @@ fn detectEmbedFileUpdate(comp: *Compilation, embed_file: *Module.EmbedFile) !voi...@@ -3755,14 +3772,17 @@ fn detectEmbedFileUpdate(comp: *Compilation, embed_file: *Module.EmbedFile) !voi
3755 @panic("TODO: handle embed file incremental update");3772 @panic("TODO: handle embed file incremental update");
3756}3773}
37573774
3758pub fn obtainCObjectCacheManifest(comp: *const Compilation) Cache.Manifest {3775pub fn obtainCObjectCacheManifest(
3776 comp: *const Compilation,
3777 owner_mod: *Package.Module,
3778) Cache.Manifest {
3759 var man = comp.cache_parent.obtain();3779 var man = comp.cache_parent.obtain();
37603780
3761 // Only things that need to be added on top of the base hash, and only things3781 // Only things that need to be added on top of the base hash, and only things
3762 // that apply both to @cImport and compiling C objects. No linking stuff here!3782 // that apply both to @cImport and compiling C objects. No linking stuff here!
3763 // Also nothing that applies only to compiling .zig code.3783 // Also nothing that applies only to compiling .zig code.
3764 man.hash.add(comp.sanitize_c);3784 man.hash.add(owner_mod.sanitize_c);
3765 man.hash.addListOfBytes(comp.clang_argv);3785 man.hash.addListOfBytes(owner_mod.clang_argv);
3766 man.hash.add(comp.config.link_libcpp);3786 man.hash.add(comp.config.link_libcpp);
37673787
3768 // When libc_installation is null it means that Zig generated this dir list3788 // When libc_installation is null it means that Zig generated this dir list
...@@ -3797,19 +3817,19 @@ pub const CImportResult = struct {...@@ -3797,19 +3817,19 @@ pub const CImportResult = struct {
3797/// Caller owns returned memory.3817/// Caller owns returned memory.
3798/// This API is currently coupled pretty tightly to stage1's needs; it will need to be reworked3818/// This API is currently coupled pretty tightly to stage1's needs; it will need to be reworked
3799/// a bit when we want to start using it from self-hosted.3819/// 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 {
3801 if (build_options.only_core_functionality) @panic("@cImport is not available in a zig2.c build");3821 if (build_options.only_core_functionality) @panic("@cImport is not available in a zig2.c build");
3802 const tracy_trace = trace(@src());3822 const tracy_trace = trace(@src());
3803 defer tracy_trace.end();3823 defer tracy_trace.end();
38043824
3805 const cimport_zig_basename = "cimport.zig";3825 const cimport_zig_basename = "cimport.zig";
38063826
3807 var man = comp.obtainCObjectCacheManifest();3827 var man = comp.obtainCObjectCacheManifest(owner_mod);
3808 defer man.deinit();3828 defer man.deinit();
38093829
3810 man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects3830 man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects
3811 man.hash.addBytes(c_src);3831 man.hash.addBytes(c_src);
3812 man.hash.add(comp.c_frontend);3832 man.hash.add(comp.config.c_frontend);
38133833
3814 // If the previous invocation resulted in clang errors, we will see a hit3834 // If the previous invocation resulted in clang errors, we will see a hit
3815 // here with 0 files in the manifest, in which case it is actually a miss.3835 // 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 {...@@ -3846,15 +3866,15 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
3846 var argv = std.ArrayList([]const u8).init(comp.gpa);3866 var argv = std.ArrayList([]const u8).init(comp.gpa);
3847 defer argv.deinit();3867 defer argv.deinit();
38483868
3849 try argv.append(@tagName(comp.c_frontend)); // argv[0] is program name, actual args start at [1]3869 try argv.append(@tagName(comp.config.c_frontend)); // argv[0] is program name, actual args start at [1]
3850 try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path);3870 try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path, owner_mod);
38513871
3852 try argv.append(out_h_path);3872 try argv.append(out_h_path);
38533873
3854 if (comp.verbose_cc) {3874 if (comp.verbose_cc) {
3855 dump_argv(argv.items);3875 dump_argv(argv.items);
3856 }3876 }
3857 var tree = switch (comp.c_frontend) {3877 var tree = switch (comp.config.c_frontend) {
3858 .aro => tree: {3878 .aro => tree: {
3859 const translate_c = @import("aro_translate_c.zig");3879 const translate_c = @import("aro_translate_c.zig");
3860 _ = translate_c;3880 _ = translate_c;
...@@ -4119,7 +4139,7 @@ fn reportRetryableEmbedFileError(...@@ -4119,7 +4139,7 @@ fn reportRetryableEmbedFileError(
4119}4139}
41204140
4121fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.Progress.Node) !void {4141fn 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) {
4123 return comp.failCObj(c_object, "aro does not support compiling C objects yet", .{});4143 return comp.failCObj(c_object, "aro does not support compiling C objects yet", .{});
4124 }4144 }
4125 if (!build_options.have_llvm) {4145 if (!build_options.have_llvm) {
...@@ -4142,7 +4162,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P...@@ -4142,7 +4162,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
4142 _ = comp.failed_c_objects.swapRemove(c_object);4162 _ = comp.failed_c_objects.swapRemove(c_object);
4143 }4163 }
41444164
4145 var man = comp.obtainCObjectCacheManifest();4165 var man = comp.obtainCObjectCacheManifest(c_object.src.owner);
4146 defer man.deinit();4166 defer man.deinit();
41474167
4148 man.hash.add(comp.clang_preprocessor_mode);4168 man.hash.add(comp.clang_preprocessor_mode);
...@@ -4219,7 +4239,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P...@@ -4219,7 +4239,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
4219 if (std.process.can_execv and direct_o and4239 if (std.process.can_execv and direct_o and
4220 comp.disable_c_depfile and comp.clang_passthrough_mode)4240 comp.disable_c_depfile and comp.clang_passthrough_mode)
4221 {4241 {
4222 try comp.addCCArgs(arena, &argv, ext, null);4242 try comp.addCCArgs(arena, &argv, ext, null, c_object.src.owner);
4223 try argv.appendSlice(c_object.src.extra_flags);4243 try argv.appendSlice(c_object.src.extra_flags);
4224 try argv.appendSlice(c_object.src.cache_exempt_flags);4244 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...@@ -4262,7 +4282,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
4262 null4282 null
4263 else4283 else
4264 try std.fmt.allocPrint(arena, "{s}.d", .{out_obj_path});4284 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);
4266 try argv.appendSlice(c_object.src.extra_flags);4286 try argv.appendSlice(c_object.src.extra_flags);
4267 try argv.appendSlice(c_object.src.cache_exempt_flags);4287 try argv.appendSlice(c_object.src.cache_exempt_flags);
42684288
...@@ -4610,7 +4630,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -4610,7 +4630,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
4610 // mode. While these defines are not normally present when calling rc.exe directly,4630 // mode. While these defines are not normally present when calling rc.exe directly,
4611 // them being defined matches the behavior of how MSVC calls rc.exe which is the more4631 // them being defined matches the behavior of how MSVC calls rc.exe which is the more
4612 // relevant behavior in this case.4632 // 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
4615 if (comp.verbose_cc) {4635 if (comp.verbose_cc) {
4616 dump_argv(argv.items);4636 dump_argv(argv.items);
...@@ -4788,11 +4808,12 @@ pub fn addTranslateCCArgs(...@@ -4788,11 +4808,12 @@ pub fn addTranslateCCArgs(
4788 argv: *std.ArrayList([]const u8),4808 argv: *std.ArrayList([]const u8),
4789 ext: FileExt,4809 ext: FileExt,
4790 out_dep_path: ?[]const u8,4810 out_dep_path: ?[]const u8,
4811 owner_mod: *Package.Module,
4791) !void {4812) !void {
4792 try argv.appendSlice(&[_][]const u8{ "-x", "c" });4813 try argv.appendSlice(&.{ "-x", "c" });
4793 try comp.addCCArgs(arena, argv, ext, out_dep_path);4814 try comp.addCCArgs(arena, argv, ext, out_dep_path, owner_mod);
4794 // This gives us access to preprocessing entities, presumably at the cost of performance.4815 // 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" });
4796}4817}
47974818
4798/// Add common C compiler args between translate-c and C object compilation.4819/// Add common C compiler args between translate-c and C object compilation.
...@@ -4825,11 +4846,11 @@ pub fn addCCArgs(...@@ -4825,11 +4846,11 @@ pub fn addCCArgs(
4825 try argv.append("-fno-caret-diagnostics");4846 try argv.append("-fno-caret-diagnostics");
4826 }4847 }
48274848
4828 if (comp.bin_file.function_sections) {4849 if (comp.function_sections) {
4829 try argv.append("-ffunction-sections");4850 try argv.append("-ffunction-sections");
4830 }4851 }
48314852
4832 if (comp.bin_file.data_sections) {4853 if (comp.data_sections) {
4833 try argv.append("-fdata-sections");4854 try argv.append("-fdata-sections");
4834 }4855 }
48354856
...@@ -5088,7 +5109,7 @@ pub fn addCCArgs(...@@ -5088,7 +5109,7 @@ pub fn addCCArgs(
5088 try argv.append("-fPIC");5109 try argv.append("-fPIC");
5089 }5110 }
50905111
5091 if (comp.unwind_tables) {5112 if (mod.unwind_tables) {
5092 try argv.append("-funwind-tables");5113 try argv.append("-funwind-tables");
5093 } else {5114 } else {
5094 try argv.append("-fno-unwind-tables");5115 try argv.append("-fno-unwind-tables");
...@@ -5174,7 +5195,7 @@ pub fn addCCArgs(...@@ -5174,7 +5195,7 @@ pub fn addCCArgs(
5174 }5195 }
51755196
5176 try argv.ensureUnusedCapacity(2);5197 try argv.ensureUnusedCapacity(2);
5177 switch (comp.bin_file.debug_format) {5198 switch (comp.config.debug_format) {
5178 .strip => {},5199 .strip => {},
5179 .code_view => {5200 .code_view => {
5180 // -g is required here because -gcodeview doesn't trigger debug info5201 // -g is required here because -gcodeview doesn't trigger debug info
...@@ -5210,7 +5231,7 @@ pub fn addCCArgs(...@@ -5210,7 +5231,7 @@ pub fn addCCArgs(
5210 try argv.append("-ffreestanding");5231 try argv.append("-ffreestanding");
5211 }5232 }
52125233
5213 try argv.appendSlice(comp.clang_argv);5234 try argv.appendSlice(mod.cc_argv);
5214}5235}
52155236
5216fn failCObj(5237fn failCObj(
...@@ -6094,6 +6115,7 @@ fn buildOutputFromZig(...@@ -6094,6 +6115,7 @@ fn buildOutputFromZig(
6094 .have_zcu = true,6115 .have_zcu = true,
6095 .emit_bin = true,6116 .emit_bin = true,
6096 .root_optimize_mode = comp.compilerRtOptMode(),6117 .root_optimize_mode = comp.compilerRtOptMode(),
6118 .root_strip = comp.compilerRtStrip(),
6097 .link_libc = comp.config.link_libc,6119 .link_libc = comp.config.link_libc,
6098 .any_unwind_tables = unwind_tables,6120 .any_unwind_tables = unwind_tables,
6099 });6121 });
...@@ -6198,6 +6220,7 @@ pub fn build_crt_file(...@@ -6198,6 +6220,7 @@ pub fn build_crt_file(
6198 .have_zcu = false,6220 .have_zcu = false,
6199 .emit_bin = true,6221 .emit_bin = true,
6200 .root_optimize_mode = comp.compilerRtOptMode(),6222 .root_optimize_mode = comp.compilerRtOptMode(),
6223 .root_strip = comp.compilerRtStrip(),
6201 .link_libc = false,6224 .link_libc = false,
6202 .lto = switch (output_mode) {6225 .lto = switch (output_mode) {
6203 .Lib => comp.config.lto,6226 .Lib => comp.config.lto,
src/Compilation/Config.zig+31
...@@ -33,9 +33,16 @@ shared_memory: bool,...@@ -33,9 +33,16 @@ shared_memory: bool,
33is_test: bool,33is_test: bool,
34test_evented_io: bool,34test_evented_io: bool,
35entry: ?[]const u8,35entry: ?[]const u8,
36debug_format: DebugFormat,
3637
37pub const CFrontend = enum { clang, aro };38pub const CFrontend = enum { clang, aro };
3839
40pub const DebugFormat = union(enum) {
41 strip,
42 dwarf: std.dwarf.Format,
43 code_view,
44};
45
39pub const Options = struct {46pub const Options = struct {
40 output_mode: std.builtin.OutputMode,47 output_mode: std.builtin.OutputMode,
41 resolved_target: Module.ResolvedTarget,48 resolved_target: Module.ResolvedTarget,
...@@ -43,6 +50,7 @@ pub const Options = struct {...@@ -43,6 +50,7 @@ pub const Options = struct {
43 have_zcu: bool,50 have_zcu: bool,
44 emit_bin: bool,51 emit_bin: bool,
45 root_optimize_mode: ?std.builtin.OptimizeMode = null,52 root_optimize_mode: ?std.builtin.OptimizeMode = null,
53 root_strip: ?bool = null,
46 link_mode: ?std.builtin.LinkMode = null,54 link_mode: ?std.builtin.LinkMode = null,
47 ensure_libc_on_non_freestanding: bool = false,55 ensure_libc_on_non_freestanding: bool = false,
48 ensure_libcpp_on_non_freestanding: bool = false,56 ensure_libcpp_on_non_freestanding: bool = false,
...@@ -51,6 +59,7 @@ pub const Options = struct {...@@ -51,6 +59,7 @@ pub const Options = struct {
51 any_unwind_tables: bool = false,59 any_unwind_tables: bool = false,
52 any_dyn_libs: bool = false,60 any_dyn_libs: bool = false,
53 any_c_source_files: bool = false,61 any_c_source_files: bool = false,
62 any_non_stripped: bool = false,
54 emit_llvm_ir: bool = false,63 emit_llvm_ir: bool = false,
55 emit_llvm_bc: bool = false,64 emit_llvm_bc: bool = false,
56 link_libc: ?bool = null,65 link_libc: ?bool = null,
...@@ -74,6 +83,7 @@ pub const Options = struct {...@@ -74,6 +83,7 @@ pub const Options = struct {
74 export_memory: ?bool = null,83 export_memory: ?bool = null,
75 shared_memory: ?bool = null,84 shared_memory: ?bool = null,
76 test_evented_io: bool = false,85 test_evented_io: bool = false,
86 debug_format: ?Config.DebugFormat = null,
77};87};
7888
79pub fn resolve(options: Options) !Config {89pub fn resolve(options: Options) !Config {
...@@ -365,6 +375,26 @@ pub fn resolve(options: Options) !Config {...@@ -365,6 +375,26 @@ pub fn resolve(options: Options) !Config {
365 break :b false;375 break :b false;
366 };376 };
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
368 return .{398 return .{
369 .output_mode = options.output_mode,399 .output_mode = options.output_mode,
370 .have_zcu = options.have_zcu,400 .have_zcu = options.have_zcu,
...@@ -388,6 +418,7 @@ pub fn resolve(options: Options) !Config {...@@ -388,6 +418,7 @@ pub fn resolve(options: Options) !Config {
388 .use_lld = use_lld,418 .use_lld = use_lld,
389 .entry = entry,419 .entry = entry,
390 .wasi_exec_model = wasi_exec_model,420 .wasi_exec_model = wasi_exec_model,
421 .debug_format = debug_format,
391 };422 };
392}423}
393424
src/Module.zig-69
...@@ -152,8 +152,6 @@ stage1_flags: packed struct {...@@ -152,8 +152,6 @@ stage1_flags: packed struct {
152 reserved: u2 = 0,152 reserved: u2 = 0,
153} = .{},153} = .{},
154154
155job_queued_update_builtin_zig: bool = true,
156
157compile_log_text: ArrayListUnmanaged(u8) = .{},155compile_log_text: ArrayListUnmanaged(u8) = .{},
158156
159emit_h: ?*GlobalEmitH,157emit_h: ?*GlobalEmitH,
...@@ -2490,7 +2488,6 @@ pub fn deinit(mod: *Module) void {...@@ -2490,7 +2488,6 @@ pub fn deinit(mod: *Module) void {
24902488
2491 mod.compile_log_text.deinit(gpa);2489 mod.compile_log_text.deinit(gpa);
24922490
2493 mod.zig_cache_artifact_directory.handle.close();
2494 mod.local_zir_cache.handle.close();2491 mod.local_zir_cache.handle.close();
2495 mod.global_zir_cache.handle.close();2492 mod.global_zir_cache.handle.close();
24962493
...@@ -3075,72 +3072,6 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {...@@ -3075,72 +3072,6 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
3075 }3072 }
3076}3073}
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
3144pub fn mapOldZirToNew(3075pub fn mapOldZirToNew(
3145 gpa: Allocator,3076 gpa: Allocator,
3146 old_zir: Zir,3077 old_zir: Zir,
src/Package/Module.zig+26-5
...@@ -33,11 +33,16 @@ cc_argv: []const []const u8,...@@ -33,11 +33,16 @@ cc_argv: []const []const u8,
33/// (SPIR-V) whether to generate a structured control flow graph or not33/// (SPIR-V) whether to generate a structured control flow graph or not
34structured_cfg: bool,34structured_cfg: bool,
3535
36/// The contents of `@import("builtin")` for this module.36/// If the module is an `@import("builtin")` module, this is the `File` that
37generated_builtin_source: []const u8,37/// is preallocated for it. Otherwise this field is null.
38builtin_file: ?*File,
3839
39pub const Deps = std.StringArrayHashMapUnmanaged(*Module);40pub const Deps = std.StringArrayHashMapUnmanaged(*Module);
4041
42pub fn isBuiltin(m: Module) bool {
43 return m.file != null;
44}
45
41pub const Tree = struct {46pub const Tree = struct {
42 /// Each `Package` exposes a `Module` with build.zig as its root source file.47 /// Each `Package` exposes a `Module` with build.zig as its root source file.
43 build_module_table: std.AutoArrayHashMapUnmanaged(MultiHashHexDigest, *Module),48 build_module_table: std.AutoArrayHashMapUnmanaged(MultiHashHexDigest, *Module),
...@@ -329,6 +334,8 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {...@@ -329,6 +334,8 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
329 .wasi_exec_model = options.global.wasi_exec_model,334 .wasi_exec_model = options.global.wasi_exec_model,
330 }, arena);335 }, arena);
331336
337 const new_file = try arena.create(File);
338
332 const digest = Cache.HashHelper.oneShot(generated_builtin_source);339 const digest = Cache.HashHelper.oneShot(generated_builtin_source);
333 const builtin_sub_path = try arena.dupe(u8, "b" ++ std.fs.path.sep_str ++ digest);340 const builtin_sub_path = try arena.dupe(u8, "b" ++ std.fs.path.sep_str ++ digest);
334 const new = try arena.create(Module);341 const new = try arena.create(Module);
...@@ -359,12 +366,25 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {...@@ -359,12 +366,25 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
359 .stack_protector = stack_protector,366 .stack_protector = stack_protector,
360 .code_model = code_model,367 .code_model = code_model,
361 .red_zone = red_zone,368 .red_zone = red_zone,
362 .generated_builtin_source = generated_builtin_source,
363 .sanitize_c = sanitize_c,369 .sanitize_c = sanitize_c,
364 .sanitize_thread = sanitize_thread,370 .sanitize_thread = sanitize_thread,
365 .unwind_tables = unwind_tables,371 .unwind_tables = unwind_tables,
366 .cc_argv = &.{},372 .cc_argv = &.{},
367 .structured_cfg = structured_cfg,373 .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,
368 };388 };
369 break :b new;389 break :b new;
370 };390 };
...@@ -391,12 +411,12 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {...@@ -391,12 +411,12 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
391 .stack_protector = stack_protector,411 .stack_protector = stack_protector,
392 .code_model = code_model,412 .code_model = code_model,
393 .red_zone = red_zone,413 .red_zone = red_zone,
394 .generated_builtin_source = builtin_mod.generated_builtin_source,
395 .sanitize_c = sanitize_c,414 .sanitize_c = sanitize_c,
396 .sanitize_thread = sanitize_thread,415 .sanitize_thread = sanitize_thread,
397 .unwind_tables = unwind_tables,416 .unwind_tables = unwind_tables,
398 .cc_argv = options.cc_argv,417 .cc_argv = options.cc_argv,
399 .structured_cfg = structured_cfg,418 .structured_cfg = structured_cfg,
419 .builtin_file = null,
400 };420 };
401421
402 try mod.deps.ensureUnusedCapacity(arena, 1);422 try mod.deps.ensureUnusedCapacity(arena, 1);
...@@ -437,8 +457,8 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*P...@@ -437,8 +457,8 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*P
437 .sanitize_thread = undefined,457 .sanitize_thread = undefined,
438 .unwind_tables = undefined,458 .unwind_tables = undefined,
439 .cc_argv = undefined,459 .cc_argv = undefined,
440 .generated_builtin_source = undefined,
441 .structured_cfg = undefined,460 .structured_cfg = undefined,
461 .builtin_file = null,
442 };462 };
443 return mod;463 return mod;
444}464}
...@@ -457,3 +477,4 @@ const Cache = std.Build.Cache;...@@ -457,3 +477,4 @@ const Cache = std.Build.Cache;
457const Builtin = @import("../Builtin.zig");477const Builtin = @import("../Builtin.zig");
458const assert = std.debug.assert;478const assert = std.debug.assert;
459const Compilation = @import("../Compilation.zig");479const Compilation = @import("../Compilation.zig");
480const File = @import("../Module.zig").File;
src/Sema.zig+6-1
...@@ -784,6 +784,11 @@ pub const Block = struct {...@@ -784,6 +784,11 @@ pub const Block = struct {
784 }784 }
785 }785 }
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
787 pub fn startAnonDecl(block: *Block) !WipAnonDecl {792 pub fn startAnonDecl(block: *Block) !WipAnonDecl {
788 return WipAnonDecl{793 return WipAnonDecl{
789 .block = block,794 .block = block,
...@@ -5733,7 +5738,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -5733,7 +5738,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
5733 // Ignore the result, all the relevant operations have written to c_import_buf already.5738 // Ignore the result, all the relevant operations have written to c_import_buf already.
5734 _ = try sema.analyzeBodyBreak(&child_block, body);5739 _ = 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|
5737 return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)});5742 return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)});
5738 defer c_import_res.deinit(gpa);5743 defer c_import_res.deinit(gpa);
57395744
src/codegen/llvm.zig+4-12
...@@ -854,9 +854,8 @@ pub const Object = struct {...@@ -854,9 +854,8 @@ pub const Object = struct {
854 /// want to iterate over it while adding entries to it.854 /// want to iterate over it while adding entries to it.
855 pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr);855 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 {
858 if (build_options.only_c) unreachable;858 if (build_options.only_c) unreachable;
859 const comp = options.comp;
860 const gpa = comp.gpa;859 const gpa = comp.gpa;
861 const target = comp.root_mod.resolved_target.result;860 const target = comp.root_mod.resolved_target.result;
862 const llvm_target_triple = try targetTriple(arena, target);861 const llvm_target_triple = try targetTriple(arena, target);
...@@ -878,14 +877,7 @@ pub const Object = struct {...@@ -878,14 +877,7 @@ pub const Object = struct {
878 var target_data: if (build_options.have_llvm) *llvm.TargetData else void = undefined;877 var target_data: if (build_options.have_llvm) *llvm.TargetData else void = undefined;
879 if (builder.useLibLlvm()) {878 if (builder.useLibLlvm()) {
880 debug_info: {879 debug_info: {
881 const debug_format = options.debug_format orelse b: {880 switch (comp.config.debug_format) {
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) {
889 .strip => break :debug_info,881 .strip => break :debug_info,
890 .code_view => builder.llvm.module.?.addModuleCodeViewFlag(),882 .code_view => builder.llvm.module.?.addModuleCodeViewFlag(),
891 .dwarf => |f| builder.llvm.module.?.addModuleDebugInfoFlag(f == .@"64"),883 .dwarf => |f| builder.llvm.module.?.addModuleDebugInfoFlag(f == .@"64"),
...@@ -961,8 +953,8 @@ pub const Object = struct {...@@ -961,8 +953,8 @@ pub const Object = struct {
961 opt_level,953 opt_level,
962 reloc_mode,954 reloc_mode,
963 code_model,955 code_model,
964 options.function_sections orelse false,956 comp.function_sections,
965 options.data_sections orelse false,957 comp.data_sections,
966 float_abi,958 float_abi,
967 if (target_util.llvmMachineAbi(target)) |s| s.ptr else null,959 if (target_util.llvmMachineAbi(target)) |s| s.ptr else null,
968 );960 );
src/libunwind.zig+2-1
...@@ -28,6 +28,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void {...@@ -28,6 +28,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void {
28 .have_zcu = false,28 .have_zcu = false,
29 .emit_bin = true,29 .emit_bin = true,
30 .root_optimize_mode = comp.compilerRtOptMode(),30 .root_optimize_mode = comp.compilerRtOptMode(),
31 .root_strip = comp.compilerRtStrip(),
31 .link_libc = true,32 .link_libc = true,
32 // Disable LTO to avoid https://github.com/llvm/llvm-project/issues/5682533 // Disable LTO to avoid https://github.com/llvm/llvm-project/issues/56825
33 .lto = false,34 .lto = false,
...@@ -131,7 +132,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void {...@@ -131,7 +132,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void {
131 .libc_installation = comp.libc_installation,132 .libc_installation = comp.libc_installation,
132 .emit_bin = emit_bin,133 .emit_bin = emit_bin,
133 .link_mode = link_mode,134 .link_mode = link_mode,
134 .function_sections = comp.bin_file.function_sections,135 .function_sections = comp.function_sections,
135 .c_source_files = &c_source_files,136 .c_source_files = &c_source_files,
136 .verbose_cc = comp.verbose_cc,137 .verbose_cc = comp.verbose_cc,
137 .verbose_link = comp.verbose_link,138 .verbose_link = comp.verbose_link,
src/link.zig+22-19
...@@ -68,9 +68,6 @@ pub const File = struct {...@@ -68,9 +68,6 @@ pub const File = struct {
68 force_undefined_symbols: std.StringArrayHashMapUnmanaged(void),68 force_undefined_symbols: std.StringArrayHashMapUnmanaged(void),
69 allow_shlib_undefined: bool,69 allow_shlib_undefined: bool,
70 stack_size: u64,70 stack_size: u64,
71 debug_format: DebugFormat,
72 function_sections: bool,
73 data_sections: bool,
7471
75 /// Prevents other processes from clobbering files in the output directory72 /// Prevents other processes from clobbering files in the output directory
76 /// of this linking operation.73 /// of this linking operation.
...@@ -78,16 +75,7 @@ pub const File = struct {...@@ -78,16 +75,7 @@ pub const File = struct {
7875
79 child_pid: ?std.ChildProcess.Id = null,76 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
87 pub const OpenOptions = struct {78 pub const OpenOptions = struct {
88 comp: *Compilation,
89 emit: Compilation.Emit,
90
91 symbol_count_hint: u64 = 32,79 symbol_count_hint: u64 = 32,
92 program_code_size_hint: u64 = 256 * 1024,80 program_code_size_hint: u64 = 256 * 1024,
9381
...@@ -95,8 +83,6 @@ pub const File = struct {...@@ -95,8 +83,6 @@ pub const File = struct {
95 entry_addr: ?u64,83 entry_addr: ?u64,
96 stack_size: ?u64,84 stack_size: ?u64,
97 image_base: ?u64,85 image_base: ?u64,
98 function_sections: bool,
99 data_sections: bool,
100 eh_frame_hdr: bool,86 eh_frame_hdr: bool,
101 emit_relocs: bool,87 emit_relocs: bool,
102 rdynamic: bool,88 rdynamic: bool,
...@@ -150,8 +136,6 @@ pub const File = struct {...@@ -150,8 +136,6 @@ pub const File = struct {
150136
151 compatibility_version: ?std.SemanticVersion,137 compatibility_version: ?std.SemanticVersion,
152138
153 debug_format: ?DebugFormat,
154
155 // TODO: remove this. libraries are resolved by the frontend.139 // TODO: remove this. libraries are resolved by the frontend.
156 lib_dirs: []const []const u8,140 lib_dirs: []const []const u8,
157 rpath_list: []const []const u8,141 rpath_list: []const []const u8,
...@@ -190,10 +174,29 @@ pub const File = struct {...@@ -190,10 +174,29 @@ pub const File = struct {
190 /// rewriting it. A malicious file is detected as incremental link failure174 /// rewriting it. A malicious file is detected as incremental link failure
191 /// and does not cause Illegal Behavior. This operation is not atomic.175 /// and does not cause Illegal Behavior. This operation is not atomic.
192 /// `arena` is used for allocations with the same lifetime as the created File.176 /// `arena` is used for allocations with the same lifetime as the created File.
193 pub fn open(arena: Allocator, options: OpenOptions) !*File {177 pub fn open(
194 switch (Tag.fromObjectFormat(options.comp.root_mod.resolved_target.result.ofmt)) {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)) {
195 inline else => |tag| {198 inline else => |tag| {
196 const ptr = try tag.Type().open(arena, options);199 const ptr = try tag.Type().createEmpty(arena, comp, emit, options);
197 return &ptr.base;200 return &ptr.base;
198 },201 },
199 }202 }
src/link/C.zig+13-13
...@@ -92,21 +92,24 @@ pub fn addString(this: *C, s: []const u8) Allocator.Error!String {...@@ -92,21 +92,24 @@ pub fn addString(this: *C, s: []const u8) Allocator.Error!String {
92 };92 };
93}93}
9494
95pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {95pub fn open(
96 const target = options.comp.root_mod.resolved_target.result;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;
97 assert(target.ofmt == .c);102 assert(target.ofmt == .c);
98 const optimize_mode = options.comp.root_mod.optimize_mode;103 const optimize_mode = comp.root_mod.optimize_mode;
99 const use_lld = build_options.have_llvm and options.comp.config.use_lld;104 const use_lld = build_options.have_llvm and comp.config.use_lld;
100 const use_llvm = options.comp.config.use_llvm;105 const use_llvm = comp.config.use_llvm;
101 const output_mode = options.comp.config.output_mode;106 const output_mode = comp.config.output_mode;
102 const link_mode = options.comp.config.link_mode;107 const link_mode = comp.config.link_mode;
103108
104 // These are caught by `Compilation.Config.resolve`.109 // These are caught by `Compilation.Config.resolve`.
105 assert(!use_lld);110 assert(!use_lld);
106 assert(!use_llvm);111 assert(!use_llvm);
107112
108 const emit = options.emit;
109
110 const file = try emit.directory.handle.createFile(emit.sub_path, .{113 const file = try emit.directory.handle.createFile(emit.sub_path, .{
111 // Truncation is done on `flush`.114 // Truncation is done on `flush`.
112 .truncate = false,115 .truncate = false,
...@@ -119,7 +122,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {...@@ -119,7 +122,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {
119 c_file.* = .{122 c_file.* = .{
120 .base = .{123 .base = .{
121 .tag = .c,124 .tag = .c,
122 .comp = options.comp,125 .comp = comp,
123 .emit = emit,126 .emit = emit,
124 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),127 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
125 .stack_size = options.stack_size orelse 16777216,128 .stack_size = options.stack_size orelse 16777216,
...@@ -129,9 +132,6 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {...@@ -129,9 +132,6 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {
129 .build_id = options.build_id,132 .build_id = options.build_id,
130 .rpath_list = options.rpath_list,133 .rpath_list = options.rpath_list,
131 .force_undefined_symbols = options.force_undefined_symbols,134 .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,
135 },135 },
136 };136 };
137137
src/link/Coff.zig+24-18
...@@ -234,44 +234,49 @@ const ideal_factor = 3;...@@ -234,44 +234,49 @@ const ideal_factor = 3;
234const minimum_text_block_size = 64;234const minimum_text_block_size = 64;
235pub const min_text_capacity = padToIdeal(minimum_text_block_size);235pub 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 {
238 if (build_options.only_c) unreachable;243 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;
240 assert(target.ofmt == .coff);245 assert(target.ofmt == .coff);
241246
242 const self = try createEmpty(arena, options);247 const self = try createEmpty(arena, comp, emit, options);
243 errdefer self.base.destroy();248 errdefer self.base.destroy();
244249
245 const use_lld = build_options.have_llvm and options.comp.config.use_lld;250 const use_lld = build_options.have_llvm and comp.config.use_lld;
246 const use_llvm = options.comp.config.use_llvm;251 const use_llvm = comp.config.use_llvm;
247252
248 if (use_lld and use_llvm) {253 if (use_lld and use_llvm) {
249 // LLVM emits the object file; LLD links it into the final product.254 // LLVM emits the object file; LLD links it into the final product.
250 return self;255 return self;
251 }256 }
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: {
254 // Open a temporary object file, not the final output file because we259 // Open a temporary object file, not the final output file because we
255 // want to link with LLD.260 // want to link with LLD.
256 const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{261 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),
258 });263 });
259 self.base.intermediary_basename = o_file_path;264 self.base.intermediary_basename = o_file_path;
260 break :p o_file_path;265 break :p o_file_path;
261 };266 };
262267
263 self.base.file = try options.emit.directory.handle.createFile(sub_path, .{268 self.base.file = try emit.directory.handle.createFile(sub_path, .{
264 .truncate = false,269 .truncate = false,
265 .read = true,270 .read = true,
266 .mode = link.File.determineMode(271 .mode = link.File.determineMode(
267 use_lld,272 use_lld,
268 options.comp.config.output_mode,273 comp.config.output_mode,
269 options.comp.config.link_mode,274 comp.config.link_mode,
270 ),275 ),
271 });276 });
272277
273 assert(self.llvm_object == null);278 assert(self.llvm_object == null);
274 const gpa = self.base.comp.gpa;279 const gpa = comp.gpa;
275280
276 try self.strtab.buffer.ensureUnusedCapacity(gpa, @sizeOf(u32));281 try self.strtab.buffer.ensureUnusedCapacity(gpa, @sizeOf(u32));
277 self.strtab.buffer.appendNTimesAssumeCapacity(0, @sizeOf(u32));282 self.strtab.buffer.appendNTimesAssumeCapacity(0, @sizeOf(u32));
...@@ -362,8 +367,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Coff {...@@ -362,8 +367,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Coff {
362 return self;367 return self;
363}368}
364369
365pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {370pub fn createEmpty(
366 const comp = options.comp;371 arena: Allocator,
372 comp: *Compilation,
373 emit: Compilation.Emit,
374 options: link.File.OpenOptions,
375) !*Coff {
367 const target = comp.root_mod.resolved_target.result;376 const target = comp.root_mod.resolved_target.result;
368 const optimize_mode = comp.root_mod.optimize_mode;377 const optimize_mode = comp.root_mod.optimize_mode;
369 const output_mode = comp.config.output_mode;378 const output_mode = comp.config.output_mode;
...@@ -380,7 +389,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {...@@ -380,7 +389,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {
380 .base = .{389 .base = .{
381 .tag = .coff,390 .tag = .coff,
382 .comp = comp,391 .comp = comp,
383 .emit = options.emit,392 .emit = emit,
384 .stack_size = options.stack_size orelse 16777216,393 .stack_size = options.stack_size orelse 16777216,
385 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug),394 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug),
386 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,395 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
...@@ -389,9 +398,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {...@@ -389,9 +398,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {
389 .build_id = options.build_id,398 .build_id = options.build_id,
390 .rpath_list = options.rpath_list,399 .rpath_list = options.rpath_list,
391 .force_undefined_symbols = options.force_undefined_symbols,400 .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,
395 },401 },
396 .ptr_width = ptr_width,402 .ptr_width = ptr_width,
397 .page_size = page_size,403 .page_size = page_size,
...@@ -423,7 +429,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {...@@ -423,7 +429,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {
423429
424 const use_llvm = comp.config.use_llvm;430 const use_llvm = comp.config.use_llvm;
425 if (use_llvm and comp.config.have_zcu) {431 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);
427 }433 }
428 return self;434 return self;
429}435}
src/link/Coff/lld.zig+1-1
...@@ -171,7 +171,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -171,7 +171,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
171171
172 try argv.append("-ERRORLIMIT:0");172 try argv.append("-ERRORLIMIT:0");
173 try argv.append("-NOLOGO");173 try argv.append("-NOLOGO");
174 if (self.base.debug_format != .strip) {174 if (comp.config.debug_format != .strip) {
175 try argv.append("-DEBUG");175 try argv.append("-DEBUG");
176176
177 const out_ext = std.fs.path.extension(full_out_path);177 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 };...@@ -228,18 +228,23 @@ pub const HashStyle = enum { sysv, gnu, both };
228pub const CompressDebugSections = enum { none, zlib, zstd };228pub const CompressDebugSections = enum { none, zlib, zstd };
229pub const SortSection = enum { name, alignment };229pub 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 {
232 if (build_options.only_c) unreachable;237 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;
234 assert(target.ofmt == .elf);239 assert(target.ofmt == .elf);
235240
236 const use_lld = build_options.have_llvm and options.comp.config.use_lld;241 const use_lld = build_options.have_llvm and comp.config.use_lld;
237 const use_llvm = options.comp.config.use_llvm;242 const use_llvm = comp.config.use_llvm;
238 const opt_zcu = options.comp.module;243 const opt_zcu = comp.module;
239 const output_mode = options.comp.config.output_mode;244 const output_mode = comp.config.output_mode;
240 const link_mode = options.comp.config.link_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);
243 errdefer self.base.destroy();248 errdefer self.base.destroy();
244249
245 if (use_lld and use_llvm) {250 if (use_lld and use_llvm) {
...@@ -250,23 +255,23 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {...@@ -250,23 +255,23 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {
250 const is_obj = output_mode == .Obj;255 const is_obj = output_mode == .Obj;
251 const is_obj_or_ar = is_obj or (output_mode == .Lib and link_mode == .Static);256 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: {
254 // Open a temporary object file, not the final output file because we259 // Open a temporary object file, not the final output file because we
255 // want to link with LLD.260 // want to link with LLD.
256 const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{261 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),
258 });263 });
259 self.base.intermediary_basename = o_file_path;264 self.base.intermediary_basename = o_file_path;
260 break :p o_file_path;265 break :p o_file_path;
261 };266 };
262267
263 self.base.file = try options.emit.directory.handle.createFile(sub_path, .{268 self.base.file = try emit.directory.handle.createFile(sub_path, .{
264 .truncate = false,269 .truncate = false,
265 .read = true,270 .read = true,
266 .mode = link.File.determineMode(use_lld, output_mode, link_mode),271 .mode = link.File.determineMode(use_lld, output_mode, link_mode),
267 });272 });
268273
269 const gpa = options.comp.gpa;274 const gpa = comp.gpa;
270275
271 // Index 0 is always a null symbol.276 // Index 0 is always a null symbol.
272 try self.symbols.append(gpa, .{});277 try self.symbols.append(gpa, .{});
...@@ -343,8 +348,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {...@@ -343,8 +348,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {
343 return self;348 return self;
344}349}
345350
346pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {351pub fn createEmpty(
347 const comp = options.comp;352 arena: Allocator,
353 comp: *Compilation,
354 emit: Compilation.Emit,
355 options: link.File.OpenOptions,
356) !*Elf {
348 const use_llvm = comp.config.use_llvm;357 const use_llvm = comp.config.use_llvm;
349 const optimize_mode = comp.root_mod.optimize_mode;358 const optimize_mode = comp.root_mod.optimize_mode;
350 const target = comp.root_mod.resolved_target.result;359 const target = comp.root_mod.resolved_target.result;
...@@ -373,7 +382,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {...@@ -373,7 +382,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {
373 .base = .{382 .base = .{
374 .tag = .elf,383 .tag = .elf,
375 .comp = comp,384 .comp = comp,
376 .emit = options.emit,385 .emit = emit,
377 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),386 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
378 .stack_size = options.stack_size orelse 16777216,387 .stack_size = options.stack_size orelse 16777216,
379 .allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os,388 .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 {...@@ -382,9 +391,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {
382 .build_id = options.build_id,391 .build_id = options.build_id,
383 .rpath_list = options.rpath_list,392 .rpath_list = options.rpath_list,
384 .force_undefined_symbols = options.force_undefined_symbols,393 .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,
388 },394 },
389 .ptr_width = ptr_width,395 .ptr_width = ptr_width,
390 .page_size = page_size,396 .page_size = page_size,
...@@ -423,7 +429,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {...@@ -423,7 +429,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {
423 .version_script = options.version_script,429 .version_script = options.version_script,
424 };430 };
425 if (use_llvm and comp.config.have_zcu) {431 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);
427 }433 }
428434
429 return self;435 return self;
...@@ -1753,7 +1759,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {...@@ -1753,7 +1759,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
1753 try argv.append("-pie");1759 try argv.append("-pie");
1754 }1760 }
17551761
1756 if (self.base.debug_format == .strip) {1762 if (comp.config.debug_format == .strip) {
1757 try argv.append("-s");1763 try argv.append("-s");
1758 }1764 }
17591765
...@@ -2640,7 +2646,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2640,7 +2646,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2640 try argv.append("--export-dynamic");2646 try argv.append("--export-dynamic");
2641 }2647 }
26422648
2643 if (self.base.debug_format == .strip) {2649 if (comp.config.debug_format == .strip) {
2644 try argv.append("-s");2650 try argv.append("-s");
2645 }2651 }
26462652
src/link/Elf/Object.zig+2-1
...@@ -293,13 +293,14 @@ fn initOutputSection(self: Object, elf_file: *Elf, shdr: ElfShdr) error{OutOfMem...@@ -293,13 +293,14 @@ fn initOutputSection(self: Object, elf_file: *Elf, shdr: ElfShdr) error{OutOfMem
293}293}
294294
295fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool {295fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool {
296 const comp = elf_file.base.comp;
296 const shdr = self.shdrs.items[index];297 const shdr = self.shdrs.items[index];
297 const name = self.getString(shdr.sh_name);298 const name = self.getString(shdr.sh_name);
298 const ignore = blk: {299 const ignore = blk: {
299 if (mem.startsWith(u8, name, ".note")) break :blk true;300 if (mem.startsWith(u8, name, ".note")) break :blk true;
300 if (mem.startsWith(u8, name, ".comment")) break :blk true;301 if (mem.startsWith(u8, name, ".comment")) break :blk true;
301 if (mem.startsWith(u8, name, ".llvm_addrsig")) break :blk true;302 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 and303 if (comp.config.debug_format == .strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and
303 mem.startsWith(u8, name, ".debug")) break :blk true;304 mem.startsWith(u8, name, ".debug")) break :blk true;
304 break :blk false;305 break :blk false;
305 };306 };
src/link/Elf/ZigObject.zig+9-3
...@@ -76,7 +76,8 @@ pub const symbol_mask: u32 = 0x7fffffff;...@@ -76,7 +76,8 @@ pub const symbol_mask: u32 = 0x7fffffff;
76pub const SHN_ATOM: u16 = 0x100;76pub const SHN_ATOM: u16 = 0x100;
7777
78pub fn init(self: *ZigObject, elf_file: *Elf) !void {78pub 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
81 try self.atoms.append(gpa, 0); // null input section82 try self.atoms.append(gpa, 0); // null input section
82 try self.relocs.append(gpa, .{}); // null relocs section83 try self.relocs.append(gpa, .{}); // null relocs section
...@@ -96,8 +97,13 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {...@@ -96,8 +97,13 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {
96 esym.st_shndx = elf.SHN_ABS;97 esym.st_shndx = elf.SHN_ABS;
97 symbol_ptr.esym_index = esym_index;98 symbol_ptr.esym_index = esym_index;
9899
99 if (elf_file.base.debug_format != .strip) {100 switch (comp.config.debug_format) {
100 self.dwarf = Dwarf.init(&elf_file.base, .dwarf32);101 .strip => {},
102 .dwarf => |v| {
103 assert(v == .@"32");
104 self.dwarf = Dwarf.init(&elf_file.base, .dwarf32);
105 },
106 .code_view => unreachable,
101 }107 }
102}108}
103109
src/link/MachO.zig+22-17
...@@ -182,18 +182,21 @@ pub const SdkLayout = enum {...@@ -182,18 +182,21 @@ pub const SdkLayout = enum {
182 vendored,182 vendored,
183};183};
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 {
186 if (build_options.only_c) unreachable;191 if (build_options.only_c) unreachable;
187 const comp = options.comp;
188 const target = comp.root_mod.resolved_target.result;192 const target = comp.root_mod.resolved_target.result;
189 const use_lld = build_options.have_llvm and comp.config.use_lld;193 const use_lld = build_options.have_llvm and comp.config.use_lld;
190 const use_llvm = comp.config.use_llvm;194 const use_llvm = comp.config.use_llvm;
191 assert(target.ofmt == .macho);195 assert(target.ofmt == .macho);
192196
193 const gpa = comp.gpa;197 const gpa = comp.gpa;
194 const emit = options.emit;
195 const mode: Mode = mode: {198 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)
197 break :mode .zld;200 break :mode .zld;
198 break :mode .incremental;201 break :mode .incremental;
199 };202 };
...@@ -201,7 +204,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {...@@ -201,7 +204,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {
201 if (comp.module == null) {204 if (comp.module == null) {
202 // No point in opening a file, we would not write anything to it.205 // No point in opening a file, we would not write anything to it.
203 // Initialize with empty.206 // Initialize with empty.
204 return createEmpty(arena, options);207 return createEmpty(arena, comp, emit, options);
205 }208 }
206 // Open a temporary object file, not the final output file because we209 // Open a temporary object file, not the final output file because we
207 // want to link with LLD.210 // want to link with LLD.
...@@ -210,7 +213,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {...@@ -210,7 +213,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {
210 });213 });
211 } else emit.sub_path;214 } else emit.sub_path;
212215
213 const self = try createEmpty(arena, options);216 const self = try createEmpty(arena, comp, emit, options);
214 errdefer self.base.destroy();217 errdefer self.base.destroy();
215218
216 if (mode == .zld) {219 if (mode == .zld) {
...@@ -232,7 +235,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {...@@ -232,7 +235,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {
232 });235 });
233 self.base.file = file;236 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) {
236 // Create dSYM bundle.239 // Create dSYM bundle.
237 log.debug("creating {s}.dSYM bundle", .{sub_path});240 log.debug("creating {s}.dSYM bundle", .{sub_path});
238241
...@@ -279,8 +282,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {...@@ -279,8 +282,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {
279 return self;282 return self;
280}283}
281284
282pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO {285pub fn createEmpty(
283 const comp = options.comp;286 arena: Allocator,
287 comp: *Compilation,
288 emit: Compilation.Emit,
289 options: link.File.OpenOptions,
290) !*MachO {
284 const optimize_mode = comp.root_mod.optimize_mode;291 const optimize_mode = comp.root_mod.optimize_mode;
285 const use_llvm = comp.config.use_llvm;292 const use_llvm = comp.config.use_llvm;
286293
...@@ -289,7 +296,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO {...@@ -289,7 +296,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO {
289 .base = .{296 .base = .{
290 .tag = .macho,297 .tag = .macho,
291 .comp = comp,298 .comp = comp,
292 .emit = options.emit,299 .emit = emit,
293 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug),300 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug),
294 .stack_size = options.stack_size orelse 16777216,301 .stack_size = options.stack_size orelse 16777216,
295 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,302 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
...@@ -298,11 +305,8 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO {...@@ -298,11 +305,8 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO {
298 .build_id = options.build_id,305 .build_id = options.build_id,
299 .rpath_list = options.rpath_list,306 .rpath_list = options.rpath_list,
300 .force_undefined_symbols = options.force_undefined_symbols,307 .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,
304 },308 },
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)
306 .zld310 .zld
307 else311 else
308 .incremental,312 .incremental,
...@@ -317,7 +321,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO {...@@ -317,7 +321,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO {
317 };321 };
318322
319 if (use_llvm and comp.module != null) {323 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);
321 }325 }
322326
323 log.debug("selected linker mode '{s}'", .{@tagName(self.mode)});327 log.debug("selected linker mode '{s}'", .{@tagName(self.mode)});
...@@ -4313,7 +4317,8 @@ fn addLocalToSymtab(self: *MachO, sym_loc: SymbolWithLoc, locals: *std.ArrayList...@@ -4313,7 +4317,8 @@ fn addLocalToSymtab(self: *MachO, sym_loc: SymbolWithLoc, locals: *std.ArrayList
4313}4317}
43144318
4315fn writeSymtab(self: *MachO) !SymtabCtx {4319fn writeSymtab(self: *MachO) !SymtabCtx {
4316 const gpa = self.base.comp.gpa;4320 const comp = self.base.comp;
4321 const gpa = comp.gpa;
43174322
4318 var locals = std.ArrayList(macho.nlist_64).init(gpa);4323 var locals = std.ArrayList(macho.nlist_64).init(gpa);
4319 defer locals.deinit();4324 defer locals.deinit();
...@@ -4368,7 +4373,7 @@ fn writeSymtab(self: *MachO) !SymtabCtx {...@@ -4368,7 +4373,7 @@ fn writeSymtab(self: *MachO) !SymtabCtx {
43684373
4369 // We generate stabs last in order to ensure that the strtab always has debug info4374 // We generate stabs last in order to ensure that the strtab always has debug info
4370 // strings trailing4375 // strings trailing
4371 if (self.base.debug_format != .strip) {4376 if (comp.config.debug_format != .strip) {
4372 for (self.objects.items) |object| {4377 for (self.objects.items) |object| {
4373 assert(self.d_sym == null); // TODO4378 assert(self.d_sym == null); // TODO
4374 try self.generateSymbolStabs(object, &locals);4379 try self.generateSymbolStabs(object, &locals);
src/link/NvPtx.zig+20-13
...@@ -25,12 +25,17 @@ const LlvmObject = @import("../codegen/llvm.zig").Object;...@@ -25,12 +25,17 @@ const LlvmObject = @import("../codegen/llvm.zig").Object;
25base: link.File,25base: link.File,
26llvm_object: *LlvmObject,26llvm_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 {
29 if (build_options.only_c) unreachable;34 if (build_options.only_c) unreachable;
3035
31 const target = options.comp.root_mod.resolved_target.result;36 const target = comp.root_mod.resolved_target.result;
32 const use_lld = build_options.have_llvm and options.comp.config.use_lld;37 const use_lld = build_options.have_llvm and comp.config.use_lld;
33 const use_llvm = options.comp.config.use_llvm;38 const use_llvm = comp.config.use_llvm;
3439
35 assert(use_llvm); // Caught by Compilation.Config.resolve.40 assert(use_llvm); // Caught by Compilation.Config.resolve.
36 assert(!use_lld); // Caught by Compilation.Config.resolve.41 assert(!use_lld); // Caught by Compilation.Config.resolve.
...@@ -42,13 +47,13 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {...@@ -42,13 +47,13 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
42 else => return error.PtxArchNotSupported,47 else => return error.PtxArchNotSupported,
43 }48 }
4449
45 const llvm_object = try LlvmObject.create(arena, options);50 const llvm_object = try LlvmObject.create(arena, comp);
46 const nvptx = try arena.create(NvPtx);51 const nvptx = try arena.create(NvPtx);
47 nvptx.* = .{52 nvptx.* = .{
48 .base = .{53 .base = .{
49 .tag = .nvptx,54 .tag = .nvptx,
50 .comp = options.comp,55 .comp = comp,
51 .emit = options.emit,56 .emit = emit,
52 .gc_sections = options.gc_sections orelse false,57 .gc_sections = options.gc_sections orelse false,
53 .stack_size = options.stack_size orelse 0,58 .stack_size = options.stack_size orelse 0,
54 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,59 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
...@@ -57,9 +62,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {...@@ -57,9 +62,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
57 .build_id = options.build_id,62 .build_id = options.build_id,
58 .rpath_list = options.rpath_list,63 .rpath_list = options.rpath_list,
59 .force_undefined_symbols = options.force_undefined_symbols,64 .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,
63 },65 },
64 .llvm_object = llvm_object,66 .llvm_object = llvm_object,
65 };67 };
...@@ -67,10 +69,15 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {...@@ -67,10 +69,15 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
67 return nvptx;69 return nvptx;
68}70}
6971
70pub fn open(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {72pub fn open(
71 const target = options.comp.root_mod.resolved_target.result;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;
72 assert(target.ofmt == .nvptx);79 assert(target.ofmt == .nvptx);
73 return createEmpty(arena, options);80 return createEmpty(arena, comp, emit, options);
74}81}
7582
76pub fn deinit(self: *NvPtx) void {83pub fn deinit(self: *NvPtx) void {
src/link/Plan9.zig+21-15
...@@ -294,8 +294,12 @@ pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases {...@@ -294,8 +294,12 @@ pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases {
294 };294 };
295}295}
296296
297pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {297pub fn createEmpty(
298 const comp = options.comp;298 arena: Allocator,
299 comp: *Compilation,
300 emit: Compilation.Emit,
301 options: link.File.OpenOptions,
302) !*Plan9 {
299 const target = comp.root_mod.resolved_target.result;303 const target = comp.root_mod.resolved_target.result;
300 const gpa = comp.gpa;304 const gpa = comp.gpa;
301 const optimize_mode = comp.root_mod.optimize_mode;305 const optimize_mode = comp.root_mod.optimize_mode;
...@@ -313,7 +317,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {...@@ -313,7 +317,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {
313 .base = .{317 .base = .{
314 .tag = .plan9,318 .tag = .plan9,
315 .comp = comp,319 .comp = comp,
316 .emit = options.emit,320 .emit = emit,
317 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),321 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
318 .stack_size = options.stack_size orelse 16777216,322 .stack_size = options.stack_size orelse 16777216,
319 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,323 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
...@@ -322,9 +326,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {...@@ -322,9 +326,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {
322 .build_id = options.build_id,326 .build_id = options.build_id,
323 .rpath_list = options.rpath_list,327 .rpath_list = options.rpath_list,
324 .force_undefined_symbols = options.force_undefined_symbols,328 .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,
328 },329 },
329 .sixtyfour_bit = sixtyfour_bit,330 .sixtyfour_bit = sixtyfour_bit,
330 .bases = undefined,331 .bases = undefined,
...@@ -1308,26 +1309,31 @@ pub fn deinit(self: *Plan9) void {...@@ -1308,26 +1309,31 @@ pub fn deinit(self: *Plan9) void {
1308 }1309 }
1309}1310}
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 {
1312 if (build_options.only_c) unreachable;1318 if (build_options.only_c) unreachable;
13131319
1314 const target = options.comp.root_mod.resolved_target.result;1320 const target = comp.root_mod.resolved_target.result;
1315 const use_lld = build_options.have_llvm and options.comp.config.use_lld;1321 const use_lld = build_options.have_llvm and comp.config.use_lld;
1316 const use_llvm = options.comp.config.use_llvm;1322 const use_llvm = comp.config.use_llvm;
13171323
1318 assert(!use_llvm); // Caught by Compilation.Config.resolve.1324 assert(!use_llvm); // Caught by Compilation.Config.resolve.
1319 assert(!use_lld); // Caught by Compilation.Config.resolve.1325 assert(!use_lld); // Caught by Compilation.Config.resolve.
1320 assert(target.ofmt == .plan9);1326 assert(target.ofmt == .plan9);
13211327
1322 const self = try createEmpty(arena, options);1328 const self = try createEmpty(arena, comp, emit, options);
1323 errdefer self.base.destroy();1329 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, .{
1326 .read = true,1332 .read = true,
1327 .mode = link.File.determineMode(1333 .mode = link.File.determineMode(
1328 use_lld,1334 use_lld,
1329 options.comp.config.output_mode,1335 comp.config.output_mode,
1330 options.comp.config.link_mode,1336 comp.config.link_mode,
1331 ),1337 ),
1332 });1338 });
1333 errdefer file.close();1339 errdefer file.close();
...@@ -1335,7 +1341,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {...@@ -1335,7 +1341,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {
13351341
1336 self.bases = defaultBaseAddrs(target.cpu.arch);1342 self.bases = defaultBaseAddrs(target.cpu.arch);
13371343
1338 const gpa = options.comp.gpa;1344 const gpa = comp.gpa;
13391345
1340 try self.syms.appendSlice(gpa, &.{1346 try self.syms.appendSlice(gpa, &.{
1341 // we include the global offset table to make it easier for debugging1347 // 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,...@@ -49,16 +49,21 @@ object: codegen.Object,
4949
50pub const base_tag: link.File.Tag = .spirv;50pub const base_tag: link.File.Tag = .spirv;
5151
52pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV {52pub fn createEmpty(
53 const gpa = options.comp.gpa;53 arena: Allocator,
54 const target = options.comp.root_mod.resolved_target.result;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
56 const self = try arena.create(SpirV);61 const self = try arena.create(SpirV);
57 self.* = .{62 self.* = .{
58 .base = .{63 .base = .{
59 .tag = .spirv,64 .tag = .spirv,
60 .comp = options.comp,65 .comp = comp,
61 .emit = options.emit,66 .emit = emit,
62 .gc_sections = options.gc_sections orelse false,67 .gc_sections = options.gc_sections orelse false,
63 .stack_size = options.stack_size orelse 0,68 .stack_size = options.stack_size orelse 0,
64 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,69 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
...@@ -67,9 +72,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV {...@@ -67,9 +72,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV {
67 .build_id = options.build_id,72 .build_id = options.build_id,
68 .rpath_list = options.rpath_list,73 .rpath_list = options.rpath_list,
69 .force_undefined_symbols = options.force_undefined_symbols,74 .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" },
73 },75 },
74 .object = codegen.Object.init(gpa),76 .object = codegen.Object.init(gpa),
75 };77 };
...@@ -90,22 +92,27 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV {...@@ -90,22 +92,27 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV {
90 return self;92 return self;
91}93}
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 {
94 if (build_options.only_c) unreachable;101 if (build_options.only_c) unreachable;
95102
96 const target = options.comp.root_mod.resolved_target.result;103 const target = comp.root_mod.resolved_target.result;
97 const use_lld = build_options.have_llvm and options.comp.config.use_lld;104 const use_lld = build_options.have_llvm and comp.config.use_lld;
98 const use_llvm = options.comp.config.use_llvm;105 const use_llvm = comp.config.use_llvm;
99106
100 assert(!use_llvm); // Caught by Compilation.Config.resolve.107 assert(!use_llvm); // Caught by Compilation.Config.resolve.
101 assert(!use_lld); // Caught by Compilation.Config.resolve.108 assert(!use_lld); // Caught by Compilation.Config.resolve.
102 assert(target.ofmt == .spirv); // Caught by Compilation.Config.resolve.109 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);
105 errdefer spirv.base.destroy();112 errdefer spirv.base.destroy();
106113
107 // TODO: read the file and keep valid parts instead of truncating114 // 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, .{
109 .truncate = true,116 .truncate = true,
110 .read = true,117 .read = true,
111 });118 });
src/link/Wasm.zig+24-17
...@@ -373,9 +373,13 @@ pub const StringTable = struct {...@@ -373,9 +373,13 @@ pub const StringTable = struct {
373 }373 }
374};374};
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 {
377 if (build_options.only_c) unreachable;382 if (build_options.only_c) unreachable;
378 const comp = options.comp;
379 const gpa = comp.gpa;383 const gpa = comp.gpa;
380 const target = comp.root_mod.resolved_target.result;384 const target = comp.root_mod.resolved_target.result;
381 assert(target.ofmt == .wasm);385 assert(target.ofmt == .wasm);
...@@ -385,7 +389,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {...@@ -385,7 +389,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
385 const output_mode = comp.config.output_mode;389 const output_mode = comp.config.output_mode;
386 const shared_memory = comp.config.shared_memory;390 const shared_memory = comp.config.shared_memory;
387391
388 const wasm = try createEmpty(arena, options);392 const wasm = try createEmpty(arena, comp, emit, options);
389 errdefer wasm.base.destroy();393 errdefer wasm.base.destroy();
390394
391 if (use_lld and use_llvm) {395 if (use_lld and use_llvm) {
...@@ -393,18 +397,18 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {...@@ -393,18 +397,18 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
393 return wasm;397 return wasm;
394 }398 }
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: {
397 // Open a temporary object file, not the final output file because we401 // Open a temporary object file, not the final output file because we
398 // want to link with LLD.402 // want to link with LLD.
399 const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{403 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),
401 });405 });
402 wasm.base.intermediary_basename = o_file_path;406 wasm.base.intermediary_basename = o_file_path;
403 break :p o_file_path;407 break :p o_file_path;
404 };408 };
405409
406 // TODO: read the file and keep valid parts instead of truncating410 // 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, .{
408 .truncate = true,412 .truncate = true,
409 .read = true,413 .read = true,
410 .mode = if (fs.has_executable_bit)414 .mode = if (fs.has_executable_bit)
...@@ -530,8 +534,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {...@@ -530,8 +534,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
530 return wasm;534 return wasm;
531}535}
532536
533pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {537pub fn createEmpty(
534 const comp = options.comp;538 arena: Allocator,
539 comp: *Compilation,
540 emit: Compilation.Emit,
541 options: link.File.OpenOptions,
542) !*Wasm {
535 const use_llvm = comp.config.use_llvm;543 const use_llvm = comp.config.use_llvm;
536 const output_mode = comp.config.output_mode;544 const output_mode = comp.config.output_mode;
537545
...@@ -540,7 +548,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {...@@ -540,7 +548,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
540 .base = .{548 .base = .{
541 .tag = .wasm,549 .tag = .wasm,
542 .comp = comp,550 .comp = comp,
543 .emit = options.emit,551 .emit = emit,
544 .gc_sections = options.gc_sections orelse (output_mode != .Obj),552 .gc_sections = options.gc_sections orelse (output_mode != .Obj),
545 .stack_size = options.stack_size orelse std.wasm.page_size * 16, // 1MB553 .stack_size = options.stack_size orelse std.wasm.page_size * 16, // 1MB
546 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,554 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
...@@ -549,9 +557,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {...@@ -549,9 +557,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
549 .build_id = options.build_id,557 .build_id = options.build_id,
550 .rpath_list = options.rpath_list,558 .rpath_list = options.rpath_list,
551 .force_undefined_symbols = options.force_undefined_symbols,559 .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,
555 },560 },
556 .name = undefined,561 .name = undefined,
557 .import_table = options.import_table,562 .import_table = options.import_table,
...@@ -566,7 +571,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {...@@ -566,7 +571,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
566 };571 };
567572
568 if (use_llvm) {573 if (use_llvm) {
569 wasm.llvm_object = try LlvmObject.create(arena, options);574 wasm.llvm_object = try LlvmObject.create(arena, comp);
570 }575 }
571 return wasm;576 return wasm;
572}577}
...@@ -4205,11 +4210,11 @@ fn writeToFile(...@@ -4205,11 +4210,11 @@ fn writeToFile(
4205 if (data_section_index) |data_index| {4210 if (data_section_index) |data_index| {
4206 try wasm.emitDataRelocations(&binary_bytes, data_index, symbol_table);4211 try wasm.emitDataRelocations(&binary_bytes, data_index, symbol_table);
4207 }4212 }
4208 } else if (wasm.base.debug_format != .strip) {4213 } else if (comp.config.debug_format != .strip) {
4209 try wasm.emitNameSection(&binary_bytes, arena);4214 try wasm.emitNameSection(&binary_bytes, arena);
4210 }4215 }
42114216
4212 if (wasm.base.debug_format != .strip) {4217 if (comp.config.debug_format != .strip) {
4213 // The build id must be computed on the main sections only,4218 // The build id must be computed on the main sections only,
4214 // so we have to do it now, before the debug sections.4219 // so we have to do it now, before the debug sections.
4215 switch (wasm.base.build_id) {4220 switch (wasm.base.build_id) {
...@@ -4748,7 +4753,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -4748,7 +4753,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
4748 try argv.append("--no-gc-sections");4753 try argv.append("--no-gc-sections");
4749 }4754 }
47504755
4751 if (wasm.base.debug_format == .strip) {4756 if (comp.config.debug_format == .strip) {
4752 try argv.append("-s");4757 try argv.append("-s");
4753 }4758 }
47544759
...@@ -5276,7 +5281,9 @@ pub fn storeDeclType(wasm: *Wasm, decl_index: InternPool.DeclIndex, func_type: s...@@ -5276,7 +5281,9 @@ pub fn storeDeclType(wasm: *Wasm, decl_index: InternPool.DeclIndex, func_type: s
5276fn markReferences(wasm: *Wasm) !void {5281fn markReferences(wasm: *Wasm) !void {
5277 const tracy = trace(@src());5282 const tracy = trace(@src());
5278 defer tracy.end();5283 defer tracy.end();
5284
5279 const do_garbage_collect = wasm.base.gc_sections;5285 const do_garbage_collect = wasm.base.gc_sections;
5286 const comp = wasm.base.comp;
52805287
5281 for (wasm.resolved_symbols.keys()) |sym_loc| {5288 for (wasm.resolved_symbols.keys()) |sym_loc| {
5282 const sym = sym_loc.getSymbol(wasm);5289 const sym = sym_loc.getSymbol(wasm);
...@@ -5287,7 +5294,7 @@ fn markReferences(wasm: *Wasm) !void {...@@ -5287,7 +5294,7 @@ fn markReferences(wasm: *Wasm) !void {
52875294
5288 // Debug sections may require to be parsed and marked when it contains5295 // Debug sections may require to be parsed and marked when it contains
5289 // relocations to alive symbols.5296 // 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) {
5291 const file = sym_loc.file orelse continue; // Incremental debug info is done independently5298 const file = sym_loc.file orelse continue; // Incremental debug info is done independently
5292 const object = &wasm.objects.items[file];5299 const object = &wasm.objects.items[file];
5293 const atom_index = try Object.parseSymbolIntoAtom(object, file, sym_loc.index, wasm);5300 const atom_index = try Object.parseSymbolIntoAtom(object, file, sym_loc.index, wasm);
src/main.zig+19-14
...@@ -892,7 +892,6 @@ fn buildOutputType(...@@ -892,7 +892,6 @@ fn buildOutputType(
892 var contains_res_file: bool = false;892 var contains_res_file: bool = false;
893 var reference_trace: ?u32 = null;893 var reference_trace: ?u32 = null;
894 var pdb_out_path: ?[]const u8 = null;894 var pdb_out_path: ?[]const u8 = null;
895 var debug_format: ?link.File.DebugFormat = null;
896 var error_limit: ?Module.ErrorInt = null;895 var error_limit: ?Module.ErrorInt = null;
897 // These are before resolving sysroot.896 // These are before resolving sysroot.
898 var lib_dir_args: std.ArrayListUnmanaged([]const u8) = .{};897 var lib_dir_args: std.ArrayListUnmanaged([]const u8) = .{};
...@@ -1054,6 +1053,8 @@ fn buildOutputType(...@@ -1054,6 +1053,8 @@ fn buildOutputType(
1054 create_module.opts.any_sanitize_thread = true;1053 create_module.opts.any_sanitize_thread = true;
1055 if (mod_opts.unwind_tables == true)1054 if (mod_opts.unwind_tables == true)
1056 create_module.opts.any_unwind_tables = true;1055 create_module.opts.any_unwind_tables = true;
1056 if (mod_opts.strip == false)
1057 create_module.opts.any_non_stripped = true;
10571058
1058 const root_src = try introspect.resolvePath(arena, root_src_orig);1059 const root_src = try introspect.resolvePath(arena, root_src_orig);
1059 try create_module.modules.put(arena, mod_name, .{1060 try create_module.modules.put(arena, mod_name, .{
...@@ -1480,9 +1481,9 @@ fn buildOutputType(...@@ -1480,9 +1481,9 @@ fn buildOutputType(
1480 } else if (mem.eql(u8, arg, "-fno-strip")) {1481 } else if (mem.eql(u8, arg, "-fno-strip")) {
1481 mod_opts.strip = false;1482 mod_opts.strip = false;
1482 } else if (mem.eql(u8, arg, "-gdwarf32")) {1483 } else if (mem.eql(u8, arg, "-gdwarf32")) {
1483 debug_format = .{ .dwarf = .@"32" };1484 create_module.opts.debug_format = .{ .dwarf = .@"32" };
1484 } else if (mem.eql(u8, arg, "-gdwarf64")) {1485 } else if (mem.eql(u8, arg, "-gdwarf64")) {
1485 debug_format = .{ .dwarf = .@"64" };1486 create_module.opts.debug_format = .{ .dwarf = .@"64" };
1486 } else if (mem.eql(u8, arg, "-fformatted-panics")) {1487 } else if (mem.eql(u8, arg, "-fformatted-panics")) {
1487 formatted_panics = true;1488 formatted_panics = true;
1488 } else if (mem.eql(u8, arg, "-fno-formatted-panics")) {1489 } else if (mem.eql(u8, arg, "-fno-formatted-panics")) {
...@@ -1989,11 +1990,11 @@ fn buildOutputType(...@@ -1989,11 +1990,11 @@ fn buildOutputType(
1989 },1990 },
1990 .gdwarf32 => {1991 .gdwarf32 => {
1991 mod_opts.strip = false;1992 mod_opts.strip = false;
1992 debug_format = .{ .dwarf = .@"32" };1993 create_module.opts.debug_format = .{ .dwarf = .@"32" };
1993 },1994 },
1994 .gdwarf64 => {1995 .gdwarf64 => {
1995 mod_opts.strip = false;1996 mod_opts.strip = false;
1996 debug_format = .{ .dwarf = .@"64" };1997 create_module.opts.debug_format = .{ .dwarf = .@"64" };
1997 },1998 },
1998 .sanitize => {1999 .sanitize => {
1999 if (mem.eql(u8, it.only_arg, "undefined")) {2000 if (mem.eql(u8, it.only_arg, "undefined")) {
...@@ -2532,6 +2533,8 @@ fn buildOutputType(...@@ -2532,6 +2533,8 @@ fn buildOutputType(
2532 create_module.opts.any_sanitize_thread = true;2533 create_module.opts.any_sanitize_thread = true;
2533 if (mod_opts.unwind_tables == true)2534 if (mod_opts.unwind_tables == true)
2534 create_module.opts.any_unwind_tables = true;2535 create_module.opts.any_unwind_tables = true;
2536 if (mod_opts.strip == false)
2537 create_module.opts.any_non_stripped = true;
25352538
2536 const src_path = try introspect.resolvePath(arena, unresolved_src_path);2539 const src_path = try introspect.resolvePath(arena, unresolved_src_path);
2537 try create_module.modules.put(arena, "main", .{2540 try create_module.modules.put(arena, "main", .{
...@@ -3359,7 +3362,6 @@ fn buildOutputType(...@@ -3359,7 +3362,6 @@ fn buildOutputType(
3359 .emit_docs = emit_docs_resolved.data,3362 .emit_docs = emit_docs_resolved.data,
3360 .emit_implib = emit_implib_resolved.data,3363 .emit_implib = emit_implib_resolved.data,
3361 .dll_export_fns = dll_export_fns,3364 .dll_export_fns = dll_export_fns,
3362 .keep_source_files_loaded = false,
3363 .lib_dirs = lib_dirs.items,3365 .lib_dirs = lib_dirs.items,
3364 .rpath_list = rpath_list.items,3366 .rpath_list = rpath_list.items,
3365 .symbol_wrap_set = symbol_wrap_set,3367 .symbol_wrap_set = symbol_wrap_set,
...@@ -3443,7 +3445,6 @@ fn buildOutputType(...@@ -3443,7 +3445,6 @@ fn buildOutputType(
3443 .test_runner_path = test_runner_path,3445 .test_runner_path = test_runner_path,
3444 .disable_lld_caching = !output_to_cache,3446 .disable_lld_caching = !output_to_cache,
3445 .subsystem = subsystem,3447 .subsystem = subsystem,
3446 .debug_format = debug_format,
3447 .debug_compile_errors = debug_compile_errors,3448 .debug_compile_errors = debug_compile_errors,
3448 .enable_link_snapshots = enable_link_snapshots,3449 .enable_link_snapshots = enable_link_snapshots,
3449 .install_name = install_name,3450 .install_name = install_name,
...@@ -3484,7 +3485,9 @@ fn buildOutputType(...@@ -3484,7 +3485,9 @@ fn buildOutputType(
3484 defer if (!comp_destroyed) comp.destroy();3485 defer if (!comp_destroyed) comp.destroy();
34853486
3486 if (show_builtin) {3487 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);
3488 }3491 }
3489 switch (listen) {3492 switch (listen) {
3490 .none => {},3493 .none => {},
...@@ -3737,6 +3740,7 @@ fn createModule(...@@ -3737,6 +3740,7 @@ fn createModule(
3737 const resolved_target = cli_mod.inherited.resolved_target.?;3740 const resolved_target = cli_mod.inherited.resolved_target.?;
3738 create_module.opts.resolved_target = resolved_target;3741 create_module.opts.resolved_target = resolved_target;
3739 create_module.opts.root_optimize_mode = cli_mod.inherited.optimize_mode;3742 create_module.opts.root_optimize_mode = cli_mod.inherited.optimize_mode;
3743 create_module.opts.root_strip = cli_mod.inherited.strip;
3740 const target = resolved_target.result;3744 const target = resolved_target.result;
37413745
3742 // First, remove libc, libc++, and compiler_rt libraries from the system libraries list.3746 // 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...@@ -4366,12 +4370,12 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati
43664370
4367 const translated_zig_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{comp.root_name});4371 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);
4370 man.want_shared_lock = false;4374 man.want_shared_lock = false;
4371 defer man.deinit();4375 defer man.deinit();
43724376
4373 man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects4377 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);
4375 Compilation.cache_helpers.hashCSource(&man, c_source_file) catch |err| {4379 Compilation.cache_helpers.hashCSource(&man, c_source_file) catch |err| {
4376 fatal("unable to process '{s}': {s}", .{ c_source_file.src_path, @errorName(err) });4380 fatal("unable to process '{s}': {s}", .{ c_source_file.src_path, @errorName(err) });
4377 };4381 };
...@@ -4380,14 +4384,14 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati...@@ -4380,14 +4384,14 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati
4380 const digest = if (try man.hit()) man.final() else digest: {4384 const digest = if (try man.hit()) man.final() else digest: {
4381 if (fancy_output) |p| p.cache_hit = false;4385 if (fancy_output) |p| p.cache_hit = false;
4382 var argv = std.ArrayList([]const u8).init(arena);4386 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
4385 var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{});4389 var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{});
4386 defer zig_cache_tmp_dir.close();4390 defer zig_cache_tmp_dir.close();
43874391
4388 const ext = Compilation.classifyFileExt(c_source_file.src_path);4392 const ext = Compilation.classifyFileExt(c_source_file.src_path);
4389 const out_dep_path: ?[]const u8 = blk: {4393 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())
4391 break :blk null;4395 break :blk null;
43924396
4393 const c_src_basename = fs.path.basename(c_source_file.src_path);4397 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...@@ -4397,14 +4401,15 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati
4397 };4401 };
43984402
4399 // TODO4403 // 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);
4401 try argv.append(c_source_file.src_path);4406 try argv.append(c_source_file.src_path);
44024407
4403 if (comp.verbose_cc) {4408 if (comp.verbose_cc) {
4404 Compilation.dump_argv(argv.items);4409 Compilation.dump_argv(argv.items);
4405 }4410 }
44064411
4407 var tree = switch (comp.c_frontend) {4412 var tree = switch (comp.config.c_frontend) {
4408 .aro => tree: {4413 .aro => tree: {
4409 const aro = @import("aro");4414 const aro = @import("aro");
4410 const translate_c = @import("aro_translate_c.zig");4415 const translate_c = @import("aro_translate_c.zig");