authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-12-10 15:25:06-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-01 17:51:18-07:00
log12de7e3472cb2292e75578d33a8b8cc91f1ef0b0
tree77d38282ed0b8cc4911df38b702c09762b52c681
parentb92e30ff0bd2b77a486451b21d17666a311407f3

WIP: move many global settings to become per-Module

Much of the logic from Compilation.create() is extracted into Compilation.Config.resolve() which accepts many optional settings and produces concrete settings. This separate step is needed by API users of Compilation so that they can pass the resolved global settings to the Module creation function, which itself needs to resolve per-Module settings. Since the target and other things are no longer global settings, I did not want them stored in link.File (in the `options` field). That options field was already a kludge; those options should be resolved into concrete settings. This commit also starts to work on that, deleting link.Options, moving the fields into Compilation and ObjectFormat-specific structs instead. Some fields were ephemeral and should not have been stored at all, such as symbol_size_hint. The link.File object of Compilation is now a `?*link.File` and `null` when -fno-emit-bin is passed. It is now arena-allocated along with Compilation itself, avoiding some messy cleanup code that was there before. On the command line, it is now possible to configure the standard library itself by using `--mod std` just like any other module. This meant that the CLI needed to create the standard library module rather than having Compilation create it. There are a lot of changes in this commit and it's still not done. I didn't realize how quickly this changeset was going to balloon out of control, and there are still many lines that need to be changed before it even compiles successfully. * introduce std.Build.Cache.HashHelper.oneShot * add error_tracing to std.Build.Module * extract build.zig file generation into src/Builtin.zig * each CSourceFile and RcSourceFile now has a Module owner, which determines some of the C compiler flags.

16 files changed, 3250 insertions(+), 2694 deletions(-)

CMakeLists.txt+1
...@@ -521,6 +521,7 @@ set(ZIG_STAGE2_SOURCES...@@ -521,6 +521,7 @@ set(ZIG_STAGE2_SOURCES
521 "${CMAKE_SOURCE_DIR}/src/Air.zig"521 "${CMAKE_SOURCE_DIR}/src/Air.zig"
522 "${CMAKE_SOURCE_DIR}/src/AstGen.zig"522 "${CMAKE_SOURCE_DIR}/src/AstGen.zig"
523 "${CMAKE_SOURCE_DIR}/src/Compilation.zig"523 "${CMAKE_SOURCE_DIR}/src/Compilation.zig"
524 "${CMAKE_SOURCE_DIR}/src/Compilation/Config.zig"
524 "${CMAKE_SOURCE_DIR}/src/Liveness.zig"525 "${CMAKE_SOURCE_DIR}/src/Liveness.zig"
525 "${CMAKE_SOURCE_DIR}/src/Module.zig"526 "${CMAKE_SOURCE_DIR}/src/Module.zig"
526 "${CMAKE_SOURCE_DIR}/src/Package.zig"527 "${CMAKE_SOURCE_DIR}/src/Package.zig"
lib/std/Build/Cache.zig+14
...@@ -312,6 +312,20 @@ pub const HashHelper = struct {...@@ -312,6 +312,20 @@ pub const HashHelper = struct {
312 ) catch unreachable;312 ) catch unreachable;
313 return out_digest;313 return out_digest;
314 }314 }
315
316 pub fn oneShot(bytes: []const u8) [hex_digest_len]u8 {
317 var hasher: Hasher = hasher_init;
318 hasher.update(bytes);
319 var bin_digest: BinDigest = undefined;
320 hasher.final(&bin_digest);
321 var out_digest: [hex_digest_len]u8 = undefined;
322 _ = fmt.bufPrint(
323 &out_digest,
324 "{s}",
325 .{fmt.fmtSliceHexLower(&bin_digest)},
326 ) catch unreachable;
327 return out_digest;
328 }
315};329};
316330
317pub const Lock = struct {331pub const Lock = struct {
lib/std/Build/Module.zig+4
...@@ -34,6 +34,7 @@ valgrind: ?bool,...@@ -34,6 +34,7 @@ valgrind: ?bool,
34pic: ?bool,34pic: ?bool,
35red_zone: ?bool,35red_zone: ?bool,
36omit_frame_pointer: ?bool,36omit_frame_pointer: ?bool,
37error_tracing: ?bool,
37link_libc: ?bool,38link_libc: ?bool,
38link_libcpp: ?bool,39link_libcpp: ?bool,
3940
...@@ -177,6 +178,7 @@ pub const CreateOptions = struct {...@@ -177,6 +178,7 @@ pub const CreateOptions = struct {
177 /// Whether to omit the stack frame pointer. Frees up a register and makes it178 /// Whether to omit the stack frame pointer. Frees up a register and makes it
178 /// more difficult to obtain stack traces. Has target-dependent effects.179 /// more difficult to obtain stack traces. Has target-dependent effects.
179 omit_frame_pointer: ?bool = null,180 omit_frame_pointer: ?bool = null,
181 error_tracing: ?bool = null,
180};182};
181183
182pub const Import = struct {184pub const Import = struct {
...@@ -216,6 +218,7 @@ pub fn init(m: *Module, owner: *std.Build, options: CreateOptions, compile: ?*St...@@ -216,6 +218,7 @@ pub fn init(m: *Module, owner: *std.Build, options: CreateOptions, compile: ?*St
216 .pic = options.pic,218 .pic = options.pic,
217 .red_zone = options.red_zone,219 .red_zone = options.red_zone,
218 .omit_frame_pointer = options.omit_frame_pointer,220 .omit_frame_pointer = options.omit_frame_pointer,
221 .error_tracing = options.error_tracing,
219 .export_symbol_names = &.{},222 .export_symbol_names = &.{},
220 };223 };
221224
...@@ -601,6 +604,7 @@ pub fn appendZigProcessFlags(...@@ -601,6 +604,7 @@ pub fn appendZigProcessFlags(
601 try addFlag(zig_args, m.stack_check, "-fstack-check", "-fno-stack-check");604 try addFlag(zig_args, m.stack_check, "-fstack-check", "-fno-stack-check");
602 try addFlag(zig_args, m.stack_protector, "-fstack-protector", "-fno-stack-protector");605 try addFlag(zig_args, m.stack_protector, "-fstack-protector", "-fno-stack-protector");
603 try addFlag(zig_args, m.omit_frame_pointer, "-fomit-frame-pointer", "-fno-omit-frame-pointer");606 try addFlag(zig_args, m.omit_frame_pointer, "-fomit-frame-pointer", "-fno-omit-frame-pointer");
607 try addFlag(zig_args, m.error_tracing, "-ferror-tracing", "-fno-error-tracing");
604 try addFlag(zig_args, m.sanitize_c, "-fsanitize-c", "-fno-sanitize-c");608 try addFlag(zig_args, m.sanitize_c, "-fsanitize-c", "-fno-sanitize-c");
605 try addFlag(zig_args, m.sanitize_thread, "-fsanitize-thread", "-fno-sanitize-thread");609 try addFlag(zig_args, m.sanitize_thread, "-fsanitize-thread", "-fno-sanitize-thread");
606 try addFlag(zig_args, m.valgrind, "-fvalgrind", "-fno-valgrind");610 try addFlag(zig_args, m.valgrind, "-fvalgrind", "-fno-valgrind");
src/Builtin.zig created+240
...@@ -0,0 +1,240 @@
1target: std.Target,
2zig_backend: std.builtin.CompilerBackend,
3output_mode: std.builtin.OutputMode,
4link_mode: std.builtin.LinkMode,
5is_test: bool,
6test_evented_io: bool,
7single_threaded: bool,
8link_libc: bool,
9link_libcpp: bool,
10optimize_mode: std.builtin.OptimizeMode,
11error_tracing: bool,
12valgrind: bool,
13sanitize_thread: bool,
14pic: bool,
15pie: bool,
16strip: bool,
17code_model: std.builtin.CodeModel,
18omit_frame_pointer: bool,
19wasi_exec_model: std.builtin.WasiExecModel,
20
21pub fn generate(opts: @This(), allocator: Allocator) Allocator.Error![:0]u8 {
22 var buffer = std.ArrayList(u8).init(allocator);
23 defer buffer.deinit();
24
25 const target = opts.target;
26 const generic_arch_name = target.cpu.arch.genericName();
27 const zig_backend = opts.zig_backend;
28
29 @setEvalBranchQuota(4000);
30 try buffer.writer().print(
31 \\const std = @import("std");
32 \\/// Zig version. When writing code that supports multiple versions of Zig, prefer
33 \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.
34 \\pub const zig_version = std.SemanticVersion.parse(zig_version_string) catch unreachable;
35 \\pub const zig_version_string = "{s}";
36 \\pub const zig_backend = std.builtin.CompilerBackend.{};
37 \\
38 \\pub const output_mode = std.builtin.OutputMode.{};
39 \\pub const link_mode = std.builtin.LinkMode.{};
40 \\pub const is_test = {};
41 \\pub const single_threaded = {};
42 \\pub const abi = std.Target.Abi.{};
43 \\pub const cpu: std.Target.Cpu = .{{
44 \\ .arch = .{},
45 \\ .model = &std.Target.{}.cpu.{},
46 \\ .features = std.Target.{}.featureSet(&[_]std.Target.{}.Feature{{
47 \\
48 , .{
49 build_options.version,
50 std.zig.fmtId(@tagName(zig_backend)),
51 std.zig.fmtId(@tagName(opts.output_mode)),
52 std.zig.fmtId(@tagName(opts.link_mode)),
53 opts.is_test,
54 opts.single_threaded,
55 std.zig.fmtId(@tagName(target.abi)),
56 std.zig.fmtId(@tagName(target.cpu.arch)),
57 std.zig.fmtId(generic_arch_name),
58 std.zig.fmtId(target.cpu.model.name),
59 std.zig.fmtId(generic_arch_name),
60 std.zig.fmtId(generic_arch_name),
61 });
62
63 for (target.cpu.arch.allFeaturesList(), 0..) |feature, index_usize| {
64 const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));
65 const is_enabled = target.cpu.features.isEnabled(index);
66 if (is_enabled) {
67 try buffer.writer().print(" .{},\n", .{std.zig.fmtId(feature.name)});
68 }
69 }
70 try buffer.writer().print(
71 \\ }}),
72 \\}};
73 \\pub const os = std.Target.Os{{
74 \\ .tag = .{},
75 \\ .version_range = .{{
76 ,
77 .{std.zig.fmtId(@tagName(target.os.tag))},
78 );
79
80 switch (target.os.getVersionRange()) {
81 .none => try buffer.appendSlice(" .none = {} },\n"),
82 .semver => |semver| try buffer.writer().print(
83 \\ .semver = .{{
84 \\ .min = .{{
85 \\ .major = {},
86 \\ .minor = {},
87 \\ .patch = {},
88 \\ }},
89 \\ .max = .{{
90 \\ .major = {},
91 \\ .minor = {},
92 \\ .patch = {},
93 \\ }},
94 \\ }}}},
95 \\
96 , .{
97 semver.min.major,
98 semver.min.minor,
99 semver.min.patch,
100
101 semver.max.major,
102 semver.max.minor,
103 semver.max.patch,
104 }),
105 .linux => |linux| try buffer.writer().print(
106 \\ .linux = .{{
107 \\ .range = .{{
108 \\ .min = .{{
109 \\ .major = {},
110 \\ .minor = {},
111 \\ .patch = {},
112 \\ }},
113 \\ .max = .{{
114 \\ .major = {},
115 \\ .minor = {},
116 \\ .patch = {},
117 \\ }},
118 \\ }},
119 \\ .glibc = .{{
120 \\ .major = {},
121 \\ .minor = {},
122 \\ .patch = {},
123 \\ }},
124 \\ }}}},
125 \\
126 , .{
127 linux.range.min.major,
128 linux.range.min.minor,
129 linux.range.min.patch,
130
131 linux.range.max.major,
132 linux.range.max.minor,
133 linux.range.max.patch,
134
135 linux.glibc.major,
136 linux.glibc.minor,
137 linux.glibc.patch,
138 }),
139 .windows => |windows| try buffer.writer().print(
140 \\ .windows = .{{
141 \\ .min = {s},
142 \\ .max = {s},
143 \\ }}}},
144 \\
145 ,
146 .{ windows.min, windows.max },
147 ),
148 }
149 try buffer.appendSlice(
150 \\};
151 \\pub const target: std.Target = .{
152 \\ .cpu = cpu,
153 \\ .os = os,
154 \\ .abi = abi,
155 \\ .ofmt = object_format,
156 \\
157 );
158
159 if (target.dynamic_linker.get()) |dl| {
160 try buffer.writer().print(
161 \\ .dynamic_linker = std.Target.DynamicLinker.init("{s}"),
162 \\}};
163 \\
164 , .{dl});
165 } else {
166 try buffer.appendSlice(
167 \\ .dynamic_linker = std.Target.DynamicLinker.none,
168 \\};
169 \\
170 );
171 }
172
173 // This is so that compiler_rt and libc.zig libraries know whether they
174 // will eventually be linked with libc. They make different decisions
175 // about what to export depending on whether another libc will be linked
176 // in. For example, compiler_rt will not export the __chkstk symbol if it
177 // knows libc will provide it, and likewise c.zig will not export memcpy.
178 const link_libc = opts.link_libc;
179
180 try buffer.writer().print(
181 \\pub const object_format = std.Target.ObjectFormat.{};
182 \\pub const mode = std.builtin.OptimizeMode.{};
183 \\pub const link_libc = {};
184 \\pub const link_libcpp = {};
185 \\pub const have_error_return_tracing = {};
186 \\pub const valgrind_support = {};
187 \\pub const sanitize_thread = {};
188 \\pub const position_independent_code = {};
189 \\pub const position_independent_executable = {};
190 \\pub const strip_debug_info = {};
191 \\pub const code_model = std.builtin.CodeModel.{};
192 \\pub const omit_frame_pointer = {};
193 \\
194 , .{
195 std.zig.fmtId(@tagName(target.ofmt)),
196 std.zig.fmtId(@tagName(opts.optimize_mode)),
197 link_libc,
198 opts.link_libcpp,
199 opts.error_tracing,
200 opts.valgrind,
201 opts.sanitize_thread,
202 opts.pic,
203 opts.pie,
204 opts.strip,
205 std.zig.fmtId(@tagName(opts.code_model)),
206 opts.omit_frame_pointer,
207 });
208
209 if (target.os.tag == .wasi) {
210 const wasi_exec_model_fmt = std.zig.fmtId(@tagName(opts.wasi_exec_model));
211 try buffer.writer().print(
212 \\pub const wasi_exec_model = std.builtin.WasiExecModel.{};
213 \\
214 , .{wasi_exec_model_fmt});
215 }
216
217 if (opts.is_test) {
218 try buffer.appendSlice(
219 \\pub var test_functions: []const std.builtin.TestFn = undefined; // overwritten later
220 \\
221 );
222 if (opts.test_evented_io) {
223 try buffer.appendSlice(
224 \\pub const test_io_mode = .evented;
225 \\
226 );
227 } else {
228 try buffer.appendSlice(
229 \\pub const test_io_mode = .blocking;
230 \\
231 );
232 }
233 }
234
235 return buffer.toOwnedSliceSentinel(0);
236}
237
238const std = @import("std");
239const Allocator = std.mem.Allocator;
240const build_options = @import("build_options");
src/Compilation.zig+431-1026
...@@ -38,12 +38,43 @@ const Autodoc = @import("Autodoc.zig");...@@ -38,12 +38,43 @@ const 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");
4040
41pub const Config = @import("Compilation/Config.zig");
42
41/// General-purpose allocator. Used for both temporary and long-term storage.43/// General-purpose allocator. Used for both temporary and long-term storage.
42gpa: Allocator,44gpa: Allocator,
43/// Arena-allocated memory, mostly used during initialization. However, it can be used45/// Arena-allocated memory, mostly used during initialization. However, it can be used
44/// for other things requiring the same lifetime as the `Compilation`.46/// for other things requiring the same lifetime as the `Compilation`.
45arena: std.heap.ArenaAllocator,47arena: std.heap.ArenaAllocator,
46bin_file: *link.File,48/// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.
49/// TODO: rename to zcu: ?*Zcu
50module: ?*Module,
51/// All compilations have a root module because this is where some important
52/// settings are stored, such as target and optimization mode. This module
53/// might not have any .zig code associated with it, however.
54root_mod: *Package.Module,
55
56/// User-specified settings that have all the defaults resolved into concrete values.
57config: Config,
58
59/// This is `null` when `-fno-emit-bin` is used.
60bin_file: ?*link.File,
61
62/// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin)
63sysroot: ?[]const u8,
64/// This is `null` when not building a Windows DLL, or when `-fno-emit-implib` is used.
65implib_emit: ?Emit,
66/// This is non-null when `-femit-docs` is provided.
67docs_emit: ?Emit,
68root_name: [:0]const u8,
69cache_mode: CacheMode,
70include_compiler_rt: bool,
71objects: []Compilation.LinkObject,
72/// These are *always* dynamically linked. Static libraries will be
73/// provided as positional arguments.
74system_libs: std.StringArrayHashMapUnmanaged(SystemLib),
75version: ?std.SemanticVersion,
76libc_installation: ?*const LibCInstallation,
77
47c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},78c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},
48win32_resource_table: if (build_options.only_core_functionality) void else std.AutoArrayHashMapUnmanaged(*Win32Resource, void) =79win32_resource_table: if (build_options.only_core_functionality) void else std.AutoArrayHashMapUnmanaged(*Win32Resource, void) =
49 if (build_options.only_core_functionality) {} else .{},80 if (build_options.only_core_functionality) {} else .{},
...@@ -87,8 +118,6 @@ failed_win32_resources: if (build_options.only_core_functionality) void else std...@@ -87,8 +118,6 @@ failed_win32_resources: if (build_options.only_core_functionality) void else std
87misc_failures: std.AutoArrayHashMapUnmanaged(MiscTask, MiscError) = .{},118misc_failures: std.AutoArrayHashMapUnmanaged(MiscTask, MiscError) = .{},
88119
89keep_source_files_loaded: bool,120keep_source_files_loaded: bool,
90c_frontend: CFrontend,
91sanitize_c: bool,
92/// When this is `true` it means invoking clang as a sub-process is expected to inherit121/// When this is `true` it means invoking clang as a sub-process is expected to inherit
93/// stdin, stdout, stderr, and if it returns non success, to forward the exit code.122/// stdin, stdout, stderr, and if it returns non success, to forward the exit code.
94/// Otherwise we attempt to parse the error messages and expose them via the Compilation API.123/// Otherwise we attempt to parse the error messages and expose them via the Compilation API.
...@@ -107,8 +136,6 @@ verbose_llvm_cpu_features: bool,...@@ -107,8 +136,6 @@ verbose_llvm_cpu_features: bool,
107disable_c_depfile: bool,136disable_c_depfile: bool,
108time_report: bool,137time_report: bool,
109stack_report: bool,138stack_report: bool,
110unwind_tables: bool,
111test_evented_io: bool,
112debug_compiler_runtime_libs: bool,139debug_compiler_runtime_libs: bool,
113debug_compile_errors: bool,140debug_compile_errors: bool,
114job_queued_compiler_rt_lib: bool = false,141job_queued_compiler_rt_lib: bool = false,
...@@ -118,7 +145,6 @@ formatted_panics: bool = false,...@@ -118,7 +145,6 @@ formatted_panics: bool = false,
118last_update_was_cache_hit: bool = false,145last_update_was_cache_hit: bool = false,
119146
120c_source_files: []const CSourceFile,147c_source_files: []const CSourceFile,
121clang_argv: []const []const u8,
122rc_source_files: []const RcSourceFile,148rc_source_files: []const RcSourceFile,
123cache_parent: *Cache,149cache_parent: *Cache,
124/// Path to own executable for invoking `zig clang`.150/// Path to own executable for invoking `zig clang`.
...@@ -194,7 +220,29 @@ emit_llvm_bc: ?EmitLoc,...@@ -194,7 +220,29 @@ emit_llvm_bc: ?EmitLoc,
194work_queue_wait_group: WaitGroup = .{},220work_queue_wait_group: WaitGroup = .{},
195astgen_wait_group: WaitGroup = .{},221astgen_wait_group: WaitGroup = .{},
196222
197pub const default_stack_protector_buffer_size = 4;223pub const Emit = struct {
224 /// Where the output will go.
225 directory: Directory,
226 /// Path to the output file, relative to `directory`.
227 sub_path: []const u8,
228
229 /// Returns the full path to `basename` if it were in the same directory as the
230 /// `Emit` sub_path.
231 pub fn basenamePath(emit: Emit, arena: Allocator, basename: [:0]const u8) ![:0]const u8 {
232 const full_path = if (emit.directory.path) |p|
233 try std.fs.path.join(arena, &[_][]const u8{ p, emit.sub_path })
234 else
235 emit.sub_path;
236
237 if (std.fs.path.dirname(full_path)) |dirname| {
238 return try std.fs.path.joinZ(arena, &.{ dirname, basename });
239 } else {
240 return basename;
241 }
242 }
243};
244
245pub const default_stack_protector_buffer_size = target_util.default_stack_protector_buffer_size;
198pub const SemaError = Module.SemaError;246pub const SemaError = Module.SemaError;
199247
200pub const CRTFile = struct {248pub const CRTFile = struct {
...@@ -208,8 +256,8 @@ pub const CRTFile = struct {...@@ -208,8 +256,8 @@ pub const CRTFile = struct {
208 }256 }
209};257};
210258
211// supported languages for "zig clang -x <lang>".259/// Supported languages for "zig clang -x <lang>".
212// Loosely based on llvm-project/clang/include/clang/Driver/Types.def260/// Loosely based on llvm-project/clang/include/clang/Driver/Types.def
213pub const LangToExt = std.ComptimeStringMap(FileExt, .{261pub const LangToExt = std.ComptimeStringMap(FileExt, .{
214 .{ "c", .c },262 .{ "c", .c },
215 .{ "c-header", .h },263 .{ "c-header", .h },
...@@ -226,16 +274,20 @@ pub const LangToExt = std.ComptimeStringMap(FileExt, .{...@@ -226,16 +274,20 @@ pub const LangToExt = std.ComptimeStringMap(FileExt, .{
226274
227/// For passing to a C compiler.275/// For passing to a C compiler.
228pub const CSourceFile = struct {276pub const CSourceFile = struct {
277 /// Many C compiler flags are determined by settings contained in the owning Module.
278 owner: *Package.Module,
229 src_path: []const u8,279 src_path: []const u8,
230 extra_flags: []const []const u8 = &.{},280 extra_flags: []const []const u8 = &.{},
231 /// Same as extra_flags except they are not added to the Cache hash.281 /// Same as extra_flags except they are not added to the Cache hash.
232 cache_exempt_flags: []const []const u8 = &.{},282 cache_exempt_flags: []const []const u8 = &.{},
233 // this field is non-null iff language was explicitly set with "-x lang".283 /// This field is non-null if and only if the language was explicitly set
284 /// with "-x lang".
234 ext: ?FileExt = null,285 ext: ?FileExt = null,
235};286};
236287
237/// For passing to resinator.288/// For passing to resinator.
238pub const RcSourceFile = struct {289pub const RcSourceFile = struct {
290 owner: *Package.Module,
239 src_path: []const u8,291 src_path: []const u8,
240 extra_flags: []const []const u8 = &.{},292 extra_flags: []const []const u8 = &.{},
241};293};
...@@ -742,6 +794,22 @@ pub const EmitLoc = struct {...@@ -742,6 +794,22 @@ pub const EmitLoc = struct {
742};794};
743795
744pub const cache_helpers = struct {796pub const cache_helpers = struct {
797 pub fn addResolvedTarget(
798 hh: *Cache.HashHelper,
799 resolved_target: Package.Module.ResolvedTarget,
800 ) void {
801 const target = resolved_target.result;
802 hh.add(target.cpu.arch);
803 hh.addBytes(target.cpu.model.name);
804 hh.add(target.cpu.features.ints);
805 hh.add(target.os.tag);
806 hh.add(target.os.getVersionRange());
807 hh.add(target.abi);
808 hh.add(target.ofmt);
809 hh.add(resolved_target.is_native_os);
810 hh.add(resolved_target.is_native_abi);
811 }
812
745 pub fn addEmitLoc(hh: *Cache.HashHelper, emit_loc: EmitLoc) void {813 pub fn addEmitLoc(hh: *Cache.HashHelper, emit_loc: EmitLoc) void {
746 hh.addBytes(emit_loc.basename);814 hh.addBytes(emit_loc.basename);
747 }815 }
...@@ -751,7 +819,7 @@ pub const cache_helpers = struct {...@@ -751,7 +819,7 @@ pub const cache_helpers = struct {
751 addEmitLoc(hh, optional_emit_loc orelse return);819 addEmitLoc(hh, optional_emit_loc orelse return);
752 }820 }
753821
754 pub fn hashCSource(self: *Cache.Manifest, c_source: Compilation.CSourceFile) !void {822 pub fn hashCSource(self: *Cache.Manifest, c_source: CSourceFile) !void {
755 _ = try self.addFile(c_source.src_path, null);823 _ = try self.addFile(c_source.src_path, null);
756 // Hash the extra flags, with special care to call addFile for file parameters.824 // Hash the extra flags, with special care to call addFile for file parameters.
757 // TODO this logic can likely be improved by utilizing clang_options_data.zig.825 // TODO this logic can likely be improved by utilizing clang_options_data.zig.
...@@ -770,8 +838,6 @@ pub const cache_helpers = struct {...@@ -770,8 +838,6 @@ pub const cache_helpers = struct {
770 }838 }
771};839};
772840
773pub const CFrontend = enum { clang, aro };
774
775pub const ClangPreprocessorMode = enum {841pub const ClangPreprocessorMode = enum {
776 no,842 no,
777 /// This means we are doing `zig cc -E -o <path>`.843 /// This means we are doing `zig cc -E -o <path>`.
...@@ -798,11 +864,21 @@ pub const InitOptions = struct {...@@ -798,11 +864,21 @@ pub const InitOptions = struct {
798 zig_lib_directory: Directory,864 zig_lib_directory: Directory,
799 local_cache_directory: Directory,865 local_cache_directory: Directory,
800 global_cache_directory: Directory,866 global_cache_directory: Directory,
801 target: Target,
802 root_name: []const u8,
803 main_mod: ?*Package.Module,
804 output_mode: std.builtin.OutputMode,
805 thread_pool: *ThreadPool,867 thread_pool: *ThreadPool,
868 self_exe_path: ?[]const u8 = null,
869
870 /// Options that have been resolved by calling `resolveDefaults`.
871 config: Compilation.Config,
872
873 root_mod: *Package.Module,
874 /// Normally, `main_mod` and `root_mod` are the same. The exception is `zig
875 /// test`, in which `root_mod` is the test runner, and `main_mod` is the
876 /// user's source file which has the tests.
877 main_mod: ?*Package.Module,
878 /// This is provided so that the API user has a chance to tweak the
879 /// per-module settings of the standard library.
880 std_mod: *Package.Module,
881 root_name: []const u8,
806 sysroot: ?[]const u8 = null,882 sysroot: ?[]const u8 = null,
807 /// `null` means to not emit a binary file.883 /// `null` means to not emit a binary file.
808 emit_bin: ?EmitLoc,884 emit_bin: ?EmitLoc,
...@@ -818,7 +894,6 @@ pub const InitOptions = struct {...@@ -818,7 +894,6 @@ pub const InitOptions = struct {
818 emit_docs: ?EmitLoc = null,894 emit_docs: ?EmitLoc = null,
819 /// `null` means to not emit an import lib.895 /// `null` means to not emit an import lib.
820 emit_implib: ?EmitLoc = null,896 emit_implib: ?EmitLoc = null,
821 link_mode: ?std.builtin.LinkMode = null,
822 dll_export_fns: ?bool = false,897 dll_export_fns: ?bool = false,
823 /// Normally when using LLD to link, Zig uses a file named "lld.id" in the898 /// Normally when using LLD to link, Zig uses a file named "lld.id" in the
824 /// same directory as the output binary which contains the hash of the link899 /// same directory as the output binary which contains the hash of the link
...@@ -828,14 +903,12 @@ pub const InitOptions = struct {...@@ -828,14 +903,12 @@ pub const InitOptions = struct {
828 /// this flag would be set to disable this machinery to avoid false positives.903 /// this flag would be set to disable this machinery to avoid false positives.
829 disable_lld_caching: bool = false,904 disable_lld_caching: bool = false,
830 cache_mode: CacheMode = .incremental,905 cache_mode: CacheMode = .incremental,
831 optimize_mode: std.builtin.OptimizeMode = .Debug,
832 keep_source_files_loaded: bool = false,906 keep_source_files_loaded: bool = false,
833 clang_argv: []const []const u8 = &[0][]const u8{},
834 lib_dirs: []const []const u8 = &[0][]const u8{},907 lib_dirs: []const []const u8 = &[0][]const u8{},
835 rpath_list: []const []const u8 = &[0][]const u8{},908 rpath_list: []const []const u8 = &[0][]const u8{},
836 symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{},909 symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{},
837 c_source_files: []const CSourceFile = &[0]CSourceFile{},910 c_source_files: []const CSourceFile = &.{},
838 rc_source_files: []const RcSourceFile = &[0]RcSourceFile{},911 rc_source_files: []const RcSourceFile = &.{},
839 manifest_file: ?[]const u8 = null,912 manifest_file: ?[]const u8 = null,
840 rc_includes: RcIncludes = .any,913 rc_includes: RcIncludes = .any,
841 link_objects: []LinkObject = &[0]LinkObject{},914 link_objects: []LinkObject = &[0]LinkObject{},
...@@ -849,40 +922,16 @@ pub const InitOptions = struct {...@@ -849,40 +922,16 @@ pub const InitOptions = struct {
849 /// * mman922 /// * mman
850 /// * signal923 /// * signal
851 wasi_emulated_libs: []const wasi_libc.CRTFile = &[0]wasi_libc.CRTFile{},924 wasi_emulated_libs: []const wasi_libc.CRTFile = &[0]wasi_libc.CRTFile{},
852 link_libc: bool = false,
853 link_libcpp: bool = false,
854 link_libunwind: bool = false,
855 want_pic: ?bool = null,
856 /// This means that if the output mode is an executable it will be a925 /// This means that if the output mode is an executable it will be a
857 /// Position Independent Executable. If the output mode is not an926 /// Position Independent Executable. If the output mode is not an
858 /// executable this field is ignored.927 /// executable this field is ignored.
859 want_pie: ?bool = null,
860 want_sanitize_c: ?bool = null,
861 want_stack_check: ?bool = null,
862 /// null means default.
863 /// 0 means no stack protector.
864 /// other number means stack protection with that buffer size.
865 want_stack_protector: ?u32 = null,
866 want_red_zone: ?bool = null,
867 omit_frame_pointer: ?bool = null,
868 want_valgrind: ?bool = null,
869 want_tsan: ?bool = null,
870 want_compiler_rt: ?bool = null,928 want_compiler_rt: ?bool = null,
871 want_lto: ?bool = null,929 want_lto: ?bool = null,
872 want_unwind_tables: ?bool = null,
873 use_llvm: ?bool = null,
874 use_lib_llvm: ?bool = null,
875 use_lld: ?bool = null,
876 use_clang: ?bool = null,
877 single_threaded: ?bool = null,
878 strip: ?bool = null,
879 formatted_panics: ?bool = null,930 formatted_panics: ?bool = null,
880 rdynamic: bool = false,931 rdynamic: bool = false,
881 function_sections: bool = false,932 function_sections: bool = false,
882 data_sections: bool = false,933 data_sections: bool = false,
883 no_builtin: bool = false,934 no_builtin: bool = false,
884 is_native_os: bool,
885 is_native_abi: bool,
886 time_report: bool = false,935 time_report: bool = false,
887 stack_report: bool = false,936 stack_report: bool = false,
888 link_eh_frame_hdr: bool = false,937 link_eh_frame_hdr: bool = false,
...@@ -893,14 +942,11 @@ pub const InitOptions = struct {...@@ -893,14 +942,11 @@ pub const InitOptions = struct {
893 linker_gc_sections: ?bool = null,942 linker_gc_sections: ?bool = null,
894 linker_allow_shlib_undefined: ?bool = null,943 linker_allow_shlib_undefined: ?bool = null,
895 linker_bind_global_refs_locally: ?bool = null,944 linker_bind_global_refs_locally: ?bool = null,
896 linker_import_memory: ?bool = null,
897 linker_export_memory: ?bool = null,
898 linker_import_symbols: bool = false,945 linker_import_symbols: bool = false,
899 linker_import_table: bool = false,946 linker_import_table: bool = false,
900 linker_export_table: bool = false,947 linker_export_table: bool = false,
901 linker_initial_memory: ?u64 = null,948 linker_initial_memory: ?u64 = null,
902 linker_max_memory: ?u64 = null,949 linker_max_memory: ?u64 = null,
903 linker_shared_memory: bool = false,
904 linker_global_base: ?u64 = null,950 linker_global_base: ?u64 = null,
905 linker_export_symbol_names: []const []const u8 = &.{},951 linker_export_symbol_names: []const []const u8 = &.{},
906 linker_print_gc_sections: bool = false,952 linker_print_gc_sections: bool = false,
...@@ -938,8 +984,6 @@ pub const InitOptions = struct {...@@ -938,8 +984,6 @@ pub const InitOptions = struct {
938 verbose_llvm_bc: ?[]const u8 = null,984 verbose_llvm_bc: ?[]const u8 = null,
939 verbose_cimport: bool = false,985 verbose_cimport: bool = false,
940 verbose_llvm_cpu_features: bool = false,986 verbose_llvm_cpu_features: bool = false,
941 is_test: bool = false,
942 test_evented_io: bool = false,
943 debug_compiler_runtime_libs: bool = false,987 debug_compiler_runtime_libs: bool = false,
944 debug_compile_errors: bool = false,988 debug_compile_errors: bool = false,
945 /// Normally when you create a `Compilation`, Zig will automatically build989 /// Normally when you create a `Compilation`, Zig will automatically build
...@@ -952,23 +996,18 @@ pub const InitOptions = struct {...@@ -952,23 +996,18 @@ pub const InitOptions = struct {
952 force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{},996 force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{},
953 stack_size_override: ?u64 = null,997 stack_size_override: ?u64 = null,
954 image_base_override: ?u64 = null,998 image_base_override: ?u64 = null,
955 self_exe_path: ?[]const u8 = null,
956 version: ?std.SemanticVersion = null,999 version: ?std.SemanticVersion = null,
957 compatibility_version: ?std.SemanticVersion = null,1000 compatibility_version: ?std.SemanticVersion = null,
958 libc_installation: ?*const LibCInstallation = null,1001 libc_installation: ?*const LibCInstallation = null,
959 machine_code_model: std.builtin.CodeModel = .default,
960 clang_preprocessor_mode: ClangPreprocessorMode = .no,1002 clang_preprocessor_mode: ClangPreprocessorMode = .no,
961 /// This is for stage1 and should be deleted upon completion of self-hosting.1003 /// This is for stage1 and should be deleted upon completion of self-hosting.
962 color: Color = .auto,1004 color: Color = .auto,
963 reference_trace: ?u32 = null,1005 reference_trace: ?u32 = null,
964 error_tracing: ?bool = null,
965 test_filter: ?[]const u8 = null,1006 test_filter: ?[]const u8 = null,
966 test_name_prefix: ?[]const u8 = null,1007 test_name_prefix: ?[]const u8 = null,
967 test_runner_path: ?[]const u8 = null,1008 test_runner_path: ?[]const u8 = null,
968 subsystem: ?std.Target.SubSystem = null,1009 subsystem: ?std.Target.SubSystem = null,
969 dwarf_format: ?std.dwarf.Format = null,1010 dwarf_format: ?std.dwarf.Format = null,
970 /// WASI-only. Type of WASI execution model ("command" or "reactor").
971 wasi_exec_model: ?std.builtin.WasiExecModel = null,
972 /// (Zig compiler development) Enable dumping linker's state as JSON.1011 /// (Zig compiler development) Enable dumping linker's state as JSON.
973 enable_link_snapshots: bool = false,1012 enable_link_snapshots: bool = false,
974 /// (Darwin) Install name of the dylib1013 /// (Darwin) Install name of the dylib
...@@ -989,77 +1028,93 @@ pub const InitOptions = struct {...@@ -989,77 +1028,93 @@ pub const InitOptions = struct {
989 pdb_source_path: ?[]const u8 = null,1028 pdb_source_path: ?[]const u8 = null,
990 /// (Windows) PDB output path1029 /// (Windows) PDB output path
991 pdb_out_path: ?[]const u8 = null,1030 pdb_out_path: ?[]const u8 = null,
992 error_limit: ?Module.ErrorInt = null,1031 error_limit: ?Compilation.Module.ErrorInt = null,
993 /// (SPIR-V) whether to generate a structured control flow graph or not1032 /// (SPIR-V) whether to generate a structured control flow graph or not
994 want_structured_cfg: ?bool = null,1033 want_structured_cfg: ?bool = null,
995};1034};
9961035
997fn addModuleTableToCacheHash(1036fn addModuleTableToCacheHash(
1037 gpa: Allocator,
1038 arena: Allocator,
998 hash: *Cache.HashHelper,1039 hash: *Cache.HashHelper,
999 arena: *std.heap.ArenaAllocator,1040 root_mod: *Package.Module,
1000 mod_table: Package.Module.Deps,
1001 seen_table: *std.AutoHashMap(*Package.Module, void),
1002 hash_type: union(enum) { path_bytes, files: *Cache.Manifest },1041 hash_type: union(enum) { path_bytes, files: *Cache.Manifest },
1003) (error{OutOfMemory} || std.os.GetCwdError)!void {1042) (error{OutOfMemory} || std.os.GetCwdError)!void {
1004 const allocator = arena.allocator();1043 var seen_table: std.AutoArrayHashMapUnmanaged(*Package.Module, void) = .{};
10051044 try seen_table.put(gpa, root_mod, {});
1006 const module_indices = try allocator.alloc(u32, mod_table.count());1045
1007 // Copy over the hashmap entries to our slice1046 const SortByName = struct {
1008 for (module_indices, 0..) |*module_index, index| module_index.* = @intCast(index);1047 names: []const []const u8,
1009 // Sort the slice by package name1048
1010 mem.sortUnstable(u32, module_indices, &mod_table, struct {1049 pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool {
1011 fn lessThan(deps: *const Package.Module.Deps, lhs: u32, rhs: u32) bool {1050 const lhs_key = ctx.names[lhs_index];
1012 const keys = deps.keys();1051 const rhs_key = ctx.names[rhs_index];
1013 return std.mem.lessThan(u8, keys[lhs], keys[rhs]);1052 return mem.lessThan(u8, lhs_key, rhs_key);
1014 }1053 }
1015 }.lessThan);1054 };
10161055
1017 for (module_indices) |module_index| {1056 var i: usize = 0;
1018 const module = mod_table.values()[module_index];1057 while (i < seen_table.count()) : (i += 1) {
1019 if ((try seen_table.getOrPut(module)).found_existing) continue;1058 const mod = seen_table.keys()[i];
1059
1060 cache_helpers.addResolvedTarget(hash, mod.resolved_target);
1061 hash.add(mod.optimize_mode);
1062 hash.add(mod.code_model);
1063 hash.add(mod.single_threaded);
1064 hash.add(mod.error_tracing);
1065 hash.add(mod.valgrind);
1066 hash.add(mod.pic);
1067 hash.add(mod.strip);
1068 hash.add(mod.omit_frame_pointer);
1069 hash.add(mod.stack_check);
1070 hash.add(mod.red_zone);
1071 hash.add(mod.sanitize_c);
1072 hash.add(mod.sanitize_thread);
10201073
1021 // Finally insert the package name and path to the cache hash.
1022 hash.addBytes(mod_table.keys()[module_index]);
1023 switch (hash_type) {1074 switch (hash_type) {
1024 .path_bytes => {1075 .path_bytes => {
1025 hash.addBytes(module.root_src_path);1076 hash.addBytes(mod.root_src_path);
1026 hash.addOptionalBytes(module.root.root_dir.path);1077 hash.addOptionalBytes(mod.root.root_dir.path);
1027 hash.addBytes(module.root.sub_path);1078 hash.addBytes(mod.root.sub_path);
1028 },1079 },
1029 .files => |man| {1080 .files => |man| {
1030 const pkg_zig_file = try module.root.joinString(1081 const pkg_zig_file = try mod.root.joinString(arena, mod.root_src_path);
1031 allocator,
1032 module.root_src_path,
1033 );
1034 _ = try man.addFile(pkg_zig_file, null);1082 _ = try man.addFile(pkg_zig_file, null);
1035 },1083 },
1036 }1084 }
1037 // Recurse to handle the module's dependencies1085
1038 try addModuleTableToCacheHash(hash, arena, module.deps, seen_table, hash_type);1086 mod.deps.sortUnstable(SortByName{ .names = mod.deps.keys() });
1087
1088 hash.addListOfBytes(mod.deps.keys());
1089
1090 const deps = mod.deps.values();
1091 try seen_table.ensureUnusedCapacity(gpa, deps.len);
1092 for (deps) |dep| seen_table.putAssumeCapacity(dep, {});
1039 }1093 }
1040}1094}
10411095
1042pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {1096pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1043 const is_dyn_lib = switch (options.output_mode) {1097 const output_mode = options.config.output_mode;
1098 const is_dyn_lib = switch (output_mode) {
1044 .Obj, .Exe => false,1099 .Obj, .Exe => false,
1045 .Lib => (options.link_mode orelse .Static) == .Dynamic,1100 .Lib => options.config.link_mode == .Dynamic,
1046 };1101 };
1047 const is_exe_or_dyn_lib = switch (options.output_mode) {1102 const is_exe_or_dyn_lib = switch (output_mode) {
1048 .Obj => false,1103 .Obj => false,
1049 .Lib => is_dyn_lib,1104 .Lib => is_dyn_lib,
1050 .Exe => true,1105 .Exe => true,
1051 };1106 };
10521107
1053 // WASI-only. Resolve the optional exec-model option, defaults to command.
1054 const wasi_exec_model = if (options.target.os.tag != .wasi) undefined else options.wasi_exec_model orelse .command;
1055
1056 if (options.linker_export_table and options.linker_import_table) {1108 if (options.linker_export_table and options.linker_import_table) {
1057 return error.ExportTableAndImportTableConflict;1109 return error.ExportTableAndImportTableConflict;
1058 }1110 }
10591111
1112 const have_zcu = options.root_mod.root_src_path.len != 0;
1113
1060 const comp: *Compilation = comp: {1114 const comp: *Compilation = comp: {
1061 // For allocations that have the same lifetime as Compilation. This arena is used only during this1115 // For allocations that have the same lifetime as Compilation. This
1062 // initialization and then is freed in deinit().1116 // arena is used only during this initialization and then is freed in
1117 // deinit().
1063 var arena_allocator = std.heap.ArenaAllocator.init(gpa);1118 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
1064 errdefer arena_allocator.deinit();1119 errdefer arena_allocator.deinit();
1065 const arena = arena_allocator.allocator();1120 const arena = arena_allocator.allocator();
...@@ -1069,366 +1124,145 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1069,366 +1124,145 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1069 const comp = try arena.create(Compilation);1124 const comp = try arena.create(Compilation);
1070 const root_name = try arena.dupeZ(u8, options.root_name);1125 const root_name = try arena.dupeZ(u8, options.root_name);
10711126
1072 // Make a decision on whether to use LLVM or our own backend.1127 const use_llvm = options.config.use_llvm;
1073 const use_lib_llvm = options.use_lib_llvm orelse build_options.have_llvm;
1074 const use_llvm = blk: {
1075 if (options.use_llvm) |explicit|
1076 break :blk explicit;
1077
1078 // If emitting to LLVM bitcode object format, must use LLVM backend.
1079 if (options.emit_llvm_ir != null or options.emit_llvm_bc != null)
1080 break :blk true;
1081
1082 // If we have no zig code to compile, no need for LLVM.
1083 if (options.main_mod == null)
1084 break :blk false;
1085
1086 // If we cannot use LLVM libraries, then our own backends will be a
1087 // better default since the LLVM backend can only produce bitcode
1088 // and not an object file or executable.
1089 if (!use_lib_llvm)
1090 break :blk false;
1091
1092 // If LLVM does not support the target, then we can't use it.
1093 if (!target_util.hasLlvmSupport(options.target, options.target.ofmt))
1094 break :blk false;
1095
1096 // Prefer LLVM for release builds.
1097 if (options.optimize_mode != .Debug)
1098 break :blk true;
1099
1100 // At this point we would prefer to use our own self-hosted backend,
1101 // because the compilation speed is better than LLVM. But only do it if
1102 // we are confident in the robustness of the backend.
1103 break :blk !target_util.selfHostedBackendIsAsRobustAsLlvm(options.target);
1104 };
1105 if (!use_llvm) {
1106 if (options.use_llvm == true) {
1107 return error.ZigCompilerNotBuiltWithLLVMExtensions;
1108 }
1109 if (options.emit_llvm_ir != null or options.emit_llvm_bc != null) {
1110 return error.EmittingLlvmModuleRequiresUsingLlvmBackend;
1111 }
1112 }
11131128
1114 // TODO: once we support incremental compilation for the LLVM backend via1129 // TODO: once we support incremental compilation for the LLVM backend via
1115 // saving the LLVM module into a bitcode file and restoring it, along with1130 // saving the LLVM module into a bitcode file and restoring it, along with
1116 // compiler state, the second clause here can be removed so that incremental1131 // compiler state, the second clause here can be removed so that incremental
1117 // cache mode is used for LLVM backend too. We need some fuzz testing before1132 // cache mode is used for LLVM backend too. We need some fuzz testing before
1118 // that can be enabled.1133 // that can be enabled.
1119 const cache_mode = if ((use_llvm or options.main_mod == null) and !options.disable_lld_caching)1134 const cache_mode = if ((use_llvm or !have_zcu) and !options.disable_lld_caching)
1120 CacheMode.whole1135 CacheMode.whole
1121 else1136 else
1122 options.cache_mode;1137 options.cache_mode;
11231138
1124 const tsan = options.want_tsan orelse false;1139 const any_unwind_tables = options.config.any_unwind_tables;
1125 // TSAN is implemented in C++ so it requires linking libc++.
1126 const link_libcpp = options.link_libcpp or tsan;
1127 const link_libc = link_libcpp or options.link_libc or options.link_libunwind or
1128 target_util.osRequiresLibC(options.target);
1129
1130 const link_libunwind = options.link_libunwind or
1131 (link_libcpp and target_util.libcNeedsLibUnwind(options.target));
1132 const unwind_tables = options.want_unwind_tables orelse
1133 (link_libunwind or target_util.needUnwindTables(options.target));
1134 const link_eh_frame_hdr = options.link_eh_frame_hdr or unwind_tables;
1135 const build_id = options.build_id orelse .none;
11361140
1137 // Make a decision on whether to use LLD or our own linker.1141 const link_eh_frame_hdr = options.link_eh_frame_hdr or any_unwind_tables;
1138 const use_lld = options.use_lld orelse blk: {1142 const build_id = options.build_id orelse .none;
1139 if (options.target.isDarwin()) {
1140 break :blk false;
1141 }
1142
1143 if (!build_options.have_llvm)
1144 break :blk false;
1145
1146 if (options.target.ofmt == .c)
1147 break :blk false;
1148
1149 if (options.want_lto) |lto| {
1150 if (lto) {
1151 break :blk true;
1152 }
1153 }
1154
1155 // Our linker can't handle objects or most advanced options yet.
1156 if (options.link_objects.len != 0 or
1157 options.c_source_files.len != 0 or
1158 options.frameworks.len != 0 or
1159 options.system_lib_names.len != 0 or
1160 options.link_libc or options.link_libcpp or
1161 link_eh_frame_hdr or
1162 options.link_emit_relocs or
1163 options.output_mode == .Lib or
1164 options.linker_script != null or options.version_script != null or
1165 options.emit_implib != null or
1166 build_id != .none or
1167 options.symbol_wrap_set.count() > 0)
1168 {
1169 break :blk true;
1170 }
1171
1172 if (use_llvm) {
1173 // If stage1 generates an object file, self-hosted linker is not
1174 // yet sophisticated enough to handle that.
1175 break :blk options.main_mod != null;
1176 }
1177
1178 break :blk false;
1179 };
1180
1181 const lto = blk: {
1182 if (options.want_lto) |want_lto| {
1183 if (want_lto and !use_lld and !options.target.isDarwin())
1184 return error.LtoUnavailableWithoutLld;
1185 break :blk want_lto;
1186 } else if (!use_lld) {
1187 // zig ld LTO support is tracked by
1188 // https://github.com/ziglang/zig/issues/8680
1189 break :blk false;
1190 } else if (options.c_source_files.len == 0) {
1191 break :blk false;
1192 } else if (options.target.cpu.arch.isRISCV()) {
1193 // Clang and LLVM currently don't support RISC-V target-abi for LTO.
1194 // Compiling with LTO may fail or produce undesired results.
1195 // See https://reviews.llvm.org/D71387
1196 // See https://reviews.llvm.org/D102582
1197 break :blk false;
1198 } else switch (options.output_mode) {
1199 .Lib, .Obj => break :blk false,
1200 .Exe => switch (options.optimize_mode) {
1201 .Debug => break :blk false,
1202 .ReleaseSafe, .ReleaseFast, .ReleaseSmall => break :blk true,
1203 },
1204 }
1205 };
1206
1207 const must_dynamic_link = dl: {
1208 if (target_util.cannotDynamicLink(options.target))
1209 break :dl false;
1210 if (is_exe_or_dyn_lib and link_libc and
1211 (options.target.isGnuLibC() or target_util.osRequiresLibC(options.target)))
1212 {
1213 break :dl true;
1214 }
1215 const any_dyn_libs: bool = x: {
1216 if (options.system_lib_names.len != 0)
1217 break :x true;
1218 for (options.link_objects) |obj| {
1219 switch (classifyFileExt(obj.path)) {
1220 .shared_library => break :x true,
1221 else => continue,
1222 }
1223 }
1224 break :x false;
1225 };
1226 if (any_dyn_libs) {
1227 // When creating a executable that links to system libraries,
1228 // we require dynamic linking, but we must not link static libraries
1229 // or object files dynamically!
1230 break :dl (options.output_mode == .Exe);
1231 }
12321143
1233 break :dl false;1144 const link_libc = options.config.link_libc;
1234 };
1235 const default_link_mode: std.builtin.LinkMode = blk: {
1236 if (must_dynamic_link) {
1237 break :blk .Dynamic;
1238 } else if (is_exe_or_dyn_lib and link_libc and
1239 options.is_native_abi and options.target.abi.isMusl())
1240 {
1241 // If targeting the system's native ABI and the system's
1242 // libc is musl, link dynamically by default.
1243 break :blk .Dynamic;
1244 } else {
1245 break :blk .Static;
1246 }
1247 };
1248 const link_mode: std.builtin.LinkMode = if (options.link_mode) |lm| blk: {
1249 if (lm == .Static and must_dynamic_link) {
1250 return error.UnableToStaticLink;
1251 }
1252 break :blk lm;
1253 } else default_link_mode;
12541145
1255 const dll_export_fns = options.dll_export_fns orelse (is_dyn_lib or options.rdynamic);1146 const dll_export_fns = options.dll_export_fns orelse (is_dyn_lib or options.rdynamic);
12561147
1257 const libc_dirs = try detectLibCIncludeDirs(1148 const libc_dirs = try detectLibCIncludeDirs(
1258 arena,1149 arena,
1259 options.zig_lib_directory.path.?,1150 options.zig_lib_directory.path.?,
1260 options.target,1151 options.root_mod.resolved_target.result,
1261 options.is_native_abi,1152 options.root_mod.resolved_target.is_native_abi,
1262 link_libc,1153 link_libc,
1263 options.libc_installation,1154 options.libc_installation,
1264 );1155 );
12651156
1266 const rc_dirs = try detectWin32ResourceIncludeDirs(1157 // The include directories used when preprocessing .rc files are separate from the
1267 arena,1158 // target. Which include directories are used is determined by `options.rc_includes`.
1268 options,1159 //
1269 );1160 // Note: It should be okay that the include directories used when compiling .rc
12701161 // files differ from the include directories used when compiling the main
1271 const sysroot = options.sysroot orelse libc_dirs.sysroot;1162 // binary, since the .res format is not dependent on anything ABI-related. The
12721163 // only relevant differences would be things like `#define` constants being
1273 const pie: bool = pie: {1164 // different in the MinGW headers vs the MSVC headers, but any such
1274 if (is_dyn_lib) {1165 // differences would likely be a MinGW bug.
1275 if (options.want_pie == true) return error.OutputModeForbidsPie;1166 const rc_dirs = b: {
1276 break :pie false;1167 // Set the includes to .none here when there are no rc files to compile
1277 }1168 var includes = if (options.rc_source_files.len > 0) options.rc_includes else .none;
1278 if (target_util.requiresPIE(options.target)) {1169 const target = options.root_mod.resolved_target.result;
1279 if (options.want_pie == false) return error.TargetRequiresPie;1170 if (!options.root_mod.resolved_target.is_native_os or target.os.tag != .windows) {
1280 break :pie true;1171 switch (includes) {
1281 }1172 // MSVC can't be found when the host isn't Windows, so short-circuit.
1282 if (tsan) {1173 .msvc => return error.WindowsSdkNotFound,
1283 if (options.want_pie == false) return error.TsanRequiresPie;1174 // Skip straight to gnu since we won't be able to detect
1284 break :pie true;1175 // MSVC on non-Windows hosts.
1285 }1176 .any => includes = .gnu,
1286 if (options.want_pie) |want_pie| {1177 .none, .gnu => {},
1287 break :pie want_pie;
1288 }
1289 break :pie false;
1290 };
1291
1292 const must_pic: bool = b: {
1293 if (target_util.requiresPIC(options.target, link_libc))
1294 break :b true;
1295 break :b link_mode == .Dynamic;
1296 };
1297 const pic = if (options.want_pic) |explicit| pic: {
1298 if (!explicit) {
1299 if (must_pic) {
1300 return error.TargetRequiresPIC;
1301 }
1302 if (pie) {
1303 return error.PIERequiresPIC;
1304 }1178 }
1305 }1179 }
1306 break :pic explicit;1180 while (true) switch (includes) {
1307 } else pie or must_pic;1181 .any, .msvc => break :b detectLibCIncludeDirs(
13081182 arena,
1309 // Make a decision on whether to use Clang or Aro for translate-c and compiling C files.1183 options.zig_lib_directory.path.?,
1310 const c_frontend: CFrontend = blk: {1184 .{
1311 if (options.use_clang) |want_clang| {1185 .cpu = target.cpu,
1312 break :blk if (want_clang) .clang else .aro;1186 .os = target.os,
1313 }1187 .abi = .msvc,
1314 break :blk if (build_options.have_llvm) .clang else .aro;1188 .ofmt = target.ofmt,
1315 };1189 },
1316 if (!build_options.have_llvm and c_frontend == .clang) {1190 options.root_mod.resolved_target.is_native_abi,
1317 return error.ZigCompilerNotBuiltWithLLVMExtensions;1191 // The .rc preprocessor will need to know the libc include dirs even if we
1318 }1192 // are not linking libc, so force 'link_libc' to true
13191193 true,
1320 const is_safe_mode = switch (options.optimize_mode) {1194 options.libc_installation,
1321 .Debug, .ReleaseSafe => true,1195 ) catch |err| {
1322 .ReleaseFast, .ReleaseSmall => false,1196 if (includes == .any) {
1323 };1197 // fall back to mingw
13241198 includes = .gnu;
1325 const sanitize_c = options.want_sanitize_c orelse is_safe_mode;1199 continue;
13261200 }
1327 const stack_check: bool = options.want_stack_check orelse b: {1201 return err;
1328 if (!target_util.supportsStackProbing(options.target)) break :b false;1202 },
1329 break :b is_safe_mode;1203 .gnu => break :b try detectLibCFromBuilding(arena, options.zig_lib_directory.path.?, .{
1204 .cpu = target.cpu,
1205 .os = target.os,
1206 .abi = .gnu,
1207 .ofmt = target.ofmt,
1208 }),
1209 .none => break :b LibCDirs{
1210 .libc_include_dir_list = &[0][]u8{},
1211 .libc_installation = null,
1212 .libc_framework_dir_list = &.{},
1213 .sysroot = null,
1214 .darwin_sdk_layout = null,
1215 },
1216 };
1330 };1217 };
1331 if (stack_check and !target_util.supportsStackProbing(options.target))
1332 return error.StackCheckUnsupportedByTarget;
1333
1334 const stack_protector: u32 = sp: {
1335 const zig_backend = zigBackend(options.target, use_llvm);
1336 if (!target_util.supportsStackProtector(options.target, zig_backend)) {
1337 if (options.want_stack_protector) |x| {
1338 if (x > 0) return error.StackProtectorUnsupportedByTarget;
1339 }
1340 break :sp 0;
1341 }
1342
1343 // This logic is checking for linking libc because otherwise our start code
1344 // which is trying to set up TLS (i.e. the fs/gs registers) but the stack
1345 // protection code depends on fs/gs registers being already set up.
1346 // If we were able to annotate start code, or perhaps the entire std lib,
1347 // as being exempt from stack protection checks, we could change this logic
1348 // to supporting stack protection even when not linking libc.
1349 // TODO file issue about this
1350 if (!link_libc) {
1351 if (options.want_stack_protector) |x| {
1352 if (x > 0) return error.StackProtectorUnavailableWithoutLibC;
1353 }
1354 break :sp 0;
1355 }
13561218
1357 if (options.want_stack_protector) |x| break :sp x;1219 const sysroot = options.sysroot orelse libc_dirs.sysroot;
1358 if (is_safe_mode) break :sp default_stack_protector_buffer_size;
1359 break :sp 0;
1360 };
13611220
1362 const include_compiler_rt = options.want_compiler_rt orelse1221 const include_compiler_rt = options.want_compiler_rt orelse
1363 (!options.skip_linker_dependencies and is_exe_or_dyn_lib);1222 (!options.skip_linker_dependencies and is_exe_or_dyn_lib);
13641223
1365 const single_threaded = st: {1224 if (include_compiler_rt and output_mode == .Obj) {
1366 if (target_util.isSingleThreaded(options.target)) {1225 // For objects, this mechanism relies on essentially `_ = @import("compiler-rt");`
1367 if (options.single_threaded == false)1226 // injected into the object.
1368 return error.TargetRequiresSingleThreaded;1227 const compiler_rt_mod = try Package.Module.create(arena, .{
1369 break :st true;1228 .global_cache_directory = options.global_cache_directory,
1370 }1229 .paths = .{
1371 if (options.main_mod != null) {1230 .root = .{
1372 const zig_backend = zigBackend(options.target, use_llvm);1231 .root_dir = options.zig_lib_directory,
1373 if (!target_util.supportsThreads(options.target, zig_backend)) {1232 },
1374 if (options.single_threaded == false)1233 .root_src_path = "compiler_rt.zig",
1375 return error.BackendRequiresSingleThreaded;1234 },
1376 break :st true;1235 .fully_qualified_name = "compiler_rt",
1377 }1236 .cc_argv = &.{},
1378 }1237 .inherited = .{},
1379 break :st options.single_threaded orelse false;1238 .global = options.config,
1380 };1239 .parent = options.root_mod,
13811240 .builtin_mod = options.root_mod.getBuiltinDependency(),
1382 const llvm_cpu_features: ?[*:0]const u8 = if (use_llvm) blk: {1241 });
1383 var buf = std.ArrayList(u8).init(arena);1242 try options.root_mod.deps.putNoClobber(arena, "compiler_rt", compiler_rt_mod);
1384 for (options.target.cpu.arch.allFeaturesList(), 0..) |feature, index_usize| {1243 }
1385 const index = @as(Target.Cpu.Feature.Set.Index, @intCast(index_usize));
1386 const is_enabled = options.target.cpu.features.isEnabled(index);
1387
1388 if (feature.llvm_name) |llvm_name| {
1389 const plus_or_minus = "-+"[@intFromBool(is_enabled)];
1390 try buf.ensureUnusedCapacity(2 + llvm_name.len);
1391 buf.appendAssumeCapacity(plus_or_minus);
1392 buf.appendSliceAssumeCapacity(llvm_name);
1393 buf.appendSliceAssumeCapacity(",");
1394 }
1395 }
1396 if (buf.items.len == 0) break :blk "";
1397 assert(mem.endsWith(u8, buf.items, ","));
1398 buf.items[buf.items.len - 1] = 0;
1399 buf.shrinkAndFree(buf.items.len);
1400 break :blk buf.items[0 .. buf.items.len - 1 :0].ptr;
1401 } else null;
14021244
1403 if (options.verbose_llvm_cpu_features) {1245 if (options.verbose_llvm_cpu_features) {
1404 if (llvm_cpu_features) |cf| print: {1246 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {
1247 const target = options.root_mod.resolved_target.result;
1405 std.debug.getStderrMutex().lock();1248 std.debug.getStderrMutex().lock();
1406 defer std.debug.getStderrMutex().unlock();1249 defer std.debug.getStderrMutex().unlock();
1407 const stderr = std.io.getStdErr().writer();1250 const stderr = std.io.getStdErr().writer();
1408 nosuspend stderr.print("compilation: {s}\n", .{options.root_name}) catch break :print;1251 nosuspend {
1409 nosuspend stderr.print(" target: {s}\n", .{try options.target.zigTriple(arena)}) catch break :print;1252 stderr.print("compilation: {s}\n", .{options.root_name}) catch break :print;
1410 nosuspend stderr.print(" cpu: {s}\n", .{options.target.cpu.model.name}) catch break :print;1253 stderr.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;
1411 nosuspend stderr.print(" features: {s}\n", .{cf}) catch {};1254 stderr.print(" cpu: {s}\n", .{target.cpu.model.name}) catch break :print;
1255 stderr.print(" features: {s}\n", .{cf}) catch {};
1256 }
1412 }1257 }
1413 }1258 }
14141259
1415 const strip = options.strip orelse !target_util.hasDebugInfo(options.target);1260 const linker_optimization: u8 = options.linker_optimization orelse switch (options.root_mod.optimize_mode) {
1416 const valgrind: bool = b: {
1417 if (!target_util.hasValgrindSupport(options.target)) break :b false;
1418 if (options.want_valgrind) |explicit| break :b explicit;
1419 if (strip) break :b false;
1420 break :b options.optimize_mode == .Debug;
1421 };
1422 if (!valgrind and options.want_valgrind == true)
1423 return error.ValgrindUnsupportedOnTarget;
1424
1425 const red_zone = options.want_red_zone orelse target_util.hasRedZone(options.target);
1426 const omit_frame_pointer = options.omit_frame_pointer orelse (options.optimize_mode != .Debug);
1427 const linker_optimization: u8 = options.linker_optimization orelse switch (options.optimize_mode) {
1428 .Debug => @as(u8, 0),1261 .Debug => @as(u8, 0),
1429 else => @as(u8, 3),1262 else => @as(u8, 3),
1430 };1263 };
1431 const formatted_panics = options.formatted_panics orelse (options.optimize_mode == .Debug);1264 // TODO: https://github.com/ziglang/zig/issues/17969
1265 const formatted_panics = options.formatted_panics orelse (options.root_mod.optimize_mode == .Debug);
14321266
1433 const error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1);1267 const error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1);
14341268
...@@ -1453,43 +1287,25 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1453,43 +1287,25 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1453 // This is shared hasher state common to zig source and all C source files.1287 // This is shared hasher state common to zig source and all C source files.
1454 cache.hash.addBytes(build_options.version);1288 cache.hash.addBytes(build_options.version);
1455 cache.hash.add(builtin.zig_backend);1289 cache.hash.add(builtin.zig_backend);
1456 cache.hash.add(options.optimize_mode);1290 cache.hash.add(options.config.pie);
1457 cache.hash.add(options.target.cpu.arch);1291 cache.hash.add(options.config.lto);
1458 cache.hash.addBytes(options.target.cpu.model.name);1292 cache.hash.add(options.config.link_mode);
1459 cache.hash.add(options.target.cpu.features.ints);
1460 cache.hash.add(options.target.os.tag);
1461 cache.hash.add(options.target.os.getVersionRange());
1462 cache.hash.add(options.is_native_os);
1463 cache.hash.add(options.target.abi);
1464 cache.hash.add(options.target.ofmt);
1465 cache.hash.add(pic);
1466 cache.hash.add(pie);
1467 cache.hash.add(lto);
1468 cache.hash.add(unwind_tables);
1469 cache.hash.add(tsan);
1470 cache.hash.add(stack_check);
1471 cache.hash.add(stack_protector);
1472 cache.hash.add(red_zone);
1473 cache.hash.add(omit_frame_pointer);
1474 cache.hash.add(link_mode);
1475 cache.hash.add(options.function_sections);1293 cache.hash.add(options.function_sections);
1476 cache.hash.add(options.data_sections);1294 cache.hash.add(options.data_sections);
1477 cache.hash.add(options.no_builtin);1295 cache.hash.add(options.no_builtin);
1478 cache.hash.add(strip);
1479 cache.hash.add(link_libc);1296 cache.hash.add(link_libc);
1480 cache.hash.add(link_libcpp);1297 cache.hash.add(options.config.link_libcpp);
1481 cache.hash.add(link_libunwind);1298 cache.hash.add(options.config.link_libunwind);
1482 cache.hash.add(options.output_mode);1299 cache.hash.add(output_mode);
1483 cache.hash.add(options.machine_code_model);
1484 cache.hash.addOptional(options.dwarf_format);1300 cache.hash.addOptional(options.dwarf_format);
1485 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_bin);1301 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_bin);
1486 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_implib);1302 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_implib);
1487 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs);1303 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs);
1488 cache.hash.addBytes(options.root_name);1304 cache.hash.addBytes(options.root_name);
1489 if (options.target.os.tag == .wasi) cache.hash.add(wasi_exec_model);1305 cache.hash.add(options.config.wasi_exec_model);
1490 // TODO audit this and make sure everything is in it1306 // TODO audit this and make sure everything is in it
14911307
1492 const module: ?*Module = if (options.main_mod) |main_mod| blk: {1308 const zcu: ?*Module = if (have_zcu) blk: {
1493 // Options that are specific to zig source files, that cannot be1309 // Options that are specific to zig source files, that cannot be
1494 // modified between incremental updates.1310 // modified between incremental updates.
1495 var hash = cache.hash;1311 var hash = cache.hash;
...@@ -1502,13 +1318,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1502,13 +1318,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1502 // do want to namespace different source file names because they are1318 // do want to namespace different source file names because they are
1503 // likely different compilations and therefore this would be likely to1319 // likely different compilations and therefore this would be likely to
1504 // cause cache hits.1320 // cause cache hits.
1505 hash.addBytes(main_mod.root_src_path);1321 try addModuleTableToCacheHash(gpa, arena, &hash, options.root_mod, .path_bytes);
1506 hash.addOptionalBytes(main_mod.root.root_dir.path);
1507 hash.addBytes(main_mod.root.sub_path);
1508 {
1509 var seen_table = std.AutoHashMap(*Package.Module, void).init(arena);
1510 try addModuleTableToCacheHash(&hash, &arena_allocator, main_mod.deps, &seen_table, .path_bytes);
1511 }
1512 },1322 },
1513 .whole => {1323 .whole => {
1514 // In this case, we postpone adding the input source file until1324 // In this case, we postpone adding the input source file until
...@@ -1518,13 +1328,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1518,13 +1328,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1518 }1328 }
15191329
1520 // Synchronize with other matching comments: ZigOnlyHashStuff1330 // Synchronize with other matching comments: ZigOnlyHashStuff
1521 hash.add(valgrind);
1522 hash.add(single_threaded);
1523 hash.add(use_llvm);1331 hash.add(use_llvm);
1524 hash.add(use_lib_llvm);1332 hash.add(options.config.use_lib_llvm);
1525 hash.add(dll_export_fns);1333 hash.add(dll_export_fns);
1526 hash.add(options.is_test);1334 hash.add(options.config.is_test);
1527 hash.add(options.test_evented_io);1335 hash.add(options.config.test_evented_io);
1528 hash.addOptionalBytes(options.test_filter);1336 hash.addOptionalBytes(options.test_filter);
1529 hash.addOptionalBytes(options.test_name_prefix);1337 hash.addOptionalBytes(options.test_name_prefix);
1530 hash.add(options.skip_linker_dependencies);1338 hash.add(options.skip_linker_dependencies);
...@@ -1565,85 +1373,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1565,85 +1373,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1565 .path = try options.local_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}),1373 .path = try options.local_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}),
1566 };1374 };
15671375
1568 const builtin_mod = try Package.Module.create(arena, .{
1569 .root = .{ .root_dir = zig_cache_artifact_directory },
1570 .root_src_path = "builtin.zig",
1571 .fully_qualified_name = "builtin",
1572 });
1573
1574 // When you're testing std, the main module is std. In that case,
1575 // we'll just set the std module to the main one, since avoiding
1576 // the errors caused by duplicating it is more effort than it's
1577 // worth.
1578 const main_mod_is_std = m: {
1579 const std_path = try std.fs.path.resolve(arena, &[_][]const u8{
1580 options.zig_lib_directory.path orelse ".",
1581 "std",
1582 "std.zig",
1583 });
1584 const main_path = try std.fs.path.resolve(arena, &[_][]const u8{
1585 main_mod.root.root_dir.path orelse ".",
1586 main_mod.root.sub_path,
1587 main_mod.root_src_path,
1588 });
1589 break :m mem.eql(u8, main_path, std_path);
1590 };
1591
1592 const std_mod = if (main_mod_is_std)
1593 main_mod
1594 else
1595 try Package.Module.create(arena, .{
1596 .root = .{
1597 .root_dir = options.zig_lib_directory,
1598 .sub_path = "std",
1599 },
1600 .root_src_path = "std.zig",
1601 .fully_qualified_name = "std",
1602 });
1603
1604 const root_mod = if (options.is_test) root_mod: {
1605 const test_mod = if (options.test_runner_path) |test_runner| test_mod: {
1606 const pkg = try Package.Module.create(arena, .{
1607 .root = .{
1608 .root_dir = Directory.cwd(),
1609 .sub_path = std.fs.path.dirname(test_runner) orelse "",
1610 },
1611 .root_src_path = std.fs.path.basename(test_runner),
1612 .fully_qualified_name = "root",
1613 });
1614
1615 pkg.deps = try main_mod.deps.clone(arena);
1616 break :test_mod pkg;
1617 } else try Package.Module.create(arena, .{
1618 .root = .{
1619 .root_dir = options.zig_lib_directory,
1620 },
1621 .root_src_path = "test_runner.zig",
1622 .fully_qualified_name = "root",
1623 });
1624
1625 break :root_mod test_mod;
1626 } else main_mod;
1627
1628 const compiler_rt_mod = if (include_compiler_rt and options.output_mode == .Obj) compiler_rt_mod: {
1629 break :compiler_rt_mod try Package.Module.create(arena, .{
1630 .root = .{
1631 .root_dir = options.zig_lib_directory,
1632 },
1633 .root_src_path = "compiler_rt.zig",
1634 .fully_qualified_name = "compiler_rt",
1635 });
1636 } else null;
1637
1638 {
1639 try main_mod.deps.ensureUnusedCapacity(arena, 4);
1640 main_mod.deps.putAssumeCapacity("builtin", builtin_mod);
1641 main_mod.deps.putAssumeCapacity("root", root_mod);
1642 main_mod.deps.putAssumeCapacity("std", std_mod);
1643 if (compiler_rt_mod) |m|
1644 main_mod.deps.putAssumeCapacity("compiler_rt", m);
1645 }
1646
1647 // Pre-open the directory handles for cached ZIR code so that it does not need1376 // Pre-open the directory handles for cached ZIR code so that it does not need
1648 // to redundantly happen for each AstGen operation.1377 // to redundantly happen for each AstGen operation.
1649 const zir_sub_dir = "z";1378 const zir_sub_dir = "z";
...@@ -1674,13 +1403,14 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1674,13 +1403,14 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1674 // However we currently do not have serialization of such metadata, so for now1403 // However we currently do not have serialization of such metadata, so for now
1675 // we set up an empty Module that does the entire compilation fresh.1404 // we set up an empty Module that does the entire compilation fresh.
16761405
1677 const module = try arena.create(Module);1406 const zcu = try arena.create(Module);
1678 errdefer module.deinit();1407 errdefer zcu.deinit();
1679 module.* = .{1408 zcu.* = .{
1680 .gpa = gpa,1409 .gpa = gpa,
1681 .comp = comp,1410 .comp = comp,
1682 .main_mod = main_mod,1411 .main_mod = options.main_mod orelse options.root_mod,
1683 .root_mod = root_mod,1412 .root_mod = options.root_mod,
1413 .std_mod = options.std_mod,
1684 .zig_cache_artifact_directory = zig_cache_artifact_directory,1414 .zig_cache_artifact_directory = zig_cache_artifact_directory,
1685 .global_zir_cache = global_zir_cache,1415 .global_zir_cache = global_zir_cache,
1686 .local_zir_cache = local_zir_cache,1416 .local_zir_cache = local_zir_cache,
...@@ -1688,31 +1418,24 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1688,31 +1418,24 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1688 .tmp_hack_arena = std.heap.ArenaAllocator.init(gpa),1418 .tmp_hack_arena = std.heap.ArenaAllocator.init(gpa),
1689 .error_limit = error_limit,1419 .error_limit = error_limit,
1690 };1420 };
1691 try module.init();1421 try zcu.init();
16921422
1693 break :blk module;1423 break :blk zcu;
1694 } else blk: {1424 } else blk: {
1695 if (options.emit_h != null) return error.NoZigModuleForCHeader;1425 if (options.emit_h != null) return error.NoZigModuleForCHeader;
1696 break :blk null;1426 break :blk null;
1697 };1427 };
1698 errdefer if (module) |zm| zm.deinit();1428 errdefer if (zcu) |u| u.deinit();
1699
1700 const error_return_tracing = !strip and switch (options.optimize_mode) {
1701 .Debug, .ReleaseSafe => (!options.target.isWasm() or options.target.os.tag == .emscripten) and
1702 !options.target.cpu.arch.isBpf() and (options.error_tracing orelse true),
1703 .ReleaseFast => options.error_tracing orelse false,
1704 .ReleaseSmall => false,
1705 };
17061429
1707 // For resource management purposes.1430 // For resource management purposes.
1708 var owned_link_dir: ?std.fs.Dir = null;1431 var owned_link_dir: ?std.fs.Dir = null;
1709 errdefer if (owned_link_dir) |*dir| dir.close();1432 errdefer if (owned_link_dir) |*dir| dir.close();
17101433
1711 const bin_file_emit: ?link.Emit = blk: {1434 const bin_file_emit: ?Emit = blk: {
1712 const emit_bin = options.emit_bin orelse break :blk null;1435 const emit_bin = options.emit_bin orelse break :blk null;
17131436
1714 if (emit_bin.directory) |directory| {1437 if (emit_bin.directory) |directory| {
1715 break :blk link.Emit{1438 break :blk Emit{
1716 .directory = directory,1439 .directory = directory,
1717 .sub_path = emit_bin.basename,1440 .sub_path = emit_bin.basename,
1718 };1441 };
...@@ -1725,9 +1448,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1725,9 +1448,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1725 .incremental => {},1448 .incremental => {},
1726 }1449 }
17271450
1728 if (module) |zm| {1451 if (zcu) |u| {
1729 break :blk link.Emit{1452 break :blk Emit{
1730 .directory = zm.zig_cache_artifact_directory,1453 .directory = u.zig_cache_artifact_directory,
1731 .sub_path = emit_bin.basename,1454 .sub_path = emit_bin.basename,
1732 };1455 };
1733 }1456 }
...@@ -1752,17 +1475,17 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1752,17 +1475,17 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1752 .handle = artifact_dir,1475 .handle = artifact_dir,
1753 .path = try options.local_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}),1476 .path = try options.local_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}),
1754 };1477 };
1755 break :blk link.Emit{1478 break :blk Emit{
1756 .directory = link_artifact_directory,1479 .directory = link_artifact_directory,
1757 .sub_path = emit_bin.basename,1480 .sub_path = emit_bin.basename,
1758 };1481 };
1759 };1482 };
17601483
1761 const implib_emit: ?link.Emit = blk: {1484 const implib_emit: ?Emit = blk: {
1762 const emit_implib = options.emit_implib orelse break :blk null;1485 const emit_implib = options.emit_implib orelse break :blk null;
17631486
1764 if (emit_implib.directory) |directory| {1487 if (emit_implib.directory) |directory| {
1765 break :blk link.Emit{1488 break :blk Emit{
1766 .directory = directory,1489 .directory = directory,
1767 .sub_path = emit_implib.basename,1490 .sub_path = emit_implib.basename,
1768 };1491 };
...@@ -1776,13 +1499,13 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1776,13 +1499,13 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
17761499
1777 // Use the same directory as the bin. The CLI already emits an1500 // Use the same directory as the bin. The CLI already emits an
1778 // error if -fno-emit-bin is combined with -femit-implib.1501 // error if -fno-emit-bin is combined with -femit-implib.
1779 break :blk link.Emit{1502 break :blk Emit{
1780 .directory = bin_file_emit.?.directory,1503 .directory = bin_file_emit.?.directory,
1781 .sub_path = emit_implib.basename,1504 .sub_path = emit_implib.basename,
1782 };1505 };
1783 };1506 };
17841507
1785 const docs_emit: ?link.Emit = blk: {1508 const docs_emit: ?Emit = blk: {
1786 const emit_docs = options.emit_docs orelse break :blk null;1509 const emit_docs = options.emit_docs orelse break :blk null;
17871510
1788 if (emit_docs.directory) |directory| {1511 if (emit_docs.directory) |directory| {
...@@ -1805,7 +1528,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1805,7 +1528,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1805 };1528 };
18061529
1807 break :blk .{1530 break :blk .{
1808 .directory = module.?.zig_cache_artifact_directory,1531 .directory = zcu.?.zig_cache_artifact_directory,
1809 .sub_path = emit_docs.basename,1532 .sub_path = emit_docs.basename,
1810 };1533 };
1811 };1534 };
...@@ -1828,131 +1551,20 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1828,131 +1551,20 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1828 system_libs.putAssumeCapacity(lib_name, options.system_lib_infos[i]);1551 system_libs.putAssumeCapacity(lib_name, options.system_lib_infos[i]);
1829 }1552 }
18301553
1831 const bin_file = try link.File.openPath(gpa, .{1554 const each_lib_rpath = options.each_lib_rpath orelse
1832 .emit = bin_file_emit,1555 options.root_mod.resolved_target.is_native_os;
1833 .implib_emit = implib_emit,1556
1834 .docs_emit = docs_emit,
1835 .root_name = root_name,
1836 .module = module,
1837 .target = options.target,
1838 .sysroot = sysroot,
1839 .output_mode = options.output_mode,
1840 .link_mode = link_mode,
1841 .optimize_mode = options.optimize_mode,
1842 .use_lld = use_lld,
1843 .use_llvm = use_llvm,
1844 .use_lib_llvm = use_lib_llvm,
1845 .link_libc = link_libc,
1846 .link_libcpp = link_libcpp,
1847 .link_libunwind = link_libunwind,
1848 .darwin_sdk_layout = libc_dirs.darwin_sdk_layout,
1849 .objects = options.link_objects,
1850 .frameworks = options.frameworks,
1851 .framework_dirs = options.framework_dirs,
1852 .system_libs = system_libs,
1853 .wasi_emulated_libs = options.wasi_emulated_libs,
1854 .lib_dirs = options.lib_dirs,
1855 .rpath_list = options.rpath_list,
1856 .symbol_wrap_set = options.symbol_wrap_set,
1857 .strip = strip,
1858 .is_native_os = options.is_native_os,
1859 .is_native_abi = options.is_native_abi,
1860 .function_sections = options.function_sections,
1861 .data_sections = options.data_sections,
1862 .no_builtin = options.no_builtin,
1863 .allow_shlib_undefined = options.linker_allow_shlib_undefined,
1864 .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,
1865 .compress_debug_sections = options.linker_compress_debug_sections orelse .none,
1866 .module_definition_file = options.linker_module_definition_file,
1867 .sort_section = options.linker_sort_section,
1868 .import_memory = options.linker_import_memory orelse false,
1869 .export_memory = options.linker_export_memory orelse !(options.linker_import_memory orelse false),
1870 .import_symbols = options.linker_import_symbols,
1871 .import_table = options.linker_import_table,
1872 .export_table = options.linker_export_table,
1873 .initial_memory = options.linker_initial_memory,
1874 .max_memory = options.linker_max_memory,
1875 .shared_memory = options.linker_shared_memory,
1876 .global_base = options.linker_global_base,
1877 .export_symbol_names = options.linker_export_symbol_names,
1878 .print_gc_sections = options.linker_print_gc_sections,
1879 .print_icf_sections = options.linker_print_icf_sections,
1880 .print_map = options.linker_print_map,
1881 .opt_bisect_limit = options.linker_opt_bisect_limit,
1882 .z_nodelete = options.linker_z_nodelete,
1883 .z_notext = options.linker_z_notext,
1884 .z_defs = options.linker_z_defs,
1885 .z_origin = options.linker_z_origin,
1886 .z_nocopyreloc = options.linker_z_nocopyreloc,
1887 .z_now = options.linker_z_now,
1888 .z_relro = options.linker_z_relro,
1889 .z_common_page_size = options.linker_z_common_page_size,
1890 .z_max_page_size = options.linker_z_max_page_size,
1891 .tsaware = options.linker_tsaware,
1892 .nxcompat = options.linker_nxcompat,
1893 .dynamicbase = options.linker_dynamicbase,
1894 .linker_optimization = linker_optimization,
1895 .major_subsystem_version = options.major_subsystem_version,
1896 .minor_subsystem_version = options.minor_subsystem_version,
1897 .entry = options.entry,
1898 .stack_size_override = options.stack_size_override,
1899 .image_base_override = options.image_base_override,
1900 .include_compiler_rt = include_compiler_rt,
1901 .linker_script = options.linker_script,
1902 .version_script = options.version_script,
1903 .gc_sections = options.linker_gc_sections,
1904 .eh_frame_hdr = link_eh_frame_hdr,
1905 .emit_relocs = options.link_emit_relocs,
1906 .rdynamic = options.rdynamic,
1907 .soname = options.soname,
1908 .version = options.version,
1909 .compatibility_version = options.compatibility_version,
1910 .libc_installation = libc_dirs.libc_installation,
1911 .pic = pic,
1912 .pie = pie,
1913 .lto = lto,
1914 .valgrind = valgrind,
1915 .tsan = tsan,
1916 .stack_check = stack_check,
1917 .stack_protector = stack_protector,
1918 .red_zone = red_zone,
1919 .omit_frame_pointer = omit_frame_pointer,
1920 .single_threaded = single_threaded,
1921 .verbose_link = options.verbose_link,
1922 .machine_code_model = options.machine_code_model,
1923 .dll_export_fns = dll_export_fns,
1924 .error_return_tracing = error_return_tracing,
1925 .llvm_cpu_features = llvm_cpu_features,
1926 .skip_linker_dependencies = options.skip_linker_dependencies,
1927 .each_lib_rpath = options.each_lib_rpath orelse options.is_native_os,
1928 .build_id = build_id,
1929 .cache_mode = cache_mode,
1930 .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole,
1931 .subsystem = options.subsystem,
1932 .is_test = options.is_test,
1933 .dwarf_format = options.dwarf_format,
1934 .wasi_exec_model = wasi_exec_model,
1935 .hash_style = options.hash_style,
1936 .enable_link_snapshots = options.enable_link_snapshots,
1937 .install_name = options.install_name,
1938 .entitlements = options.entitlements,
1939 .pagezero_size = options.pagezero_size,
1940 .headerpad_size = options.headerpad_size,
1941 .headerpad_max_install_names = options.headerpad_max_install_names,
1942 .dead_strip_dylibs = options.dead_strip_dylibs,
1943 .force_undefined_symbols = options.force_undefined_symbols,
1944 .pdb_source_path = options.pdb_source_path,
1945 .pdb_out_path = options.pdb_out_path,
1946 .want_structured_cfg = options.want_structured_cfg,
1947 });
1948 errdefer bin_file.destroy();
1949 comp.* = .{1557 comp.* = .{
1950 .gpa = gpa,1558 .gpa = gpa,
1951 .arena = arena_allocator,1559 .arena = arena_allocator,
1560 .module = zcu,
1561 .root_mod = options.root_mod,
1562 .config = options.config,
1563 .bin_file = null,
1564 .cache_mode = cache_mode,
1952 .zig_lib_directory = options.zig_lib_directory,1565 .zig_lib_directory = options.zig_lib_directory,
1953 .local_cache_directory = options.local_cache_directory,1566 .local_cache_directory = options.local_cache_directory,
1954 .global_cache_directory = options.global_cache_directory,1567 .global_cache_directory = options.global_cache_directory,
1955 .bin_file = bin_file,
1956 .whole_bin_sub_path = whole_bin_sub_path,1568 .whole_bin_sub_path = whole_bin_sub_path,
1957 .whole_implib_sub_path = whole_implib_sub_path,1569 .whole_implib_sub_path = whole_implib_sub_path,
1958 .whole_docs_sub_path = whole_docs_sub_path,1570 .whole_docs_sub_path = whole_docs_sub_path,
...@@ -1966,8 +1578,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1966,8 +1578,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1966 .astgen_work_queue = std.fifo.LinearFifo(*Module.File, .Dynamic).init(gpa),1578 .astgen_work_queue = std.fifo.LinearFifo(*Module.File, .Dynamic).init(gpa),
1967 .embed_file_work_queue = std.fifo.LinearFifo(*Module.EmbedFile, .Dynamic).init(gpa),1579 .embed_file_work_queue = std.fifo.LinearFifo(*Module.EmbedFile, .Dynamic).init(gpa),
1968 .keep_source_files_loaded = options.keep_source_files_loaded,1580 .keep_source_files_loaded = options.keep_source_files_loaded,
1969 .c_frontend = c_frontend,
1970 .clang_argv = options.clang_argv,
1971 .c_source_files = options.c_source_files,1581 .c_source_files = options.c_source_files,
1972 .rc_source_files = options.rc_source_files,1582 .rc_source_files = options.rc_source_files,
1973 .cache_parent = cache,1583 .cache_parent = cache,
...@@ -1975,7 +1585,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1975,7 +1585,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1975 .libc_include_dir_list = libc_dirs.libc_include_dir_list,1585 .libc_include_dir_list = libc_dirs.libc_include_dir_list,
1976 .libc_framework_dir_list = libc_dirs.libc_framework_dir_list,1586 .libc_framework_dir_list = libc_dirs.libc_framework_dir_list,
1977 .rc_include_dir_list = rc_dirs.libc_include_dir_list,1587 .rc_include_dir_list = rc_dirs.libc_include_dir_list,
1978 .sanitize_c = sanitize_c,
1979 .thread_pool = options.thread_pool,1588 .thread_pool = options.thread_pool,
1980 .clang_passthrough_mode = options.clang_passthrough_mode,1589 .clang_passthrough_mode = options.clang_passthrough_mode,
1981 .clang_preprocessor_mode = options.clang_preprocessor_mode,1590 .clang_preprocessor_mode = options.clang_preprocessor_mode,
...@@ -1994,22 +1603,110 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1994,22 +1603,110 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1994 .formatted_panics = formatted_panics,1603 .formatted_panics = formatted_panics,
1995 .time_report = options.time_report,1604 .time_report = options.time_report,
1996 .stack_report = options.stack_report,1605 .stack_report = options.stack_report,
1997 .unwind_tables = unwind_tables,
1998 .test_filter = options.test_filter,1606 .test_filter = options.test_filter,
1999 .test_name_prefix = options.test_name_prefix,1607 .test_name_prefix = options.test_name_prefix,
2000 .test_evented_io = options.test_evented_io,
2001 .debug_compiler_runtime_libs = options.debug_compiler_runtime_libs,1608 .debug_compiler_runtime_libs = options.debug_compiler_runtime_libs,
2002 .debug_compile_errors = options.debug_compile_errors,1609 .debug_compile_errors = options.debug_compile_errors,
2003 .libcxx_abi_version = options.libcxx_abi_version,1610 .libcxx_abi_version = options.libcxx_abi_version,
1611 .implib_emit = implib_emit,
1612 .docs_emit = docs_emit,
1613 .root_name = root_name,
1614 .sysroot = sysroot,
1615 .system_libs = system_libs,
1616 .version = options.version,
1617 .libc_installation = libc_dirs.libc_installation,
1618 .include_compiler_rt = include_compiler_rt,
1619 .objects = options.link_objects,
2004 };1620 };
1621
1622 if (bin_file_emit) |emit| {
1623 comp.bin_file = try link.File.open(arena, .{
1624 .comp = comp,
1625 .emit = emit,
1626 .optimization = linker_optimization,
1627 .linker_script = options.linker_script,
1628 .z_nodelete = options.linker_z_nodelete,
1629 .z_notext = options.linker_z_notext,
1630 .z_defs = options.linker_z_defs,
1631 .z_origin = options.linker_z_origin,
1632 .z_nocopyreloc = options.linker_z_nocopyreloc,
1633 .z_now = options.linker_z_now,
1634 .z_relro = options.linker_z_relro,
1635 .z_common_page_size = options.linker_z_common_page_size,
1636 .z_max_page_size = options.linker_z_max_page_size,
1637 .darwin_sdk_layout = libc_dirs.darwin_sdk_layout,
1638 .frameworks = options.frameworks,
1639 .framework_dirs = options.framework_dirs,
1640 .wasi_emulated_libs = options.wasi_emulated_libs,
1641 .lib_dirs = options.lib_dirs,
1642 .rpath_list = options.rpath_list,
1643 .symbol_wrap_set = options.symbol_wrap_set,
1644 .function_sections = options.function_sections,
1645 .data_sections = options.data_sections,
1646 .no_builtin = options.no_builtin,
1647 .allow_shlib_undefined = options.linker_allow_shlib_undefined,
1648 .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,
1649 .compress_debug_sections = options.linker_compress_debug_sections orelse .none,
1650 .module_definition_file = options.linker_module_definition_file,
1651 .sort_section = options.linker_sort_section,
1652 .import_symbols = options.linker_import_symbols,
1653 .import_table = options.linker_import_table,
1654 .export_table = options.linker_export_table,
1655 .initial_memory = options.linker_initial_memory,
1656 .max_memory = options.linker_max_memory,
1657 .global_base = options.linker_global_base,
1658 .export_symbol_names = options.linker_export_symbol_names,
1659 .print_gc_sections = options.linker_print_gc_sections,
1660 .print_icf_sections = options.linker_print_icf_sections,
1661 .print_map = options.linker_print_map,
1662 .opt_bisect_limit = options.linker_opt_bisect_limit,
1663 .tsaware = options.linker_tsaware,
1664 .nxcompat = options.linker_nxcompat,
1665 .dynamicbase = options.linker_dynamicbase,
1666 .major_subsystem_version = options.major_subsystem_version,
1667 .minor_subsystem_version = options.minor_subsystem_version,
1668 .stack_size_override = options.stack_size_override,
1669 .image_base_override = options.image_base_override,
1670 .version_script = options.version_script,
1671 .gc_sections = options.linker_gc_sections,
1672 .eh_frame_hdr = link_eh_frame_hdr,
1673 .emit_relocs = options.link_emit_relocs,
1674 .rdynamic = options.rdynamic,
1675 .soname = options.soname,
1676 .compatibility_version = options.compatibility_version,
1677 .verbose_link = options.verbose_link,
1678 .dll_export_fns = dll_export_fns,
1679 .skip_linker_dependencies = options.skip_linker_dependencies,
1680 .parent_compilation_link_libc = options.parent_compilation_link_libc,
1681 .each_lib_rpath = each_lib_rpath,
1682 .build_id = build_id,
1683 .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole,
1684 .subsystem = options.subsystem,
1685 .dwarf_format = options.dwarf_format,
1686 .hash_style = options.hash_style,
1687 .enable_link_snapshots = options.enable_link_snapshots,
1688 .install_name = options.install_name,
1689 .entitlements = options.entitlements,
1690 .pagezero_size = options.pagezero_size,
1691 .headerpad_size = options.headerpad_size,
1692 .headerpad_max_install_names = options.headerpad_max_install_names,
1693 .dead_strip_dylibs = options.dead_strip_dylibs,
1694 .force_undefined_symbols = options.force_undefined_symbols,
1695 .pdb_source_path = options.pdb_source_path,
1696 .pdb_out_path = options.pdb_out_path,
1697 .want_structured_cfg = options.want_structured_cfg,
1698 .entry_addr = null, // CLI does not expose this option (yet?)
1699 });
1700 }
1701
2005 break :comp comp;1702 break :comp comp;
2006 };1703 };
2007 errdefer comp.destroy();1704 errdefer comp.destroy();
20081705
2009 const target = comp.getTarget();1706 const target = options.root_mod.resolved_target.result;
20101707
2011 const capable_of_building_compiler_rt = canBuildLibCompilerRt(target, comp.bin_file.options.use_llvm);1708 const capable_of_building_compiler_rt = canBuildLibCompilerRt(target, options.config.use_llvm);
2012 const capable_of_building_zig_libc = canBuildZigLibC(target, comp.bin_file.options.use_llvm);1709 const capable_of_building_zig_libc = canBuildZigLibC(target, options.config.use_llvm);
20131710
2014 // Add a `CObject` for each `c_source_files`.1711 // Add a `CObject` for each `c_source_files`.
2015 try comp.c_object_table.ensureTotalCapacity(gpa, options.c_source_files.len);1712 try comp.c_object_table.ensureTotalCapacity(gpa, options.c_source_files.len);
...@@ -2109,7 +1806,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -2109,7 +1806,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
2109 });1806 });
2110 }1807 }
2111 comp.work_queue.writeAssumeCapacity(&[_]Job{1808 comp.work_queue.writeAssumeCapacity(&[_]Job{
2112 .{ .wasi_libc_crt_file = wasi_libc.execModelCrtFile(wasi_exec_model) },1809 .{ .wasi_libc_crt_file = wasi_libc.execModelCrtFile(options.config.wasi_exec_model) },
2113 .{ .wasi_libc_crt_file = .libc_a },1810 .{ .wasi_libc_crt_file = .libc_a },
2114 });1811 });
2115 }1812 }
...@@ -2171,7 +1868,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -2171,7 +1868,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
2171 if (is_exe_or_dyn_lib) {1868 if (is_exe_or_dyn_lib) {
2172 log.debug("queuing a job to build compiler_rt_lib", .{});1869 log.debug("queuing a job to build compiler_rt_lib", .{});
2173 comp.job_queued_compiler_rt_lib = true;1870 comp.job_queued_compiler_rt_lib = true;
2174 } else if (options.output_mode != .Obj) {1871 } else if (output_mode != .Obj) {
2175 log.debug("queuing a job to build compiler_rt_obj", .{});1872 log.debug("queuing a job to build compiler_rt_obj", .{});
2176 // In this case we are making a static library, so we ask1873 // In this case we are making a static library, so we ask
2177 // for a compiler-rt object to put in it.1874 // for a compiler-rt object to put in it.
...@@ -2283,7 +1980,7 @@ pub fn clearMiscFailures(comp: *Compilation) void {...@@ -2283,7 +1980,7 @@ pub fn clearMiscFailures(comp: *Compilation) void {
2283}1980}
22841981
2285pub fn getTarget(self: Compilation) Target {1982pub fn getTarget(self: Compilation) Target {
2286 return self.bin_file.options.target;1983 return self.root_mod.resolved_target.result;
2287}1984}
22881985
2289fn restorePrevZigCacheArtifactDirectory(comp: *Compilation, directory: *Directory) void {1986fn restorePrevZigCacheArtifactDirectory(comp: *Compilation, directory: *Directory) void {
...@@ -2436,7 +2133,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void...@@ -2436,7 +2133,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
24362133
2437 // Make sure std.zig is inside the import_table. We unconditionally need2134 // Make sure std.zig is inside the import_table. We unconditionally need
2438 // it for start.zig.2135 // it for start.zig.
2439 const std_mod = module.main_mod.deps.get("std").?;2136 const std_mod = module.std_mod;
2440 _ = try module.importPkg(std_mod);2137 _ = try module.importPkg(std_mod);
24412138
2442 // Normally we rely on importing std to in turn import the root source file2139 // Normally we rely on importing std to in turn import the root source file
...@@ -2449,7 +2146,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void...@@ -2449,7 +2146,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
2449 _ = try module.importPkg(module.main_mod);2146 _ = try module.importPkg(module.main_mod);
2450 }2147 }
24512148
2452 if (module.main_mod.deps.get("compiler_rt")) |compiler_rt_mod| {2149 if (module.root_mod.deps.get("compiler_rt")) |compiler_rt_mod| {
2453 _ = try module.importPkg(compiler_rt_mod);2150 _ = try module.importPkg(compiler_rt_mod);
2454 }2151 }
24552152
...@@ -2474,7 +2171,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void...@@ -2474,7 +2171,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
2474 try comp.work_queue.writeItem(.{ .analyze_mod = module.main_mod });2171 try comp.work_queue.writeItem(.{ .analyze_mod = module.main_mod });
2475 }2172 }
24762173
2477 if (module.main_mod.deps.get("compiler_rt")) |compiler_rt_mod| {2174 if (module.root_mod.deps.get("compiler_rt")) |compiler_rt_mod| {
2478 try comp.work_queue.writeItem(.{ .analyze_mod = compiler_rt_mod });2175 try comp.work_queue.writeItem(.{ .analyze_mod = compiler_rt_mod });
2479 }2176 }
2480 }2177 }
...@@ -2699,16 +2396,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -2699,16 +2396,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
2699 if (comp.bin_file.options.module) |mod| {2396 if (comp.bin_file.options.module) |mod| {
2700 const main_zig_file = try mod.main_mod.root.joinString(arena, mod.main_mod.root_src_path);2397 const main_zig_file = try mod.main_mod.root.joinString(arena, mod.main_mod.root_src_path);
2701 _ = try man.addFile(main_zig_file, null);2398 _ = try man.addFile(main_zig_file, null);
2702 {2399 try addModuleTableToCacheHash(gpa, arena, &man.hash, mod.main_mod, .{ .files = man });
2703 var seen_table = std.AutoHashMap(*Package.Module, void).init(arena);
2704
2705 // Skip builtin.zig; it is useless as an input, and we don't want to have to
2706 // write it before checking for a cache hit.
2707 const builtin_mod = mod.main_mod.deps.get("builtin").?;
2708 try seen_table.put(builtin_mod, {});
2709
2710 try addModuleTableToCacheHash(&man.hash, &arena_allocator, mod.main_mod.deps, &seen_table, .{ .files = man });
2711 }
27122400
2713 // Synchronize with other matching comments: ZigOnlyHashStuff2401 // Synchronize with other matching comments: ZigOnlyHashStuff
2714 man.hash.add(comp.bin_file.options.valgrind);2402 man.hash.add(comp.bin_file.options.valgrind);
...@@ -2762,8 +2450,6 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -2762,8 +2450,6 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
2762 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_ir);2450 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_ir);
2763 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc);2451 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc);
27642452
2765 man.hash.addListOfBytes(comp.clang_argv);
2766
2767 man.hash.addOptional(comp.bin_file.options.stack_size_override);2453 man.hash.addOptional(comp.bin_file.options.stack_size_override);
2768 man.hash.addOptional(comp.bin_file.options.image_base_override);2454 man.hash.addOptional(comp.bin_file.options.image_base_override);
2769 man.hash.addOptional(comp.bin_file.options.gc_sections);2455 man.hash.addOptional(comp.bin_file.options.gc_sections);
...@@ -3341,7 +3027,7 @@ pub const ErrorNoteHashContext = struct {...@@ -3341,7 +3027,7 @@ pub const ErrorNoteHashContext = struct {
3341 const eb = ctx.eb.tmpBundle();3027 const eb = ctx.eb.tmpBundle();
3342 const msg_a = eb.nullTerminatedString(a.msg);3028 const msg_a = eb.nullTerminatedString(a.msg);
3343 const msg_b = eb.nullTerminatedString(b.msg);3029 const msg_b = eb.nullTerminatedString(b.msg);
3344 if (!std.mem.eql(u8, msg_a, msg_b)) return false;3030 if (!mem.eql(u8, msg_a, msg_b)) return false;
33453031
3346 if (a.src_loc == .none and b.src_loc == .none) return true;3032 if (a.src_loc == .none and b.src_loc == .none) return true;
3347 if (a.src_loc == .none or b.src_loc == .none) return false;3033 if (a.src_loc == .none or b.src_loc == .none) return false;
...@@ -3351,7 +3037,7 @@ pub const ErrorNoteHashContext = struct {...@@ -3351,7 +3037,7 @@ pub const ErrorNoteHashContext = struct {
3351 const src_path_a = eb.nullTerminatedString(src_a.src_path);3037 const src_path_a = eb.nullTerminatedString(src_a.src_path);
3352 const src_path_b = eb.nullTerminatedString(src_b.src_path);3038 const src_path_b = eb.nullTerminatedString(src_b.src_path);
33533039
3354 return std.mem.eql(u8, src_path_a, src_path_b) and3040 return mem.eql(u8, src_path_a, src_path_b) and
3355 src_a.line == src_b.line and3041 src_a.line == src_b.line and
3356 src_a.column == src_b.column and3042 src_a.column == src_b.column and
3357 src_a.span_main == src_b.span_main;3043 src_a.span_main == src_b.span_main;
...@@ -4149,7 +3835,7 @@ pub const CImportResult = struct {...@@ -4149,7 +3835,7 @@ pub const CImportResult = struct {
4149 cache_hit: bool,3835 cache_hit: bool,
4150 errors: std.zig.ErrorBundle,3836 errors: std.zig.ErrorBundle,
41513837
4152 pub fn deinit(result: *CImportResult, gpa: std.mem.Allocator) void {3838 pub fn deinit(result: *CImportResult, gpa: mem.Allocator) void {
4153 result.errors.deinit(gpa);3839 result.errors.deinit(gpa);
4154 }3840 }
4155};3841};
...@@ -5321,9 +5007,9 @@ pub fn addCCArgs(...@@ -5321,9 +5007,9 @@ pub fn addCCArgs(
5321 argv.appendAssumeCapacity(arg);5007 argv.appendAssumeCapacity(arg);
5322 }5008 }
5323 }5009 }
5324 const mcmodel = comp.bin_file.options.machine_code_model;5010 const code_model = comp.bin_file.options.machine_code_model;
5325 if (mcmodel != .default) {5011 if (code_model != .default) {
5326 try argv.append(try std.fmt.allocPrint(arena, "-mcmodel={s}", .{@tagName(mcmodel)}));5012 try argv.append(try std.fmt.allocPrint(arena, "-mcmodel={s}", .{@tagName(code_model)}));
5327 }5013 }
53285014
5329 switch (target.os.tag) {5015 switch (target.os.tag) {
...@@ -5618,68 +5304,6 @@ fn failCObjWithOwnedDiagBundle(...@@ -5618,68 +5304,6 @@ fn failCObjWithOwnedDiagBundle(
5618 return error.AnalysisFail;5304 return error.AnalysisFail;
5619}5305}
56205306
5621/// The include directories used when preprocessing .rc files are separate from the
5622/// target. Which include directories are used is determined by `options.rc_includes`.
5623///
5624/// Note: It should be okay that the include directories used when compiling .rc
5625/// files differ from the include directories used when compiling the main
5626/// binary, since the .res format is not dependent on anything ABI-related. The
5627/// only relevant differences would be things like `#define` constants being
5628/// different in the MinGW headers vs the MSVC headers, but any such
5629/// differences would likely be a MinGW bug.
5630fn detectWin32ResourceIncludeDirs(arena: Allocator, options: InitOptions) !LibCDirs {
5631 // Set the includes to .none here when there are no rc files to compile
5632 var includes = if (options.rc_source_files.len > 0) options.rc_includes else .none;
5633 if (builtin.target.os.tag != .windows) {
5634 switch (includes) {
5635 // MSVC can't be found when the host isn't Windows, so short-circuit.
5636 .msvc => return error.WindowsSdkNotFound,
5637 // Skip straight to gnu since we won't be able to detect MSVC on non-Windows hosts.
5638 .any => includes = .gnu,
5639 .none, .gnu => {},
5640 }
5641 }
5642 while (true) {
5643 switch (includes) {
5644 .any, .msvc => return detectLibCIncludeDirs(
5645 arena,
5646 options.zig_lib_directory.path.?,
5647 .{
5648 .cpu = options.target.cpu,
5649 .os = options.target.os,
5650 .abi = .msvc,
5651 .ofmt = options.target.ofmt,
5652 },
5653 options.is_native_abi,
5654 // The .rc preprocessor will need to know the libc include dirs even if we
5655 // are not linking libc, so force 'link_libc' to true
5656 true,
5657 options.libc_installation,
5658 ) catch |err| {
5659 if (includes == .any) {
5660 // fall back to mingw
5661 includes = .gnu;
5662 continue;
5663 }
5664 return err;
5665 },
5666 .gnu => return detectLibCFromBuilding(arena, options.zig_lib_directory.path.?, .{
5667 .cpu = options.target.cpu,
5668 .os = options.target.os,
5669 .abi = .gnu,
5670 .ofmt = options.target.ofmt,
5671 }),
5672 .none => return LibCDirs{
5673 .libc_include_dir_list = &[0][]u8{},
5674 .libc_installation = null,
5675 .libc_framework_dir_list = &.{},
5676 .sysroot = null,
5677 .darwin_sdk_layout = null,
5678 },
5679 }
5680 }
5681}
5682
5683fn failWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, comptime format: []const u8, args: anytype) SemaError {5307fn failWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, comptime format: []const u8, args: anytype) SemaError {
5684 @setCold(true);5308 @setCold(true);
5685 var bundle: ErrorBundle.Wip = undefined;5309 var bundle: ErrorBundle.Wip = undefined;
...@@ -6061,7 +5685,7 @@ const LibCDirs = struct {...@@ -6061,7 +5685,7 @@ const LibCDirs = struct {
6061 libc_installation: ?*const LibCInstallation,5685 libc_installation: ?*const LibCInstallation,
6062 libc_framework_dir_list: []const []const u8,5686 libc_framework_dir_list: []const []const u8,
6063 sysroot: ?[]const u8,5687 sysroot: ?[]const u8,
6064 darwin_sdk_layout: ?link.DarwinSdkLayout,5688 darwin_sdk_layout: ?link.File.MachO.SdkLayout,
6065};5689};
60665690
6067fn getZigShippedLibCIncludeDirsDarwin(arena: Allocator, zig_lib_dir: []const u8) !LibCDirs {5691fn getZigShippedLibCIncludeDirsDarwin(arena: Allocator, zig_lib_dir: []const u8) !LibCDirs {
...@@ -6374,7 +5998,7 @@ fn parseLldStderr(comp: *Compilation, comptime prefix: []const u8, stderr: []con...@@ -6374,7 +5998,7 @@ fn parseLldStderr(comp: *Compilation, comptime prefix: []const u8, stderr: []con
6374 err.context_lines = try context_lines.toOwnedSlice();5998 err.context_lines = try context_lines.toOwnedSlice();
6375 }5999 }
63766000
6377 var split = std.mem.splitSequence(u8, line, "error: ");6001 var split = mem.splitSequence(u8, line, "error: ");
6378 _ = split.first();6002 _ = split.first();
63796003
6380 const duped_msg = try std.fmt.allocPrint(comp.gpa, "{s}: {s}", .{ prefix, split.rest() });6004 const duped_msg = try std.fmt.allocPrint(comp.gpa, "{s}: {s}", .{ prefix, split.rest() });
...@@ -6427,7 +6051,7 @@ fn canBuildLibCompilerRt(target: std.Target, use_llvm: bool) bool {...@@ -6427,7 +6051,7 @@ fn canBuildLibCompilerRt(target: std.Target, use_llvm: bool) bool {
6427 .spirv32, .spirv64 => return false,6051 .spirv32, .spirv64 => return false,
6428 else => {},6052 else => {},
6429 }6053 }
6430 return switch (zigBackend(target, use_llvm)) {6054 return switch (target_util.zigBackend(target, use_llvm)) {
6431 .stage2_llvm => true,6055 .stage2_llvm => true,
6432 .stage2_x86_64 => if (target.ofmt == .elf) true else build_options.have_llvm,6056 .stage2_x86_64 => if (target.ofmt == .elf) true else build_options.have_llvm,
6433 else => build_options.have_llvm,6057 else => build_options.have_llvm,
...@@ -6445,7 +6069,7 @@ fn canBuildZigLibC(target: std.Target, use_llvm: bool) bool {...@@ -6445,7 +6069,7 @@ fn canBuildZigLibC(target: std.Target, use_llvm: bool) bool {
6445 .spirv32, .spirv64 => return false,6069 .spirv32, .spirv64 => return false,
6446 else => {},6070 else => {},
6447 }6071 }
6448 return switch (zigBackend(target, use_llvm)) {6072 return switch (target_util.zigBackend(target, use_llvm)) {
6449 .stage2_llvm => true,6073 .stage2_llvm => true,
6450 .stage2_x86_64 => if (target.ofmt == .elf) true else build_options.have_llvm,6074 .stage2_x86_64 => if (target.ofmt == .elf) true else build_options.have_llvm,
6451 else => build_options.have_llvm,6075 else => build_options.have_llvm,
...@@ -6454,236 +6078,7 @@ fn canBuildZigLibC(target: std.Target, use_llvm: bool) bool {...@@ -6454,236 +6078,7 @@ fn canBuildZigLibC(target: std.Target, use_llvm: bool) bool {
64546078
6455pub fn getZigBackend(comp: Compilation) std.builtin.CompilerBackend {6079pub fn getZigBackend(comp: Compilation) std.builtin.CompilerBackend {
6456 const target = comp.bin_file.options.target;6080 const target = comp.bin_file.options.target;
6457 return zigBackend(target, comp.bin_file.options.use_llvm);6081 return target_util.zigBackend(target, comp.bin_file.options.use_llvm);
6458}
6459
6460fn zigBackend(target: std.Target, use_llvm: bool) std.builtin.CompilerBackend {
6461 if (use_llvm) return .stage2_llvm;
6462 if (target.ofmt == .c) return .stage2_c;
6463 return switch (target.cpu.arch) {
6464 .wasm32, .wasm64 => std.builtin.CompilerBackend.stage2_wasm,
6465 .arm, .armeb, .thumb, .thumbeb => .stage2_arm,
6466 .x86_64 => .stage2_x86_64,
6467 .x86 => .stage2_x86,
6468 .aarch64, .aarch64_be, .aarch64_32 => .stage2_aarch64,
6469 .riscv64 => .stage2_riscv64,
6470 .sparc64 => .stage2_sparc64,
6471 .spirv64 => .stage2_spirv64,
6472 else => .other,
6473 };
6474}
6475
6476pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Allocator.Error![:0]u8 {
6477 const tracy_trace = trace(@src());
6478 defer tracy_trace.end();
6479
6480 var buffer = std.ArrayList(u8).init(allocator);
6481 defer buffer.deinit();
6482
6483 const target = comp.getTarget();
6484 const generic_arch_name = target.cpu.arch.genericName();
6485 const zig_backend = comp.getZigBackend();
6486
6487 @setEvalBranchQuota(4000);
6488 try buffer.writer().print(
6489 \\const std = @import("std");
6490 \\/// Zig version. When writing code that supports multiple versions of Zig, prefer
6491 \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.
6492 \\pub const zig_version = std.SemanticVersion.parse(zig_version_string) catch unreachable;
6493 \\pub const zig_version_string = "{s}";
6494 \\pub const zig_backend = std.builtin.CompilerBackend.{};
6495 \\
6496 \\pub const output_mode = std.builtin.OutputMode.{};
6497 \\pub const link_mode = std.builtin.LinkMode.{};
6498 \\pub const is_test = {};
6499 \\pub const single_threaded = {};
6500 \\pub const abi = std.Target.Abi.{};
6501 \\pub const cpu: std.Target.Cpu = .{{
6502 \\ .arch = .{},
6503 \\ .model = &std.Target.{}.cpu.{},
6504 \\ .features = std.Target.{}.featureSet(&[_]std.Target.{}.Feature{{
6505 \\
6506 , .{
6507 build_options.version,
6508 std.zig.fmtId(@tagName(zig_backend)),
6509 std.zig.fmtId(@tagName(comp.bin_file.options.output_mode)),
6510 std.zig.fmtId(@tagName(comp.bin_file.options.link_mode)),
6511 comp.bin_file.options.is_test,
6512 comp.bin_file.options.single_threaded,
6513 std.zig.fmtId(@tagName(target.abi)),
6514 std.zig.fmtId(@tagName(target.cpu.arch)),
6515 std.zig.fmtId(generic_arch_name),
6516 std.zig.fmtId(target.cpu.model.name),
6517 std.zig.fmtId(generic_arch_name),
6518 std.zig.fmtId(generic_arch_name),
6519 });
6520
6521 for (target.cpu.arch.allFeaturesList(), 0..) |feature, index_usize| {
6522 const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));
6523 const is_enabled = target.cpu.features.isEnabled(index);
6524 if (is_enabled) {
6525 try buffer.writer().print(" .{},\n", .{std.zig.fmtId(feature.name)});
6526 }
6527 }
6528 try buffer.writer().print(
6529 \\ }}),
6530 \\}};
6531 \\pub const os = std.Target.Os{{
6532 \\ .tag = .{},
6533 \\ .version_range = .{{
6534 ,
6535 .{std.zig.fmtId(@tagName(target.os.tag))},
6536 );
6537
6538 switch (target.os.getVersionRange()) {
6539 .none => try buffer.appendSlice(" .none = {} },\n"),
6540 .semver => |semver| try buffer.writer().print(
6541 \\ .semver = .{{
6542 \\ .min = .{{
6543 \\ .major = {},
6544 \\ .minor = {},
6545 \\ .patch = {},
6546 \\ }},
6547 \\ .max = .{{
6548 \\ .major = {},
6549 \\ .minor = {},
6550 \\ .patch = {},
6551 \\ }},
6552 \\ }}}},
6553 \\
6554 , .{
6555 semver.min.major,
6556 semver.min.minor,
6557 semver.min.patch,
6558
6559 semver.max.major,
6560 semver.max.minor,
6561 semver.max.patch,
6562 }),
6563 .linux => |linux| try buffer.writer().print(
6564 \\ .linux = .{{
6565 \\ .range = .{{
6566 \\ .min = .{{
6567 \\ .major = {},
6568 \\ .minor = {},
6569 \\ .patch = {},
6570 \\ }},
6571 \\ .max = .{{
6572 \\ .major = {},
6573 \\ .minor = {},
6574 \\ .patch = {},
6575 \\ }},
6576 \\ }},
6577 \\ .glibc = .{{
6578 \\ .major = {},
6579 \\ .minor = {},
6580 \\ .patch = {},
6581 \\ }},
6582 \\ }}}},
6583 \\
6584 , .{
6585 linux.range.min.major,
6586 linux.range.min.minor,
6587 linux.range.min.patch,
6588
6589 linux.range.max.major,
6590 linux.range.max.minor,
6591 linux.range.max.patch,
6592
6593 linux.glibc.major,
6594 linux.glibc.minor,
6595 linux.glibc.patch,
6596 }),
6597 .windows => |windows| try buffer.writer().print(
6598 \\ .windows = .{{
6599 \\ .min = {s},
6600 \\ .max = {s},
6601 \\ }}}},
6602 \\
6603 ,
6604 .{ windows.min, windows.max },
6605 ),
6606 }
6607 try buffer.appendSlice(
6608 \\};
6609 \\pub const target: std.Target = .{
6610 \\ .cpu = cpu,
6611 \\ .os = os,
6612 \\ .abi = abi,
6613 \\ .ofmt = object_format,
6614 \\
6615 );
6616
6617 if (target.dynamic_linker.get()) |dl| {
6618 try buffer.writer().print(
6619 \\ .dynamic_linker = std.Target.DynamicLinker.init("{s}"),
6620 \\}};
6621 \\
6622 , .{dl});
6623 } else {
6624 try buffer.appendSlice(
6625 \\ .dynamic_linker = std.Target.DynamicLinker.none,
6626 \\};
6627 \\
6628 );
6629 }
6630
6631 try buffer.writer().print(
6632 \\pub const object_format = std.Target.ObjectFormat.{};
6633 \\pub const mode = std.builtin.OptimizeMode.{};
6634 \\pub const link_libc = {};
6635 \\pub const link_libcpp = {};
6636 \\pub const have_error_return_tracing = {};
6637 \\pub const valgrind_support = {};
6638 \\pub const sanitize_thread = {};
6639 \\pub const position_independent_code = {};
6640 \\pub const position_independent_executable = {};
6641 \\pub const strip_debug_info = {};
6642 \\pub const code_model = std.builtin.CodeModel.{};
6643 \\pub const omit_frame_pointer = {};
6644 \\
6645 , .{
6646 std.zig.fmtId(@tagName(target.ofmt)),
6647 std.zig.fmtId(@tagName(comp.bin_file.options.optimize_mode)),
6648 comp.bin_file.options.link_libc,
6649 comp.bin_file.options.link_libcpp,
6650 comp.bin_file.options.error_return_tracing,
6651 comp.bin_file.options.valgrind,
6652 comp.bin_file.options.tsan,
6653 comp.bin_file.options.pic,
6654 comp.bin_file.options.pie,
6655 comp.bin_file.options.strip,
6656 std.zig.fmtId(@tagName(comp.bin_file.options.machine_code_model)),
6657 comp.bin_file.options.omit_frame_pointer,
6658 });
6659
6660 if (target.os.tag == .wasi) {
6661 const wasi_exec_model_fmt = std.zig.fmtId(@tagName(comp.bin_file.options.wasi_exec_model));
6662 try buffer.writer().print(
6663 \\pub const wasi_exec_model = std.builtin.WasiExecModel.{};
6664 \\
6665 , .{wasi_exec_model_fmt});
6666 }
6667
6668 if (comp.bin_file.options.is_test) {
6669 try buffer.appendSlice(
6670 \\pub var test_functions: []const std.builtin.TestFn = undefined; // overwritten later
6671 \\
6672 );
6673 if (comp.test_evented_io) {
6674 try buffer.appendSlice(
6675 \\pub const test_io_mode = .evented;
6676 \\
6677 );
6678 } else {
6679 try buffer.appendSlice(
6680 \\pub const test_io_mode = .blocking;
6681 \\
6682 );
6683 }
6684 }
6685
6686 return buffer.toOwnedSliceSentinel(0);
6687}6082}
66886083
6689pub fn updateSubCompilation(6084pub fn updateSubCompilation(
...@@ -6730,21 +6125,46 @@ fn buildOutputFromZig(...@@ -6730,21 +6125,46 @@ fn buildOutputFromZig(
6730 const tracy_trace = trace(@src());6125 const tracy_trace = trace(@src());
6731 defer tracy_trace.end();6126 defer tracy_trace.end();
67326127
6128 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
6129 defer arena_allocator.deinit();
6130 const arena = arena_allocator.allocator();
6131
6733 assert(output_mode != .Exe);6132 assert(output_mode != .Exe);
67346133
6735 var main_mod: Package.Module = .{6134 const config = try Config.resolve(.{
6736 .root = .{ .root_dir = comp.zig_lib_directory },6135 .output_mode = output_mode,
6737 .root_src_path = src_basename,6136 .resolved_target = comp.root_mod.resolved_target,
6137 .is_test = false,
6138 .have_zcu = true,
6139 .emit_bin = true,
6140 .root_optimize_mode = comp.compilerRtOptMode(),
6141 });
6142
6143 const root_mod = Package.Module.create(.{
6144 .paths = .{
6145 .root = .{ .root_dir = comp.zig_lib_directory },
6146 .root_src_path = src_basename,
6147 },
6738 .fully_qualified_name = "root",6148 .fully_qualified_name = "root",
6739 };6149 .inherited = .{
6150 .strip = comp.compilerRtStrip(),
6151 .stack_check = false,
6152 .stack_protector = 0,
6153 .red_zone = comp.root_mod.red_zone,
6154 .omit_frame_pointer = comp.root_mod.omit_frame_pointer,
6155 .unwind_tables = comp.bin_file.options.eh_frame_hdr,
6156 .pic = comp.root_mod.pic,
6157 },
6158 .global = config,
6159 .cc_argv = &.{},
6160 });
6740 const root_name = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len];6161 const root_name = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len];
6741 const target = comp.getTarget();6162 const target = comp.getTarget();
6742 const bin_basename = try std.zig.binNameAlloc(comp.gpa, .{6163 const bin_basename = try std.zig.binNameAlloc(arena, .{
6743 .root_name = root_name,6164 .root_name = root_name,
6744 .target = target,6165 .target = target,
6745 .output_mode = output_mode,6166 .output_mode = output_mode,
6746 });6167 });
6747 defer comp.gpa.free(bin_basename);
67486168
6749 const emit_bin = Compilation.EmitLoc{6169 const emit_bin = Compilation.EmitLoc{
6750 .directory = null, // Put it in the cache directory.6170 .directory = null, // Put it in the cache directory.
...@@ -6754,33 +6174,18 @@ fn buildOutputFromZig(...@@ -6754,33 +6174,18 @@ fn buildOutputFromZig(
6754 .global_cache_directory = comp.global_cache_directory,6174 .global_cache_directory = comp.global_cache_directory,
6755 .local_cache_directory = comp.global_cache_directory,6175 .local_cache_directory = comp.global_cache_directory,
6756 .zig_lib_directory = comp.zig_lib_directory,6176 .zig_lib_directory = comp.zig_lib_directory,
6177 .resolved = config,
6757 .cache_mode = .whole,6178 .cache_mode = .whole,
6758 .target = target,
6759 .root_name = root_name,6179 .root_name = root_name,
6760 .main_mod = &main_mod,6180 .root_mod = root_mod,
6761 .output_mode = output_mode,
6762 .thread_pool = comp.thread_pool,6181 .thread_pool = comp.thread_pool,
6763 .libc_installation = comp.bin_file.options.libc_installation,6182 .libc_installation = comp.bin_file.options.libc_installation,
6764 .emit_bin = emit_bin,6183 .emit_bin = emit_bin,
6765 .optimize_mode = comp.compilerRtOptMode(),
6766 .link_mode = .Static,6184 .link_mode = .Static,
6767 .function_sections = true,6185 .function_sections = true,
6768 .data_sections = true,6186 .data_sections = true,
6769 .no_builtin = true,6187 .no_builtin = true,
6770 .want_sanitize_c = false,
6771 .want_stack_check = false,
6772 .want_stack_protector = 0,
6773 .want_red_zone = comp.bin_file.options.red_zone,
6774 .omit_frame_pointer = comp.bin_file.options.omit_frame_pointer,
6775 .want_valgrind = false,
6776 .want_tsan = false,
6777 .want_unwind_tables = comp.bin_file.options.eh_frame_hdr,
6778 .want_pic = comp.bin_file.options.pic,
6779 .want_pie = null,
6780 .emit_h = null,6188 .emit_h = null,
6781 .strip = comp.compilerRtStrip(),
6782 .is_native_os = comp.bin_file.options.is_native_os,
6783 .is_native_abi = comp.bin_file.options.is_native_abi,
6784 .self_exe_path = comp.self_exe_path,6189 .self_exe_path = comp.self_exe_path,
6785 .verbose_cc = comp.verbose_cc,6190 .verbose_cc = comp.verbose_cc,
6786 .verbose_link = comp.bin_file.options.verbose_link,6191 .verbose_link = comp.bin_file.options.verbose_link,
...@@ -6815,7 +6220,7 @@ pub fn build_crt_file(...@@ -6815,7 +6220,7 @@ pub fn build_crt_file(
6815 output_mode: std.builtin.OutputMode,6220 output_mode: std.builtin.OutputMode,
6816 misc_task_tag: MiscTask,6221 misc_task_tag: MiscTask,
6817 prog_node: *std.Progress.Node,6222 prog_node: *std.Progress.Node,
6818 c_source_files: []const Compilation.CSourceFile,6223 c_source_files: []const CSourceFile,
6819) !void {6224) !void {
6820 const tracy_trace = trace(@src());6225 const tracy_trace = trace(@src());
6821 defer tracy_trace.end();6226 defer tracy_trace.end();
src/Compilation/Config.zig created+382
...@@ -0,0 +1,382 @@
1//! User-specified settings that have all the defaults resolved into concrete values.
2
3have_zcu: bool,
4output_mode: std.builtin.OutputMode,
5link_mode: std.builtin.LinkMode,
6link_libc: bool,
7link_libcpp: bool,
8link_libunwind: bool,
9any_unwind_tables: bool,
10pie: bool,
11/// If this is true then linker code is responsible for making an LLVM IR
12/// Module, outputting it to an object file, and then linking that together
13/// with link options and other objects. Otherwise (depending on `use_lld`)
14/// linker code directly outputs and updates the final binary.
15use_llvm: bool,
16/// Whether or not the LLVM library API will be used by the LLVM backend.
17use_lib_llvm: bool,
18/// If this is true then linker code is responsible for outputting an object
19/// file and then using LLD to link it together with the link options and other
20/// objects. Otherwise (depending on `use_llvm`) linker code directly outputs
21/// and updates the final binary.
22use_lld: bool,
23c_frontend: CFrontend,
24lto: bool,
25/// WASI-only. Type of WASI execution model ("command" or "reactor").
26/// Always set to `command` for non-WASI targets.
27wasi_exec_model: std.builtin.WasiExecModel,
28import_memory: bool,
29export_memory: bool,
30shared_memory: bool,
31is_test: bool,
32test_evented_io: bool,
33entry: ?[]const u8,
34
35pub const CFrontend = enum { clang, aro };
36
37pub const Options = struct {
38 output_mode: std.builtin.OutputMode,
39 resolved_target: Module.ResolvedTarget,
40 is_test: bool,
41 have_zcu: bool,
42 emit_bin: bool,
43 root_optimize_mode: ?std.builtin.OptimizeMode = null,
44 link_mode: ?std.builtin.LinkMode = null,
45 ensure_libc_on_non_freestanding: bool = false,
46 ensure_libcpp_on_non_freestanding: bool = false,
47 any_non_single_threaded: bool = false,
48 any_sanitize_thread: bool = false,
49 any_unwind_tables: bool = false,
50 any_dyn_libs: bool = false,
51 c_source_files_len: usize = 0,
52 emit_llvm_ir: bool = false,
53 emit_llvm_bc: bool = false,
54 link_libc: ?bool = null,
55 link_libcpp: ?bool = null,
56 link_libunwind: ?bool = null,
57 pie: ?bool = null,
58 use_llvm: ?bool = null,
59 use_lib_llvm: ?bool = null,
60 use_lld: ?bool = null,
61 use_clang: ?bool = null,
62 lto: ?bool = null,
63 entry: union(enum) {
64 default,
65 disabled,
66 enabled,
67 named: []const u8,
68 } = .default,
69 /// WASI-only. Type of WASI execution model ("command" or "reactor").
70 wasi_exec_model: ?std.builtin.WasiExecModel = null,
71 import_memory: ?bool = null,
72 export_memory: ?bool = null,
73 shared_memory: ?bool = null,
74 test_evented_io: bool = false,
75};
76
77pub fn resolve(options: Options) !Config {
78 const target = options.resolved_target.result;
79
80 // WASI-only. Resolve the optional exec-model option, defaults to command.
81 if (target.os.tag != .wasi and options.wasi_exec_model != null)
82 return error.WasiExecModelRequiresWasi;
83 const wasi_exec_model = options.wasi_exec_model orelse .command;
84
85 const shared_memory = b: {
86 if (!target.cpu.arch.isWasm()) {
87 if (options.shared_memory == true) return error.SharedMemoryIsWasmOnly;
88 break :b false;
89 }
90 if (options.output_mode == .Obj) {
91 if (options.shared_memory == true) return error.ObjectFilesCannotShareMemory;
92 break :b false;
93 }
94 if (!std.Target.wasm.featureSetHasAll(target.cpu.features, .{ .atomics, .bulk_memory })) {
95 if (options.shared_memory == true)
96 return error.SharedMemoryRequiresAtomicsAndBulkMemory;
97 break :b false;
98 }
99 if (options.any_non_single_threaded) {
100 if (options.shared_memory == false)
101 return error.ThreadsRequireSharedMemory;
102 break :b true;
103 }
104 break :b options.shared_memory orelse false;
105 };
106
107 const entry: ?[]const u8 = switch (options.entry) {
108 .disabled => null,
109 .default => b: {
110 if (options.output_mode != .Exe) break :b null;
111 break :b target_util.defaultEntrySymbolName(target, wasi_exec_model) orelse
112 return error.UnknownTargetEntryPoint;
113 },
114 .enabled => target_util.defaultEntrySymbolName(target, wasi_exec_model) orelse
115 return error.UnknownTargetEntryPoint,
116 .named => |name| name,
117 };
118 if (entry != null and options.output_mode != .Exe)
119 return error.NonExecutableEntryPoint;
120
121 // *If* the LLVM backend were to be selected, should Zig use the LLVM
122 // library to build the LLVM module?
123 const use_lib_llvm = b: {
124 if (!build_options.have_llvm) {
125 if (options.use_lib_llvm == true) return error.LlvmLibraryUnavailable;
126 break :b false;
127 }
128 break :b options.use_lib_llvm orelse true;
129 };
130
131 const root_optimize_mode = options.root_optimize_mode orelse .Debug;
132
133 // Make a decision on whether to use LLVM backend for machine code generation.
134 // Note that using the LLVM backend does not necessarily mean using LLVM libraries.
135 // For example, Zig can emit .bc and .ll files directly, and this is still considered
136 // using "the LLVM backend".
137 const use_llvm = b: {
138 // If emitting to LLVM bitcode object format, must use LLVM backend.
139 if (options.emit_llvm_ir or options.emit_llvm_bc) {
140 if (options.use_llvm == false) return error.EmittingLlvmModuleRequiresLlvmBackend;
141 break :b true;
142 }
143
144 // If LLVM does not support the target, then we can't use it.
145 if (!target_util.hasLlvmSupport(target, target.ofmt)) {
146 if (options.use_llvm == true) return error.LlvmLacksTargetSupport;
147 break :b false;
148 }
149
150 if (options.use_llvm) |x| break :b x;
151
152 // If we have no zig code to compile, no need for LLVM.
153 if (!options.have_zcu) break :b false;
154
155 // If we cannot use LLVM libraries, then our own backends will be a
156 // better default since the LLVM backend can only produce bitcode
157 // and not an object file or executable.
158 if (!use_lib_llvm) break :b false;
159
160 // Prefer LLVM for release builds.
161 if (root_optimize_mode != .Debug) break :b true;
162
163 // At this point we would prefer to use our own self-hosted backend,
164 // because the compilation speed is better than LLVM. But only do it if
165 // we are confident in the robustness of the backend.
166 break :b !target_util.selfHostedBackendIsAsRobustAsLlvm(target);
167 };
168
169 if (!use_lib_llvm and use_llvm and options.emit_bin) {
170 // Explicit request to use LLVM to produce an object file, but without
171 // using LLVM libraries. Impossible.
172 return error.EmittingBinaryRequiresLlvmLibrary;
173 }
174
175 // Make a decision on whether to use LLD or our own linker.
176 const use_lld = b: {
177 if (target.isDarwin()) {
178 if (options.use_lld == true) return error.LldIncompatibleOs;
179 break :b false;
180 }
181
182 if (!build_options.have_llvm) {
183 if (options.use_lld == true) return error.LldUnavailable;
184 break :b false;
185 }
186
187 if (target.ofmt == .c) {
188 if (options.use_lld == true) return error.LldIncompatibleObjectFormat;
189 break :b false;
190 }
191
192 if (options.lto == true) {
193 if (options.use_lld == false) return error.LtoRequiresLld;
194 break :b true;
195 }
196
197 if (options.use_lld) |x| break :b x;
198 break :b true;
199 };
200
201 // Make a decision on whether to use Clang or Aro for translate-c and compiling C files.
202 const c_frontend: CFrontend = b: {
203 if (!build_options.have_llvm) {
204 if (options.use_clang == true) return error.ClangUnavailable;
205 break :b .aro;
206 }
207 if (options.use_clang) |clang| {
208 break :b if (clang) .clang else .aro;
209 }
210 break :b .clang;
211 };
212
213 const lto = b: {
214 if (!use_lld) {
215 // zig ld LTO support is tracked by
216 // https://github.com/ziglang/zig/issues/8680
217 if (options.lto == true) return error.LtoRequiresLld;
218 break :b false;
219 }
220
221 if (options.lto) |x| break :b x;
222 if (options.c_source_files_len == 0) break :b false;
223
224 if (target.cpu.arch.isRISCV()) {
225 // Clang and LLVM currently don't support RISC-V target-abi for LTO.
226 // Compiling with LTO may fail or produce undesired results.
227 // See https://reviews.llvm.org/D71387
228 // See https://reviews.llvm.org/D102582
229 break :b false;
230 }
231
232 break :b switch (options.output_mode) {
233 .Lib, .Obj => false,
234 .Exe => switch (root_optimize_mode) {
235 .Debug => false,
236 .ReleaseSafe, .ReleaseFast, .ReleaseSmall => true,
237 },
238 };
239 };
240
241 const link_libcpp = b: {
242 if (options.link_libcpp == true) break :b true;
243 if (options.any_sanitize_thread) {
244 // TSAN is (for now...) implemented in C++ so it requires linking libc++.
245 if (options.link_libcpp == false) return error.SanitizeThreadRequiresLibCpp;
246 break :b true;
247 }
248 if (options.ensure_libcpp_on_non_freestanding and target.os.tag != .freestanding)
249 break :b true;
250
251 break :b false;
252 };
253
254 const link_libunwind = b: {
255 if (link_libcpp and target_util.libcNeedsLibUnwind(target)) {
256 if (options.link_libunwind == false) return error.LibCppRequiresLibUnwind;
257 break :b true;
258 }
259 break :b options.link_libunwind orelse false;
260 };
261
262 const link_libc = b: {
263 if (target_util.osRequiresLibC(target)) {
264 if (options.link_libc == false) return error.OsRequiresLibC;
265 break :b true;
266 }
267 if (link_libcpp) {
268 if (options.link_libc == false) return error.LibCppRequiresLibC;
269 break :b true;
270 }
271 if (link_libunwind) {
272 if (options.link_libc == false) return error.LibUnwindRequiresLibC;
273 break :b true;
274 }
275 if (options.link_libc) |x| break :b x;
276 if (options.ensure_libc_on_non_freestanding and target.os.tag != .freestanding)
277 break :b true;
278
279 break :b false;
280 };
281
282 const any_unwind_tables = options.any_unwind_tables or
283 link_libunwind or target_util.needUnwindTables(target);
284
285 const link_mode = b: {
286 const explicitly_exe_or_dyn_lib = switch (options.output_mode) {
287 .Obj => false,
288 .Lib => (options.link_mode orelse .Static) == .Dynamic,
289 .Exe => true,
290 };
291
292 if (target_util.cannotDynamicLink(target)) {
293 if (options.link_mode == .Dynamic) return error.TargetCannotDynamicLink;
294 break :b .Static;
295 }
296 if (explicitly_exe_or_dyn_lib and link_libc and
297 (target.isGnuLibC() or target_util.osRequiresLibC(target)))
298 {
299 if (options.link_mode == .Static) return error.LibCRequiresDynamicLinking;
300 break :b .Dynamic;
301 }
302 // When creating a executable that links to system libraries, we
303 // require dynamic linking, but we must not link static libraries
304 // or object files dynamically!
305 if (options.any_dyn_libs and options.output_mode == .Exe) {
306 if (options.link_mode == .Static) return error.SharedLibrariesRequireDynamicLinking;
307 break :b .Dynamic;
308 }
309
310 if (options.link_mode) |link_mode| break :b link_mode;
311
312 if (explicitly_exe_or_dyn_lib and link_libc and
313 options.resolved_target.is_native_abi and target.abi.isMusl())
314 {
315 // If targeting the system's native ABI and the system's libc is
316 // musl, link dynamically by default.
317 break :b .Dynamic;
318 }
319
320 // Static is generally a better default. Fight me.
321 break :b .Static;
322 };
323
324 const import_memory = options.import_memory orelse false;
325 const export_memory = b: {
326 if (link_mode == .Dynamic) {
327 if (options.export_memory == true) return error.ExportMemoryAndDynamicIncompatible;
328 break :b false;
329 }
330 if (options.export_memory) |x| break :b x;
331 break :b !import_memory;
332 };
333
334 const pie: bool = b: {
335 switch (options.output_mode) {
336 .Obj, .Exe => {},
337 .Lib => if (link_mode == .Dynamic) {
338 if (options.pie == true) return error.DynamicLibraryPrecludesPie;
339 break :b false;
340 },
341 }
342 if (target_util.requiresPIE(target)) {
343 if (options.pie == false) return error.TargetRequiresPie;
344 break :b true;
345 }
346 if (options.any_sanitize_thread) {
347 if (options.pie == false) return error.SanitizeThreadRequiresPie;
348 break :b true;
349 }
350 if (options.pie) |pie| break :b pie;
351 break :b false;
352 };
353
354 return .{
355 .output_mode = options.output_mode,
356 .have_zcu = options.have_zcu,
357 .is_test = options.is_test,
358 .test_evented_io = options.test_evented_io,
359 .link_mode = link_mode,
360 .link_libc = link_libc,
361 .link_libcpp = link_libcpp,
362 .link_libunwind = link_libunwind,
363 .any_unwind_tables = any_unwind_tables,
364 .pie = pie,
365 .lto = lto,
366 .import_memory = import_memory,
367 .export_memory = export_memory,
368 .shared_memory = shared_memory,
369 .c_frontend = c_frontend,
370 .use_llvm = use_llvm,
371 .use_lib_llvm = use_lib_llvm,
372 .use_lld = use_lld,
373 .entry = entry,
374 .wasi_exec_model = wasi_exec_model,
375 };
376}
377
378const std = @import("std");
379const Module = @import("../Package.zig").Module;
380const Config = @This();
381const target_util = @import("../target.zig");
382const build_options = @import("build_options");
src/Module.zig+3-5
...@@ -59,6 +59,7 @@ root_mod: *Package.Module,...@@ -59,6 +59,7 @@ root_mod: *Package.Module,
59/// Normally, `main_mod` and `root_mod` are the same. The exception is `zig test`, in which59/// Normally, `main_mod` and `root_mod` are the same. The exception is `zig test`, in which
60/// `root_mod` is the test runner, and `main_mod` is the user's source file which has the tests.60/// `root_mod` is the test runner, and `main_mod` is the user's source file which has the tests.
61main_mod: *Package.Module,61main_mod: *Package.Module,
62std_mod: *Package.Module,
62sema_prog_node: std.Progress.Node = undefined,63sema_prog_node: std.Progress.Node = undefined,
6364
64/// Used by AstGen worker to load and store ZIR cache.65/// Used by AstGen worker to load and store ZIR cache.
...@@ -3599,7 +3600,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -3599,7 +3600,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
35993600
3600 // TODO: figure out how this works under incremental changes to builtin.zig!3601 // TODO: figure out how this works under incremental changes to builtin.zig!
3601 const builtin_type_target_index: InternPool.Index = blk: {3602 const builtin_type_target_index: InternPool.Index = blk: {
3602 const std_mod = mod.main_mod.deps.get("std").?;3603 const std_mod = mod.std_mod;
3603 if (decl.getFileScope(mod).mod != std_mod) break :blk .none;3604 if (decl.getFileScope(mod).mod != std_mod) break :blk .none;
3604 // We're in the std module.3605 // We're in the std module.
3605 const std_file = (try mod.importPkg(std_mod)).file;3606 const std_file = (try mod.importPkg(std_mod)).file;
...@@ -3924,10 +3925,7 @@ pub fn importFile(...@@ -3924,10 +3925,7 @@ pub fn importFile(
3924 import_string: []const u8,3925 import_string: []const u8,
3925) !ImportFileResult {3926) !ImportFileResult {
3926 if (std.mem.eql(u8, import_string, "std")) {3927 if (std.mem.eql(u8, import_string, "std")) {
3927 return mod.importPkg(mod.main_mod.deps.get("std").?);3928 return mod.importPkg(mod.std_mod);
3928 }
3929 if (std.mem.eql(u8, import_string, "builtin")) {
3930 return mod.importPkg(mod.main_mod.deps.get("builtin").?);
3931 }3929 }
3932 if (std.mem.eql(u8, import_string, "root")) {3930 if (std.mem.eql(u8, import_string, "root")) {
3933 return mod.importPkg(mod.root_mod);3931 return mod.importPkg(mod.root_mod);
src/Package/Module.zig+403-6
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1//! Corresponds to something that Zig source code can `@import`.1//! Corresponds to something that Zig source code can `@import`.
2//! Not to be confused with src/Module.zig which should be renamed2//! Not to be confused with src/Module.zig which will be renamed
3//! to something else. https://github.com/ziglang/zig/issues/143073//! to Zcu. https://github.com/ziglang/zig/issues/14307
44
5/// Only files inside this directory can be imported.5/// Only files inside this directory can be imported.
6root: Package.Path,6root: Package.Path,
...@@ -14,6 +14,26 @@ fully_qualified_name: []const u8,...@@ -14,6 +14,26 @@ fully_qualified_name: []const u8,
14/// responsible for detecting these names and using the correct package.14/// responsible for detecting these names and using the correct package.
15deps: Deps = .{},15deps: Deps = .{},
1616
17resolved_target: ResolvedTarget,
18optimize_mode: std.builtin.OptimizeMode,
19code_model: std.builtin.CodeModel,
20single_threaded: bool,
21error_tracing: bool,
22valgrind: bool,
23pic: bool,
24strip: bool,
25omit_frame_pointer: bool,
26stack_check: bool,
27stack_protector: u32,
28red_zone: bool,
29sanitize_c: bool,
30sanitize_thread: bool,
31unwind_tables: bool,
32cc_argv: []const []const u8,
33
34/// The contents of `@import("builtin")` for this module.
35generated_builtin_source: []const u8,
36
17pub const Deps = std.StringArrayHashMapUnmanaged(*Module);37pub const Deps = std.StringArrayHashMapUnmanaged(*Module);
1838
19pub const Tree = struct {39pub const Tree = struct {
...@@ -21,10 +41,382 @@ pub const Tree = struct {...@@ -21,10 +41,382 @@ pub const Tree = struct {
21 build_module_table: std.AutoArrayHashMapUnmanaged(MultiHashHexDigest, *Module),41 build_module_table: std.AutoArrayHashMapUnmanaged(MultiHashHexDigest, *Module),
22};42};
2343
24pub fn create(allocator: Allocator, m: Module) Allocator.Error!*Module {44pub const CreateOptions = struct {
25 const new = try allocator.create(Module);45 /// Where to store builtin.zig. The global cache directory is used because
26 new.* = m;46 /// it is a pure function based on CLI flags.
27 return new;47 global_cache_directory: Cache.Directory,
48 paths: Paths,
49 fully_qualified_name: []const u8,
50
51 cc_argv: []const []const u8,
52 inherited: Inherited,
53 global: Compilation.Config,
54 /// If this is null then `resolved_target` must be non-null.
55 parent: ?*Package.Module,
56
57 builtin_mod: ?*Package.Module,
58
59 pub const Paths = struct {
60 root: Package.Path,
61 /// Relative to `root`. May contain path separators.
62 root_src_path: []const u8,
63 };
64
65 pub const Inherited = struct {
66 /// If this is null then `parent` must be non-null.
67 resolved_target: ?ResolvedTarget = null,
68 optimize_mode: ?std.builtin.OptimizeMode = null,
69 code_model: ?std.builtin.CodeModel = null,
70 single_threaded: ?bool = null,
71 error_tracing: ?bool = null,
72 valgrind: ?bool = null,
73 pic: ?bool = null,
74 strip: ?bool = null,
75 omit_frame_pointer: ?bool = null,
76 stack_check: ?bool = null,
77 /// null means default.
78 /// 0 means no stack protector.
79 /// other number means stack protection with that buffer size.
80 stack_protector: ?u32 = null,
81 red_zone: ?bool = null,
82 unwind_tables: ?bool = null,
83 sanitize_c: ?bool = null,
84 sanitize_thread: ?bool = null,
85 };
86};
87
88pub const ResolvedTarget = struct {
89 result: std.Target,
90 is_native_os: bool,
91 is_native_abi: bool,
92 llvm_cpu_features: ?[*:0]const u8 = null,
93};
94
95/// At least one of `parent` and `resolved_target` must be non-null.
96pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
97 const resolved_target = options.inherited.resolved_target orelse options.parent.?.resolved_target;
98 const target = resolved_target.result;
99
100 const optimize_mode = options.inherited.optimize_mode orelse
101 if (options.parent) |p| p.optimize_mode else .Debug;
102
103 const unwind_tables = options.inherited.unwind_tables orelse
104 if (options.parent) |p| p.unwind_tables else options.global.any_unwind_tables;
105
106 const strip = b: {
107 if (options.inherited.strip) |x| break :b x;
108 if (options.parent) |p| break :b p.strip;
109 if (optimize_mode == .ReleaseSmall) break :b true;
110 if (!target_util.hasDebugInfo(target)) break :b true;
111 break :b false;
112 };
113
114 const valgrind = b: {
115 if (!target_util.hasValgrindSupport(target)) {
116 if (options.inherited.valgrind == true)
117 return error.ValgrindUnsupportedOnTarget;
118 break :b false;
119 }
120 if (options.inherited.valgrind) |x| break :b x;
121 if (options.parent) |p| break :b p.valgrind;
122 if (strip) break :b false;
123 break :b optimize_mode == .Debug;
124 };
125
126 const zig_backend = target_util.zigBackend(target, options.global.use_llvm);
127
128 const single_threaded = b: {
129 if (target_util.alwaysSingleThreaded(target)) {
130 if (options.inherited.single_threaded == false)
131 return error.TargetRequiresSingleThreaded;
132 break :b true;
133 }
134
135 if (options.global.have_zcu) {
136 if (!target_util.supportsThreads(target, zig_backend)) {
137 if (options.inherited.single_threaded == false)
138 return error.BackendRequiresSingleThreaded;
139 break :b true;
140 }
141 }
142
143 if (options.inherited.single_threaded) |x| break :b x;
144 if (options.parent) |p| break :b p.single_threaded;
145 break :b target_util.defaultSingleThreaded(target);
146 };
147
148 const error_tracing = b: {
149 if (options.inherited.error_tracing) |x| break :b x;
150 if (options.parent) |p| break :b p.error_tracing;
151 if (strip) break :b false;
152 break :b switch (optimize_mode) {
153 .Debug => true,
154 .ReleaseSafe, .ReleaseFast, .ReleaseSmall => false,
155 };
156 };
157
158 const pic = b: {
159 if (target_util.requiresPIC(target, options.global.link_libc)) {
160 if (options.inherited.pic == false)
161 return error.TargetRequiresPic;
162 break :b true;
163 }
164 if (options.global.pie) {
165 if (options.inherited.pic == false)
166 return error.PieRequiresPic;
167 break :b true;
168 }
169 if (options.global.link_mode == .Dynamic) {
170 if (options.inherited.pic == false)
171 return error.DynamicLinkingRequiresPic;
172 break :b true;
173 }
174 if (options.inherited.pic) |x| break :b x;
175 if (options.parent) |p| break :b p.pic;
176 break :b false;
177 };
178
179 const red_zone = b: {
180 if (!target_util.hasRedZone(target)) {
181 if (options.inherited.red_zone == true)
182 return error.TargetHasNoRedZone;
183 break :b true;
184 }
185 if (options.inherited.red_zone) |x| break :b x;
186 if (options.parent) |p| break :b p.red_zone;
187 break :b true;
188 };
189
190 const omit_frame_pointer = b: {
191 if (options.inherited.omit_frame_pointer) |x| break :b x;
192 if (options.parent) |p| break :b p.omit_frame_pointer;
193 if (optimize_mode == .Debug) break :b false;
194 break :b true;
195 };
196
197 const sanitize_thread = b: {
198 if (options.inherited.sanitize_thread) |x| break :b x;
199 if (options.parent) |p| break :b p.sanitize_thread;
200 break :b false;
201 };
202
203 const code_model = b: {
204 if (options.inherited.code_model) |x| break :b x;
205 if (options.parent) |p| break :b p.code_model;
206 break :b .default;
207 };
208
209 const is_safe_mode = switch (optimize_mode) {
210 .Debug, .ReleaseSafe => true,
211 .ReleaseFast, .ReleaseSmall => false,
212 };
213
214 const sanitize_c = b: {
215 if (options.inherited.sanitize_c) |x| break :b x;
216 if (options.parent) |p| break :b p.sanitize_c;
217 break :b is_safe_mode;
218 };
219
220 const stack_check = b: {
221 if (!target_util.supportsStackProbing(target)) {
222 if (options.inherited.stack_check == true)
223 return error.StackCheckUnsupportedByTarget;
224 break :b false;
225 }
226 if (options.inherited.stack_check) |x| break :b x;
227 if (options.parent) |p| break :b p.stack_check;
228 break :b is_safe_mode;
229 };
230
231 const stack_protector: u32 = sp: {
232 if (!target_util.supportsStackProtector(target, zig_backend)) {
233 if (options.inherited.stack_protector) |x| {
234 if (x > 0) return error.StackProtectorUnsupportedByTarget;
235 }
236 break :sp 0;
237 }
238
239 // This logic is checking for linking libc because otherwise our start code
240 // which is trying to set up TLS (i.e. the fs/gs registers) but the stack
241 // protection code depends on fs/gs registers being already set up.
242 // If we were able to annotate start code, or perhaps the entire std lib,
243 // as being exempt from stack protection checks, we could change this logic
244 // to supporting stack protection even when not linking libc.
245 // TODO file issue about this
246 if (!options.global.link_libc) {
247 if (options.inherited.stack_protector) |x| {
248 if (x > 0) return error.StackProtectorUnavailableWithoutLibC;
249 }
250 break :sp 0;
251 }
252
253 if (options.inherited.stack_protector) |x| break :sp x;
254 if (options.parent) |p| break :sp p.stack_protector;
255 if (!is_safe_mode) break :sp 0;
256
257 break :sp target_util.default_stack_protector_buffer_size;
258 };
259
260 const llvm_cpu_features: ?[*:0]const u8 = b: {
261 if (resolved_target.llvm_cpu_features) |x| break :b x;
262 if (!options.global.use_llvm) break :b null;
263
264 var buf = std.ArrayList(u8).init(arena);
265 for (target.cpu.arch.allFeaturesList(), 0..) |feature, index_usize| {
266 const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));
267 const is_enabled = target.cpu.features.isEnabled(index);
268
269 if (feature.llvm_name) |llvm_name| {
270 const plus_or_minus = "-+"[@intFromBool(is_enabled)];
271 try buf.ensureUnusedCapacity(2 + llvm_name.len);
272 buf.appendAssumeCapacity(plus_or_minus);
273 buf.appendSliceAssumeCapacity(llvm_name);
274 buf.appendSliceAssumeCapacity(",");
275 }
276 }
277 if (buf.items.len == 0) break :b "";
278 assert(std.mem.endsWith(u8, buf.items, ","));
279 buf.items[buf.items.len - 1] = 0;
280 buf.shrinkAndFree(buf.items.len);
281 break :b buf.items[0 .. buf.items.len - 1 :0].ptr;
282 };
283
284 const builtin_mod = options.builtin_mod orelse b: {
285 const generated_builtin_source = try Builtin.generate(.{
286 .target = target,
287 .zig_backend = zig_backend,
288 .output_mode = options.global.output_mode,
289 .link_mode = options.global.link_mode,
290 .is_test = options.global.is_test,
291 .test_evented_io = options.global.test_evented_io,
292 .single_threaded = single_threaded,
293 .link_libc = options.global.link_libc,
294 .link_libcpp = options.global.link_libcpp,
295 .optimize_mode = optimize_mode,
296 .error_tracing = error_tracing,
297 .valgrind = valgrind,
298 .sanitize_thread = sanitize_thread,
299 .pic = pic,
300 .pie = options.global.pie,
301 .strip = strip,
302 .code_model = code_model,
303 .omit_frame_pointer = omit_frame_pointer,
304 .wasi_exec_model = options.global.wasi_exec_model,
305 }, arena);
306
307 const digest = Cache.HashHelper.oneShot(generated_builtin_source);
308 const builtin_sub_path = try arena.dupe(u8, "b" ++ std.fs.path.sep_str ++ digest);
309 const new = try arena.create(Module);
310 new.* = .{
311 .root = .{
312 .root_dir = options.global_cache_directory,
313 .sub_path = builtin_sub_path,
314 },
315 .root_src_path = "builtin.zig",
316 .fully_qualified_name = if (options.parent == null)
317 "builtin"
318 else
319 try std.fmt.allocPrint(arena, "{s}.builtin", .{options.fully_qualified_name}),
320 .resolved_target = .{
321 .result = target,
322 .is_native_os = resolved_target.is_native_os,
323 .is_native_abi = resolved_target.is_native_abi,
324 .llvm_cpu_features = llvm_cpu_features,
325 },
326 .optimize_mode = optimize_mode,
327 .single_threaded = single_threaded,
328 .error_tracing = error_tracing,
329 .valgrind = valgrind,
330 .pic = pic,
331 .strip = strip,
332 .omit_frame_pointer = omit_frame_pointer,
333 .stack_check = stack_check,
334 .stack_protector = stack_protector,
335 .code_model = code_model,
336 .red_zone = red_zone,
337 .generated_builtin_source = generated_builtin_source,
338 .sanitize_c = sanitize_c,
339 .sanitize_thread = sanitize_thread,
340 .unwind_tables = unwind_tables,
341 .cc_argv = &.{},
342 };
343 break :b new;
344 };
345
346 const mod = try arena.create(Module);
347 mod.* = .{
348 .root = options.paths.root,
349 .root_src_path = options.paths.root_src_path,
350 .fully_qualified_name = options.fully_qualified_name,
351 .resolved_target = .{
352 .result = target,
353 .is_native_os = resolved_target.is_native_os,
354 .is_native_abi = resolved_target.is_native_abi,
355 .llvm_cpu_features = llvm_cpu_features,
356 },
357 .optimize_mode = optimize_mode,
358 .single_threaded = single_threaded,
359 .error_tracing = error_tracing,
360 .valgrind = valgrind,
361 .pic = pic,
362 .strip = strip,
363 .omit_frame_pointer = omit_frame_pointer,
364 .stack_check = stack_check,
365 .stack_protector = stack_protector,
366 .code_model = code_model,
367 .red_zone = red_zone,
368 .generated_builtin_source = builtin_mod.generated_builtin_source,
369 .sanitize_c = sanitize_c,
370 .sanitize_thread = sanitize_thread,
371 .unwind_tables = unwind_tables,
372 .cc_argv = options.cc_argv,
373 };
374
375 try mod.deps.ensureUnusedCapacity(arena, 1);
376 mod.deps.putAssumeCapacityNoClobber("builtin", builtin_mod);
377
378 return mod;
379}
380
381/// All fields correspond to `CreateOptions`.
382pub const LimitedOptions = struct {
383 root: Package.Path,
384 root_src_path: []const u8,
385 fully_qualified_name: []const u8,
386};
387
388/// This one can only be used if the Module will only be used for AstGen and earlier in
389/// the pipeline. Illegal behavior occurs if a limited module touches Sema.
390pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*Package.Module {
391 const mod = try gpa.create(Module);
392 mod.* = .{
393 .root = options.root,
394 .root_src_path = options.root_src_path,
395 .fully_qualified_name = options.fully_qualified_name,
396
397 .resolved_target = undefined,
398 .optimize_mode = undefined,
399 .code_model = undefined,
400 .single_threaded = undefined,
401 .error_tracing = undefined,
402 .valgrind = undefined,
403 .pic = undefined,
404 .strip = undefined,
405 .omit_frame_pointer = undefined,
406 .stack_check = undefined,
407 .stack_protector = undefined,
408 .red_zone = undefined,
409 .sanitize_c = undefined,
410 .sanitize_thread = undefined,
411 .unwind_tables = undefined,
412 .cc_argv = undefined,
413 .generated_builtin_source = undefined,
414 };
415 return mod;
416}
417
418pub fn getBuiltinDependency(m: *Module) *Module {
419 return m.deps.values()[0];
28}420}
29421
30const Module = @This();422const Module = @This();
...@@ -32,3 +424,8 @@ const Package = @import("../Package.zig");...@@ -32,3 +424,8 @@ const Package = @import("../Package.zig");
32const std = @import("std");424const std = @import("std");
33const Allocator = std.mem.Allocator;425const Allocator = std.mem.Allocator;
34const MultiHashHexDigest = Package.Manifest.MultiHashHexDigest;426const MultiHashHexDigest = Package.Manifest.MultiHashHexDigest;
427const target_util = @import("../target.zig");
428const Cache = std.Build.Cache;
429const Builtin = @import("../Builtin.zig");
430const assert = std.debug.assert;
431const Compilation = @import("../Compilation.zig");
src/Sema.zig+1-1
...@@ -36668,7 +36668,7 @@ fn getBuiltinDecl(sema: *Sema, block: *Block, name: []const u8) CompileError!Int...@@ -36668,7 +36668,7 @@ fn getBuiltinDecl(sema: *Sema, block: *Block, name: []const u8) CompileError!Int
3666836668
36669 const mod = sema.mod;36669 const mod = sema.mod;
36670 const ip = &mod.intern_pool;36670 const ip = &mod.intern_pool;
36671 const std_mod = mod.main_mod.deps.get("std").?;36671 const std_mod = mod.std_mod;
36672 const std_file = (mod.importPkg(std_mod) catch unreachable).file;36672 const std_file = (mod.importPkg(std_mod) catch unreachable).file;
36673 const opt_builtin_inst = (try sema.namespaceLookupRef(36673 const opt_builtin_inst = (try sema.namespaceLookupRef(
36674 block,36674 block,
src/codegen/llvm.zig+12-26
...@@ -853,16 +853,9 @@ pub const Object = struct {...@@ -853,16 +853,9 @@ pub const Object = struct {
853 /// want to iterate over it while adding entries to it.853 /// want to iterate over it while adding entries to it.
854 pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr);854 pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr);
855855
856 pub fn create(gpa: Allocator, options: link.Options) !*Object {856 pub fn create(arena: Allocator, options: link.File.OpenOptions) !*Object {
857 const obj = try gpa.create(Object);857 const gpa = options.comp.gpa;
858 errdefer gpa.destroy(obj);858 const llvm_target_triple = try targetTriple(arena, options.target);
859 obj.* = try Object.init(gpa, options);
860 return obj;
861 }
862
863 pub fn init(gpa: Allocator, options: link.Options) !Object {
864 const llvm_target_triple = try targetTriple(gpa, options.target);
865 defer gpa.free(llvm_target_triple);
866859
867 var builder = try Builder.init(.{860 var builder = try Builder.init(.{
868 .allocator = gpa,861 .allocator = gpa,
...@@ -899,19 +892,14 @@ pub const Object = struct {...@@ -899,19 +892,14 @@ pub const Object = struct {
899 // TODO: the only concern I have with this is WASI as either host or target, should892 // TODO: the only concern I have with this is WASI as either host or target, should
900 // we leave the paths as relative then?893 // we leave the paths as relative then?
901 const compile_unit_dir_z = blk: {894 const compile_unit_dir_z = blk: {
902 var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
903 if (options.module) |mod| m: {895 if (options.module) |mod| m: {
904 const d = try mod.root_mod.root.joinStringZ(builder.gpa, "");896 const d = try mod.root_mod.root.joinStringZ(arena, "");
905 if (d.len == 0) break :m;897 if (d.len == 0) break :m;
906 if (std.fs.path.isAbsolute(d)) break :blk d;898 if (std.fs.path.isAbsolute(d)) break :blk d;
907 const abs = std.fs.realpath(d, &buf) catch break :blk d;899 break :blk std.fs.realpathAlloc(arena, d) catch d;
908 builder.gpa.free(d);
909 break :blk try builder.gpa.dupeZ(u8, abs);
910 }900 }
911 const cwd = try std.process.getCwd(&buf);901 break :blk try std.process.getCwdAlloc(arena);
912 break :blk try builder.gpa.dupeZ(u8, cwd);
913 };902 };
914 defer builder.gpa.free(compile_unit_dir_z);
915903
916 builder.llvm.di_compile_unit = builder.llvm.di_builder.?.createCompileUnit(904 builder.llvm.di_compile_unit = builder.llvm.di_builder.?.createCompileUnit(
917 DW.LANG.C99,905 DW.LANG.C99,
...@@ -989,7 +977,8 @@ pub const Object = struct {...@@ -989,7 +977,8 @@ pub const Object = struct {
989 }977 }
990 }978 }
991979
992 return .{980 const obj = try arena.create(Object);
981 obj.* = .{
993 .gpa = gpa,982 .gpa = gpa,
994 .builder = builder,983 .builder = builder,
995 .module = options.module.?,984 .module = options.module.?,
...@@ -1009,9 +998,11 @@ pub const Object = struct {...@@ -1009,9 +998,11 @@ pub const Object = struct {
1009 .null_opt_usize = .no_init,998 .null_opt_usize = .no_init,
1010 .struct_field_map = .{},999 .struct_field_map = .{},
1011 };1000 };
1001 return obj;
1012 }1002 }
10131003
1014 pub fn deinit(self: *Object, gpa: Allocator) void {1004 pub fn deinit(self: *Object) void {
1005 const gpa = self.gpa;
1015 self.di_map.deinit(gpa);1006 self.di_map.deinit(gpa);
1016 self.di_type_map.deinit(gpa);1007 self.di_type_map.deinit(gpa);
1017 if (self.builder.useLibLlvm()) {1008 if (self.builder.useLibLlvm()) {
...@@ -1028,11 +1019,6 @@ pub const Object = struct {...@@ -1028,11 +1019,6 @@ pub const Object = struct {
1028 self.* = undefined;1019 self.* = undefined;
1029 }1020 }
10301021
1031 pub fn destroy(self: *Object, gpa: Allocator) void {
1032 self.deinit(gpa);
1033 gpa.destroy(self);
1034 }
1035
1036 fn locPath(1022 fn locPath(
1037 arena: Allocator,1023 arena: Allocator,
1038 opt_loc: ?Compilation.EmitLoc,1024 opt_loc: ?Compilation.EmitLoc,
...@@ -2899,7 +2885,7 @@ pub const Object = struct {...@@ -2899,7 +2885,7 @@ pub const Object = struct {
2899 fn getStackTraceType(o: *Object) Allocator.Error!Type {2885 fn getStackTraceType(o: *Object) Allocator.Error!Type {
2900 const mod = o.module;2886 const mod = o.module;
29012887
2902 const std_mod = mod.main_mod.deps.get("std").?;2888 const std_mod = mod.std_mod;
2903 const std_file = (mod.importPkg(std_mod) catch unreachable).file;2889 const std_file = (mod.importPkg(std_mod) catch unreachable).file;
29042890
2905 const builtin_str = try mod.intern_pool.getOrPutString(mod.gpa, "builtin");2891 const builtin_str = try mod.intern_pool.getOrPutString(mod.gpa, "builtin");
src/link.zig+182-343
...@@ -66,237 +66,18 @@ pub fn hashAddFrameworks(man: *Cache.Manifest, hm: []const Framework) !void {...@@ -66,237 +66,18 @@ pub fn hashAddFrameworks(man: *Cache.Manifest, hm: []const Framework) !void {
6666
67pub const producer_string = if (builtin.is_test) "zig test" else "zig " ++ build_options.version;67pub const producer_string = if (builtin.is_test) "zig test" else "zig " ++ build_options.version;
6868
69pub const Emit = struct {
70 /// Where the output will go.
71 directory: Compilation.Directory,
72 /// Path to the output file, relative to `directory`.
73 sub_path: []const u8,
74
75 /// Returns the full path to `basename` if it were in the same directory as the
76 /// `Emit` sub_path.
77 pub fn basenamePath(emit: Emit, arena: Allocator, basename: [:0]const u8) ![:0]const u8 {
78 const full_path = if (emit.directory.path) |p|
79 try fs.path.join(arena, &[_][]const u8{ p, emit.sub_path })
80 else
81 emit.sub_path;
82
83 if (fs.path.dirname(full_path)) |dirname| {
84 return try fs.path.joinZ(arena, &.{ dirname, basename });
85 } else {
86 return basename;
87 }
88 }
89};
90
91pub const Options = struct {
92 /// This is `null` when `-fno-emit-bin` is used.
93 emit: ?Emit,
94 /// This is `null` when not building a Windows DLL, or when `-fno-emit-implib` is used.
95 implib_emit: ?Emit,
96 /// This is non-null when `-femit-docs` is provided.
97 docs_emit: ?Emit,
98 target: std.Target,
99 output_mode: std.builtin.OutputMode,
100 link_mode: std.builtin.LinkMode,
101 optimize_mode: std.builtin.OptimizeMode,
102 machine_code_model: std.builtin.CodeModel,
103 root_name: [:0]const u8,
104 /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.
105 module: ?*Module,
106 /// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin)
107 sysroot: ?[]const u8,
108 /// Used for calculating how much space to reserve for symbols in case the binary file
109 /// does not already have a symbol table.
110 symbol_count_hint: u64 = 32,
111 /// Used for calculating how much space to reserve for executable program code in case
112 /// the binary file does not already have such a section.
113 program_code_size_hint: u64 = 256 * 1024,
114 entry_addr: ?u64 = null,
115 entry: ?[]const u8,
116 stack_size_override: ?u64,
117 image_base_override: ?u64,
118 /// 0 means no stack protector
119 /// other value means stack protector with that buffer size.
120 stack_protector: u32,
121 cache_mode: CacheMode,
122 include_compiler_rt: bool,
123 /// Set to `true` to omit debug info.
124 strip: bool,
125 /// If this is true then this link code is responsible for outputting an object
126 /// file and then using LLD to link it together with the link options and other objects.
127 /// Otherwise (depending on `use_llvm`) this link code directly outputs and updates the final binary.
128 use_lld: bool,
129 /// If this is true then this link code is responsible for making an LLVM IR Module,
130 /// outputting it to an object file, and then linking that together with link options and
131 /// other objects.
132 /// Otherwise (depending on `use_lld`) this link code directly outputs and updates the final binary.
133 use_llvm: bool,
134 use_lib_llvm: bool,
135 link_libc: bool,
136 link_libcpp: bool,
137 link_libunwind: bool,
138 darwin_sdk_layout: ?DarwinSdkLayout,
139 function_sections: bool,
140 data_sections: bool,
141 no_builtin: bool,
142 eh_frame_hdr: bool,
143 emit_relocs: bool,
144 rdynamic: bool,
145 z_nodelete: bool,
146 z_notext: bool,
147 z_defs: bool,
148 z_origin: bool,
149 z_nocopyreloc: bool,
150 z_now: bool,
151 z_relro: bool,
152 z_common_page_size: ?u64,
153 z_max_page_size: ?u64,
154 tsaware: bool,
155 nxcompat: bool,
156 dynamicbase: bool,
157 linker_optimization: u8,
158 compress_debug_sections: CompressDebugSections,
159 bind_global_refs_locally: bool,
160 import_memory: bool,
161 export_memory: bool,
162 import_symbols: bool,
163 import_table: bool,
164 export_table: bool,
165 initial_memory: ?u64,
166 max_memory: ?u64,
167 shared_memory: bool,
168 export_symbol_names: []const []const u8,
169 global_base: ?u64,
170 is_native_os: bool,
171 is_native_abi: bool,
172 pic: bool,
173 pie: bool,
174 lto: bool,
175 valgrind: bool,
176 tsan: bool,
177 stack_check: bool,
178 red_zone: bool,
179 omit_frame_pointer: bool,
180 single_threaded: bool,
181 verbose_link: bool,
182 dll_export_fns: bool,
183 error_return_tracing: bool,
184 skip_linker_dependencies: bool,
185 each_lib_rpath: bool,
186 build_id: std.zig.BuildId,
187 disable_lld_caching: bool,
188 is_test: bool,
189 hash_style: HashStyle,
190 sort_section: ?SortSection,
191 major_subsystem_version: ?u32,
192 minor_subsystem_version: ?u32,
193 gc_sections: ?bool = null,
194 allow_shlib_undefined: ?bool,
195 subsystem: ?std.Target.SubSystem,
196 linker_script: ?[]const u8,
197 version_script: ?[]const u8,
198 soname: ?[]const u8,
199 llvm_cpu_features: ?[*:0]const u8,
200 print_gc_sections: bool,
201 print_icf_sections: bool,
202 print_map: bool,
203 opt_bisect_limit: i32,
204
205 objects: []Compilation.LinkObject,
206 framework_dirs: []const []const u8,
207 frameworks: []const Framework,
208 /// These are *always* dynamically linked. Static libraries will be
209 /// provided as positional arguments.
210 system_libs: std.StringArrayHashMapUnmanaged(SystemLib),
211 wasi_emulated_libs: []const wasi_libc.CRTFile,
212 // TODO: remove this. libraries are resolved by the frontend.
213 lib_dirs: []const []const u8,
214 rpath_list: []const []const u8,
215
216 /// List of symbols forced as undefined in the symbol table
217 /// thus forcing their resolution by the linker.
218 /// Corresponds to `-u <symbol>` for ELF/MachO and `/include:<symbol>` for COFF/PE.
219 force_undefined_symbols: std.StringArrayHashMapUnmanaged(void),
220 /// Use a wrapper function for symbol. Any undefined reference to symbol
221 /// will be resolved to __wrap_symbol. Any undefined reference to
222 /// __real_symbol will be resolved to symbol. This can be used to provide a
223 /// wrapper for a system function. The wrapper function should be called
224 /// __wrap_symbol. If it wishes to call the system function, it should call
225 /// __real_symbol.
226 symbol_wrap_set: std.StringArrayHashMapUnmanaged(void),
227
228 version: ?std.SemanticVersion,
229 compatibility_version: ?std.SemanticVersion,
230 libc_installation: ?*const LibCInstallation,
231
232 dwarf_format: ?std.dwarf.Format,
233
234 /// WASI-only. Type of WASI execution model ("command" or "reactor").
235 wasi_exec_model: std.builtin.WasiExecModel = undefined,
236
237 /// (Zig compiler development) Enable dumping of linker's state as JSON.
238 enable_link_snapshots: bool = false,
239
240 /// (Darwin) Install name for the dylib
241 install_name: ?[]const u8 = null,
242
243 /// (Darwin) Path to entitlements file
244 entitlements: ?[]const u8 = null,
245
246 /// (Darwin) size of the __PAGEZERO segment
247 pagezero_size: ?u64 = null,
248
249 /// (Darwin) set minimum space for future expansion of the load commands
250 headerpad_size: ?u32 = null,
251
252 /// (Darwin) set enough space as if all paths were MATPATHLEN
253 headerpad_max_install_names: bool = false,
254
255 /// (Darwin) remove dylibs that are unreachable by the entry point or exported symbols
256 dead_strip_dylibs: bool = false,
257
258 /// (Windows) PDB source path prefix to instruct the linker how to resolve relative
259 /// paths when consolidating CodeView streams into a single PDB file.
260 pdb_source_path: ?[]const u8 = null,
261
262 /// (Windows) PDB output path
263 pdb_out_path: ?[]const u8 = null,
264
265 /// (Windows) .def file to specify when linking
266 module_definition_file: ?[]const u8 = null,
267
268 /// (SPIR-V) whether to generate a structured control flow graph or not
269 want_structured_cfg: ?bool = null,
270
271 pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {
272 return if (options.use_lld) .Obj else options.output_mode;
273 }
274
275 pub fn move(self: *Options) Options {
276 const copied_state = self.*;
277 self.system_libs = .{};
278 self.force_undefined_symbols = .{};
279 return copied_state;
280 }
281};
282
283pub const HashStyle = enum { sysv, gnu, both };69pub const HashStyle = enum { sysv, gnu, both };
28470
285pub const CompressDebugSections = enum { none, zlib, zstd };71pub const CompressDebugSections = enum { none, zlib, zstd };
28672
287/// The filesystem layout of darwin SDK elements.
288pub const DarwinSdkLayout = enum {
289 /// macOS SDK layout: TOP { /usr/include, /usr/lib, /System/Library/Frameworks }.
290 sdk,
291 /// Shipped libc layout: TOP { /lib/libc/include, /lib/libc/darwin, <NONE> }.
292 vendored,
293};
294
295pub const File = struct {73pub const File = struct {
296 tag: Tag,74 tag: Tag,
297 options: Options,75
76 /// The owner of this output File.
77 comp: *Compilation,
78 emit: Compilation.Emit,
79
298 file: ?fs.File,80 file: ?fs.File,
299 allocator: Allocator,
300 /// When linking with LLD, this linker code will output an object file only at81 /// When linking with LLD, this linker code will output an object file only at
301 /// this location, and then this path can be placed on the LLD linker line.82 /// this location, and then this path can be placed on the LLD linker line.
302 intermediary_basename: ?[]const u8 = null,83 intermediary_basename: ?[]const u8 = null,
...@@ -307,103 +88,132 @@ pub const File = struct {...@@ -307,103 +88,132 @@ pub const File = struct {
30788
308 child_pid: ?std.ChildProcess.Id = null,89 child_pid: ?std.ChildProcess.Id = null,
30990
91 pub const OpenOptions = struct {
92 comp: *Compilation,
93 emit: Compilation.Emit,
94
95 symbol_count_hint: u64 = 32,
96 program_code_size_hint: u64 = 256 * 1024,
97
98 /// Virtual address of the entry point procedure relative to image base.
99 entry_addr: ?u64,
100 stack_size_override: ?u64,
101 image_base_override: ?u64,
102 function_sections: bool,
103 data_sections: bool,
104 no_builtin: bool,
105 eh_frame_hdr: bool,
106 emit_relocs: bool,
107 rdynamic: bool,
108 optimization: u8,
109 linker_script: ?[]const u8,
110 z_nodelete: bool,
111 z_notext: bool,
112 z_defs: bool,
113 z_origin: bool,
114 z_nocopyreloc: bool,
115 z_now: bool,
116 z_relro: bool,
117 z_common_page_size: ?u64,
118 z_max_page_size: ?u64,
119 tsaware: bool,
120 nxcompat: bool,
121 dynamicbase: bool,
122 compress_debug_sections: CompressDebugSections,
123 bind_global_refs_locally: bool,
124 import_symbols: bool,
125 import_table: bool,
126 export_table: bool,
127 initial_memory: ?u64,
128 max_memory: ?u64,
129 export_symbol_names: []const []const u8,
130 global_base: ?u64,
131 verbose_link: bool,
132 dll_export_fns: bool,
133 skip_linker_dependencies: bool,
134 parent_compilation_link_libc: bool,
135 each_lib_rpath: bool,
136 build_id: std.zig.BuildId,
137 disable_lld_caching: bool,
138 hash_style: HashStyle,
139 sort_section: ?SortSection,
140 major_subsystem_version: ?u32,
141 minor_subsystem_version: ?u32,
142 gc_sections: ?bool = null,
143 allow_shlib_undefined: ?bool,
144 subsystem: ?std.Target.SubSystem,
145 version_script: ?[]const u8,
146 soname: ?[]const u8,
147 print_gc_sections: bool,
148 print_icf_sections: bool,
149 print_map: bool,
150 opt_bisect_limit: i32,
151
152 /// List of symbols forced as undefined in the symbol table
153 /// thus forcing their resolution by the linker.
154 /// Corresponds to `-u <symbol>` for ELF/MachO and `/include:<symbol>` for COFF/PE.
155 force_undefined_symbols: std.StringArrayHashMapUnmanaged(void),
156 /// Use a wrapper function for symbol. Any undefined reference to symbol
157 /// will be resolved to __wrap_symbol. Any undefined reference to
158 /// __real_symbol will be resolved to symbol. This can be used to provide a
159 /// wrapper for a system function. The wrapper function should be called
160 /// __wrap_symbol. If it wishes to call the system function, it should call
161 /// __real_symbol.
162 symbol_wrap_set: std.StringArrayHashMapUnmanaged(void),
163
164 compatibility_version: ?std.SemanticVersion,
165
166 dwarf_format: ?std.dwarf.Format,
167
168 // TODO: remove this. libraries are resolved by the frontend.
169 lib_dirs: []const []const u8,
170 rpath_list: []const []const u8,
171
172 /// (Zig compiler development) Enable dumping of linker's state as JSON.
173 enable_link_snapshots: bool,
174
175 /// (Darwin) Install name for the dylib
176 install_name: ?[]const u8,
177 /// (Darwin) Path to entitlements file
178 entitlements: ?[]const u8,
179 /// (Darwin) size of the __PAGEZERO segment
180 pagezero_size: ?u64,
181 /// (Darwin) set minimum space for future expansion of the load commands
182 headerpad_size: ?u32,
183 /// (Darwin) set enough space as if all paths were MATPATHLEN
184 headerpad_max_install_names: bool,
185 /// (Darwin) remove dylibs that are unreachable by the entry point or exported symbols
186 dead_strip_dylibs: bool,
187 framework_dirs: []const []const u8,
188 frameworks: []const Framework,
189 darwin_sdk_layout: ?MachO.SdkLayout,
190
191 /// (Windows) PDB source path prefix to instruct the linker how to resolve relative
192 /// paths when consolidating CodeView streams into a single PDB file.
193 pdb_source_path: ?[]const u8,
194 /// (Windows) PDB output path
195 pdb_out_path: ?[]const u8,
196 /// (Windows) .def file to specify when linking
197 module_definition_file: ?[]const u8,
198
199 /// (SPIR-V) whether to generate a structured control flow graph or not
200 want_structured_cfg: ?bool,
201
202 wasi_emulated_libs: []const wasi_libc.CRTFile,
203 };
204
310 /// Attempts incremental linking, if the file already exists. If205 /// Attempts incremental linking, if the file already exists. If
311 /// incremental linking fails, falls back to truncating the file and206 /// incremental linking fails, falls back to truncating the file and
312 /// rewriting it. A malicious file is detected as incremental link failure207 /// rewriting it. A malicious file is detected as incremental link failure
313 /// and does not cause Illegal Behavior. This operation is not atomic.208 /// and does not cause Illegal Behavior. This operation is not atomic.
314 pub fn openPath(allocator: Allocator, options: Options) !*File {209 /// `arena` is used for allocations with the same lifetime as the created File.
315 const have_macho = !build_options.only_c;210 pub fn open(arena: Allocator, options: OpenOptions) !*File {
316 if (have_macho and options.target.ofmt == .macho) {211 switch (Tag.fromObjectFormat(options.comp.root_mod.resolved_target.result.ofmt)) {
317 return &(try MachO.openPath(allocator, options)).base;212 inline else => |tag| {
318 }213 const ptr = try tag.Type().open(arena, options);
319214 return &ptr.base;
320 if (options.emit == null) {215 },
321 return switch (options.target.ofmt) {
322 .coff => &(try Coff.createEmpty(allocator, options)).base,
323 .elf => &(try Elf.createEmpty(allocator, options)).base,
324 .macho => unreachable,
325 .wasm => &(try Wasm.createEmpty(allocator, options)).base,
326 .plan9 => return &(try Plan9.createEmpty(allocator, options)).base,
327 .c => unreachable, // Reported error earlier.
328 .spirv => &(try SpirV.createEmpty(allocator, options)).base,
329 .nvptx => &(try NvPtx.createEmpty(allocator, options)).base,
330 .hex => return error.HexObjectFormatUnimplemented,
331 .raw => return error.RawObjectFormatUnimplemented,
332 .dxcontainer => return error.DirectXContainerObjectFormatUnimplemented,
333 };
334 }
335 const emit = options.emit.?;
336 const use_lld = build_options.have_llvm and options.use_lld; // comptime-known false when !have_llvm
337 const sub_path = if (use_lld) blk: {
338 if (options.module == null) {
339 // No point in opening a file, we would not write anything to it.
340 // Initialize with empty.
341 return switch (options.target.ofmt) {
342 .coff => &(try Coff.createEmpty(allocator, options)).base,
343 .elf => &(try Elf.createEmpty(allocator, options)).base,
344 .macho => unreachable,
345 .plan9 => &(try Plan9.createEmpty(allocator, options)).base,
346 .wasm => &(try Wasm.createEmpty(allocator, options)).base,
347 .c => unreachable, // Reported error earlier.
348 .spirv => &(try SpirV.createEmpty(allocator, options)).base,
349 .nvptx => &(try NvPtx.createEmpty(allocator, options)).base,
350 .hex => return error.HexObjectFormatUnimplemented,
351 .raw => return error.RawObjectFormatUnimplemented,
352 .dxcontainer => return error.DirectXContainerObjectFormatUnimplemented,
353 };
354 }
355 // Open a temporary object file, not the final output file because we
356 // want to link with LLD.
357 break :blk try std.fmt.allocPrint(allocator, "{s}{s}", .{
358 emit.sub_path, options.target.ofmt.fileExt(options.target.cpu.arch),
359 });
360 } else emit.sub_path;
361 errdefer if (use_lld) allocator.free(sub_path);
362
363 const file: *File = f: {
364 switch (options.target.ofmt) {
365 .coff => {
366 if (build_options.only_c) unreachable;
367 break :f &(try Coff.openPath(allocator, sub_path, options)).base;
368 },
369 .elf => {
370 if (build_options.only_c) unreachable;
371 break :f &(try Elf.openPath(allocator, sub_path, options)).base;
372 },
373 .macho => unreachable,
374 .plan9 => {
375 if (build_options.only_c) unreachable;
376 break :f &(try Plan9.openPath(allocator, sub_path, options)).base;
377 },
378 .wasm => {
379 if (build_options.only_c) unreachable;
380 break :f &(try Wasm.openPath(allocator, sub_path, options)).base;
381 },
382 .c => {
383 break :f &(try C.openPath(allocator, sub_path, options)).base;
384 },
385 .spirv => {
386 if (build_options.only_c) unreachable;
387 break :f &(try SpirV.openPath(allocator, sub_path, options)).base;
388 },
389 .nvptx => {
390 if (build_options.only_c) unreachable;
391 break :f &(try NvPtx.openPath(allocator, sub_path, options)).base;
392 },
393 .hex => return error.HexObjectFormatUnimplemented,
394 .raw => return error.RawObjectFormatUnimplemented,
395 .dxcontainer => return error.DirectXContainerObjectFormatUnimplemented,
396 }
397 };
398
399 if (use_lld) {
400 // TODO this intermediary_basename isn't enough; in the case of `zig build-exe`,
401 // we also want to put the intermediary object file in the cache while the
402 // main emit directory is the cwd.
403 file.intermediary_basename = sub_path;
404 }216 }
405
406 return file;
407 }217 }
408218
409 pub fn cast(base: *File, comptime T: type) ?*T {219 pub fn cast(base: *File, comptime T: type) ?*T {
...@@ -664,56 +474,45 @@ pub const File = struct {...@@ -664,56 +474,45 @@ pub const File = struct {
664 pub fn destroy(base: *File) void {474 pub fn destroy(base: *File) void {
665 base.releaseLock();475 base.releaseLock();
666 if (base.file) |f| f.close();476 if (base.file) |f| f.close();
667 if (base.intermediary_basename) |sub_path| base.allocator.free(sub_path);
668 base.options.system_libs.deinit(base.allocator);
669 base.options.force_undefined_symbols.deinit(base.allocator);
670 switch (base.tag) {477 switch (base.tag) {
671 .coff => {478 .coff => {
672 if (build_options.only_c) unreachable;479 if (build_options.only_c) unreachable;
673 const parent = @fieldParentPtr(Coff, "base", base);480 const parent = @fieldParentPtr(Coff, "base", base);
674 parent.deinit();481 parent.deinit();
675 base.allocator.destroy(parent);
676 },482 },
677 .elf => {483 .elf => {
678 if (build_options.only_c) unreachable;484 if (build_options.only_c) unreachable;
679 const parent = @fieldParentPtr(Elf, "base", base);485 const parent = @fieldParentPtr(Elf, "base", base);
680 parent.deinit();486 parent.deinit();
681 base.allocator.destroy(parent);
682 },487 },
683 .macho => {488 .macho => {
684 if (build_options.only_c) unreachable;489 if (build_options.only_c) unreachable;
685 const parent = @fieldParentPtr(MachO, "base", base);490 const parent = @fieldParentPtr(MachO, "base", base);
686 parent.deinit();491 parent.deinit();
687 base.allocator.destroy(parent);
688 },492 },
689 .c => {493 .c => {
690 const parent = @fieldParentPtr(C, "base", base);494 const parent = @fieldParentPtr(C, "base", base);
691 parent.deinit();495 parent.deinit();
692 base.allocator.destroy(parent);
693 },496 },
694 .wasm => {497 .wasm => {
695 if (build_options.only_c) unreachable;498 if (build_options.only_c) unreachable;
696 const parent = @fieldParentPtr(Wasm, "base", base);499 const parent = @fieldParentPtr(Wasm, "base", base);
697 parent.deinit();500 parent.deinit();
698 base.allocator.destroy(parent);
699 },501 },
700 .spirv => {502 .spirv => {
701 if (build_options.only_c) unreachable;503 if (build_options.only_c) unreachable;
702 const parent = @fieldParentPtr(SpirV, "base", base);504 const parent = @fieldParentPtr(SpirV, "base", base);
703 parent.deinit();505 parent.deinit();
704 base.allocator.destroy(parent);
705 },506 },
706 .plan9 => {507 .plan9 => {
707 if (build_options.only_c) unreachable;508 if (build_options.only_c) unreachable;
708 const parent = @fieldParentPtr(Plan9, "base", base);509 const parent = @fieldParentPtr(Plan9, "base", base);
709 parent.deinit();510 parent.deinit();
710 base.allocator.destroy(parent);
711 },511 },
712 .nvptx => {512 .nvptx => {
713 if (build_options.only_c) unreachable;513 if (build_options.only_c) unreachable;
714 const parent = @fieldParentPtr(NvPtx, "base", base);514 const parent = @fieldParentPtr(NvPtx, "base", base);
715 parent.deinit();515 parent.deinit();
716 base.allocator.destroy(parent);
717 },516 },
718 }517 }
719 }518 }
...@@ -1197,6 +996,35 @@ pub const File = struct {...@@ -1197,6 +996,35 @@ pub const File = struct {
1197 spirv,996 spirv,
1198 plan9,997 plan9,
1199 nvptx,998 nvptx,
999
1000 pub fn Type(comptime tag: Tag) type {
1001 return switch (tag) {
1002 .coff => Coff,
1003 .elf => Elf,
1004 .macho => MachO,
1005 .c => C,
1006 .wasm => Wasm,
1007 .spirv => SpirV,
1008 .plan9 => Plan9,
1009 .nvptx => NvPtx,
1010 };
1011 }
1012
1013 pub fn fromObjectFormat(ofmt: std.Target.ObjectFormat) Tag {
1014 return switch (ofmt) {
1015 .coff => .coff,
1016 .elf => .elf,
1017 .macho => .macho,
1018 .wasm => .wasm,
1019 .plan9 => .plan9,
1020 .c => .c,
1021 .spirv => .spirv,
1022 .nvptx => .nvptx,
1023 .hex => @panic("TODO implement hex object format"),
1024 .raw => @panic("TODO implement raw object format"),
1025 .dxcontainer => @panic("TODO implement dxcontainer object format"),
1026 };
1027 }
1200 };1028 };
12011029
1202 pub const ErrorFlags = struct {1030 pub const ErrorFlags = struct {
...@@ -1235,6 +1063,33 @@ pub const File = struct {...@@ -1235,6 +1063,33 @@ pub const File = struct {
1235 }1063 }
1236 };1064 };
12371065
1066 pub fn effectiveOutputMode(
1067 use_lld: bool,
1068 output_mode: std.builtin.OutputMode,
1069 ) std.builtin.OutputMode {
1070 return if (use_lld) .Obj else output_mode;
1071 }
1072
1073 pub fn determineMode(
1074 use_lld: bool,
1075 output_mode: std.builtin.OutputMode,
1076 link_mode: std.builtin.LinkMode,
1077 ) fs.File.Mode {
1078 // On common systems with a 0o022 umask, 0o777 will still result in a file created
1079 // with 0o755 permissions, but it works appropriately if the system is configured
1080 // more leniently. As another data point, C's fopen seems to open files with the
1081 // 666 mode.
1082 const executable_mode = if (builtin.target.os.tag == .windows) 0 else 0o777;
1083 switch (effectiveOutputMode(use_lld, output_mode)) {
1084 .Lib => return switch (link_mode) {
1085 .Dynamic => executable_mode,
1086 .Static => fs.File.default_mode,
1087 },
1088 .Exe => return executable_mode,
1089 .Obj => return fs.File.default_mode,
1090 }
1091 }
1092
1238 pub const C = @import("link/C.zig");1093 pub const C = @import("link/C.zig");
1239 pub const Coff = @import("link/Coff.zig");1094 pub const Coff = @import("link/Coff.zig");
1240 pub const Plan9 = @import("link/Plan9.zig");1095 pub const Plan9 = @import("link/Plan9.zig");
...@@ -1245,19 +1100,3 @@ pub const File = struct {...@@ -1245,19 +1100,3 @@ pub const File = struct {
1245 pub const NvPtx = @import("link/NvPtx.zig");1100 pub const NvPtx = @import("link/NvPtx.zig");
1246 pub const Dwarf = @import("link/Dwarf.zig");1101 pub const Dwarf = @import("link/Dwarf.zig");
1247};1102};
1248
1249pub fn determineMode(options: Options) fs.File.Mode {
1250 // On common systems with a 0o022 umask, 0o777 will still result in a file created
1251 // with 0o755 permissions, but it works appropriately if the system is configured
1252 // more leniently. As another data point, C's fopen seems to open files with the
1253 // 666 mode.
1254 const executable_mode = if (builtin.target.os.tag == .windows) 0 else 0o777;
1255 switch (options.effectiveOutputMode()) {
1256 .Lib => return switch (options.link_mode) {
1257 .Dynamic => executable_mode,
1258 .Static => fs.File.default_mode,
1259 },
1260 .Exe => return executable_mode,
1261 .Obj => return fs.File.default_mode,
1262 }
1263}
src/link/Coff.zig+169-146
...@@ -48,9 +48,6 @@ got_table_count_dirty: bool = true,...@@ -48,9 +48,6 @@ got_table_count_dirty: bool = true,
48got_table_contents_dirty: bool = true,48got_table_contents_dirty: bool = true,
49imports_count_dirty: bool = true,49imports_count_dirty: bool = true,
5050
51/// Virtual address of the entry point procedure relative to image base.
52entry_addr: ?u32 = null,
53
54/// Table of tracked LazySymbols.51/// Table of tracked LazySymbols.
55lazy_syms: LazySymbolTable = .{},52lazy_syms: LazySymbolTable = .{},
5653
...@@ -226,44 +223,150 @@ const ideal_factor = 3;...@@ -226,44 +223,150 @@ const ideal_factor = 3;
226const minimum_text_block_size = 64;223const minimum_text_block_size = 64;
227pub const min_text_capacity = padToIdeal(minimum_text_block_size);224pub const min_text_capacity = padToIdeal(minimum_text_block_size);
228225
229pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Coff {226pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Coff {
230 assert(options.target.ofmt == .coff);227 if (build_options.only_c) unreachable;
228 const target = options.comp.root_mod.resolved_target.result;
229 assert(target.ofmt == .coff);
230
231 const self = try createEmpty(arena, options);
232 errdefer self.base.destroy();
233
234 const use_lld = build_options.have_llvm and options.comp.config.use_lld;
235 const use_llvm = build_options.have_llvm and options.comp.config.use_llvm;
231236
232 if (options.use_llvm) {237 if (use_lld and use_llvm) {
233 return createEmpty(allocator, options);238 // LLVM emits the object file; LLD links it into the final product.
239 return self;
234 }240 }
235241
236 const self = try createEmpty(allocator, options);242 const sub_path = if (!use_lld) options.emit.sub_path else p: {
237 errdefer self.base.destroy();243 // Open a temporary object file, not the final output file because we
244 // want to link with LLD.
245 const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{
246 options.emit.sub_path, target.ofmt.fileExt(target.cpu.arch),
247 });
248 self.base.intermediary_basename = o_file_path;
249 break :p o_file_path;
250 };
238251
239 const file = try options.emit.?.directory.handle.createFile(sub_path, .{252 self.base.file = try options.emit.directory.handle.createFile(sub_path, .{
240 .truncate = false,253 .truncate = false,
241 .read = true,254 .read = true,
242 .mode = link.determineMode(options),255 .mode = link.File.determineMode(
256 use_lld,
257 options.comp.config.output_mode,
258 options.comp.config.link_mode,
259 ),
243 });260 });
244 self.base.file = file;
245261
246 try self.populateMissingMetadata();262 assert(self.llvm_object == null);
263 const gpa = self.base.comp.gpa;
264
265 try self.strtab.buffer.ensureUnusedCapacity(gpa, @sizeOf(u32));
266 self.strtab.buffer.appendNTimesAssumeCapacity(0, @sizeOf(u32));
267
268 try self.temp_strtab.buffer.append(gpa, 0);
269
270 // Index 0 is always a null symbol.
271 try self.locals.append(gpa, .{
272 .name = [_]u8{0} ** 8,
273 .value = 0,
274 .section_number = .UNDEFINED,
275 .type = .{ .base_type = .NULL, .complex_type = .NULL },
276 .storage_class = .NULL,
277 .number_of_aux_symbols = 0,
278 });
279
280 if (self.text_section_index == null) {
281 const file_size: u32 = @intCast(options.program_code_size_hint);
282 self.text_section_index = try self.allocateSection(".text", file_size, .{
283 .CNT_CODE = 1,
284 .MEM_EXECUTE = 1,
285 .MEM_READ = 1,
286 });
287 }
288
289 if (self.got_section_index == null) {
290 const file_size = @as(u32, @intCast(options.symbol_count_hint)) * self.ptr_width.size();
291 self.got_section_index = try self.allocateSection(".got", file_size, .{
292 .CNT_INITIALIZED_DATA = 1,
293 .MEM_READ = 1,
294 });
295 }
296
297 if (self.rdata_section_index == null) {
298 const file_size: u32 = self.page_size;
299 self.rdata_section_index = try self.allocateSection(".rdata", file_size, .{
300 .CNT_INITIALIZED_DATA = 1,
301 .MEM_READ = 1,
302 });
303 }
304
305 if (self.data_section_index == null) {
306 const file_size: u32 = self.page_size;
307 self.data_section_index = try self.allocateSection(".data", file_size, .{
308 .CNT_INITIALIZED_DATA = 1,
309 .MEM_READ = 1,
310 .MEM_WRITE = 1,
311 });
312 }
313
314 if (self.idata_section_index == null) {
315 const file_size = @as(u32, @intCast(options.symbol_count_hint)) * self.ptr_width.size();
316 self.idata_section_index = try self.allocateSection(".idata", file_size, .{
317 .CNT_INITIALIZED_DATA = 1,
318 .MEM_READ = 1,
319 });
320 }
321
322 if (self.reloc_section_index == null) {
323 const file_size = @as(u32, @intCast(options.symbol_count_hint)) * @sizeOf(coff.BaseRelocation);
324 self.reloc_section_index = try self.allocateSection(".reloc", file_size, .{
325 .CNT_INITIALIZED_DATA = 1,
326 .MEM_DISCARDABLE = 1,
327 .MEM_READ = 1,
328 });
329 }
330
331 if (self.strtab_offset == null) {
332 const file_size = @as(u32, @intCast(self.strtab.buffer.items.len));
333 self.strtab_offset = self.findFreeSpace(file_size, @alignOf(u32)); // 4bytes aligned seems like a good idea here
334 log.debug("found strtab free space 0x{x} to 0x{x}", .{ self.strtab_offset.?, self.strtab_offset.? + file_size });
335 }
336
337 {
338 // We need to find out what the max file offset is according to section headers.
339 // Otherwise, we may end up with an COFF binary with file size not matching the final section's
340 // offset + it's filesize.
341 // TODO I don't like this here one bit
342 var max_file_offset: u64 = 0;
343 for (self.sections.items(.header)) |header| {
344 if (header.pointer_to_raw_data + header.size_of_raw_data > max_file_offset) {
345 max_file_offset = header.pointer_to_raw_data + header.size_of_raw_data;
346 }
347 }
348 try self.base.file.?.pwriteAll(&[_]u8{0}, max_file_offset);
349 }
247350
248 return self;351 return self;
249}352}
250353
251pub fn createEmpty(gpa: Allocator, options: link.Options) !*Coff {354pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {
252 const ptr_width: PtrWidth = switch (options.target.ptrBitWidth()) {355 const target = options.comp.root_mod.resolved_target.result;
356 const ptr_width: PtrWidth = switch (target.ptrBitWidth()) {
253 0...32 => .p32,357 0...32 => .p32,
254 33...64 => .p64,358 33...64 => .p64,
255 else => return error.UnsupportedCOFFArchitecture,359 else => return error.UnsupportedCOFFArchitecture,
256 };360 };
257 const page_size: u32 = switch (options.target.cpu.arch) {361 const page_size: u32 = switch (target.cpu.arch) {
258 else => 0x1000,362 else => 0x1000,
259 };363 };
260 const self = try gpa.create(Coff);364 const self = try arena.create(Coff);
261 errdefer gpa.destroy(self);
262 self.* = .{365 self.* = .{
263 .base = .{366 .base = .{
264 .tag = .coff,367 .tag = .coff,
265 .options = options,368 .comp = options.comp,
266 .allocator = gpa,369 .emit = options.emit,
267 .file = null,370 .file = null,
268 },371 },
269 .ptr_width = ptr_width,372 .ptr_width = ptr_width,
...@@ -271,16 +374,17 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Coff {...@@ -271,16 +374,17 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Coff {
271 .data_directories = comptime mem.zeroes([coff.IMAGE_NUMBEROF_DIRECTORY_ENTRIES]coff.ImageDataDirectory),374 .data_directories = comptime mem.zeroes([coff.IMAGE_NUMBEROF_DIRECTORY_ENTRIES]coff.ImageDataDirectory),
272 };375 };
273376
274 if (options.use_llvm) {377 const use_llvm = build_options.have_llvm and options.comp.config.use_llvm;
275 self.llvm_object = try LlvmObject.create(gpa, options);378 if (use_llvm and options.comp.config.have_zcu) {
379 self.llvm_object = try LlvmObject.create(arena, options);
276 }380 }
277 return self;381 return self;
278}382}
279383
280pub fn deinit(self: *Coff) void {384pub fn deinit(self: *Coff) void {
281 const gpa = self.base.allocator;385 const gpa = self.base.comp.gpa;
282386
283 if (self.llvm_object) |llvm_object| llvm_object.destroy(gpa);387 if (self.llvm_object) |llvm_object| llvm_object.deinit();
284388
285 for (self.objects.items) |*object| {389 for (self.objects.items) |*object| {
286 object.deinit(gpa);390 object.deinit(gpa);
...@@ -349,97 +453,6 @@ pub fn deinit(self: *Coff) void {...@@ -349,97 +453,6 @@ pub fn deinit(self: *Coff) void {
349 self.base_relocs.deinit(gpa);453 self.base_relocs.deinit(gpa);
350}454}
351455
352fn populateMissingMetadata(self: *Coff) !void {
353 assert(self.llvm_object == null);
354 const gpa = self.base.allocator;
355
356 try self.strtab.buffer.ensureUnusedCapacity(gpa, @sizeOf(u32));
357 self.strtab.buffer.appendNTimesAssumeCapacity(0, @sizeOf(u32));
358
359 try self.temp_strtab.buffer.append(gpa, 0);
360
361 // Index 0 is always a null symbol.
362 try self.locals.append(gpa, .{
363 .name = [_]u8{0} ** 8,
364 .value = 0,
365 .section_number = .UNDEFINED,
366 .type = .{ .base_type = .NULL, .complex_type = .NULL },
367 .storage_class = .NULL,
368 .number_of_aux_symbols = 0,
369 });
370
371 if (self.text_section_index == null) {
372 const file_size = @as(u32, @intCast(self.base.options.program_code_size_hint));
373 self.text_section_index = try self.allocateSection(".text", file_size, .{
374 .CNT_CODE = 1,
375 .MEM_EXECUTE = 1,
376 .MEM_READ = 1,
377 });
378 }
379
380 if (self.got_section_index == null) {
381 const file_size = @as(u32, @intCast(self.base.options.symbol_count_hint)) * self.ptr_width.size();
382 self.got_section_index = try self.allocateSection(".got", file_size, .{
383 .CNT_INITIALIZED_DATA = 1,
384 .MEM_READ = 1,
385 });
386 }
387
388 if (self.rdata_section_index == null) {
389 const file_size: u32 = self.page_size;
390 self.rdata_section_index = try self.allocateSection(".rdata", file_size, .{
391 .CNT_INITIALIZED_DATA = 1,
392 .MEM_READ = 1,
393 });
394 }
395
396 if (self.data_section_index == null) {
397 const file_size: u32 = self.page_size;
398 self.data_section_index = try self.allocateSection(".data", file_size, .{
399 .CNT_INITIALIZED_DATA = 1,
400 .MEM_READ = 1,
401 .MEM_WRITE = 1,
402 });
403 }
404
405 if (self.idata_section_index == null) {
406 const file_size = @as(u32, @intCast(self.base.options.symbol_count_hint)) * self.ptr_width.size();
407 self.idata_section_index = try self.allocateSection(".idata", file_size, .{
408 .CNT_INITIALIZED_DATA = 1,
409 .MEM_READ = 1,
410 });
411 }
412
413 if (self.reloc_section_index == null) {
414 const file_size = @as(u32, @intCast(self.base.options.symbol_count_hint)) * @sizeOf(coff.BaseRelocation);
415 self.reloc_section_index = try self.allocateSection(".reloc", file_size, .{
416 .CNT_INITIALIZED_DATA = 1,
417 .MEM_DISCARDABLE = 1,
418 .MEM_READ = 1,
419 });
420 }
421
422 if (self.strtab_offset == null) {
423 const file_size = @as(u32, @intCast(self.strtab.buffer.items.len));
424 self.strtab_offset = self.findFreeSpace(file_size, @alignOf(u32)); // 4bytes aligned seems like a good idea here
425 log.debug("found strtab free space 0x{x} to 0x{x}", .{ self.strtab_offset.?, self.strtab_offset.? + file_size });
426 }
427
428 {
429 // We need to find out what the max file offset is according to section headers.
430 // Otherwise, we may end up with an COFF binary with file size not matching the final section's
431 // offset + it's filesize.
432 // TODO I don't like this here one bit
433 var max_file_offset: u64 = 0;
434 for (self.sections.items(.header)) |header| {
435 if (header.pointer_to_raw_data + header.size_of_raw_data > max_file_offset) {
436 max_file_offset = header.pointer_to_raw_data + header.size_of_raw_data;
437 }
438 }
439 try self.base.file.?.pwriteAll(&[_]u8{0}, max_file_offset);
440 }
441}
442
443fn allocateSection(self: *Coff, name: []const u8, size: u32, flags: coff.SectionHeaderFlags) !u16 {456fn allocateSection(self: *Coff, name: []const u8, size: u32, flags: coff.SectionHeaderFlags) !u16 {
444 const index = @as(u16, @intCast(self.sections.slice().len));457 const index = @as(u16, @intCast(self.sections.slice().len));
445 const off = self.findFreeSpace(size, default_file_alignment);458 const off = self.findFreeSpace(size, default_file_alignment);
...@@ -471,8 +484,9 @@ fn allocateSection(self: *Coff, name: []const u8, size: u32, flags: coff.Section...@@ -471,8 +484,9 @@ fn allocateSection(self: *Coff, name: []const u8, size: u32, flags: coff.Section
471 .number_of_linenumbers = 0,484 .number_of_linenumbers = 0,
472 .flags = flags,485 .flags = flags,
473 };486 };
487 const gpa = self.base.comp.gpa;
474 try self.setSectionName(&header, name);488 try self.setSectionName(&header, name);
475 try self.sections.append(self.base.allocator, .{ .header = header });489 try self.sections.append(gpa, .{ .header = header });
476 return index;490 return index;
477}491}
478492
...@@ -654,7 +668,7 @@ fn allocateAtom(self: *Coff, atom_index: Atom.Index, new_atom_size: u32, alignme...@@ -654,7 +668,7 @@ fn allocateAtom(self: *Coff, atom_index: Atom.Index, new_atom_size: u32, alignme
654}668}
655669
656pub fn allocateSymbol(self: *Coff) !u32 {670pub fn allocateSymbol(self: *Coff) !u32 {
657 const gpa = self.base.allocator;671 const gpa = self.base.comp.gpa;
658 try self.locals.ensureUnusedCapacity(gpa, 1);672 try self.locals.ensureUnusedCapacity(gpa, 1);
659673
660 const index = blk: {674 const index = blk: {
...@@ -682,7 +696,7 @@ pub fn allocateSymbol(self: *Coff) !u32 {...@@ -682,7 +696,7 @@ pub fn allocateSymbol(self: *Coff) !u32 {
682}696}
683697
684fn allocateGlobal(self: *Coff) !u32 {698fn allocateGlobal(self: *Coff) !u32 {
685 const gpa = self.base.allocator;699 const gpa = self.base.comp.gpa;
686 try self.globals.ensureUnusedCapacity(gpa, 1);700 try self.globals.ensureUnusedCapacity(gpa, 1);
687701
688 const index = blk: {702 const index = blk: {
...@@ -706,15 +720,16 @@ fn allocateGlobal(self: *Coff) !u32 {...@@ -706,15 +720,16 @@ fn allocateGlobal(self: *Coff) !u32 {
706}720}
707721
708fn addGotEntry(self: *Coff, target: SymbolWithLoc) !void {722fn addGotEntry(self: *Coff, target: SymbolWithLoc) !void {
723 const gpa = self.base.comp.gpa;
709 if (self.got_table.lookup.contains(target)) return;724 if (self.got_table.lookup.contains(target)) return;
710 const got_index = try self.got_table.allocateEntry(self.base.allocator, target);725 const got_index = try self.got_table.allocateEntry(gpa, target);
711 try self.writeOffsetTableEntry(got_index);726 try self.writeOffsetTableEntry(got_index);
712 self.got_table_count_dirty = true;727 self.got_table_count_dirty = true;
713 self.markRelocsDirtyByTarget(target);728 self.markRelocsDirtyByTarget(target);
714}729}
715730
716pub fn createAtom(self: *Coff) !Atom.Index {731pub fn createAtom(self: *Coff) !Atom.Index {
717 const gpa = self.base.allocator;732 const gpa = self.base.comp.gpa;
718 const atom_index = @as(Atom.Index, @intCast(self.atoms.items.len));733 const atom_index = @as(Atom.Index, @intCast(self.atoms.items.len));
719 const atom = try self.atoms.addOne(gpa);734 const atom = try self.atoms.addOne(gpa);
720 const sym_index = try self.allocateSymbol();735 const sym_index = try self.allocateSymbol();
...@@ -759,7 +774,7 @@ fn writeAtom(self: *Coff, atom_index: Atom.Index, code: []u8) !void {...@@ -759,7 +774,7 @@ fn writeAtom(self: *Coff, atom_index: Atom.Index, code: []u8) !void {
759 file_offset + code.len,774 file_offset + code.len,
760 });775 });
761776
762 const gpa = self.base.allocator;777 const gpa = self.base.comp.gpa;
763778
764 // Gather relocs which can be resolved.779 // Gather relocs which can be resolved.
765 // We need to do this as we will be applying different slide values depending780 // We need to do this as we will be applying different slide values depending
...@@ -870,7 +885,7 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {...@@ -870,7 +885,7 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {
870885
871 if (is_hot_update_compatible) {886 if (is_hot_update_compatible) {
872 if (self.base.child_pid) |handle| {887 if (self.base.child_pid) |handle| {
873 const gpa = self.base.allocator;888 const gpa = self.base.comp.gpa;
874 const slide = @intFromPtr(self.hot_state.loaded_base_address.?);889 const slide = @intFromPtr(self.hot_state.loaded_base_address.?);
875 const actual_vmaddr = vmaddr + slide;890 const actual_vmaddr = vmaddr + slide;
876 const pvaddr = @as(*anyopaque, @ptrFromInt(actual_vmaddr));891 const pvaddr = @as(*anyopaque, @ptrFromInt(actual_vmaddr));
...@@ -974,7 +989,7 @@ pub fn ptraceDetach(self: *Coff, handle: std.ChildProcess.Id) void {...@@ -974,7 +989,7 @@ pub fn ptraceDetach(self: *Coff, handle: std.ChildProcess.Id) void {
974fn freeAtom(self: *Coff, atom_index: Atom.Index) void {989fn freeAtom(self: *Coff, atom_index: Atom.Index) void {
975 log.debug("freeAtom {d}", .{atom_index});990 log.debug("freeAtom {d}", .{atom_index});
976991
977 const gpa = self.base.allocator;992 const gpa = self.base.comp.gpa;
978993
979 // Remove any relocs and base relocs associated with this Atom994 // Remove any relocs and base relocs associated with this Atom
980 Atom.freeRelocations(self, atom_index);995 Atom.freeRelocations(self, atom_index);
...@@ -1061,7 +1076,8 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air:...@@ -1061,7 +1076,8 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air:
1061 self.freeUnnamedConsts(decl_index);1076 self.freeUnnamedConsts(decl_index);
1062 Atom.freeRelocations(self, atom_index);1077 Atom.freeRelocations(self, atom_index);
10631078
1064 var code_buffer = std.ArrayList(u8).init(self.base.allocator);1079 const gpa = self.base.comp.gpa;
1080 var code_buffer = std.ArrayList(u8).init(gpa);
1065 defer code_buffer.deinit();1081 defer code_buffer.deinit();
10661082
1067 const res = try codegen.generateFunction(1083 const res = try codegen.generateFunction(
...@@ -1090,7 +1106,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air:...@@ -1090,7 +1106,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air:
1090}1106}
10911107
1092pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 {1108pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 {
1093 const gpa = self.base.allocator;1109 const gpa = self.base.comp.gpa;
1094 const mod = self.base.options.module.?;1110 const mod = self.base.options.module.?;
1095 const decl = mod.declPtr(decl_index);1111 const decl = mod.declPtr(decl_index);
1096 const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index);1112 const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index);
...@@ -1121,7 +1137,7 @@ const LowerConstResult = union(enum) {...@@ -1121,7 +1137,7 @@ const LowerConstResult = union(enum) {
1121};1137};
11221138
1123fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, required_alignment: InternPool.Alignment, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult {1139fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, required_alignment: InternPool.Alignment, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult {
1124 const gpa = self.base.allocator;1140 const gpa = self.base.comp.gpa;
11251141
1126 var code_buffer = std.ArrayList(u8).init(gpa);1142 var code_buffer = std.ArrayList(u8).init(gpa);
1127 defer code_buffer.deinit();1143 defer code_buffer.deinit();
...@@ -1174,13 +1190,14 @@ pub fn updateDecl(...@@ -1174,13 +1190,14 @@ pub fn updateDecl(
1174 return;1190 return;
1175 }1191 }
11761192
1193 const gpa = self.base.comp.gpa;
1177 if (decl.isExtern(mod)) {1194 if (decl.isExtern(mod)) {
1178 // TODO make this part of getGlobalSymbol1195 // TODO make this part of getGlobalSymbol
1179 const variable = decl.getOwnedVariable(mod).?;1196 const variable = decl.getOwnedVariable(mod).?;
1180 const name = mod.intern_pool.stringToSlice(decl.name);1197 const name = mod.intern_pool.stringToSlice(decl.name);
1181 const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name);1198 const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name);
1182 const global_index = try self.getGlobalSymbol(name, lib_name);1199 const global_index = try self.getGlobalSymbol(name, lib_name);
1183 try self.need_got_table.put(self.base.allocator, global_index, {});1200 try self.need_got_table.put(gpa, global_index, {});
1184 return;1201 return;
1185 }1202 }
11861203
...@@ -1188,7 +1205,7 @@ pub fn updateDecl(...@@ -1188,7 +1205,7 @@ pub fn updateDecl(
1188 Atom.freeRelocations(self, atom_index);1205 Atom.freeRelocations(self, atom_index);
1189 const atom = self.getAtom(atom_index);1206 const atom = self.getAtom(atom_index);
11901207
1191 var code_buffer = std.ArrayList(u8).init(self.base.allocator);1208 var code_buffer = std.ArrayList(u8).init(gpa);
1192 defer code_buffer.deinit();1209 defer code_buffer.deinit();
11931210
1194 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;1211 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;
...@@ -1220,7 +1237,7 @@ fn updateLazySymbolAtom(...@@ -1220,7 +1237,7 @@ fn updateLazySymbolAtom(
1220 atom_index: Atom.Index,1237 atom_index: Atom.Index,
1221 section_index: u16,1238 section_index: u16,
1222) !void {1239) !void {
1223 const gpa = self.base.allocator;1240 const gpa = self.base.comp.gpa;
1224 const mod = self.base.options.module.?;1241 const mod = self.base.options.module.?;
12251242
1226 var required_alignment: InternPool.Alignment = .none;1243 var required_alignment: InternPool.Alignment = .none;
...@@ -1281,8 +1298,9 @@ fn updateLazySymbolAtom(...@@ -1281,8 +1298,9 @@ fn updateLazySymbolAtom(
1281}1298}
12821299
1283pub fn getOrCreateAtomForLazySymbol(self: *Coff, sym: link.File.LazySymbol) !Atom.Index {1300pub fn getOrCreateAtomForLazySymbol(self: *Coff, sym: link.File.LazySymbol) !Atom.Index {
1301 const gpa = self.base.comp.gpa;
1284 const mod = self.base.options.module.?;1302 const mod = self.base.options.module.?;
1285 const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl(mod));1303 const gop = try self.lazy_syms.getOrPut(gpa, sym.getDecl(mod));
1286 errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();1304 errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
1287 if (!gop.found_existing) gop.value_ptr.* = .{};1305 if (!gop.found_existing) gop.value_ptr.* = .{};
1288 const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) {1306 const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) {
...@@ -1305,7 +1323,8 @@ pub fn getOrCreateAtomForLazySymbol(self: *Coff, sym: link.File.LazySymbol) !Ato...@@ -1305,7 +1323,8 @@ pub fn getOrCreateAtomForLazySymbol(self: *Coff, sym: link.File.LazySymbol) !Ato
1305}1323}
13061324
1307pub fn getOrCreateAtomForDecl(self: *Coff, decl_index: InternPool.DeclIndex) !Atom.Index {1325pub fn getOrCreateAtomForDecl(self: *Coff, decl_index: InternPool.DeclIndex) !Atom.Index {
1308 const gop = try self.decls.getOrPut(self.base.allocator, decl_index);1326 const gpa = self.base.comp.gpa;
1327 const gop = try self.decls.getOrPut(gpa, decl_index);
1309 if (!gop.found_existing) {1328 if (!gop.found_existing) {
1310 gop.value_ptr.* = .{1329 gop.value_ptr.* = .{
1311 .atom = try self.createAtom(),1330 .atom = try self.createAtom(),
...@@ -1401,7 +1420,7 @@ fn updateDeclCode(self: *Coff, decl_index: InternPool.DeclIndex, code: []u8, com...@@ -1401,7 +1420,7 @@ fn updateDeclCode(self: *Coff, decl_index: InternPool.DeclIndex, code: []u8, com
1401}1420}
14021421
1403fn freeUnnamedConsts(self: *Coff, decl_index: InternPool.DeclIndex) void {1422fn freeUnnamedConsts(self: *Coff, decl_index: InternPool.DeclIndex) void {
1404 const gpa = self.base.allocator;1423 const gpa = self.base.comp.gpa;
1405 const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return;1424 const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return;
1406 for (unnamed_consts.items) |atom_index| {1425 for (unnamed_consts.items) |atom_index| {
1407 self.freeAtom(atom_index);1426 self.freeAtom(atom_index);
...@@ -1412,6 +1431,7 @@ fn freeUnnamedConsts(self: *Coff, decl_index: InternPool.DeclIndex) void {...@@ -1412,6 +1431,7 @@ fn freeUnnamedConsts(self: *Coff, decl_index: InternPool.DeclIndex) void {
1412pub fn freeDecl(self: *Coff, decl_index: InternPool.DeclIndex) void {1431pub fn freeDecl(self: *Coff, decl_index: InternPool.DeclIndex) void {
1413 if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index);1432 if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index);
14141433
1434 const gpa = self.base.comp.gpa;
1415 const mod = self.base.options.module.?;1435 const mod = self.base.options.module.?;
1416 const decl = mod.declPtr(decl_index);1436 const decl = mod.declPtr(decl_index);
14171437
...@@ -1421,7 +1441,7 @@ pub fn freeDecl(self: *Coff, decl_index: InternPool.DeclIndex) void {...@@ -1421,7 +1441,7 @@ pub fn freeDecl(self: *Coff, decl_index: InternPool.DeclIndex) void {
1421 var kv = const_kv;1441 var kv = const_kv;
1422 self.freeAtom(kv.value.atom);1442 self.freeAtom(kv.value.atom);
1423 self.freeUnnamedConsts(decl_index);1443 self.freeUnnamedConsts(decl_index);
1424 kv.value.exports.deinit(self.base.allocator);1444 kv.value.exports.deinit(gpa);
1425 }1445 }
1426}1446}
14271447
...@@ -1476,7 +1496,7 @@ pub fn updateExports(...@@ -1476,7 +1496,7 @@ pub fn updateExports(
14761496
1477 if (self.base.options.emit == null) return;1497 if (self.base.options.emit == null) return;
14781498
1479 const gpa = self.base.allocator;1499 const gpa = self.base.comp.gpa;
14801500
1481 const metadata = switch (exported) {1501 const metadata = switch (exported) {
1482 .decl_index => |decl_index| blk: {1502 .decl_index => |decl_index| blk: {
...@@ -1574,7 +1594,7 @@ pub fn deleteDeclExport(...@@ -1574,7 +1594,7 @@ pub fn deleteDeclExport(
1574 const name = mod.intern_pool.stringToSlice(name_ip);1594 const name = mod.intern_pool.stringToSlice(name_ip);
1575 const sym_index = metadata.getExportPtr(self, name) orelse return;1595 const sym_index = metadata.getExportPtr(self, name) orelse return;
15761596
1577 const gpa = self.base.allocator;1597 const gpa = self.base.comp.gpa;
1578 const sym_loc = SymbolWithLoc{ .sym_index = sym_index.*, .file = null };1598 const sym_loc = SymbolWithLoc{ .sym_index = sym_index.*, .file = null };
1579 const sym = self.getSymbolPtr(sym_loc);1599 const sym = self.getSymbolPtr(sym_loc);
1580 log.debug("deleting export '{s}'", .{name});1600 log.debug("deleting export '{s}'", .{name});
...@@ -1602,7 +1622,7 @@ pub fn deleteDeclExport(...@@ -1602,7 +1622,7 @@ pub fn deleteDeclExport(
1602}1622}
16031623
1604fn resolveGlobalSymbol(self: *Coff, current: SymbolWithLoc) !void {1624fn resolveGlobalSymbol(self: *Coff, current: SymbolWithLoc) !void {
1605 const gpa = self.base.allocator;1625 const gpa = self.base.comp.gpa;
1606 const sym = self.getSymbol(current);1626 const sym = self.getSymbol(current);
1607 const sym_name = self.getSymbolName(current);1627 const sym_name = self.getSymbolName(current);
16081628
...@@ -1653,7 +1673,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -1653,7 +1673,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
1653 sub_prog_node.activate();1673 sub_prog_node.activate();
1654 defer sub_prog_node.end();1674 defer sub_prog_node.end();
16551675
1656 const gpa = self.base.allocator;1676 const gpa = self.base.comp.gpa;
16571677
1658 const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;1678 const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
16591679
...@@ -1794,7 +1814,7 @@ pub fn lowerAnonDecl(...@@ -1794,7 +1814,7 @@ pub fn lowerAnonDecl(
1794 explicit_alignment: InternPool.Alignment,1814 explicit_alignment: InternPool.Alignment,
1795 src_loc: Module.SrcLoc,1815 src_loc: Module.SrcLoc,
1796) !codegen.Result {1816) !codegen.Result {
1797 const gpa = self.base.allocator;1817 const gpa = self.base.comp.gpa;
1798 const mod = self.base.options.module.?;1818 const mod = self.base.options.module.?;
1799 const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val));1819 const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val));
1800 const decl_alignment = switch (explicit_alignment) {1820 const decl_alignment = switch (explicit_alignment) {
...@@ -1868,7 +1888,7 @@ pub fn getGlobalSymbol(self: *Coff, name: []const u8, lib_name_name: ?[]const u8...@@ -1868,7 +1888,7 @@ pub fn getGlobalSymbol(self: *Coff, name: []const u8, lib_name_name: ?[]const u8
1868 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };1888 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
1869 gop.value_ptr.* = sym_loc;1889 gop.value_ptr.* = sym_loc;
18701890
1871 const gpa = self.base.allocator;1891 const gpa = self.base.comp.gpa;
1872 const sym = self.getSymbolPtr(sym_loc);1892 const sym = self.getSymbolPtr(sym_loc);
1873 try self.setSymbolName(sym, name);1893 try self.setSymbolName(sym, name);
1874 sym.storage_class = .EXTERNAL;1894 sym.storage_class = .EXTERNAL;
...@@ -1895,7 +1915,7 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl_index: InternPool...@@ -1895,7 +1915,7 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl_index: InternPool
1895/// TODO: note that .ABSOLUTE is used as padding within each block; we could use this fact to do1915/// TODO: note that .ABSOLUTE is used as padding within each block; we could use this fact to do
1896/// incremental updates and writes into the table instead of doing it all at once1916/// incremental updates and writes into the table instead of doing it all at once
1897fn writeBaseRelocations(self: *Coff) !void {1917fn writeBaseRelocations(self: *Coff) !void {
1898 const gpa = self.base.allocator;1918 const gpa = self.base.comp.gpa;
18991919
1900 var page_table = std.AutoHashMap(u32, std.ArrayList(coff.BaseRelocation)).init(gpa);1920 var page_table = std.AutoHashMap(u32, std.ArrayList(coff.BaseRelocation)).init(gpa);
1901 defer {1921 defer {
...@@ -2006,7 +2026,7 @@ fn writeImportTables(self: *Coff) !void {...@@ -2006,7 +2026,7 @@ fn writeImportTables(self: *Coff) !void {
2006 if (self.idata_section_index == null) return;2026 if (self.idata_section_index == null) return;
2007 if (!self.imports_count_dirty) return;2027 if (!self.imports_count_dirty) return;
20082028
2009 const gpa = self.base.allocator;2029 const gpa = self.base.comp.gpa;
20102030
2011 const ext = ".dll";2031 const ext = ".dll";
2012 const header = &self.sections.items(.header)[self.idata_section_index.?];2032 const header = &self.sections.items(.header)[self.idata_section_index.?];
...@@ -2154,7 +2174,8 @@ fn writeStrtab(self: *Coff) !void {...@@ -2154,7 +2174,8 @@ fn writeStrtab(self: *Coff) !void {
21542174
2155 log.debug("writing strtab from 0x{x} to 0x{x}", .{ self.strtab_offset.?, self.strtab_offset.? + needed_size });2175 log.debug("writing strtab from 0x{x} to 0x{x}", .{ self.strtab_offset.?, self.strtab_offset.? + needed_size });
21562176
2157 var buffer = std.ArrayList(u8).init(self.base.allocator);2177 const gpa = self.base.comp.gpa;
2178 var buffer = std.ArrayList(u8).init(gpa);
2158 defer buffer.deinit();2179 defer buffer.deinit();
2159 try buffer.ensureTotalCapacityPrecise(needed_size);2180 try buffer.ensureTotalCapacityPrecise(needed_size);
2160 buffer.appendSliceAssumeCapacity(self.strtab.buffer.items);2181 buffer.appendSliceAssumeCapacity(self.strtab.buffer.items);
...@@ -2176,7 +2197,7 @@ fn writeDataDirectoriesHeaders(self: *Coff) !void {...@@ -2176,7 +2197,7 @@ fn writeDataDirectoriesHeaders(self: *Coff) !void {
2176}2197}
21772198
2178fn writeHeader(self: *Coff) !void {2199fn writeHeader(self: *Coff) !void {
2179 const gpa = self.base.allocator;2200 const gpa = self.base.comp.gpa;
2180 var buffer = std.ArrayList(u8).init(gpa);2201 var buffer = std.ArrayList(u8).init(gpa);
2181 defer buffer.deinit();2202 defer buffer.deinit();
2182 const writer = buffer.writer();2203 const writer = buffer.writer();
...@@ -2499,7 +2520,7 @@ pub fn getOrPutGlobalPtr(self: *Coff, name: []const u8) !GetOrPutGlobalPtrResult...@@ -2499,7 +2520,7 @@ pub fn getOrPutGlobalPtr(self: *Coff, name: []const u8) !GetOrPutGlobalPtrResult
2499 if (self.getGlobalPtr(name)) |ptr| {2520 if (self.getGlobalPtr(name)) |ptr| {
2500 return GetOrPutGlobalPtrResult{ .found_existing = true, .value_ptr = ptr };2521 return GetOrPutGlobalPtrResult{ .found_existing = true, .value_ptr = ptr };
2501 }2522 }
2502 const gpa = self.base.allocator;2523 const gpa = self.base.comp.gpa;
2503 const global_index = try self.allocateGlobal();2524 const global_index = try self.allocateGlobal();
2504 const global_name = try gpa.dupe(u8, name);2525 const global_name = try gpa.dupe(u8, name);
2505 _ = try self.resolver.put(gpa, global_name, global_index);2526 _ = try self.resolver.put(gpa, global_name, global_index);
...@@ -2530,7 +2551,8 @@ fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !v...@@ -2530,7 +2551,8 @@ fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !v
2530 @memset(header.name[name.len..], 0);2551 @memset(header.name[name.len..], 0);
2531 return;2552 return;
2532 }2553 }
2533 const offset = try self.strtab.insert(self.base.allocator, name);2554 const gpa = self.base.comp.gpa;
2555 const offset = try self.strtab.insert(gpa, name);
2534 const name_offset = fmt.bufPrint(&header.name, "/{d}", .{offset}) catch unreachable;2556 const name_offset = fmt.bufPrint(&header.name, "/{d}", .{offset}) catch unreachable;
2535 @memset(header.name[name_offset.len..], 0);2557 @memset(header.name[name_offset.len..], 0);
2536}2558}
...@@ -2549,7 +2571,8 @@ fn setSymbolName(self: *Coff, symbol: *coff.Symbol, name: []const u8) !void {...@@ -2549,7 +2571,8 @@ fn setSymbolName(self: *Coff, symbol: *coff.Symbol, name: []const u8) !void {
2549 @memset(symbol.name[name.len..], 0);2571 @memset(symbol.name[name.len..], 0);
2550 return;2572 return;
2551 }2573 }
2552 const offset = try self.strtab.insert(self.base.allocator, name);2574 const gpa = self.base.comp.gpa;
2575 const offset = try self.strtab.insert(gpa, name);
2553 @memset(symbol.name[0..4], 0);2576 @memset(symbol.name[0..4], 0);
2554 mem.writeInt(u32, symbol.name[4..8], offset, .little);2577 mem.writeInt(u32, symbol.name[4..8], offset, .little);
2555}2578}
src/link/Elf.zig+103-83
...@@ -200,26 +200,34 @@ pub const min_text_capacity = padToIdeal(minimum_atom_size);...@@ -200,26 +200,34 @@ pub const min_text_capacity = padToIdeal(minimum_atom_size);
200200
201pub const PtrWidth = enum { p32, p64 };201pub const PtrWidth = enum { p32, p64 };
202202
203pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Elf {203pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {
204 assert(options.target.ofmt == .elf);204 if (build_options.only_c) unreachable;
205 const target = options.comp.root_mod.resolved_target.result;
206 assert(target.ofmt == .elf);
205207
206 const self = try createEmpty(allocator, options);208 const use_lld = build_options.have_llvm and options.comp.config.use_lld;
209 const use_llvm = build_options.have_llvm and options.comp.config.use_llvm;
210
211 const self = try createEmpty(arena, options);
207 errdefer self.base.destroy();212 errdefer self.base.destroy();
208213
214 if (use_lld and use_llvm) {
215 // LLVM emits the object file; LLD links it into the final product.
216 return self;
217 }
218
209 const is_obj = options.output_mode == .Obj;219 const is_obj = options.output_mode == .Obj;
210 const is_obj_or_ar = is_obj or (options.output_mode == .Lib and options.link_mode == .Static);220 const is_obj_or_ar = is_obj or (options.output_mode == .Lib and options.link_mode == .Static);
211221
212 if (options.use_llvm) {222 const sub_path = if (!use_lld) options.emit.sub_path else p: {
213 const use_lld = build_options.have_llvm and self.base.options.use_lld;223 // Open a temporary object file, not the final output file because we
214 if (use_lld) return self;224 // want to link with LLD.
215225 const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{
216 if (options.module != null) {226 options.emit.sub_path, target.ofmt.fileExt(target.cpu.arch),
217 self.base.intermediary_basename = try std.fmt.allocPrint(allocator, "{s}{s}", .{227 });
218 sub_path, options.target.ofmt.fileExt(options.target.cpu.arch),228 self.base.intermediary_basename = o_file_path;
219 });229 break :p o_file_path;
220 }230 };
221 }
222 errdefer if (self.base.intermediary_basename) |path| allocator.free(path);
223231
224 self.base.file = try options.emit.?.directory.handle.createFile(sub_path, .{232 self.base.file = try options.emit.?.directory.handle.createFile(sub_path, .{
225 .truncate = false,233 .truncate = false,
...@@ -227,24 +235,26 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option...@@ -227,24 +235,26 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
227 .mode = link.determineMode(options),235 .mode = link.determineMode(options),
228 });236 });
229237
238 const gpa = options.comp.gpa;
239
230 // Index 0 is always a null symbol.240 // Index 0 is always a null symbol.
231 try self.symbols.append(allocator, .{});241 try self.symbols.append(gpa, .{});
232 // Index 0 is always a null symbol.242 // Index 0 is always a null symbol.
233 try self.symbols_extra.append(allocator, 0);243 try self.symbols_extra.append(gpa, 0);
234 // Allocate atom index 0 to null atom244 // Allocate atom index 0 to null atom
235 try self.atoms.append(allocator, .{});245 try self.atoms.append(gpa, .{});
236 // Append null file at index 0246 // Append null file at index 0
237 try self.files.append(allocator, .null);247 try self.files.append(gpa, .null);
238 // Append null byte to string tables248 // Append null byte to string tables
239 try self.shstrtab.append(allocator, 0);249 try self.shstrtab.append(gpa, 0);
240 try self.strtab.append(allocator, 0);250 try self.strtab.append(gpa, 0);
241 // There must always be a null shdr in index 0251 // There must always be a null shdr in index 0
242 _ = try self.addSection(.{ .name = "" });252 _ = try self.addSection(.{ .name = "" });
243 // Append null symbol in output symtab253 // Append null symbol in output symtab
244 try self.symtab.append(allocator, null_sym);254 try self.symtab.append(gpa, null_sym);
245255
246 if (!is_obj_or_ar) {256 if (!is_obj_or_ar) {
247 try self.dynstrtab.append(allocator, 0);257 try self.dynstrtab.append(gpa, 0);
248258
249 // Initialize PT_PHDR program header259 // Initialize PT_PHDR program header
250 const p_align: u16 = switch (self.ptr_width) {260 const p_align: u16 = switch (self.ptr_width) {
...@@ -283,10 +293,10 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option...@@ -283,10 +293,10 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
283 }293 }
284294
285 if (options.module != null and !options.use_llvm) {295 if (options.module != null and !options.use_llvm) {
286 const index = @as(File.Index, @intCast(try self.files.addOne(allocator)));296 const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));
287 self.files.set(index, .{ .zig_object = .{297 self.files.set(index, .{ .zig_object = .{
288 .index = index,298 .index = index,
289 .path = try std.fmt.allocPrint(self.base.allocator, "{s}.o", .{std.fs.path.stem(299 .path = try std.fmt.allocPrint(arena, "{s}.o", .{std.fs.path.stem(
290 options.module.?.main_mod.root_src_path,300 options.module.?.main_mod.root_src_path,
291 )}),301 )}),
292 } });302 } });
...@@ -298,16 +308,16 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option...@@ -298,16 +308,16 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
298 return self;308 return self;
299}309}
300310
301pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {311pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {
302 const ptr_width: PtrWidth = switch (options.target.ptrBitWidth()) {312 const target = options.comp.root_mod.resolved_target.result;
313 const ptr_width: PtrWidth = switch (target.ptrBitWidth()) {
303 0...32 => .p32,314 0...32 => .p32,
304 33...64 => .p64,315 33...64 => .p64,
305 else => return error.UnsupportedELFArchitecture,316 else => return error.UnsupportedELFArchitecture,
306 };317 };
307 const self = try gpa.create(Elf);318 const self = try arena.create(Elf);
308 errdefer gpa.destroy(self);
309319
310 const page_size: u32 = switch (options.target.cpu.arch) {320 const page_size: u32 = switch (target.cpu.arch) {
311 .powerpc64le => 0x10000,321 .powerpc64le => 0x10000,
312 .sparc64 => 0x2000,322 .sparc64 => 0x2000,
313 else => 0x1000,323 else => 0x1000,
...@@ -321,25 +331,25 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {...@@ -321,25 +331,25 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {
321 self.* = .{331 self.* = .{
322 .base = .{332 .base = .{
323 .tag = .elf,333 .tag = .elf,
324 .options = options,334 .comp = options.comp,
325 .allocator = gpa,335 .emit = options.emit,
326 .file = null,336 .file = null,
327 },337 },
328 .ptr_width = ptr_width,338 .ptr_width = ptr_width,
329 .page_size = page_size,339 .page_size = page_size,
330 .default_sym_version = default_sym_version,340 .default_sym_version = default_sym_version,
331 };341 };
332 if (options.use_llvm and options.module != null) {342 if (options.use_llvm and options.comp.config.have_zcu) {
333 self.llvm_object = try LlvmObject.create(gpa, options);343 self.llvm_object = try LlvmObject.create(arena, options);
334 }344 }
335345
336 return self;346 return self;
337}347}
338348
339pub fn deinit(self: *Elf) void {349pub fn deinit(self: *Elf) void {
340 const gpa = self.base.allocator;350 const gpa = self.base.comp.gpa;
341351
342 if (self.llvm_object) |llvm_object| llvm_object.destroy(gpa);352 if (self.llvm_object) |llvm_object| llvm_object.deinit();
343353
344 for (self.files.items(.tags), self.files.items(.data)) |tag, *data| switch (tag) {354 for (self.files.items(.tags), self.files.items(.data)) |tag, *data| switch (tag) {
345 .null => {},355 .null => {},
...@@ -496,10 +506,11 @@ fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) u64 {...@@ -496,10 +506,11 @@ fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) u64 {
496506
497/// TODO move to ZigObject507/// TODO move to ZigObject
498pub fn initMetadata(self: *Elf) !void {508pub fn initMetadata(self: *Elf) !void {
499 const gpa = self.base.allocator;509 const gpa = self.base.comp.gpa;
500 const ptr_size = self.ptrWidthBytes();510 const ptr_size = self.ptrWidthBytes();
501 const ptr_bit_width = self.base.options.target.ptrBitWidth();511 const target = self.base.comp.root_mod.resolved_target.result;
502 const is_linux = self.base.options.target.os.tag == .linux;512 const ptr_bit_width = target.ptrBitWidth();
513 const is_linux = target.os.tag == .linux;
503 const zig_object = self.zigObjectPtr().?;514 const zig_object = self.zigObjectPtr().?;
504515
505 const fillSection = struct {516 const fillSection = struct {
...@@ -943,7 +954,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -943,7 +954,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
943 if (use_lld) return;954 if (use_lld) return;
944 }955 }
945956
946 const gpa = self.base.allocator;957 const gpa = self.base.comp.gpa;
947 var sub_prog_node = prog_node.start("ELF Flush", 0);958 var sub_prog_node = prog_node.start("ELF Flush", 0);
948 sub_prog_node.activate();959 sub_prog_node.activate();
949 defer sub_prog_node.end();960 defer sub_prog_node.end();
...@@ -952,7 +963,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -952,7 +963,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
952 defer arena_allocator.deinit();963 defer arena_allocator.deinit();
953 const arena = arena_allocator.allocator();964 const arena = arena_allocator.allocator();
954965
955 const target = self.base.options.target;966 const target = self.base.comp.root_mod.resolved_target.result;
956 const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.967 const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.
957 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});968 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
958 const module_obj_path: ?[]const u8 = if (self.base.intermediary_basename) |path| blk: {969 const module_obj_path: ?[]const u8 = if (self.base.intermediary_basename) |path| blk: {
...@@ -1303,7 +1314,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1303,7 +1314,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1303}1314}
13041315
1305pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {1316pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {
1306 const gpa = self.base.allocator;1317 const gpa = self.base.comp.gpa;
13071318
1308 var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);1319 var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);
1309 defer positionals.deinit();1320 defer positionals.deinit();
...@@ -1447,7 +1458,7 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const...@@ -1447,7 +1458,7 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const
1447}1458}
14481459
1449pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {1460pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {
1450 const gpa = self.base.allocator;1461 const gpa = self.base.comp.gpa;
14511462
1452 var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);1463 var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);
1453 defer positionals.deinit();1464 defer positionals.deinit();
...@@ -1524,7 +1535,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {...@@ -1524,7 +1535,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
1524 defer arena_allocator.deinit();1535 defer arena_allocator.deinit();
1525 const arena = arena_allocator.allocator();1536 const arena = arena_allocator.allocator();
15261537
1527 const target = self.base.options.target;1538 const target = self.base.comp.root_mod.resolved_target.result;
1528 const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.1539 const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.
1529 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});1540 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
1530 const module_obj_path: ?[]const u8 = if (self.base.intermediary_basename) |path| blk: {1541 const module_obj_path: ?[]const u8 = if (self.base.intermediary_basename) |path| blk: {
...@@ -1574,7 +1585,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {...@@ -1574,7 +1585,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
1574 }1585 }
1575 } else {1586 } else {
1576 if (!self.isStatic()) {1587 if (!self.isStatic()) {
1577 if (self.base.options.target.dynamic_linker.get()) |path| {1588 if (target.dynamic_linker.get()) |path| {
1578 try argv.append("-dynamic-linker");1589 try argv.append("-dynamic-linker");
1579 try argv.append(path);1590 try argv.append(path);
1580 }1591 }
...@@ -1842,7 +1853,7 @@ fn parseObject(self: *Elf, path: []const u8) ParseError!void {...@@ -1842,7 +1853,7 @@ fn parseObject(self: *Elf, path: []const u8) ParseError!void {
1842 const tracy = trace(@src());1853 const tracy = trace(@src());
1843 defer tracy.end();1854 defer tracy.end();
18441855
1845 const gpa = self.base.allocator;1856 const gpa = self.base.comp.gpa;
1846 const in_file = try std.fs.cwd().openFile(path, .{});1857 const in_file = try std.fs.cwd().openFile(path, .{});
1847 defer in_file.close();1858 defer in_file.close();
1848 const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32));1859 const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32));
...@@ -1862,7 +1873,7 @@ fn parseArchive(self: *Elf, path: []const u8, must_link: bool) ParseError!void {...@@ -1862,7 +1873,7 @@ fn parseArchive(self: *Elf, path: []const u8, must_link: bool) ParseError!void {
1862 const tracy = trace(@src());1873 const tracy = trace(@src());
1863 defer tracy.end();1874 defer tracy.end();
18641875
1865 const gpa = self.base.allocator;1876 const gpa = self.base.comp.gpa;
1866 const in_file = try std.fs.cwd().openFile(path, .{});1877 const in_file = try std.fs.cwd().openFile(path, .{});
1867 defer in_file.close();1878 defer in_file.close();
1868 const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32));1879 const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32));
...@@ -1888,7 +1899,7 @@ fn parseSharedObject(self: *Elf, lib: SystemLib) ParseError!void {...@@ -1888,7 +1899,7 @@ fn parseSharedObject(self: *Elf, lib: SystemLib) ParseError!void {
1888 const tracy = trace(@src());1899 const tracy = trace(@src());
1889 defer tracy.end();1900 defer tracy.end();
18901901
1891 const gpa = self.base.allocator;1902 const gpa = self.base.comp.gpa;
1892 const in_file = try std.fs.cwd().openFile(lib.path, .{});1903 const in_file = try std.fs.cwd().openFile(lib.path, .{});
1893 defer in_file.close();1904 defer in_file.close();
1894 const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32));1905 const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32));
...@@ -1910,7 +1921,7 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {...@@ -1910,7 +1921,7 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {
1910 const tracy = trace(@src());1921 const tracy = trace(@src());
1911 defer tracy.end();1922 defer tracy.end();
19121923
1913 const gpa = self.base.allocator;1924 const gpa = self.base.comp.gpa;
1914 const in_file = try std.fs.cwd().openFile(lib.path, .{});1925 const in_file = try std.fs.cwd().openFile(lib.path, .{});
1915 defer in_file.close();1926 defer in_file.close();
1916 const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32));1927 const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32));
...@@ -1996,7 +2007,7 @@ fn accessLibPath(...@@ -1996,7 +2007,7 @@ fn accessLibPath(
1996 link_mode: ?std.builtin.LinkMode,2007 link_mode: ?std.builtin.LinkMode,
1997) !bool {2008) !bool {
1998 const sep = fs.path.sep_str;2009 const sep = fs.path.sep_str;
1999 const target = self.base.options.target;2010 const target = self.base.comp.root_mod.resolved_target.result;
2000 test_path.clearRetainingCapacity();2011 test_path.clearRetainingCapacity();
2001 const prefix = if (link_mode != null) "lib" else "";2012 const prefix = if (link_mode != null) "lib" else "";
2002 const suffix = if (link_mode) |mode| switch (mode) {2013 const suffix = if (link_mode) |mode| switch (mode) {
...@@ -2190,7 +2201,7 @@ fn claimUnresolvedObject(self: *Elf) void {...@@ -2190,7 +2201,7 @@ fn claimUnresolvedObject(self: *Elf) void {
2190/// This is also the point where we will report undefined symbols for any2201/// This is also the point where we will report undefined symbols for any
2191/// alloc sections.2202/// alloc sections.
2192fn scanRelocs(self: *Elf) !void {2203fn scanRelocs(self: *Elf) !void {
2193 const gpa = self.base.allocator;2204 const gpa = self.base.comp.gpa;
21942205
2195 var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Atom.Index)).init(gpa);2206 var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Atom.Index)).init(gpa);
2196 defer {2207 defer {
...@@ -2293,7 +2304,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2293,7 +2304,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2293 const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe;2304 const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe;
2294 const have_dynamic_linker = self.base.options.link_libc and2305 const have_dynamic_linker = self.base.options.link_libc and
2295 self.base.options.link_mode == .Dynamic and is_exe_or_dyn_lib;2306 self.base.options.link_mode == .Dynamic and is_exe_or_dyn_lib;
2296 const target = self.base.options.target;2307 const target = self.base.comp.root_mod.resolved_target.result;
2297 const gc_sections = self.base.options.gc_sections orelse !is_obj;2308 const gc_sections = self.base.options.gc_sections orelse !is_obj;
2298 const stack_size = self.base.options.stack_size_override orelse 16777216;2309 const stack_size = self.base.options.stack_size_override orelse 16777216;
2299 const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os;2310 const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os;
...@@ -2374,7 +2385,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2374,7 +2385,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2374 man.hash.addBytes(libc_installation.crt_dir.?);2385 man.hash.addBytes(libc_installation.crt_dir.?);
2375 }2386 }
2376 if (have_dynamic_linker) {2387 if (have_dynamic_linker) {
2377 man.hash.addOptionalBytes(self.base.options.target.dynamic_linker.get());2388 man.hash.addOptionalBytes(target.dynamic_linker.get());
2378 }2389 }
2379 }2390 }
2380 man.hash.addOptionalBytes(self.base.options.soname);2391 man.hash.addOptionalBytes(self.base.options.soname);
...@@ -2687,7 +2698,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2687,7 +2698,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2687 }2698 }
26882699
2689 if (have_dynamic_linker) {2700 if (have_dynamic_linker) {
2690 if (self.base.options.target.dynamic_linker.get()) |dynamic_linker| {2701 if (target.dynamic_linker.get()) |dynamic_linker| {
2691 try argv.append("-dynamic-linker");2702 try argv.append("-dynamic-linker");
2692 try argv.append(dynamic_linker);2703 try argv.append(dynamic_linker);
2693 }2704 }
...@@ -2937,7 +2948,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2937,7 +2948,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2937}2948}
29382949
2939fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64) void {2950fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64) void {
2940 const target_endian = self.base.options.target.cpu.arch.endian();2951 const target = self.base.comp.root_mod.resolved_target.result;
2952 const target_endian = target.cpu.arch.endian();
2941 switch (self.ptr_width) {2953 switch (self.ptr_width) {
2942 .p32 => mem.writeInt(u32, buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(addr)), target_endian),2954 .p32 => mem.writeInt(u32, buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(addr)), target_endian),
2943 .p64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), addr, target_endian),2955 .p64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), addr, target_endian),
...@@ -2945,8 +2957,9 @@ fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64)...@@ -2945,8 +2957,9 @@ fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64)
2945}2957}
29462958
2947fn writeShdrTable(self: *Elf) !void {2959fn writeShdrTable(self: *Elf) !void {
2948 const gpa = self.base.allocator;2960 const gpa = self.base.comp.gpa;
2949 const target_endian = self.base.options.target.cpu.arch.endian();2961 const target = self.base.comp.root_mod.resolved_target.result;
2962 const target_endian = target.cpu.arch.endian();
2950 const foreign_endian = target_endian != builtin.cpu.arch.endian();2963 const foreign_endian = target_endian != builtin.cpu.arch.endian();
2951 const shsize: u64 = switch (self.ptr_width) {2964 const shsize: u64 = switch (self.ptr_width) {
2952 .p32 => @sizeOf(elf.Elf32_Shdr),2965 .p32 => @sizeOf(elf.Elf32_Shdr),
...@@ -3001,8 +3014,9 @@ fn writeShdrTable(self: *Elf) !void {...@@ -3001,8 +3014,9 @@ fn writeShdrTable(self: *Elf) !void {
3001}3014}
30023015
3003fn writePhdrTable(self: *Elf) !void {3016fn writePhdrTable(self: *Elf) !void {
3004 const gpa = self.base.allocator;3017 const gpa = self.base.comp.gpa;
3005 const target_endian = self.base.options.target.cpu.arch.endian();3018 const target = self.base.comp.root_mod.resolved_target.result;
3019 const target_endian = target.cpu.arch.endian();
3006 const foreign_endian = target_endian != builtin.cpu.arch.endian();3020 const foreign_endian = target_endian != builtin.cpu.arch.endian();
3007 const phdr_table = &self.phdrs.items[self.phdr_table_index.?];3021 const phdr_table = &self.phdrs.items[self.phdr_table_index.?];
30083022
...@@ -3054,7 +3068,8 @@ fn writeElfHeader(self: *Elf) !void {...@@ -3054,7 +3068,8 @@ fn writeElfHeader(self: *Elf) !void {
3054 };3068 };
3055 index += 1;3069 index += 1;
30563070
3057 const endian = self.base.options.target.cpu.arch.endian();3071 const target = self.base.comp.root_mod.resolved_target.result;
3072 const endian = target.cpu.arch.endian();
3058 hdr_buf[index] = switch (endian) {3073 hdr_buf[index] = switch (endian) {
3059 .little => elf.ELFDATA2LSB,3074 .little => elf.ELFDATA2LSB,
3060 .big => elf.ELFDATA2MSB,3075 .big => elf.ELFDATA2MSB,
...@@ -3083,7 +3098,7 @@ fn writeElfHeader(self: *Elf) !void {...@@ -3083,7 +3098,7 @@ fn writeElfHeader(self: *Elf) !void {
3083 mem.writeInt(u16, hdr_buf[index..][0..2], @intFromEnum(elf_type), endian);3098 mem.writeInt(u16, hdr_buf[index..][0..2], @intFromEnum(elf_type), endian);
3084 index += 2;3099 index += 2;
30853100
3086 const machine = self.base.options.target.cpu.arch.toElfMachine();3101 const machine = target.cpu.arch.toElfMachine();
3087 mem.writeInt(u16, hdr_buf[index..][0..2], @intFromEnum(machine), endian);3102 mem.writeInt(u16, hdr_buf[index..][0..2], @intFromEnum(machine), endian);
3088 index += 2;3103 index += 2;
30893104
...@@ -3248,7 +3263,7 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {...@@ -3248,7 +3263,7 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {
32483263
3249 for (self.shdrs.items) |shdr| {3264 for (self.shdrs.items) |shdr| {
3250 if (self.getStartStopBasename(shdr)) |name| {3265 if (self.getStartStopBasename(shdr)) |name| {
3251 const gpa = self.base.allocator;3266 const gpa = self.base.comp.gpa;
3252 try self.start_stop_indexes.ensureUnusedCapacity(gpa, 2);3267 try self.start_stop_indexes.ensureUnusedCapacity(gpa, 2);
32533268
3254 const start = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name});3269 const start = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name});
...@@ -3394,6 +3409,7 @@ fn initOutputSections(self: *Elf) !void {...@@ -3394,6 +3409,7 @@ fn initOutputSections(self: *Elf) !void {
3394}3409}
33953410
3396fn initSyntheticSections(self: *Elf) !void {3411fn initSyntheticSections(self: *Elf) !void {
3412 const target = self.base.comp.root_mod.resolved_target.result;
3397 const ptr_size = self.ptrWidthBytes();3413 const ptr_size = self.ptrWidthBytes();
33983414
3399 const needs_eh_frame = for (self.objects.items) |index| {3415 const needs_eh_frame = for (self.objects.items) |index| {
...@@ -3503,7 +3519,7 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3503,7 +3519,7 @@ fn initSyntheticSections(self: *Elf) !void {
3503 // a segfault in the dynamic linker trying to load a binary that is static3519 // a segfault in the dynamic linker trying to load a binary that is static
3504 // and doesn't contain .dynamic section.3520 // and doesn't contain .dynamic section.
3505 if (self.isStatic() and !self.base.options.pie) break :blk false;3521 if (self.isStatic() and !self.base.options.pie) break :blk false;
3506 break :blk self.base.options.target.dynamic_linker.get() != null;3522 break :blk target.dynamic_linker.get() != null;
3507 };3523 };
3508 if (needs_interp) {3524 if (needs_interp) {
3509 self.interp_section_index = try self.addSection(.{3525 self.interp_section_index = try self.addSection(.{
...@@ -3613,7 +3629,7 @@ fn initSectionsObject(self: *Elf) !void {...@@ -3613,7 +3629,7 @@ fn initSectionsObject(self: *Elf) !void {
3613}3629}
36143630
3615fn initComdatGroups(self: *Elf) !void {3631fn initComdatGroups(self: *Elf) !void {
3616 const gpa = self.base.allocator;3632 const gpa = self.base.comp.gpa;
36173633
3618 for (self.objects.items) |index| {3634 for (self.objects.items) |index| {
3619 const object = self.file(index).?.object;3635 const object = self.file(index).?.object;
...@@ -3732,7 +3748,7 @@ fn initSpecialPhdrs(self: *Elf) !void {...@@ -3732,7 +3748,7 @@ fn initSpecialPhdrs(self: *Elf) !void {
3732/// Ties are broken by the file prority which corresponds to the inclusion of input sections in this output section3748/// Ties are broken by the file prority which corresponds to the inclusion of input sections in this output section
3733/// we are about to sort.3749/// we are about to sort.
3734fn sortInitFini(self: *Elf) !void {3750fn sortInitFini(self: *Elf) !void {
3735 const gpa = self.base.allocator;3751 const gpa = self.base.comp.gpa;
37363752
3737 const Entry = struct {3753 const Entry = struct {
3738 priority: i32,3754 priority: i32,
...@@ -3872,7 +3888,7 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void {...@@ -3872,7 +3888,7 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void {
3872 }3888 }
3873 };3889 };
38743890
3875 const gpa = self.base.allocator;3891 const gpa = self.base.comp.gpa;
3876 var entries = try std.ArrayList(Entry).initCapacity(gpa, self.phdrs.items.len);3892 var entries = try std.ArrayList(Entry).initCapacity(gpa, self.phdrs.items.len);
3877 defer entries.deinit();3893 defer entries.deinit();
3878 for (0..self.phdrs.items.len) |phndx| {3894 for (0..self.phdrs.items.len) |phndx| {
...@@ -3977,7 +3993,7 @@ fn sortShdrs(self: *Elf) !void {...@@ -3977,7 +3993,7 @@ fn sortShdrs(self: *Elf) !void {
3977 }3993 }
3978 };3994 };
39793995
3980 const gpa = self.base.allocator;3996 const gpa = self.base.comp.gpa;
3981 var entries = try std.ArrayList(Entry).initCapacity(gpa, self.shdrs.items.len);3997 var entries = try std.ArrayList(Entry).initCapacity(gpa, self.shdrs.items.len);
3982 defer entries.deinit();3998 defer entries.deinit();
3983 for (0..self.shdrs.items.len) |shndx| {3999 for (0..self.shdrs.items.len) |shndx| {
...@@ -4004,7 +4020,7 @@ fn sortShdrs(self: *Elf) !void {...@@ -4004,7 +4020,7 @@ fn sortShdrs(self: *Elf) !void {
4004}4020}
40054021
4006fn resetShdrIndexes(self: *Elf, backlinks: []const u16) !void {4022fn resetShdrIndexes(self: *Elf, backlinks: []const u16) !void {
4007 const gpa = self.base.allocator;4023 const gpa = self.base.comp.gpa;
40084024
4009 for (&[_]*?u16{4025 for (&[_]*?u16{
4010 &self.eh_frame_section_index,4026 &self.eh_frame_section_index,
...@@ -4187,6 +4203,7 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u16) !void {...@@ -4187,6 +4203,7 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u16) !void {
4187}4203}
41884204
4189fn updateSectionSizes(self: *Elf) !void {4205fn updateSectionSizes(self: *Elf) !void {
4206 const target = self.base.comp.root_mod.resolved_target.result;
4190 for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| {4207 for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| {
4191 const shdr = &self.shdrs.items[shndx];4208 const shdr = &self.shdrs.items[shndx];
4192 for (atom_list.items) |atom_index| {4209 for (atom_list.items) |atom_index| {
...@@ -4244,7 +4261,7 @@ fn updateSectionSizes(self: *Elf) !void {...@@ -4244,7 +4261,7 @@ fn updateSectionSizes(self: *Elf) !void {
4244 }4261 }
42454262
4246 if (self.interp_section_index) |index| {4263 if (self.interp_section_index) |index| {
4247 self.shdrs.items[index].sh_size = self.base.options.target.dynamic_linker.get().?.len + 1;4264 self.shdrs.items[index].sh_size = target.dynamic_linker.get().?.len + 1;
4248 }4265 }
42494266
4250 if (self.hash_section_index) |index| {4267 if (self.hash_section_index) |index| {
...@@ -4453,7 +4470,7 @@ fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void {...@@ -4453,7 +4470,7 @@ fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void {
4453 // as we are more interested in quick turnaround and compatibility4470 // as we are more interested in quick turnaround and compatibility
4454 // with `findFreeSpace` mechanics than anything else.4471 // with `findFreeSpace` mechanics than anything else.
4455 const Cover = std.ArrayList(u16);4472 const Cover = std.ArrayList(u16);
4456 const gpa = self.base.allocator;4473 const gpa = self.base.comp.gpa;
4457 var covers: [max_number_of_object_segments]Cover = undefined;4474 var covers: [max_number_of_object_segments]Cover = undefined;
4458 for (&covers) |*cover| {4475 for (&covers) |*cover| {
4459 cover.* = Cover.init(gpa);4476 cover.* = Cover.init(gpa);
...@@ -4691,7 +4708,7 @@ fn allocateAtoms(self: *Elf) void {...@@ -4691,7 +4708,7 @@ fn allocateAtoms(self: *Elf) void {
4691}4708}
46924709
4693fn writeAtoms(self: *Elf) !void {4710fn writeAtoms(self: *Elf) !void {
4694 const gpa = self.base.allocator;4711 const gpa = self.base.comp.gpa;
46954712
4696 var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Atom.Index)).init(gpa);4713 var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Atom.Index)).init(gpa);
4697 defer {4714 defer {
...@@ -4779,7 +4796,7 @@ fn writeAtoms(self: *Elf) !void {...@@ -4779,7 +4796,7 @@ fn writeAtoms(self: *Elf) !void {
4779}4796}
47804797
4781fn writeAtomsObject(self: *Elf) !void {4798fn writeAtomsObject(self: *Elf) !void {
4782 const gpa = self.base.allocator;4799 const gpa = self.base.comp.gpa;
47834800
4784 // TODO iterate over `output_sections` directly4801 // TODO iterate over `output_sections` directly
4785 for (self.shdrs.items, 0..) |shdr, shndx| {4802 for (self.shdrs.items, 0..) |shdr, shndx| {
...@@ -4852,7 +4869,7 @@ fn updateSymtabSize(self: *Elf) !void {...@@ -4852,7 +4869,7 @@ fn updateSymtabSize(self: *Elf) !void {
4852 var nglobals: u32 = 0;4869 var nglobals: u32 = 0;
4853 var strsize: u32 = 0;4870 var strsize: u32 = 0;
48544871
4855 const gpa = self.base.allocator;4872 const gpa = self.base.comp.gpa;
4856 var files = std.ArrayList(File.Index).init(gpa);4873 var files = std.ArrayList(File.Index).init(gpa);
4857 defer files.deinit();4874 defer files.deinit();
4858 try files.ensureTotalCapacityPrecise(self.objects.items.len + self.shared_objects.items.len + 2);4875 try files.ensureTotalCapacityPrecise(self.objects.items.len + self.shared_objects.items.len + 2);
...@@ -4935,11 +4952,12 @@ fn updateSymtabSize(self: *Elf) !void {...@@ -4935,11 +4952,12 @@ fn updateSymtabSize(self: *Elf) !void {
4935}4952}
49364953
4937fn writeSyntheticSections(self: *Elf) !void {4954fn writeSyntheticSections(self: *Elf) !void {
4938 const gpa = self.base.allocator;4955 const target = self.base.comp.root_mod.resolved_target.result;
4956 const gpa = self.base.comp.gpa;
49394957
4940 if (self.interp_section_index) |shndx| {4958 if (self.interp_section_index) |shndx| {
4941 var buffer: [256]u8 = undefined;4959 var buffer: [256]u8 = undefined;
4942 const interp = self.base.options.target.dynamic_linker.get().?;4960 const interp = target.dynamic_linker.get().?;
4943 @memcpy(buffer[0..interp.len], interp);4961 @memcpy(buffer[0..interp.len], interp);
4944 buffer[interp.len] = 0;4962 buffer[interp.len] = 0;
4945 const contents = buffer[0 .. interp.len + 1];4963 const contents = buffer[0 .. interp.len + 1];
...@@ -5065,7 +5083,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -5065,7 +5083,7 @@ fn writeSyntheticSections(self: *Elf) !void {
5065}5083}
50665084
5067fn writeSyntheticSectionsObject(self: *Elf) !void {5085fn writeSyntheticSectionsObject(self: *Elf) !void {
5068 const gpa = self.base.allocator;5086 const gpa = self.base.comp.gpa;
50695087
5070 for (self.output_rela_sections.values()) |sec| {5088 for (self.output_rela_sections.values()) |sec| {
5071 if (sec.atom_list.items.len == 0) continue;5089 if (sec.atom_list.items.len == 0) continue;
...@@ -5135,7 +5153,7 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {...@@ -5135,7 +5153,7 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {
5135}5153}
51365154
5137fn writeComdatGroups(self: *Elf) !void {5155fn writeComdatGroups(self: *Elf) !void {
5138 const gpa = self.base.allocator;5156 const gpa = self.base.comp.gpa;
5139 for (self.comdat_group_sections.items) |cgs| {5157 for (self.comdat_group_sections.items) |cgs| {
5140 const shdr = self.shdrs.items[cgs.shndx];5158 const shdr = self.shdrs.items[cgs.shndx];
5141 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;5159 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
...@@ -5160,7 +5178,8 @@ fn writeShStrtab(self: *Elf) !void {...@@ -5160,7 +5178,8 @@ fn writeShStrtab(self: *Elf) !void {
5160}5178}
51615179
5162fn writeSymtab(self: *Elf) !void {5180fn writeSymtab(self: *Elf) !void {
5163 const gpa = self.base.allocator;5181 const target = self.base.comp.root_mod.resolved_target.result;
5182 const gpa = self.base.comp.gpa;
5164 const symtab_shdr = self.shdrs.items[self.symtab_section_index.?];5183 const symtab_shdr = self.shdrs.items[self.symtab_section_index.?];
5165 const strtab_shdr = self.shdrs.items[self.strtab_section_index.?];5184 const strtab_shdr = self.shdrs.items[self.strtab_section_index.?];
5166 const sym_size: u64 = switch (self.ptr_width) {5185 const sym_size: u64 = switch (self.ptr_width) {
...@@ -5220,7 +5239,7 @@ fn writeSymtab(self: *Elf) !void {...@@ -5220,7 +5239,7 @@ fn writeSymtab(self: *Elf) !void {
5220 self.plt_got.writeSymtab(self);5239 self.plt_got.writeSymtab(self);
5221 }5240 }
52225241
5223 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();5242 const foreign_endian = target.cpu.arch.endian() != builtin.cpu.arch.endian();
5224 switch (self.ptr_width) {5243 switch (self.ptr_width) {
5225 .p32 => {5244 .p32 => {
5226 const buf = try gpa.alloc(elf.Elf32_Sym, self.symtab.items.len);5245 const buf = try gpa.alloc(elf.Elf32_Sym, self.symtab.items.len);
...@@ -5299,7 +5318,8 @@ fn ptrWidthBytes(self: Elf) u8 {...@@ -5299,7 +5318,8 @@ fn ptrWidthBytes(self: Elf) u8 {
5299/// Does not necessarily match `ptrWidthBytes` for example can be 2 bytes5318/// Does not necessarily match `ptrWidthBytes` for example can be 2 bytes
5300/// in a 32-bit ELF file.5319/// in a 32-bit ELF file.
5301pub fn archPtrWidthBytes(self: Elf) u8 {5320pub fn archPtrWidthBytes(self: Elf) u8 {
5302 return @as(u8, @intCast(@divExact(self.base.options.target.ptrBitWidth(), 8)));5321 const target = self.base.comp.root_mod.resolved_target.result;
5322 return @intCast(@divExact(target.ptrBitWidth(), 8));
5303}5323}
53045324
5305fn phdrTo32(phdr: elf.Elf64_Phdr) elf.Elf32_Phdr {5325fn phdrTo32(phdr: elf.Elf64_Phdr) elf.Elf32_Phdr {
...@@ -5694,7 +5714,7 @@ pub const AddSectionOpts = struct {...@@ -5694,7 +5714,7 @@ pub const AddSectionOpts = struct {
5694};5714};
56955715
5696pub fn addSection(self: *Elf, opts: AddSectionOpts) !u16 {5716pub fn addSection(self: *Elf, opts: AddSectionOpts) !u16 {
5697 const gpa = self.base.allocator;5717 const gpa = self.base.comp.gpa;
5698 const index = @as(u16, @intCast(self.shdrs.items.len));5718 const index = @as(u16, @intCast(self.shdrs.items.len));
5699 const shdr = try self.shdrs.addOne(gpa);5719 const shdr = try self.shdrs.addOne(gpa);
5700 shdr.* = .{5720 shdr.* = .{
...@@ -5887,7 +5907,7 @@ const GetOrPutGlobalResult = struct {...@@ -5887,7 +5907,7 @@ const GetOrPutGlobalResult = struct {
5887};5907};
58885908
5889pub fn getOrPutGlobal(self: *Elf, name: []const u8) !GetOrPutGlobalResult {5909pub fn getOrPutGlobal(self: *Elf, name: []const u8) !GetOrPutGlobalResult {
5890 const gpa = self.base.allocator;5910 const gpa = self.base.comp.gpa;
5891 const name_off = try self.strings.insert(gpa, name);5911 const name_off = try self.strings.insert(gpa, name);
5892 const gop = try self.resolver.getOrPut(gpa, name_off);5912 const gop = try self.resolver.getOrPut(gpa, name_off);
5893 if (!gop.found_existing) {5913 if (!gop.found_existing) {
...@@ -5923,7 +5943,7 @@ const GetOrCreateComdatGroupOwnerResult = struct {...@@ -5923,7 +5943,7 @@ const GetOrCreateComdatGroupOwnerResult = struct {
5923};5943};
59245944
5925pub fn getOrCreateComdatGroupOwner(self: *Elf, name: [:0]const u8) !GetOrCreateComdatGroupOwnerResult {5945pub fn getOrCreateComdatGroupOwner(self: *Elf, name: [:0]const u8) !GetOrCreateComdatGroupOwnerResult {
5926 const gpa = self.base.allocator;5946 const gpa = self.base.comp.gpa;
5927 const off = try self.strings.insert(gpa, name);5947 const off = try self.strings.insert(gpa, name);
5928 const gop = try self.comdat_groups_table.getOrPut(gpa, off);5948 const gop = try self.comdat_groups_table.getOrPut(gpa, off);
5929 if (!gop.found_existing) {5949 if (!gop.found_existing) {
...@@ -6039,7 +6059,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 {...@@ -6039,7 +6059,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 {
6039}6059}
60406060
6041fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void {6061fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void {
6042 const gpa = self.base.allocator;6062 const gpa = self.base.comp.gpa;
6043 const max_notes = 4;6063 const max_notes = 4;
60446064
6045 try self.misc_errors.ensureUnusedCapacity(gpa, undefs.count());6065 try self.misc_errors.ensureUnusedCapacity(gpa, undefs.count());
src/link/MachO.zig+139-118
...@@ -143,14 +143,23 @@ tlv_table: TlvSymbolTable = .{},...@@ -143,14 +143,23 @@ tlv_table: TlvSymbolTable = .{},
143/// Hot-code swapping state.143/// Hot-code swapping state.
144hot_state: if (is_hot_update_compatible) HotUpdateState else struct {} = .{},144hot_state: if (is_hot_update_compatible) HotUpdateState else struct {} = .{},
145145
146pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {146darwin_sdk_layout: ?SdkLayout,
147 assert(options.target.ofmt == .macho);147
148/// The filesystem layout of darwin SDK elements.
149pub const SdkLayout = enum {
150 /// macOS SDK layout: TOP { /usr/include, /usr/lib, /System/Library/Frameworks }.
151 sdk,
152 /// Shipped libc layout: TOP { /lib/libc/include, /lib/libc/darwin, <NONE> }.
153 vendored,
154};
148155
149 if (options.emit == null) {156pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {
150 return createEmpty(allocator, options);157 if (build_options.only_c) unreachable;
151 }158 const target = options.comp.root_mod.resolved_target.result;
159 assert(target.ofmt == .macho);
152160
153 const emit = options.emit.?;161 const gpa = options.comp.gpa;
162 const emit = options.emit;
154 const mode: Mode = mode: {163 const mode: Mode = mode: {
155 if (options.use_llvm or options.module == null or options.cache_mode == .whole)164 if (options.use_llvm or options.module == null or options.cache_mode == .whole)
156 break :mode .zld;165 break :mode .zld;
...@@ -160,17 +169,16 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {...@@ -160,17 +169,16 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
160 if (options.module == null) {169 if (options.module == null) {
161 // No point in opening a file, we would not write anything to it.170 // No point in opening a file, we would not write anything to it.
162 // Initialize with empty.171 // Initialize with empty.
163 return createEmpty(allocator, options);172 return createEmpty(arena, options);
164 }173 }
165 // Open a temporary object file, not the final output file because we174 // Open a temporary object file, not the final output file because we
166 // want to link with LLD.175 // want to link with LLD.
167 break :blk try std.fmt.allocPrint(allocator, "{s}{s}", .{176 break :blk try std.fmt.allocPrint(arena, "{s}{s}", .{
168 emit.sub_path, options.target.ofmt.fileExt(options.target.cpu.arch),177 emit.sub_path, target.ofmt.fileExt(target.cpu.arch),
169 });178 });
170 } else emit.sub_path;179 } else emit.sub_path;
171 errdefer if (mode == .zld) allocator.free(sub_path);
172180
173 const self = try createEmpty(allocator, options);181 const self = try createEmpty(arena, options);
174 errdefer self.base.destroy();182 errdefer self.base.destroy();
175183
176 if (mode == .zld) {184 if (mode == .zld) {
...@@ -186,7 +194,6 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {...@@ -186,7 +194,6 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
186 .read = true,194 .read = true,
187 .mode = link.determineMode(options),195 .mode = link.determineMode(options),
188 });196 });
189 errdefer file.close();
190 self.base.file = file;197 self.base.file = file;
191198
192 if (!options.strip and options.module != null) {199 if (!options.strip and options.module != null) {
...@@ -194,11 +201,10 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {...@@ -194,11 +201,10 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
194 log.debug("creating {s}.dSYM bundle", .{sub_path});201 log.debug("creating {s}.dSYM bundle", .{sub_path});
195202
196 const d_sym_path = try std.fmt.allocPrint(203 const d_sym_path = try std.fmt.allocPrint(
197 allocator,204 arena,
198 "{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF",205 "{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF",
199 .{sub_path},206 .{sub_path},
200 );207 );
201 defer allocator.free(d_sym_path);
202208
203 var d_sym_bundle = try emit.directory.handle.makeOpenPath(d_sym_path, .{});209 var d_sym_bundle = try emit.directory.handle.makeOpenPath(d_sym_path, .{});
204 defer d_sym_bundle.close();210 defer d_sym_bundle.close();
...@@ -209,21 +215,21 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {...@@ -209,21 +215,21 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
209 });215 });
210216
211 self.d_sym = .{217 self.d_sym = .{
212 .allocator = allocator,218 .allocator = gpa,
213 .dwarf = link.File.Dwarf.init(allocator, &self.base, .dwarf32),219 .dwarf = link.File.Dwarf.init(gpa, &self.base, .dwarf32),
214 .file = d_sym_file,220 .file = d_sym_file,
215 };221 };
216 }222 }
217223
218 // Index 0 is always a null symbol.224 // Index 0 is always a null symbol.
219 try self.locals.append(allocator, .{225 try self.locals.append(gpa, .{
220 .n_strx = 0,226 .n_strx = 0,
221 .n_type = 0,227 .n_type = 0,
222 .n_sect = 0,228 .n_sect = 0,
223 .n_desc = 0,229 .n_desc = 0,
224 .n_value = 0,230 .n_value = 0,
225 });231 });
226 try self.strtab.buffer.append(allocator, 0);232 try self.strtab.buffer.append(gpa, 0);
227233
228 try self.populateMissingMetadata();234 try self.populateMissingMetadata();
229235
...@@ -234,15 +240,14 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {...@@ -234,15 +240,14 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
234 return self;240 return self;
235}241}
236242
237pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO {243pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO {
238 const self = try gpa.create(MachO);244 const self = try arena.create(MachO);
239 errdefer gpa.destroy(self);
240245
241 self.* = .{246 self.* = .{
242 .base = .{247 .base = .{
243 .tag = .macho,248 .tag = .macho,
244 .options = options,249 .comp = options.comp,
245 .allocator = gpa,250 .emit = options.emit,
246 .file = null,251 .file = null,
247 },252 },
248 .mode = if (options.use_llvm or options.module == null or options.cache_mode == .whole)253 .mode = if (options.use_llvm or options.module == null or options.cache_mode == .whole)
...@@ -252,7 +257,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO {...@@ -252,7 +257,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO {
252 };257 };
253258
254 if (options.use_llvm and options.module != null) {259 if (options.use_llvm and options.module != null) {
255 self.llvm_object = try LlvmObject.create(gpa, options);260 self.llvm_object = try LlvmObject.create(arena, options);
256 }261 }
257262
258 log.debug("selected linker mode '{s}'", .{@tagName(self.mode)});263 log.debug("selected linker mode '{s}'", .{@tagName(self.mode)});
...@@ -261,20 +266,15 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO {...@@ -261,20 +266,15 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO {
261}266}
262267
263pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {268pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
264 if (self.base.options.emit == null) {269 const gpa = self.base.comp.gpa;
265 if (self.llvm_object) |llvm_object| {
266 try llvm_object.flushModule(comp, prog_node);
267 }
268 return;
269 }
270270
271 if (self.base.options.output_mode == .Lib and self.base.options.link_mode == .Static) {271 if (self.base.options.output_mode == .Lib and self.base.options.link_mode == .Static) {
272 if (build_options.have_llvm) {272 if (build_options.have_llvm) {
273 return self.base.linkAsArchive(comp, prog_node);273 return self.base.linkAsArchive(comp, prog_node);
274 } else {274 } else {
275 try self.misc_errors.ensureUnusedCapacity(self.base.allocator, 1);275 try self.misc_errors.ensureUnusedCapacity(gpa, 1);
276 self.misc_errors.appendAssumeCapacity(.{276 self.misc_errors.appendAssumeCapacity(.{
277 .msg = try self.base.allocator.dupe(u8, "TODO: non-LLVM archiver for MachO object files"),277 .msg = try gpa.dupe(u8, "TODO: non-LLVM archiver for MachO object files"),
278 });278 });
279 return error.FlushFailure;279 return error.FlushFailure;
280 }280 }
...@@ -294,7 +294,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No...@@ -294,7 +294,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
294 return try llvm_object.flushModule(comp, prog_node);294 return try llvm_object.flushModule(comp, prog_node);
295 }295 }
296296
297 var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator);297 const gpa = self.base.comp.gpa;
298 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
298 defer arena_allocator.deinit();299 defer arena_allocator.deinit();
299 const arena = arena_allocator.allocator();300 const arena = arena_allocator.allocator();
300301
...@@ -391,7 +392,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No...@@ -391,7 +392,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
391392
392 if (cache_miss) {393 if (cache_miss) {
393 for (self.dylibs.items) |*dylib| {394 for (self.dylibs.items) |*dylib| {
394 dylib.deinit(self.base.allocator);395 dylib.deinit(gpa);
395 }396 }
396 self.dylibs.clearRetainingCapacity();397 self.dylibs.clearRetainingCapacity();
397 self.dylibs_map.clearRetainingCapacity();398 self.dylibs_map.clearRetainingCapacity();
...@@ -403,7 +404,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No...@@ -403,7 +404,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
403 const in_file = try std.fs.cwd().openFile(path, .{});404 const in_file = try std.fs.cwd().openFile(path, .{});
404 defer in_file.close();405 defer in_file.close();
405406
406 var parse_ctx = ParseErrorCtx.init(self.base.allocator);407 var parse_ctx = ParseErrorCtx.init(gpa);
407 defer parse_ctx.deinit();408 defer parse_ctx.deinit();
408409
409 self.parseLibrary(410 self.parseLibrary(
...@@ -470,7 +471,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No...@@ -470,7 +471,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
470 const section = self.sections.get(sym.n_sect - 1).header;471 const section = self.sections.get(sym.n_sect - 1).header;
471 const file_offset = section.offset + sym.n_value - section.addr;472 const file_offset = section.offset + sym.n_value - section.addr;
472473
473 var code = std.ArrayList(u8).init(self.base.allocator);474 var code = std.ArrayList(u8).init(gpa);
474 defer code.deinit();475 defer code.deinit();
475 try code.resize(math.cast(usize, atom.size) orelse return error.Overflow);476 try code.resize(math.cast(usize, atom.size) orelse return error.Overflow);
476477
...@@ -518,12 +519,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No...@@ -518,12 +519,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
518 var codesig = CodeSignature.init(getPageSize(self.base.options.target.cpu.arch));519 var codesig = CodeSignature.init(getPageSize(self.base.options.target.cpu.arch));
519 codesig.code_directory.ident = self.base.options.emit.?.sub_path;520 codesig.code_directory.ident = self.base.options.emit.?.sub_path;
520 if (self.base.options.entitlements) |path| {521 if (self.base.options.entitlements) |path| {
521 try codesig.addEntitlements(self.base.allocator, path);522 try codesig.addEntitlements(gpa, path);
522 }523 }
523 try self.writeCodeSignaturePadding(&codesig);524 try self.writeCodeSignaturePadding(&codesig);
524 break :blk codesig;525 break :blk codesig;
525 } else null;526 } else null;
526 defer if (codesig) |*csig| csig.deinit(self.base.allocator);527 defer if (codesig) |*csig| csig.deinit(gpa);
527528
528 // Write load commands529 // Write load commands
529 var lc_buffer = std.ArrayList(u8).init(arena);530 var lc_buffer = std.ArrayList(u8).init(arena);
...@@ -555,12 +556,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No...@@ -555,12 +556,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
555 });556 });
556 },557 },
557 .Lib => if (self.base.options.link_mode == .Dynamic) {558 .Lib => if (self.base.options.link_mode == .Dynamic) {
558 try load_commands.writeDylibIdLC(self.base.allocator, &self.base.options, lc_writer);559 try load_commands.writeDylibIdLC(gpa, &self.base.options, lc_writer);
559 },560 },
560 else => {},561 else => {},
561 }562 }
562563
563 try load_commands.writeRpathLCs(self.base.allocator, &self.base.options, lc_writer);564 try load_commands.writeRpathLCs(gpa, &self.base.options, lc_writer);
564 try lc_writer.writeStruct(macho.source_version_command{565 try lc_writer.writeStruct(macho.source_version_command{
565 .version = 0,566 .version = 0,
566 });567 });
...@@ -644,7 +645,8 @@ pub fn resolveLibSystem(...@@ -644,7 +645,8 @@ pub fn resolveLibSystem(
644 search_dirs: []const []const u8,645 search_dirs: []const []const u8,
645 out_libs: anytype,646 out_libs: anytype,
646) !void {647) !void {
647 var tmp_arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator);648 const gpa = self.base.comp.gpa;
649 var tmp_arena_allocator = std.heap.ArenaAllocator.init(gpa);
648 defer tmp_arena_allocator.deinit();650 defer tmp_arena_allocator.deinit();
649 const tmp_arena = tmp_arena_allocator.allocator();651 const tmp_arena = tmp_arena_allocator.allocator();
650652
...@@ -775,7 +777,7 @@ fn parseObject(...@@ -775,7 +777,7 @@ fn parseObject(
775 const tracy = trace(@src());777 const tracy = trace(@src());
776 defer tracy.end();778 defer tracy.end();
777779
778 const gpa = self.base.allocator;780 const gpa = self.base.comp.gpa;
779 const mtime: u64 = mtime: {781 const mtime: u64 = mtime: {
780 const stat = file.stat() catch break :mtime 0;782 const stat = file.stat() catch break :mtime 0;
781 break :mtime @as(u64, @intCast(@divFloor(stat.mtime, 1_000_000_000)));783 break :mtime @as(u64, @intCast(@divFloor(stat.mtime, 1_000_000_000)));
...@@ -868,7 +870,7 @@ pub fn parseFatLibrary(...@@ -868,7 +870,7 @@ pub fn parseFatLibrary(
868 cpu_arch: std.Target.Cpu.Arch,870 cpu_arch: std.Target.Cpu.Arch,
869 ctx: *ParseErrorCtx,871 ctx: *ParseErrorCtx,
870) ParseError!u64 {872) ParseError!u64 {
871 const gpa = self.base.allocator;873 const gpa = self.base.comp.gpa;
872874
873 const fat_archs = try fat.parseArchs(gpa, file);875 const fat_archs = try fat.parseArchs(gpa, file);
874 defer gpa.free(fat_archs);876 defer gpa.free(fat_archs);
...@@ -892,7 +894,7 @@ fn parseArchive(...@@ -892,7 +894,7 @@ fn parseArchive(
892 must_link: bool,894 must_link: bool,
893 ctx: *ParseErrorCtx,895 ctx: *ParseErrorCtx,
894) ParseError!void {896) ParseError!void {
895 const gpa = self.base.allocator;897 const gpa = self.base.comp.gpa;
896898
897 // We take ownership of the file so that we can store it for the duration of symbol resolution.899 // We take ownership of the file so that we can store it for the duration of symbol resolution.
898 // TODO we shouldn't need to do that and could pre-parse the archive like we do for zld/ELF?900 // TODO we shouldn't need to do that and could pre-parse the archive like we do for zld/ELF?
...@@ -973,7 +975,7 @@ fn parseDylib(...@@ -973,7 +975,7 @@ fn parseDylib(
973 dylib_options: DylibOpts,975 dylib_options: DylibOpts,
974 ctx: *ParseErrorCtx,976 ctx: *ParseErrorCtx,
975) ParseError!void {977) ParseError!void {
976 const gpa = self.base.allocator;978 const gpa = self.base.comp.gpa;
977 const file_stat = try file.stat();979 const file_stat = try file.stat();
978 const file_size = math.cast(usize, file_stat.size - offset) orelse return error.Overflow;980 const file_size = math.cast(usize, file_stat.size - offset) orelse return error.Overflow;
979981
...@@ -1019,7 +1021,7 @@ fn parseLibStub(...@@ -1019,7 +1021,7 @@ fn parseLibStub(
1019 dylib_options: DylibOpts,1021 dylib_options: DylibOpts,
1020 ctx: *ParseErrorCtx,1022 ctx: *ParseErrorCtx,
1021) ParseError!void {1023) ParseError!void {
1022 const gpa = self.base.allocator;1024 const gpa = self.base.comp.gpa;
1023 var lib_stub = try LibStub.loadFromFile(gpa, file);1025 var lib_stub = try LibStub.loadFromFile(gpa, file);
1024 defer lib_stub.deinit();1026 defer lib_stub.deinit();
10251027
...@@ -1072,7 +1074,7 @@ fn addDylib(self: *MachO, dylib: Dylib, dylib_options: DylibOpts, ctx: *ParseErr...@@ -1072,7 +1074,7 @@ fn addDylib(self: *MachO, dylib: Dylib, dylib_options: DylibOpts, ctx: *ParseErr
1072 }1074 }
1073 }1075 }
10741076
1075 const gpa = self.base.allocator;1077 const gpa = self.base.comp.gpa;
1076 const gop = try self.dylibs_map.getOrPut(gpa, dylib.id.?.name);1078 const gop = try self.dylibs_map.getOrPut(gpa, dylib.id.?.name);
1077 if (gop.found_existing) return error.DylibAlreadyExists;1079 if (gop.found_existing) return error.DylibAlreadyExists;
10781080
...@@ -1098,7 +1100,7 @@ pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype) !void {...@@ -1098,7 +1100,7 @@ pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype) !void {
1098 // 2) afterwards, we parse dependents of the included dylibs1100 // 2) afterwards, we parse dependents of the included dylibs
1099 // TODO this should not be performed if the user specifies `-flat_namespace` flag.1101 // TODO this should not be performed if the user specifies `-flat_namespace` flag.
1100 // See ld64 manpages.1102 // See ld64 manpages.
1101 const gpa = self.base.allocator;1103 const gpa = self.base.comp.gpa;
11021104
1103 while (dependent_libs.readItem()) |dep_id| {1105 while (dependent_libs.readItem()) |dep_id| {
1104 defer dep_id.id.deinit(gpa);1106 defer dep_id.id.deinit(gpa);
...@@ -1162,7 +1164,8 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void {...@@ -1162,7 +1164,8 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void {
1162 log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ atom.getName(self), file_offset });1164 log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ atom.getName(self), file_offset });
11631165
1164 // Gather relocs which can be resolved.1166 // Gather relocs which can be resolved.
1165 var relocs = std.ArrayList(*Relocation).init(self.base.allocator);1167 const gpa = self.base.comp.gpa;
1168 var relocs = std.ArrayList(*Relocation).init(gpa);
1166 defer relocs.deinit();1169 defer relocs.deinit();
11671170
1168 if (self.relocs.getPtr(atom_index)) |rels| {1171 if (self.relocs.getPtr(atom_index)) |rels| {
...@@ -1237,7 +1240,7 @@ fn writeOffsetTableEntry(self: *MachO, index: usize) !void {...@@ -1237,7 +1240,7 @@ fn writeOffsetTableEntry(self: *MachO, index: usize) !void {
1237fn writeStubHelperPreamble(self: *MachO) !void {1240fn writeStubHelperPreamble(self: *MachO) !void {
1238 if (self.stub_helper_preamble_allocated) return;1241 if (self.stub_helper_preamble_allocated) return;
12391242
1240 const gpa = self.base.allocator;1243 const gpa = self.base.comp.gpa;
1241 const cpu_arch = self.base.options.target.cpu.arch;1244 const cpu_arch = self.base.options.target.cpu.arch;
1242 const size = stubs.stubHelperPreambleSize(cpu_arch);1245 const size = stubs.stubHelperPreambleSize(cpu_arch);
12431246
...@@ -1290,7 +1293,7 @@ fn writeStubTableEntry(self: *MachO, index: usize) !void {...@@ -1290,7 +1293,7 @@ fn writeStubTableEntry(self: *MachO, index: usize) !void {
1290 self.stub_table_count_dirty = false;1293 self.stub_table_count_dirty = false;
1291 }1294 }
12921295
1293 const gpa = self.base.allocator;1296 const gpa = self.base.comp.gpa;
12941297
1295 const stubs_header = self.sections.items(.header)[stubs_sect_id];1298 const stubs_header = self.sections.items(.header)[stubs_sect_id];
1296 const stub_helper_header = self.sections.items(.header)[stub_helper_sect_id];1299 const stub_helper_header = self.sections.items(.header)[stub_helper_sect_id];
...@@ -1469,7 +1472,7 @@ const CreateAtomOpts = struct {...@@ -1469,7 +1472,7 @@ const CreateAtomOpts = struct {
1469};1472};
14701473
1471pub fn createAtom(self: *MachO, sym_index: u32, opts: CreateAtomOpts) !Atom.Index {1474pub fn createAtom(self: *MachO, sym_index: u32, opts: CreateAtomOpts) !Atom.Index {
1472 const gpa = self.base.allocator;1475 const gpa = self.base.comp.gpa;
1473 const index = @as(Atom.Index, @intCast(self.atoms.items.len));1476 const index = @as(Atom.Index, @intCast(self.atoms.items.len));
1474 const atom = try self.atoms.addOne(gpa);1477 const atom = try self.atoms.addOne(gpa);
1475 atom.* = .{};1478 atom.* = .{};
...@@ -1481,7 +1484,7 @@ pub fn createAtom(self: *MachO, sym_index: u32, opts: CreateAtomOpts) !Atom.Inde...@@ -1481,7 +1484,7 @@ pub fn createAtom(self: *MachO, sym_index: u32, opts: CreateAtomOpts) !Atom.Inde
1481}1484}
14821485
1483pub fn createTentativeDefAtoms(self: *MachO) !void {1486pub fn createTentativeDefAtoms(self: *MachO) !void {
1484 const gpa = self.base.allocator;1487 const gpa = self.base.comp.gpa;
14851488
1486 for (self.globals.items) |global| {1489 for (self.globals.items) |global| {
1487 const sym = self.getSymbolPtr(global);1490 const sym = self.getSymbolPtr(global);
...@@ -1536,7 +1539,8 @@ pub fn createDyldPrivateAtom(self: *MachO) !void {...@@ -1536,7 +1539,8 @@ pub fn createDyldPrivateAtom(self: *MachO) !void {
1536 .size = @sizeOf(u64),1539 .size = @sizeOf(u64),
1537 .alignment = .@"8",1540 .alignment = .@"8",
1538 });1541 });
1539 try self.atom_by_index_table.putNoClobber(self.base.allocator, sym_index, atom_index);1542 const gpa = self.base.comp.gpa;
1543 try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom_index);
15401544
1541 if (self.data_section_index == null) {1545 if (self.data_section_index == null) {
1542 self.data_section_index = try self.initSection("__DATA", "__data", .{});1546 self.data_section_index = try self.initSection("__DATA", "__data", .{});
...@@ -1560,7 +1564,7 @@ pub fn createDyldPrivateAtom(self: *MachO) !void {...@@ -1560,7 +1564,7 @@ pub fn createDyldPrivateAtom(self: *MachO) !void {
1560}1564}
15611565
1562fn createThreadLocalDescriptorAtom(self: *MachO, sym_name: []const u8, target: SymbolWithLoc) !Atom.Index {1566fn createThreadLocalDescriptorAtom(self: *MachO, sym_name: []const u8, target: SymbolWithLoc) !Atom.Index {
1563 const gpa = self.base.allocator;1567 const gpa = self.base.comp.gpa;
1564 const size = 3 * @sizeOf(u64);1568 const size = 3 * @sizeOf(u64);
1565 const required_alignment: Alignment = .@"1";1569 const required_alignment: Alignment = .@"1";
1566 const sym_index = try self.allocateSymbol();1570 const sym_index = try self.allocateSymbol();
...@@ -1595,7 +1599,7 @@ fn createThreadLocalDescriptorAtom(self: *MachO, sym_name: []const u8, target: S...@@ -1595,7 +1599,7 @@ fn createThreadLocalDescriptorAtom(self: *MachO, sym_name: []const u8, target: S
1595pub fn createMhExecuteHeaderSymbol(self: *MachO) !void {1599pub fn createMhExecuteHeaderSymbol(self: *MachO) !void {
1596 if (self.base.options.output_mode != .Exe) return;1600 if (self.base.options.output_mode != .Exe) return;
15971601
1598 const gpa = self.base.allocator;1602 const gpa = self.base.comp.gpa;
1599 const sym_index = try self.allocateSymbol();1603 const sym_index = try self.allocateSymbol();
1600 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };1604 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };
1601 const sym = self.getSymbolPtr(sym_loc);1605 const sym = self.getSymbolPtr(sym_loc);
...@@ -1622,7 +1626,7 @@ pub fn createDsoHandleSymbol(self: *MachO) !void {...@@ -1622,7 +1626,7 @@ pub fn createDsoHandleSymbol(self: *MachO) !void {
1622 const global = self.getGlobalPtr("___dso_handle") orelse return;1626 const global = self.getGlobalPtr("___dso_handle") orelse return;
1623 if (!self.getSymbol(global.*).undf()) return;1627 if (!self.getSymbol(global.*).undf()) return;
16241628
1625 const gpa = self.base.allocator;1629 const gpa = self.base.comp.gpa;
1626 const sym_index = try self.allocateSymbol();1630 const sym_index = try self.allocateSymbol();
1627 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };1631 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };
1628 const sym = self.getSymbolPtr(sym_loc);1632 const sym = self.getSymbolPtr(sym_loc);
...@@ -1686,7 +1690,7 @@ pub fn resolveSymbols(self: *MachO) !void {...@@ -1686,7 +1690,7 @@ pub fn resolveSymbols(self: *MachO) !void {
1686}1690}
16871691
1688fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void {1692fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void {
1689 const gpa = self.base.allocator;1693 const gpa = self.base.comp.gpa;
1690 const sym = self.getSymbol(current);1694 const sym = self.getSymbol(current);
1691 const sym_name = self.getSymbolName(current);1695 const sym_name = self.getSymbolName(current);
16921696
...@@ -1800,7 +1804,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u32) !void {...@@ -1800,7 +1804,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u32) !void {
1800fn resolveSymbolsInArchives(self: *MachO) !void {1804fn resolveSymbolsInArchives(self: *MachO) !void {
1801 if (self.archives.items.len == 0) return;1805 if (self.archives.items.len == 0) return;
18021806
1803 const gpa = self.base.allocator;1807 const gpa = self.base.comp.gpa;
1804 var next_sym: usize = 0;1808 var next_sym: usize = 0;
1805 loop: while (next_sym < self.unresolved.count()) {1809 loop: while (next_sym < self.unresolved.count()) {
1806 const global = self.globals.items[self.unresolved.keys()[next_sym]];1810 const global = self.globals.items[self.unresolved.keys()[next_sym]];
...@@ -1829,7 +1833,7 @@ fn resolveSymbolsInArchives(self: *MachO) !void {...@@ -1829,7 +1833,7 @@ fn resolveSymbolsInArchives(self: *MachO) !void {
1829fn resolveSymbolsInDylibs(self: *MachO) !void {1833fn resolveSymbolsInDylibs(self: *MachO) !void {
1830 if (self.dylibs.items.len == 0) return;1834 if (self.dylibs.items.len == 0) return;
18311835
1832 const gpa = self.base.allocator;1836 const gpa = self.base.comp.gpa;
1833 var next_sym: usize = 0;1837 var next_sym: usize = 0;
1834 loop: while (next_sym < self.unresolved.count()) {1838 loop: while (next_sym < self.unresolved.count()) {
1835 const global_index = self.unresolved.keys()[next_sym];1839 const global_index = self.unresolved.keys()[next_sym];
...@@ -1899,6 +1903,7 @@ fn resolveSymbolsAtLoading(self: *MachO) !void {...@@ -1899,6 +1903,7 @@ fn resolveSymbolsAtLoading(self: *MachO) !void {
1899}1903}
19001904
1901fn resolveBoundarySymbols(self: *MachO) !void {1905fn resolveBoundarySymbols(self: *MachO) !void {
1906 const gpa = self.base.comp.gpa;
1902 var next_sym: usize = 0;1907 var next_sym: usize = 0;
1903 while (next_sym < self.unresolved.count()) {1908 while (next_sym < self.unresolved.count()) {
1904 const global_index = self.unresolved.keys()[next_sym];1909 const global_index = self.unresolved.keys()[next_sym];
...@@ -1909,7 +1914,7 @@ fn resolveBoundarySymbols(self: *MachO) !void {...@@ -1909,7 +1914,7 @@ fn resolveBoundarySymbols(self: *MachO) !void {
1909 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };1914 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };
1910 const sym = self.getSymbolPtr(sym_loc);1915 const sym = self.getSymbolPtr(sym_loc);
1911 sym.* = .{1916 sym.* = .{
1912 .n_strx = try self.strtab.insert(self.base.allocator, self.getSymbolName(global.*)),1917 .n_strx = try self.strtab.insert(gpa, self.getSymbolName(global.*)),
1913 .n_type = macho.N_SECT | macho.N_EXT,1918 .n_type = macho.N_SECT | macho.N_EXT,
1914 .n_sect = 0,1919 .n_sect = 0,
1915 .n_desc = N_BOUNDARY,1920 .n_desc = N_BOUNDARY,
...@@ -1929,9 +1934,9 @@ fn resolveBoundarySymbols(self: *MachO) !void {...@@ -1929,9 +1934,9 @@ fn resolveBoundarySymbols(self: *MachO) !void {
1929}1934}
19301935
1931pub fn deinit(self: *MachO) void {1936pub fn deinit(self: *MachO) void {
1932 const gpa = self.base.allocator;1937 const gpa = self.base.comp.gpa;
19331938
1934 if (self.llvm_object) |llvm_object| llvm_object.destroy(gpa);1939 if (self.llvm_object) |llvm_object| llvm_object.deinit();
19351940
1936 if (self.d_sym) |*d_sym| {1941 if (self.d_sym) |*d_sym| {
1937 d_sym.deinit();1942 d_sym.deinit();
...@@ -2032,7 +2037,7 @@ pub fn deinit(self: *MachO) void {...@@ -2032,7 +2037,7 @@ pub fn deinit(self: *MachO) void {
2032}2037}
20332038
2034fn freeAtom(self: *MachO, atom_index: Atom.Index) void {2039fn freeAtom(self: *MachO, atom_index: Atom.Index) void {
2035 const gpa = self.base.allocator;2040 const gpa = self.base.comp.gpa;
2036 log.debug("freeAtom {d}", .{atom_index});2041 log.debug("freeAtom {d}", .{atom_index});
20372042
2038 // Remove any relocs and base relocs associated with this Atom2043 // Remove any relocs and base relocs associated with this Atom
...@@ -2124,7 +2129,8 @@ fn growAtom(self: *MachO, atom_index: Atom.Index, new_atom_size: u64, alignment:...@@ -2124,7 +2129,8 @@ fn growAtom(self: *MachO, atom_index: Atom.Index, new_atom_size: u64, alignment:
2124}2129}
21252130
2126pub fn allocateSymbol(self: *MachO) !u32 {2131pub fn allocateSymbol(self: *MachO) !u32 {
2127 try self.locals.ensureUnusedCapacity(self.base.allocator, 1);2132 const gpa = self.base.comp.gpa;
2133 try self.locals.ensureUnusedCapacity(gpa, 1);
21282134
2129 const index = blk: {2135 const index = blk: {
2130 if (self.locals_free_list.popOrNull()) |index| {2136 if (self.locals_free_list.popOrNull()) |index| {
...@@ -2150,7 +2156,8 @@ pub fn allocateSymbol(self: *MachO) !u32 {...@@ -2150,7 +2156,8 @@ pub fn allocateSymbol(self: *MachO) !u32 {
2150}2156}
21512157
2152fn allocateGlobal(self: *MachO) !u32 {2158fn allocateGlobal(self: *MachO) !u32 {
2153 try self.globals.ensureUnusedCapacity(self.base.allocator, 1);2159 const gpa = self.base.comp.gpa;
2160 try self.globals.ensureUnusedCapacity(gpa, 1);
21542161
2155 const index = blk: {2162 const index = blk: {
2156 if (self.globals_free_list.popOrNull()) |index| {2163 if (self.globals_free_list.popOrNull()) |index| {
...@@ -2171,7 +2178,8 @@ fn allocateGlobal(self: *MachO) !u32 {...@@ -2171,7 +2178,8 @@ fn allocateGlobal(self: *MachO) !u32 {
21712178
2172pub fn addGotEntry(self: *MachO, target: SymbolWithLoc) !void {2179pub fn addGotEntry(self: *MachO, target: SymbolWithLoc) !void {
2173 if (self.got_table.lookup.contains(target)) return;2180 if (self.got_table.lookup.contains(target)) return;
2174 const got_index = try self.got_table.allocateEntry(self.base.allocator, target);2181 const gpa = self.base.comp.gpa;
2182 const got_index = try self.got_table.allocateEntry(gpa, target);
2175 if (self.got_section_index == null) {2183 if (self.got_section_index == null) {
2176 self.got_section_index = try self.initSection("__DATA_CONST", "__got", .{2184 self.got_section_index = try self.initSection("__DATA_CONST", "__got", .{
2177 .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,2185 .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
...@@ -2186,7 +2194,8 @@ pub fn addGotEntry(self: *MachO, target: SymbolWithLoc) !void {...@@ -2186,7 +2194,8 @@ pub fn addGotEntry(self: *MachO, target: SymbolWithLoc) !void {
21862194
2187pub fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {2195pub fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {
2188 if (self.stub_table.lookup.contains(target)) return;2196 if (self.stub_table.lookup.contains(target)) return;
2189 const stub_index = try self.stub_table.allocateEntry(self.base.allocator, target);2197 const gpa = self.base.comp.gpa;
2198 const stub_index = try self.stub_table.allocateEntry(gpa, target);
2190 if (self.stubs_section_index == null) {2199 if (self.stubs_section_index == null) {
2191 self.stubs_section_index = try self.initSection("__TEXT", "__stubs", .{2200 self.stubs_section_index = try self.initSection("__TEXT", "__stubs", .{
2192 .flags = macho.S_SYMBOL_STUBS |2201 .flags = macho.S_SYMBOL_STUBS |
...@@ -2212,7 +2221,8 @@ pub fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {...@@ -2212,7 +2221,8 @@ pub fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {
22122221
2213pub fn addTlvPtrEntry(self: *MachO, target: SymbolWithLoc) !void {2222pub fn addTlvPtrEntry(self: *MachO, target: SymbolWithLoc) !void {
2214 if (self.tlv_ptr_table.lookup.contains(target)) return;2223 if (self.tlv_ptr_table.lookup.contains(target)) return;
2215 _ = try self.tlv_ptr_table.allocateEntry(self.base.allocator, target);2224 const gpa = self.base.comp.gpa;
2225 _ = try self.tlv_ptr_table.allocateEntry(gpa, target);
2216 if (self.tlv_ptr_section_index == null) {2226 if (self.tlv_ptr_section_index == null) {
2217 self.tlv_ptr_section_index = try self.initSection("__DATA", "__thread_ptrs", .{2227 self.tlv_ptr_section_index = try self.initSection("__DATA", "__thread_ptrs", .{
2218 .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS,2228 .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
...@@ -2236,7 +2246,8 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air:...@@ -2236,7 +2246,8 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air:
2236 self.freeUnnamedConsts(decl_index);2246 self.freeUnnamedConsts(decl_index);
2237 Atom.freeRelocations(self, atom_index);2247 Atom.freeRelocations(self, atom_index);
22382248
2239 var code_buffer = std.ArrayList(u8).init(self.base.allocator);2249 const gpa = self.base.comp.gpa;
2250 var code_buffer = std.ArrayList(u8).init(gpa);
2240 defer code_buffer.deinit();2251 defer code_buffer.deinit();
22412252
2242 var decl_state = if (self.d_sym) |*d_sym|2253 var decl_state = if (self.d_sym) |*d_sym|
...@@ -2279,7 +2290,7 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air:...@@ -2279,7 +2290,7 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air:
2279}2290}
22802291
2281pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: InternPool.DeclIndex) !u32 {2292pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: InternPool.DeclIndex) !u32 {
2282 const gpa = self.base.allocator;2293 const gpa = self.base.comp.gpa;
2283 const mod = self.base.options.module.?;2294 const mod = self.base.options.module.?;
2284 const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index);2295 const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index);
2285 if (!gop.found_existing) {2296 if (!gop.found_existing) {
...@@ -2318,7 +2329,7 @@ fn lowerConst(...@@ -2318,7 +2329,7 @@ fn lowerConst(
2318 sect_id: u8,2329 sect_id: u8,
2319 src_loc: Module.SrcLoc,2330 src_loc: Module.SrcLoc,
2320) !LowerConstResult {2331) !LowerConstResult {
2321 const gpa = self.base.allocator;2332 const gpa = self.base.comp.gpa;
23222333
2323 var code_buffer = std.ArrayList(u8).init(gpa);2334 var code_buffer = std.ArrayList(u8).init(gpa);
2324 defer code_buffer.deinit();2335 defer code_buffer.deinit();
...@@ -2366,6 +2377,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex)...@@ -2366,6 +2377,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex)
2366 const tracy = trace(@src());2377 const tracy = trace(@src());
2367 defer tracy.end();2378 defer tracy.end();
23682379
2380 const gpa = self.base.comp.gpa;
2369 const decl = mod.declPtr(decl_index);2381 const decl = mod.declPtr(decl_index);
23702382
2371 if (decl.val.getExternFunc(mod)) |_| {2383 if (decl.val.getExternFunc(mod)) |_| {
...@@ -2375,8 +2387,8 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex)...@@ -2375,8 +2387,8 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex)
2375 if (decl.isExtern(mod)) {2387 if (decl.isExtern(mod)) {
2376 // TODO make this part of getGlobalSymbol2388 // TODO make this part of getGlobalSymbol
2377 const name = mod.intern_pool.stringToSlice(decl.name);2389 const name = mod.intern_pool.stringToSlice(decl.name);
2378 const sym_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{name});2390 const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name});
2379 defer self.base.allocator.free(sym_name);2391 defer gpa.free(sym_name);
2380 _ = try self.addUndefined(sym_name, .{ .add_got = true });2392 _ = try self.addUndefined(sym_name, .{ .add_got = true });
2381 return;2393 return;
2382 }2394 }
...@@ -2391,7 +2403,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex)...@@ -2391,7 +2403,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex)
2391 const sym_index = self.getAtom(atom_index).getSymbolIndex().?;2403 const sym_index = self.getAtom(atom_index).getSymbolIndex().?;
2392 Atom.freeRelocations(self, atom_index);2404 Atom.freeRelocations(self, atom_index);
23932405
2394 var code_buffer = std.ArrayList(u8).init(self.base.allocator);2406 var code_buffer = std.ArrayList(u8).init(gpa);
2395 defer code_buffer.deinit();2407 defer code_buffer.deinit();
23962408
2397 var decl_state: ?Dwarf.DeclState = if (self.d_sym) |*d_sym|2409 var decl_state: ?Dwarf.DeclState = if (self.d_sym) |*d_sym|
...@@ -2449,7 +2461,7 @@ fn updateLazySymbolAtom(...@@ -2449,7 +2461,7 @@ fn updateLazySymbolAtom(
2449 atom_index: Atom.Index,2461 atom_index: Atom.Index,
2450 section_index: u8,2462 section_index: u8,
2451) !void {2463) !void {
2452 const gpa = self.base.allocator;2464 const gpa = self.base.comp.gpa;
2453 const mod = self.base.options.module.?;2465 const mod = self.base.options.module.?;
24542466
2455 var required_alignment: Alignment = .none;2467 var required_alignment: Alignment = .none;
...@@ -2515,7 +2527,8 @@ fn updateLazySymbolAtom(...@@ -2515,7 +2527,8 @@ fn updateLazySymbolAtom(
25152527
2516pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.Index {2528pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.Index {
2517 const mod = self.base.options.module.?;2529 const mod = self.base.options.module.?;
2518 const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl(mod));2530 const gpa = self.base.comp.gpa;
2531 const gop = try self.lazy_syms.getOrPut(gpa, sym.getDecl(mod));
2519 errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();2532 errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
2520 if (!gop.found_existing) gop.value_ptr.* = .{};2533 if (!gop.found_existing) gop.value_ptr.* = .{};
2521 const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) {2534 const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) {
...@@ -2529,7 +2542,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.In...@@ -2529,7 +2542,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.In
2529 .unused => {2542 .unused => {
2530 const sym_index = try self.allocateSymbol();2543 const sym_index = try self.allocateSymbol();
2531 metadata.atom.* = try self.createAtom(sym_index, .{});2544 metadata.atom.* = try self.createAtom(sym_index, .{});
2532 try self.atom_by_index_table.putNoClobber(self.base.allocator, sym_index, metadata.atom.*);2545 try self.atom_by_index_table.putNoClobber(gpa, sym_index, metadata.atom.*);
2533 },2546 },
2534 .pending_flush => return metadata.atom.*,2547 .pending_flush => return metadata.atom.*,
2535 .flushed => {},2548 .flushed => {},
...@@ -2556,7 +2569,7 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: InternPo...@@ -2556,7 +2569,7 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: InternPo
2556 const init_sym_index = init_atom.getSymbolIndex().?;2569 const init_sym_index = init_atom.getSymbolIndex().?;
2557 Atom.freeRelocations(self, init_atom_index);2570 Atom.freeRelocations(self, init_atom_index);
25582571
2559 const gpa = self.base.allocator;2572 const gpa = self.base.comp.gpa;
25602573
2561 var code_buffer = std.ArrayList(u8).init(gpa);2574 var code_buffer = std.ArrayList(u8).init(gpa);
2562 defer code_buffer.deinit();2575 defer code_buffer.deinit();
...@@ -2640,11 +2653,12 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: InternPo...@@ -2640,11 +2653,12 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: InternPo
2640}2653}
26412654
2642pub fn getOrCreateAtomForDecl(self: *MachO, decl_index: InternPool.DeclIndex) !Atom.Index {2655pub fn getOrCreateAtomForDecl(self: *MachO, decl_index: InternPool.DeclIndex) !Atom.Index {
2643 const gop = try self.decls.getOrPut(self.base.allocator, decl_index);2656 const gpa = self.base.comp.gpa;
2657 const gop = try self.decls.getOrPut(gpa, decl_index);
2644 if (!gop.found_existing) {2658 if (!gop.found_existing) {
2645 const sym_index = try self.allocateSymbol();2659 const sym_index = try self.allocateSymbol();
2646 const atom_index = try self.createAtom(sym_index, .{});2660 const atom_index = try self.createAtom(sym_index, .{});
2647 try self.atom_by_index_table.putNoClobber(self.base.allocator, sym_index, atom_index);2661 try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom_index);
2648 gop.value_ptr.* = .{2662 gop.value_ptr.* = .{
2649 .atom = atom_index,2663 .atom = atom_index,
2650 .section = self.getDeclOutputSection(decl_index),2664 .section = self.getDeclOutputSection(decl_index),
...@@ -2694,7 +2708,7 @@ fn getDeclOutputSection(self: *MachO, decl_index: InternPool.DeclIndex) u8 {...@@ -2694,7 +2708,7 @@ fn getDeclOutputSection(self: *MachO, decl_index: InternPool.DeclIndex) u8 {
2694}2708}
26952709
2696fn updateDeclCode(self: *MachO, decl_index: InternPool.DeclIndex, code: []u8) !u64 {2710fn updateDeclCode(self: *MachO, decl_index: InternPool.DeclIndex, code: []u8) !u64 {
2697 const gpa = self.base.allocator;2711 const gpa = self.base.comp.gpa;
2698 const mod = self.base.options.module.?;2712 const mod = self.base.options.module.?;
2699 const decl = mod.declPtr(decl_index);2713 const decl = mod.declPtr(decl_index);
27002714
...@@ -2787,7 +2801,7 @@ pub fn updateExports(...@@ -2787,7 +2801,7 @@ pub fn updateExports(
2787 const tracy = trace(@src());2801 const tracy = trace(@src());
2788 defer tracy.end();2802 defer tracy.end();
27892803
2790 const gpa = self.base.allocator;2804 const gpa = self.base.comp.gpa;
27912805
2792 const metadata = switch (exported) {2806 const metadata = switch (exported) {
2793 .decl_index => |decl_index| blk: {2807 .decl_index => |decl_index| blk: {
...@@ -2912,7 +2926,7 @@ pub fn deleteDeclExport(...@@ -2912,7 +2926,7 @@ pub fn deleteDeclExport(
2912 if (self.llvm_object) |_| return;2926 if (self.llvm_object) |_| return;
2913 const metadata = self.decls.getPtr(decl_index) orelse return;2927 const metadata = self.decls.getPtr(decl_index) orelse return;
29142928
2915 const gpa = self.base.allocator;2929 const gpa = self.base.comp.gpa;
2916 const mod = self.base.options.module.?;2930 const mod = self.base.options.module.?;
2917 const exp_name = try std.fmt.allocPrint(gpa, "_{s}", .{mod.intern_pool.stringToSlice(name)});2931 const exp_name = try std.fmt.allocPrint(gpa, "_{s}", .{mod.intern_pool.stringToSlice(name)});
2918 defer gpa.free(exp_name);2932 defer gpa.free(exp_name);
...@@ -2941,7 +2955,7 @@ pub fn deleteDeclExport(...@@ -2941,7 +2955,7 @@ pub fn deleteDeclExport(
2941}2955}
29422956
2943fn freeUnnamedConsts(self: *MachO, decl_index: InternPool.DeclIndex) void {2957fn freeUnnamedConsts(self: *MachO, decl_index: InternPool.DeclIndex) void {
2944 const gpa = self.base.allocator;2958 const gpa = self.base.comp.gpa;
2945 const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return;2959 const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return;
2946 for (unnamed_consts.items) |atom| {2960 for (unnamed_consts.items) |atom| {
2947 self.freeAtom(atom);2961 self.freeAtom(atom);
...@@ -2951,6 +2965,7 @@ fn freeUnnamedConsts(self: *MachO, decl_index: InternPool.DeclIndex) void {...@@ -2951,6 +2965,7 @@ fn freeUnnamedConsts(self: *MachO, decl_index: InternPool.DeclIndex) void {
29512965
2952pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void {2966pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void {
2953 if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index);2967 if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index);
2968 const gpa = self.base.comp.gpa;
2954 const mod = self.base.options.module.?;2969 const mod = self.base.options.module.?;
2955 const decl = mod.declPtr(decl_index);2970 const decl = mod.declPtr(decl_index);
29562971
...@@ -2960,7 +2975,7 @@ pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void {...@@ -2960,7 +2975,7 @@ pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void {
2960 var kv = const_kv;2975 var kv = const_kv;
2961 self.freeAtom(kv.value.atom);2976 self.freeAtom(kv.value.atom);
2962 self.freeUnnamedConsts(decl_index);2977 self.freeUnnamedConsts(decl_index);
2963 kv.value.exports.deinit(self.base.allocator);2978 kv.value.exports.deinit(gpa);
2964 }2979 }
29652980
2966 if (self.d_sym) |*d_sym| {2981 if (self.d_sym) |*d_sym| {
...@@ -2993,7 +3008,7 @@ pub fn lowerAnonDecl(...@@ -2993,7 +3008,7 @@ pub fn lowerAnonDecl(
2993 explicit_alignment: InternPool.Alignment,3008 explicit_alignment: InternPool.Alignment,
2994 src_loc: Module.SrcLoc,3009 src_loc: Module.SrcLoc,
2995) !codegen.Result {3010) !codegen.Result {
2996 const gpa = self.base.allocator;3011 const gpa = self.base.comp.gpa;
2997 const mod = self.base.options.module.?;3012 const mod = self.base.options.module.?;
2998 const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val));3013 const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val));
2999 const decl_alignment = switch (explicit_alignment) {3014 const decl_alignment = switch (explicit_alignment) {
...@@ -3060,7 +3075,7 @@ pub fn getAnonDeclVAddr(self: *MachO, decl_val: InternPool.Index, reloc_info: li...@@ -3060,7 +3075,7 @@ pub fn getAnonDeclVAddr(self: *MachO, decl_val: InternPool.Index, reloc_info: li
3060fn populateMissingMetadata(self: *MachO) !void {3075fn populateMissingMetadata(self: *MachO) !void {
3061 assert(self.mode == .incremental);3076 assert(self.mode == .incremental);
30623077
3063 const gpa = self.base.allocator;3078 const gpa = self.base.comp.gpa;
3064 const cpu_arch = self.base.options.target.cpu.arch;3079 const cpu_arch = self.base.options.target.cpu.arch;
3065 const pagezero_vmsize = self.calcPagezeroSize();3080 const pagezero_vmsize = self.calcPagezeroSize();
30663081
...@@ -3228,7 +3243,8 @@ const InitSectionOpts = struct {...@@ -3228,7 +3243,8 @@ const InitSectionOpts = struct {
3228pub fn initSection(self: *MachO, segname: []const u8, sectname: []const u8, opts: InitSectionOpts) !u8 {3243pub fn initSection(self: *MachO, segname: []const u8, sectname: []const u8, opts: InitSectionOpts) !u8 {
3229 log.debug("creating section '{s},{s}'", .{ segname, sectname });3244 log.debug("creating section '{s},{s}'", .{ segname, sectname });
3230 const index = @as(u8, @intCast(self.sections.slice().len));3245 const index = @as(u8, @intCast(self.sections.slice().len));
3231 try self.sections.append(self.base.allocator, .{3246 const gpa = self.base.comp.gpa;
3247 try self.sections.append(gpa, .{
3232 .segment_index = undefined, // Segments will be created automatically later down the pipeline3248 .segment_index = undefined, // Segments will be created automatically later down the pipeline
3233 .header = .{3249 .header = .{
3234 .sectname = makeStaticString(sectname),3250 .sectname = makeStaticString(sectname),
...@@ -3248,7 +3264,7 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts...@@ -3248,7 +3264,7 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts
3248 flags: u32 = macho.S_REGULAR,3264 flags: u32 = macho.S_REGULAR,
3249 reserved2: u32 = 0,3265 reserved2: u32 = 0,
3250}) !u8 {3266}) !u8 {
3251 const gpa = self.base.allocator;3267 const gpa = self.base.comp.gpa;
3252 const page_size = getPageSize(self.base.options.target.cpu.arch);3268 const page_size = getPageSize(self.base.options.target.cpu.arch);
3253 // In incremental context, we create one section per segment pairing. This way,3269 // In incremental context, we create one section per segment pairing. This way,
3254 // we can move the segment in raw file as we please.3270 // we can move the segment in raw file as we please.
...@@ -3521,7 +3537,7 @@ fn allocateAtom(self: *MachO, atom_index: Atom.Index, new_atom_size: u64, alignm...@@ -3521,7 +3537,7 @@ fn allocateAtom(self: *MachO, atom_index: Atom.Index, new_atom_size: u64, alignm
35213537
3522pub fn getGlobalSymbol(self: *MachO, name: []const u8, lib_name: ?[]const u8) !u32 {3538pub fn getGlobalSymbol(self: *MachO, name: []const u8, lib_name: ?[]const u8) !u32 {
3523 _ = lib_name;3539 _ = lib_name;
3524 const gpa = self.base.allocator;3540 const gpa = self.base.comp.gpa;
3525 const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name});3541 const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name});
3526 defer gpa.free(sym_name);3542 defer gpa.free(sym_name);
3527 return self.addUndefined(sym_name, .{ .add_stub = true });3543 return self.addUndefined(sym_name, .{ .add_stub = true });
...@@ -3582,7 +3598,7 @@ pub fn writeLinkeditSegmentData(self: *MachO) !void {...@@ -3582,7 +3598,7 @@ pub fn writeLinkeditSegmentData(self: *MachO) !void {
3582}3598}
35833599
3584fn collectRebaseDataFromTableSection(self: *MachO, sect_id: u8, rebase: *Rebase, table: anytype) !void {3600fn collectRebaseDataFromTableSection(self: *MachO, sect_id: u8, rebase: *Rebase, table: anytype) !void {
3585 const gpa = self.base.allocator;3601 const gpa = self.base.comp.gpa;
3586 const header = self.sections.items(.header)[sect_id];3602 const header = self.sections.items(.header)[sect_id];
3587 const segment_index = self.sections.items(.segment_index)[sect_id];3603 const segment_index = self.sections.items(.segment_index)[sect_id];
3588 const segment = self.segments.items[segment_index];3604 const segment = self.segments.items[segment_index];
...@@ -3605,7 +3621,7 @@ fn collectRebaseDataFromTableSection(self: *MachO, sect_id: u8, rebase: *Rebase,...@@ -3605,7 +3621,7 @@ fn collectRebaseDataFromTableSection(self: *MachO, sect_id: u8, rebase: *Rebase,
3605}3621}
36063622
3607fn collectRebaseData(self: *MachO, rebase: *Rebase) !void {3623fn collectRebaseData(self: *MachO, rebase: *Rebase) !void {
3608 const gpa = self.base.allocator;3624 const gpa = self.base.comp.gpa;
3609 const slice = self.sections.slice();3625 const slice = self.sections.slice();
36103626
3611 for (self.rebases.keys(), 0..) |atom_index, i| {3627 for (self.rebases.keys(), 0..) |atom_index, i| {
...@@ -3715,7 +3731,7 @@ fn collectRebaseData(self: *MachO, rebase: *Rebase) !void {...@@ -3715,7 +3731,7 @@ fn collectRebaseData(self: *MachO, rebase: *Rebase) !void {
3715}3731}
37163732
3717fn collectBindDataFromTableSection(self: *MachO, sect_id: u8, bind: anytype, table: anytype) !void {3733fn collectBindDataFromTableSection(self: *MachO, sect_id: u8, bind: anytype, table: anytype) !void {
3718 const gpa = self.base.allocator;3734 const gpa = self.base.comp.gpa;
3719 const header = self.sections.items(.header)[sect_id];3735 const header = self.sections.items(.header)[sect_id];
3720 const segment_index = self.sections.items(.segment_index)[sect_id];3736 const segment_index = self.sections.items(.segment_index)[sect_id];
3721 const segment = self.segments.items[segment_index];3737 const segment = self.segments.items[segment_index];
...@@ -3746,7 +3762,7 @@ fn collectBindDataFromTableSection(self: *MachO, sect_id: u8, bind: anytype, tab...@@ -3746,7 +3762,7 @@ fn collectBindDataFromTableSection(self: *MachO, sect_id: u8, bind: anytype, tab
3746}3762}
37473763
3748fn collectBindData(self: *MachO, bind: anytype, raw_bindings: anytype) !void {3764fn collectBindData(self: *MachO, bind: anytype, raw_bindings: anytype) !void {
3749 const gpa = self.base.allocator;3765 const gpa = self.base.comp.gpa;
3750 const slice = self.sections.slice();3766 const slice = self.sections.slice();
37513767
3752 for (raw_bindings.keys(), 0..) |atom_index, i| {3768 for (raw_bindings.keys(), 0..) |atom_index, i| {
...@@ -3885,12 +3901,13 @@ fn collectBindData(self: *MachO, bind: anytype, raw_bindings: anytype) !void {...@@ -3885,12 +3901,13 @@ fn collectBindData(self: *MachO, bind: anytype, raw_bindings: anytype) !void {
38853901
3886fn collectLazyBindData(self: *MachO, bind: anytype) !void {3902fn collectLazyBindData(self: *MachO, bind: anytype) !void {
3887 const sect_id = self.la_symbol_ptr_section_index orelse return;3903 const sect_id = self.la_symbol_ptr_section_index orelse return;
3904 const gpa = self.base.comp.gpa;
3888 try self.collectBindDataFromTableSection(sect_id, bind, self.stub_table);3905 try self.collectBindDataFromTableSection(sect_id, bind, self.stub_table);
3889 try bind.finalize(self.base.allocator, self);3906 try bind.finalize(gpa, self);
3890}3907}
38913908
3892fn collectExportData(self: *MachO, trie: *Trie) !void {3909fn collectExportData(self: *MachO, trie: *Trie) !void {
3893 const gpa = self.base.allocator;3910 const gpa = self.base.comp.gpa;
38943911
3895 // TODO handle macho.EXPORT_SYMBOL_FLAGS_REEXPORT and macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER.3912 // TODO handle macho.EXPORT_SYMBOL_FLAGS_REEXPORT and macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER.
3896 log.debug("generating export trie", .{});3913 log.debug("generating export trie", .{});
...@@ -3922,7 +3939,7 @@ fn writeDyldInfoData(self: *MachO) !void {...@@ -3922,7 +3939,7 @@ fn writeDyldInfoData(self: *MachO) !void {
3922 const tracy = trace(@src());3939 const tracy = trace(@src());
3923 defer tracy.end();3940 defer tracy.end();
39243941
3925 const gpa = self.base.allocator;3942 const gpa = self.base.comp.gpa;
39263943
3927 var rebase = Rebase{};3944 var rebase = Rebase{};
3928 defer rebase.deinit(gpa);3945 defer rebase.deinit(gpa);
...@@ -4046,7 +4063,7 @@ fn addSymbolToFunctionStarts(self: *MachO, sym_loc: SymbolWithLoc, addresses: *s...@@ -4046,7 +4063,7 @@ fn addSymbolToFunctionStarts(self: *MachO, sym_loc: SymbolWithLoc, addresses: *s
4046}4063}
40474064
4048fn writeFunctionStarts(self: *MachO) !void {4065fn writeFunctionStarts(self: *MachO) !void {
4049 const gpa = self.base.allocator;4066 const gpa = self.base.comp.gpa;
4050 const seg = self.segments.items[self.header_segment_cmd_index.?];4067 const seg = self.segments.items[self.header_segment_cmd_index.?];
40514068
4052 // We need to sort by address first4069 // We need to sort by address first
...@@ -4133,7 +4150,7 @@ fn filterDataInCode(...@@ -4133,7 +4150,7 @@ fn filterDataInCode(
4133}4150}
41344151
4135pub fn writeDataInCode(self: *MachO) !void {4152pub fn writeDataInCode(self: *MachO) !void {
4136 const gpa = self.base.allocator;4153 const gpa = self.base.comp.gpa;
4137 var out_dice = std.ArrayList(macho.data_in_code_entry).init(gpa);4154 var out_dice = std.ArrayList(macho.data_in_code_entry).init(gpa);
4138 defer out_dice.deinit();4155 defer out_dice.deinit();
41394156
...@@ -4211,13 +4228,14 @@ fn addLocalToSymtab(self: *MachO, sym_loc: SymbolWithLoc, locals: *std.ArrayList...@@ -4211,13 +4228,14 @@ fn addLocalToSymtab(self: *MachO, sym_loc: SymbolWithLoc, locals: *std.ArrayList
4211 if (sym.n_desc == N_BOUNDARY) return; // boundary symbol, skip4228 if (sym.n_desc == N_BOUNDARY) return; // boundary symbol, skip
4212 if (sym.ext()) return; // an export lands in its own symtab section, skip4229 if (sym.ext()) return; // an export lands in its own symtab section, skip
4213 if (self.symbolIsTemp(sym_loc)) return; // local temp symbol, skip4230 if (self.symbolIsTemp(sym_loc)) return; // local temp symbol, skip
4231 const gpa = self.base.comp.gpa;
4214 var out_sym = sym;4232 var out_sym = sym;
4215 out_sym.n_strx = try self.strtab.insert(self.base.allocator, self.getSymbolName(sym_loc));4233 out_sym.n_strx = try self.strtab.insert(gpa, self.getSymbolName(sym_loc));
4216 try locals.append(out_sym);4234 try locals.append(out_sym);
4217}4235}
42184236
4219fn writeSymtab(self: *MachO) !SymtabCtx {4237fn writeSymtab(self: *MachO) !SymtabCtx {
4220 const gpa = self.base.allocator;4238 const gpa = self.base.comp.gpa;
42214239
4222 var locals = std.ArrayList(macho.nlist_64).init(gpa);4240 var locals = std.ArrayList(macho.nlist_64).init(gpa);
4223 defer locals.deinit();4241 defer locals.deinit();
...@@ -4322,7 +4340,7 @@ fn generateSymbolStabs(...@@ -4322,7 +4340,7 @@ fn generateSymbolStabs(
4322) !void {4340) !void {
4323 log.debug("generating stabs for '{s}'", .{object.name});4341 log.debug("generating stabs for '{s}'", .{object.name});
43244342
4325 const gpa = self.base.allocator;4343 const gpa = self.base.comp.gpa;
4326 var debug_info = object.parseDwarfInfo();4344 var debug_info = object.parseDwarfInfo();
43274345
4328 var lookup = DwarfInfo.AbbrevLookupTable.init(gpa);4346 var lookup = DwarfInfo.AbbrevLookupTable.init(gpa);
...@@ -4450,7 +4468,7 @@ fn generateSymbolStabsForSymbol(...@@ -4450,7 +4468,7 @@ fn generateSymbolStabsForSymbol(
4450 lookup: ?DwarfInfo.SubprogramLookupByName,4468 lookup: ?DwarfInfo.SubprogramLookupByName,
4451 buf: *[4]macho.nlist_64,4469 buf: *[4]macho.nlist_64,
4452) ![]const macho.nlist_64 {4470) ![]const macho.nlist_64 {
4453 const gpa = self.base.allocator;4471 const gpa = self.base.comp.gpa;
4454 const object = self.objects.items[sym_loc.getFile().?];4472 const object = self.objects.items[sym_loc.getFile().?];
4455 const sym = self.getSymbol(sym_loc);4473 const sym = self.getSymbol(sym_loc);
4456 const sym_name = self.getSymbolName(sym_loc);4474 const sym_name = self.getSymbolName(sym_loc);
...@@ -4536,7 +4554,7 @@ fn generateSymbolStabsForSymbol(...@@ -4536,7 +4554,7 @@ fn generateSymbolStabsForSymbol(
4536}4554}
45374555
4538pub fn writeStrtab(self: *MachO) !void {4556pub fn writeStrtab(self: *MachO) !void {
4539 const gpa = self.base.allocator;4557 const gpa = self.base.comp.gpa;
4540 const seg = self.getLinkeditSegmentPtr();4558 const seg = self.getLinkeditSegmentPtr();
4541 const offset = seg.fileoff + seg.filesize;4559 const offset = seg.fileoff + seg.filesize;
4542 assert(mem.isAlignedGeneric(u64, offset, @alignOf(u64)));4560 assert(mem.isAlignedGeneric(u64, offset, @alignOf(u64)));
...@@ -4565,7 +4583,7 @@ const SymtabCtx = struct {...@@ -4565,7 +4583,7 @@ const SymtabCtx = struct {
4565};4583};
45664584
4567pub fn writeDysymtab(self: *MachO, ctx: SymtabCtx) !void {4585pub fn writeDysymtab(self: *MachO, ctx: SymtabCtx) !void {
4568 const gpa = self.base.allocator;4586 const gpa = self.base.comp.gpa;
4569 const nstubs = @as(u32, @intCast(self.stub_table.lookup.count()));4587 const nstubs = @as(u32, @intCast(self.stub_table.lookup.count()));
4570 const ngot_entries = @as(u32, @intCast(self.got_table.lookup.count()));4588 const ngot_entries = @as(u32, @intCast(self.got_table.lookup.count()));
4571 const nindirectsyms = nstubs * 2 + ngot_entries;4589 const nindirectsyms = nstubs * 2 + ngot_entries;
...@@ -4671,7 +4689,8 @@ pub fn writeCodeSignature(self: *MachO, comp: *const Compilation, code_sig: *Cod...@@ -4671,7 +4689,8 @@ pub fn writeCodeSignature(self: *MachO, comp: *const Compilation, code_sig: *Cod
4671 const seg = self.segments.items[seg_id];4689 const seg = self.segments.items[seg_id];
4672 const offset = self.codesig_cmd.dataoff;4690 const offset = self.codesig_cmd.dataoff;
46734691
4674 var buffer = std.ArrayList(u8).init(self.base.allocator);4692 const gpa = self.base.comp.gpa;
4693 var buffer = std.ArrayList(u8).init(gpa);
4675 defer buffer.deinit();4694 defer buffer.deinit();
4676 try buffer.ensureTotalCapacityPrecise(code_sig.size());4695 try buffer.ensureTotalCapacityPrecise(code_sig.size());
4677 try code_sig.writeAdhocSignature(comp, .{4696 try code_sig.writeAdhocSignature(comp, .{
...@@ -4817,7 +4836,7 @@ pub fn ptraceDetach(self: *MachO, pid: std.os.pid_t) !void {...@@ -4817,7 +4836,7 @@ pub fn ptraceDetach(self: *MachO, pid: std.os.pid_t) !void {
4817}4836}
48184837
4819pub fn addUndefined(self: *MachO, name: []const u8, flags: RelocFlags) !u32 {4838pub fn addUndefined(self: *MachO, name: []const u8, flags: RelocFlags) !u32 {
4820 const gpa = self.base.allocator;4839 const gpa = self.base.comp.gpa;
48214840
4822 const gop = try self.getOrPutGlobalPtr(name);4841 const gop = try self.getOrPutGlobalPtr(name);
4823 const global_index = self.getGlobalIndex(name).?;4842 const global_index = self.getGlobalIndex(name).?;
...@@ -4842,7 +4861,8 @@ pub fn addUndefined(self: *MachO, name: []const u8, flags: RelocFlags) !u32 {...@@ -4842,7 +4861,8 @@ pub fn addUndefined(self: *MachO, name: []const u8, flags: RelocFlags) !u32 {
4842}4861}
48434862
4844fn updateRelocActions(self: *MachO, global_index: u32, flags: RelocFlags) !void {4863fn updateRelocActions(self: *MachO, global_index: u32, flags: RelocFlags) !void {
4845 const act_gop = try self.actions.getOrPut(self.base.allocator, global_index);4864 const gpa = self.base.comp.gpa;
4865 const act_gop = try self.actions.getOrPut(gpa, global_index);
4846 if (!act_gop.found_existing) {4866 if (!act_gop.found_existing) {
4847 act_gop.value_ptr.* = .{};4867 act_gop.value_ptr.* = .{};
4848 }4868 }
...@@ -5022,7 +5042,7 @@ pub fn getOrPutGlobalPtr(self: *MachO, name: []const u8) !GetOrPutGlobalPtrResul...@@ -5022,7 +5042,7 @@ pub fn getOrPutGlobalPtr(self: *MachO, name: []const u8) !GetOrPutGlobalPtrResul
5022 if (self.getGlobalPtr(name)) |ptr| {5042 if (self.getGlobalPtr(name)) |ptr| {
5023 return GetOrPutGlobalPtrResult{ .found_existing = true, .value_ptr = ptr };5043 return GetOrPutGlobalPtrResult{ .found_existing = true, .value_ptr = ptr };
5024 }5044 }
5025 const gpa = self.base.allocator;5045 const gpa = self.base.comp.gpa;
5026 const global_index = try self.allocateGlobal();5046 const global_index = try self.allocateGlobal();
5027 const global_name = try gpa.dupe(u8, name);5047 const global_name = try gpa.dupe(u8, name);
5028 _ = try self.resolver.put(gpa, global_name, global_index);5048 _ = try self.resolver.put(gpa, global_name, global_index);
...@@ -5171,6 +5191,7 @@ pub fn handleAndReportParseError(...@@ -5171,6 +5191,7 @@ pub fn handleAndReportParseError(
5171 err: ParseError,5191 err: ParseError,
5172 ctx: *const ParseErrorCtx,5192 ctx: *const ParseErrorCtx,
5173) error{OutOfMemory}!void {5193) error{OutOfMemory}!void {
5194 const gpa = self.base.comp.gpa;
5174 const cpu_arch = self.base.options.target.cpu.arch;5195 const cpu_arch = self.base.options.target.cpu.arch;
5175 switch (err) {5196 switch (err) {
5176 error.DylibAlreadyExists => {},5197 error.DylibAlreadyExists => {},
...@@ -5188,7 +5209,7 @@ pub fn handleAndReportParseError(...@@ -5188,7 +5209,7 @@ pub fn handleAndReportParseError(
5188 },5209 },
5189 error.UnknownFileType => try self.reportParseError(path, "unknown file type", .{}),5210 error.UnknownFileType => try self.reportParseError(path, "unknown file type", .{}),
5190 error.InvalidTarget, error.InvalidTargetFatLibrary => {5211 error.InvalidTarget, error.InvalidTargetFatLibrary => {
5191 var targets_string = std.ArrayList(u8).init(self.base.allocator);5212 var targets_string = std.ArrayList(u8).init(gpa);
5192 defer targets_string.deinit();5213 defer targets_string.deinit();
51935214
5194 if (ctx.detected_targets.items.len > 1) {5215 if (ctx.detected_targets.items.len > 1) {
...@@ -5226,7 +5247,7 @@ fn reportMissingLibraryError(...@@ -5226,7 +5247,7 @@ fn reportMissingLibraryError(
5226 comptime format: []const u8,5247 comptime format: []const u8,
5227 args: anytype,5248 args: anytype,
5228) error{OutOfMemory}!void {5249) error{OutOfMemory}!void {
5229 const gpa = self.base.allocator;5250 const gpa = self.base.comp.gpa;
5230 try self.misc_errors.ensureUnusedCapacity(gpa, 1);5251 try self.misc_errors.ensureUnusedCapacity(gpa, 1);
5231 const notes = try gpa.alloc(File.ErrorMsg, checked_paths.len);5252 const notes = try gpa.alloc(File.ErrorMsg, checked_paths.len);
5232 errdefer gpa.free(notes);5253 errdefer gpa.free(notes);
...@@ -5246,7 +5267,7 @@ fn reportDependencyError(...@@ -5246,7 +5267,7 @@ fn reportDependencyError(
5246 comptime format: []const u8,5267 comptime format: []const u8,
5247 args: anytype,5268 args: anytype,
5248) error{OutOfMemory}!void {5269) error{OutOfMemory}!void {
5249 const gpa = self.base.allocator;5270 const gpa = self.base.comp.gpa;
5250 try self.misc_errors.ensureUnusedCapacity(gpa, 1);5271 try self.misc_errors.ensureUnusedCapacity(gpa, 1);
5251 var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 2);5272 var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 2);
5252 defer notes.deinit();5273 defer notes.deinit();
...@@ -5266,7 +5287,7 @@ pub fn reportParseError(...@@ -5266,7 +5287,7 @@ pub fn reportParseError(
5266 comptime format: []const u8,5287 comptime format: []const u8,
5267 args: anytype,5288 args: anytype,
5268) error{OutOfMemory}!void {5289) error{OutOfMemory}!void {
5269 const gpa = self.base.allocator;5290 const gpa = self.base.comp.gpa;
5270 try self.misc_errors.ensureUnusedCapacity(gpa, 1);5291 try self.misc_errors.ensureUnusedCapacity(gpa, 1);
5271 var notes = try gpa.alloc(File.ErrorMsg, 1);5292 var notes = try gpa.alloc(File.ErrorMsg, 1);
5272 errdefer gpa.free(notes);5293 errdefer gpa.free(notes);
...@@ -5283,7 +5304,7 @@ pub fn reportUnresolvedBoundarySymbol(...@@ -5283,7 +5304,7 @@ pub fn reportUnresolvedBoundarySymbol(
5283 comptime format: []const u8,5304 comptime format: []const u8,
5284 args: anytype,5305 args: anytype,
5285) error{OutOfMemory}!void {5306) error{OutOfMemory}!void {
5286 const gpa = self.base.allocator;5307 const gpa = self.base.comp.gpa;
5287 try self.misc_errors.ensureUnusedCapacity(gpa, 1);5308 try self.misc_errors.ensureUnusedCapacity(gpa, 1);
5288 var notes = try gpa.alloc(File.ErrorMsg, 1);5309 var notes = try gpa.alloc(File.ErrorMsg, 1);
5289 errdefer gpa.free(notes);5310 errdefer gpa.free(notes);
...@@ -5295,7 +5316,7 @@ pub fn reportUnresolvedBoundarySymbol(...@@ -5295,7 +5316,7 @@ pub fn reportUnresolvedBoundarySymbol(
5295}5316}
52965317
5297pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void {5318pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void {
5298 const gpa = self.base.allocator;5319 const gpa = self.base.comp.gpa;
5299 const count = self.unresolved.count();5320 const count = self.unresolved.count();
5300 try self.misc_errors.ensureUnusedCapacity(gpa, count);5321 try self.misc_errors.ensureUnusedCapacity(gpa, count);
53015322
...@@ -5327,7 +5348,7 @@ fn reportSymbolCollision(...@@ -5327,7 +5348,7 @@ fn reportSymbolCollision(
5327 first: SymbolWithLoc,5348 first: SymbolWithLoc,
5328 other: SymbolWithLoc,5349 other: SymbolWithLoc,
5329) error{OutOfMemory}!void {5350) error{OutOfMemory}!void {
5330 const gpa = self.base.allocator;5351 const gpa = self.base.comp.gpa;
5331 try self.misc_errors.ensureUnusedCapacity(gpa, 1);5352 try self.misc_errors.ensureUnusedCapacity(gpa, 1);
53325353
5333 var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 2);5354 var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 2);
...@@ -5355,7 +5376,7 @@ fn reportSymbolCollision(...@@ -5355,7 +5376,7 @@ fn reportSymbolCollision(
5355}5376}
53565377
5357fn reportUnhandledSymbolType(self: *MachO, sym_with_loc: SymbolWithLoc) error{OutOfMemory}!void {5378fn reportUnhandledSymbolType(self: *MachO, sym_with_loc: SymbolWithLoc) error{OutOfMemory}!void {
5358 const gpa = self.base.allocator;5379 const gpa = self.base.comp.gpa;
5359 try self.misc_errors.ensureUnusedCapacity(gpa, 1);5380 try self.misc_errors.ensureUnusedCapacity(gpa, 1);
53605381
5361 const notes = try gpa.alloc(File.ErrorMsg, 1);5382 const notes = try gpa.alloc(File.ErrorMsg, 1);
src/main.zig+1112-933
...@@ -269,8 +269,6 @@ pub fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi...@@ -269,8 +269,6 @@ pub fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
269 }269 }
270 }270 }
271271
272 defer log_scopes.deinit(gpa);
273
274 const cmd = args[1];272 const cmd = args[1];
275 const cmd_args = args[2..];273 const cmd_args = args[2..];
276 if (mem.eql(u8, cmd, "build-exe")) {274 if (mem.eql(u8, cmd, "build-exe")) {
...@@ -321,7 +319,7 @@ pub fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi...@@ -321,7 +319,7 @@ pub fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
321 } else if (mem.eql(u8, cmd, "init")) {319 } else if (mem.eql(u8, cmd, "init")) {
322 return cmdInit(gpa, arena, cmd_args);320 return cmdInit(gpa, arena, cmd_args);
323 } else if (mem.eql(u8, cmd, "targets")) {321 } else if (mem.eql(u8, cmd, "targets")) {
324 const host = try std.zig.system.resolveTargetQuery(.{});322 const host = resolveTargetQueryOrFatal(.{});
325 const stdout = io.getStdOut().writer();323 const stdout = io.getStdOut().writer();
326 return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, host);324 return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, host);
327 } else if (mem.eql(u8, cmd, "version")) {325 } else if (mem.eql(u8, cmd, "version")) {
...@@ -404,37 +402,69 @@ const usage_build_generic =...@@ -404,37 +402,69 @@ const usage_build_generic =
404 \\ --global-cache-dir [path] Override the global cache directory402 \\ --global-cache-dir [path] Override the global cache directory
405 \\ --zig-lib-dir [path] Override path to Zig installation lib directory403 \\ --zig-lib-dir [path] Override path to Zig installation lib directory
406 \\404 \\
407 \\Compile Options:405 \\Global Compile Options:
406 \\ --name [name] Compilation unit name (not a file path)
407 \\ --libc [file] Provide a file which specifies libc paths
408 \\ -x language Treat subsequent input files as having type <language>
409 \\ --dep [[import=]name] Add an entry to the next module's import table
410 \\ --mod [name] [src] Create a module based on the current per-module settings.
411 \\ The first module is the main module.
412 \\ "std" can be configured by leaving src blank.
413 \\ After a --mod argument, per-module settings are reset.
414 \\ --error-limit [num] Set the maximum amount of distinct error values
415 \\ -fllvm Force using LLVM as the codegen backend
416 \\ -fno-llvm Prevent using LLVM as the codegen backend
417 \\ -flibllvm Force using the LLVM API in the codegen backend
418 \\ -fno-libllvm Prevent using the LLVM API in the codegen backend
419 \\ -fclang Force using Clang as the C/C++ compilation backend
420 \\ -fno-clang Prevent using Clang as the C/C++ compilation backend
421 \\ -fPIE Force-enable Position Independent Executable
422 \\ -fno-PIE Force-disable Position Independent Executable
423 \\ -flto Force-enable Link Time Optimization (requires LLVM extensions)
424 \\ -fno-lto Force-disable Link Time Optimization
425 \\ -fdll-export-fns Mark exported functions as DLL exports (Windows)
426 \\ -fno-dll-export-fns Force-disable marking exported functions as DLL exports
427 \\ -freference-trace[=num] Show num lines of reference trace per compile error
428 \\ -fno-reference-trace Disable reference trace
429 \\ -fbuiltin Enable implicit builtin knowledge of functions
430 \\ -fno-builtin Disable implicit builtin knowledge of functions
431 \\ -ffunction-sections Places each function in a separate section
432 \\ -fno-function-sections All functions go into same section
433 \\ -fdata-sections Places each data in a separate section
434 \\ -fno-data-sections All data go into same section
435 \\ -fformatted-panics Enable formatted safety panics
436 \\ -fno-formatted-panics Disable formatted safety panics
437 \\ -fstructured-cfg (SPIR-V) force SPIR-V kernels to use structured control flow
438 \\ -fno-structured-cfg (SPIR-V) force SPIR-V kernels to not use structured control flow
439 \\ -mexec-model=[value] (WASI) Execution model
440 \\
441 \\Per-Module Compile Options:
408 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command442 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command
443 \\ -O [mode] Choose what to optimize for
444 \\ Debug (default) Optimizations off, safety on
445 \\ ReleaseFast Optimize for performance, safety off
446 \\ ReleaseSafe Optimize for performance, safety on
447 \\ ReleaseSmall Optimize for small binary, safety off
448 \\ -ofmt=[fmt] Override target object format
449 \\ elf Executable and Linking Format
450 \\ c C source code
451 \\ wasm WebAssembly
452 \\ coff Common Object File Format (Windows)
453 \\ macho macOS relocatables
454 \\ spirv Standard, Portable Intermediate Representation V (SPIR-V)
455 \\ plan9 Plan 9 from Bell Labs object format
456 \\ hex (planned feature) Intel IHEX
457 \\ raw (planned feature) Dump machine code directly
409 \\ -mcpu [cpu] Specify target CPU and feature set458 \\ -mcpu [cpu] Specify target CPU and feature set
410 \\ -mcmodel=[default|tiny| Limit range of code and data virtual addresses459 \\ -mcmodel=[default|tiny| Limit range of code and data virtual addresses
411 \\ small|kernel|460 \\ small|kernel|
412 \\ medium|large]461 \\ medium|large]
413 \\ -x language Treat subsequent input files as having type <language>
414 \\ -mred-zone Force-enable the "red-zone"462 \\ -mred-zone Force-enable the "red-zone"
415 \\ -mno-red-zone Force-disable the "red-zone"463 \\ -mno-red-zone Force-disable the "red-zone"
416 \\ -fomit-frame-pointer Omit the stack frame pointer464 \\ -fomit-frame-pointer Omit the stack frame pointer
417 \\ -fno-omit-frame-pointer Store the stack frame pointer465 \\ -fno-omit-frame-pointer Store the stack frame pointer
418 \\ -mexec-model=[value] (WASI) Execution model
419 \\ --name [name] Override root name (not a file path)
420 \\ -O [mode] Choose what to optimize for
421 \\ Debug (default) Optimizations off, safety on
422 \\ ReleaseFast Optimize for performance, safety off
423 \\ ReleaseSafe Optimize for performance, safety on
424 \\ ReleaseSmall Optimize for small binary, safety off
425 \\ --mod [name]:[deps]:[src] Make a module available for dependency under the given name
426 \\ deps: [dep],[dep],...
427 \\ dep: [[import=]name]
428 \\ --deps [dep],[dep],... Set dependency names for the root package
429 \\ dep: [[import=]name]
430 \\ --main-mod-path Set the directory of the root module
431 \\ --error-limit [num] Set the maximum amount of distinct error values
432 \\ -fPIC Force-enable Position Independent Code466 \\ -fPIC Force-enable Position Independent Code
433 \\ -fno-PIC Force-disable Position Independent Code467 \\ -fno-PIC Force-disable Position Independent Code
434 \\ -fPIE Force-enable Position Independent Executable
435 \\ -fno-PIE Force-disable Position Independent Executable
436 \\ -flto Force-enable Link Time Optimization (requires LLVM extensions)
437 \\ -fno-lto Force-disable Link Time Optimization
438 \\ -fstack-check Enable stack probing in unsafe builds468 \\ -fstack-check Enable stack probing in unsafe builds
439 \\ -fno-stack-check Disable stack probing in safe builds469 \\ -fno-stack-check Disable stack probing in safe builds
440 \\ -fstack-protector Enable stack protection in unsafe builds470 \\ -fstack-protector Enable stack protection in unsafe builds
...@@ -445,47 +475,18 @@ const usage_build_generic =...@@ -445,47 +475,18 @@ const usage_build_generic =
445 \\ -fno-valgrind Omit valgrind client requests in debug builds475 \\ -fno-valgrind Omit valgrind client requests in debug builds
446 \\ -fsanitize-thread Enable Thread Sanitizer476 \\ -fsanitize-thread Enable Thread Sanitizer
447 \\ -fno-sanitize-thread Disable Thread Sanitizer477 \\ -fno-sanitize-thread Disable Thread Sanitizer
448 \\ -fdll-export-fns Mark exported functions as DLL exports (Windows)
449 \\ -fno-dll-export-fns Force-disable marking exported functions as DLL exports
450 \\ -funwind-tables Always produce unwind table entries for all functions478 \\ -funwind-tables Always produce unwind table entries for all functions
451 \\ -fno-unwind-tables Never produce unwind table entries479 \\ -fno-unwind-tables Never produce unwind table entries
452 \\ -fllvm Force using LLVM as the codegen backend
453 \\ -fno-llvm Prevent using LLVM as the codegen backend
454 \\ -flibllvm Force using the LLVM API in the codegen backend
455 \\ -fno-libllvm Prevent using the LLVM API in the codegen backend
456 \\ -fclang Force using Clang as the C/C++ compilation backend
457 \\ -fno-clang Prevent using Clang as the C/C++ compilation backend
458 \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error
459 \\ -fno-reference-trace Disable reference trace
460 \\ -ferror-tracing Enable error tracing in ReleaseFast mode480 \\ -ferror-tracing Enable error tracing in ReleaseFast mode
461 \\ -fno-error-tracing Disable error tracing in Debug and ReleaseSafe mode481 \\ -fno-error-tracing Disable error tracing in Debug and ReleaseSafe mode
462 \\ -fsingle-threaded Code assumes there is only one thread482 \\ -fsingle-threaded Code assumes there is only one thread
463 \\ -fno-single-threaded Code may not assume there is only one thread483 \\ -fno-single-threaded Code may not assume there is only one thread
464 \\ -fbuiltin Enable implicit builtin knowledge of functions
465 \\ -fno-builtin Disable implicit builtin knowledge of functions
466 \\ -ffunction-sections Places each function in a separate section
467 \\ -fno-function-sections All functions go into same section
468 \\ -fdata-sections Places each data in a separate section
469 \\ -fno-data-sections All data go into same section
470 \\ -fstrip Omit debug symbols484 \\ -fstrip Omit debug symbols
471 \\ -fno-strip Keep debug symbols485 \\ -fno-strip Keep debug symbols
472 \\ -fformatted-panics Enable formatted safety panics
473 \\ -fno-formatted-panics Disable formatted safety panics
474 \\ -ofmt=[mode] Override target object format
475 \\ elf Executable and Linking Format
476 \\ c C source code
477 \\ wasm WebAssembly
478 \\ coff Common Object File Format (Windows)
479 \\ macho macOS relocatables
480 \\ spirv Standard, Portable Intermediate Representation V (SPIR-V)
481 \\ plan9 Plan 9 from Bell Labs object format
482 \\ hex (planned feature) Intel IHEX
483 \\ raw (planned feature) Dump machine code directly
484 \\ -idirafter [dir] Add directory to AFTER include search path486 \\ -idirafter [dir] Add directory to AFTER include search path
485 \\ -isystem [dir] Add directory to SYSTEM include search path487 \\ -isystem [dir] Add directory to SYSTEM include search path
486 \\ -I[dir] Add directory to include search path488 \\ -I[dir] Add directory to include search path
487 \\ -D[macro]=[value] Define C [macro] to [value] (1 if [value] omitted)489 \\ -D[macro]=[value] Define C [macro] to [value] (1 if [value] omitted)
488 \\ --libc [file] Provide a file which specifies libc paths
489 \\ -cflags [flags] -- Set extra flags for the next positional C source files490 \\ -cflags [flags] -- Set extra flags for the next positional C source files
490 \\ -rcflags [flags] -- Set extra flags for the next positional .rc source files491 \\ -rcflags [flags] -- Set extra flags for the next positional .rc source files
491 \\ -rcincludes=[type] Set the type of includes to use when compiling .rc source files492 \\ -rcincludes=[type] Set the type of includes to use when compiling .rc source files
...@@ -493,26 +494,8 @@ const usage_build_generic =...@@ -493,26 +494,8 @@ const usage_build_generic =
493 \\ msvc Use msvc include paths (must be present on the system)494 \\ msvc Use msvc include paths (must be present on the system)
494 \\ gnu Use mingw include paths (distributed with Zig)495 \\ gnu Use mingw include paths (distributed with Zig)
495 \\ none Do not use any autodetected include paths496 \\ none Do not use any autodetected include paths
496 \\ -fstructured-cfg (SPIR-V) force SPIR-V kernels to use structured control flow
497 \\ -fno-structured-cfg (SPIR-V) force SPIR-V kernels to not use structured control flow
498 \\497 \\
499 \\Link Options:498 \\Global Link Options:
500 \\ -l[lib], --library [lib] Link against system library (only if actually used)
501 \\ -needed-l[lib], Link against system library (even if unused)
502 \\ --needed-library [lib]
503 \\ -weak-l[lib] link against system library marking it and all
504 \\ -weak_library [lib] referenced symbols as weak
505 \\ -L[d], --library-directory [d] Add a directory to the library search path
506 \\ -search_paths_first For each library search path, check for dynamic
507 \\ lib then static lib before proceeding to next path.
508 \\ -search_paths_first_static For each library search path, check for static
509 \\ lib then dynamic lib before proceeding to next path.
510 \\ -search_dylibs_first Search for dynamic libs in all library search
511 \\ paths, then static libs.
512 \\ -search_static_first Search for static libs in all library search
513 \\ paths, then dynamic libs.
514 \\ -search_dylibs_only Only search for dynamic libs.
515 \\ -search_static_only Only search for static libs.
516 \\ -T[script], --script [script] Use a custom linker script499 \\ -T[script], --script [script] Use a custom linker script
517 \\ --version-script [path] Provide a version .map file500 \\ --version-script [path] Provide a version .map file
518 \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)501 \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)
...@@ -529,7 +512,6 @@ const usage_build_generic =...@@ -529,7 +512,6 @@ const usage_build_generic =
529 \\ -fcompiler-rt Always include compiler-rt symbols in output512 \\ -fcompiler-rt Always include compiler-rt symbols in output
530 \\ -fno-compiler-rt Prevent including compiler-rt symbols in output513 \\ -fno-compiler-rt Prevent including compiler-rt symbols in output
531 \\ -rdynamic Add all symbols to the dynamic symbol table514 \\ -rdynamic Add all symbols to the dynamic symbol table
532 \\ -rpath [path] Add directory to the runtime library search path
533 \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library515 \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library
534 \\ -fno-each-lib-rpath Prevent adding rpath for each used dynamic library516 \\ -fno-each-lib-rpath Prevent adding rpath for each used dynamic library
535 \\ -fallow-shlib-undefined Allows undefined symbols in shared libraries517 \\ -fallow-shlib-undefined Allows undefined symbols in shared libraries
...@@ -566,11 +548,6 @@ const usage_build_generic =...@@ -566,11 +548,6 @@ const usage_build_generic =
566 \\ --subsystem [subsystem] (Windows) /SUBSYSTEM:<subsystem> to the linker548 \\ --subsystem [subsystem] (Windows) /SUBSYSTEM:<subsystem> to the linker
567 \\ --stack [size] Override default stack size549 \\ --stack [size] Override default stack size
568 \\ --image-base [addr] Set base address for executable image550 \\ --image-base [addr] Set base address for executable image
569 \\ -framework [name] (Darwin) link against framework
570 \\ -needed_framework [name] (Darwin) link against framework (even if unused)
571 \\ -needed_library [lib] link against system library (even if unused)
572 \\ -weak_framework [name] (Darwin) link against framework and mark it and all referenced symbols as weak
573 \\ -F[dir] (Darwin) add search path for frameworks
574 \\ -install_name=[value] (Darwin) add dylib's install name551 \\ -install_name=[value] (Darwin) add dylib's install name
575 \\ --entitlements [path] (Darwin) add path to entitlements file for embedding in code signature552 \\ --entitlements [path] (Darwin) add path to entitlements file for embedding in code signature
576 \\ -pagezero_size [value] (Darwin) size of the __PAGEZERO segment in hexadecimal notation553 \\ -pagezero_size [value] (Darwin) size of the __PAGEZERO segment in hexadecimal notation
...@@ -587,6 +564,30 @@ const usage_build_generic =...@@ -587,6 +564,30 @@ const usage_build_generic =
587 \\ --max-memory=[bytes] (WebAssembly) maximum size of the linear memory564 \\ --max-memory=[bytes] (WebAssembly) maximum size of the linear memory
588 \\ --shared-memory (WebAssembly) use shared linear memory565 \\ --shared-memory (WebAssembly) use shared linear memory
589 \\ --global-base=[addr] (WebAssembly) where to start to place global data566 \\ --global-base=[addr] (WebAssembly) where to start to place global data
567 \\
568 \\Per-Module Link Options:
569 \\ -l[lib], --library [lib] Link against system library (only if actually used)
570 \\ -needed-l[lib], Link against system library (even if unused)
571 \\ --needed-library [lib]
572 \\ -weak-l[lib] link against system library marking it and all
573 \\ -weak_library [lib] referenced symbols as weak
574 \\ -L[d], --library-directory [d] Add a directory to the library search path
575 \\ -search_paths_first For each library search path, check for dynamic
576 \\ lib then static lib before proceeding to next path.
577 \\ -search_paths_first_static For each library search path, check for static
578 \\ lib then dynamic lib before proceeding to next path.
579 \\ -search_dylibs_first Search for dynamic libs in all library search
580 \\ paths, then static libs.
581 \\ -search_static_first Search for static libs in all library search
582 \\ paths, then dynamic libs.
583 \\ -search_dylibs_only Only search for dynamic libs.
584 \\ -search_static_only Only search for static libs.
585 \\ -rpath [path] Add directory to the runtime library search path
586 \\ -framework [name] (Darwin) link against framework
587 \\ -needed_framework [name] (Darwin) link against framework (even if unused)
588 \\ -needed_library [lib] link against system library (even if unused)
589 \\ -weak_framework [name] (Darwin) link against framework and mark it and all referenced symbols as weak
590 \\ -F[dir] (Darwin) add search path for frameworks
590 \\ --export=[value] (WebAssembly) Force a symbol to be exported591 \\ --export=[value] (WebAssembly) Force a symbol to be exported
591 \\592 \\
592 \\Test Options:593 \\Test Options:
...@@ -758,9 +759,24 @@ const Framework = struct {...@@ -758,9 +759,24 @@ const Framework = struct {
758};759};
759760
760const CliModule = struct {761const CliModule = struct {
761 mod: *Package.Module,762 paths: Package.Module.CreateOptions.Paths,
762 /// still in CLI arg format763 cc_argv: []const []const u8,
763 deps_str: []const u8,764 inherited: Package.Module.CreateOptions.Inherited,
765 target_arch_os_abi: ?[]const u8,
766 target_mcpu: ?[]const u8,
767
768 deps: []const Dep,
769 resolved: ?*Package.Module,
770
771 c_source_files_start: usize,
772 c_source_files_end: usize,
773 rc_source_files_start: usize,
774 rc_source_files_end: usize,
775
776 pub const Dep = struct {
777 key: []const u8,
778 value: []const u8,
779 };
764};780};
765781
766fn buildOutputType(782fn buildOutputType(
...@@ -769,17 +785,12 @@ fn buildOutputType(...@@ -769,17 +785,12 @@ fn buildOutputType(
769 all_args: []const []const u8,785 all_args: []const []const u8,
770 arg_mode: ArgMode,786 arg_mode: ArgMode,
771) !void {787) !void {
772 var color: Color = .auto;
773 var optimize_mode: std.builtin.OptimizeMode = .Debug;
774 var provided_name: ?[]const u8 = null;788 var provided_name: ?[]const u8 = null;
775 var link_mode: ?std.builtin.LinkMode = null;
776 var dll_export_fns: ?bool = null;789 var dll_export_fns: ?bool = null;
777 var single_threaded: ?bool = null;
778 var root_src_file: ?[]const u8 = null;790 var root_src_file: ?[]const u8 = null;
779 var version: std.SemanticVersion = .{ .major = 0, .minor = 0, .patch = 0 };791 var version: std.SemanticVersion = .{ .major = 0, .minor = 0, .patch = 0 };
780 var have_version = false;792 var have_version = false;
781 var compatibility_version: ?std.SemanticVersion = null;793 var compatibility_version: ?std.SemanticVersion = null;
782 var strip: ?bool = null;
783 var formatted_panics: ?bool = null;794 var formatted_panics: ?bool = null;
784 var function_sections = false;795 var function_sections = false;
785 var data_sections = false;796 var data_sections = false;
...@@ -807,30 +818,11 @@ fn buildOutputType(...@@ -807,30 +818,11 @@ fn buildOutputType(
807 var emit_docs: Emit = .no;818 var emit_docs: Emit = .no;
808 var emit_implib: Emit = .yes_default_path;819 var emit_implib: Emit = .yes_default_path;
809 var emit_implib_arg_provided = false;820 var emit_implib_arg_provided = false;
810 var target_arch_os_abi: []const u8 = "native";821 var target_arch_os_abi: ?[]const u8 = null;
811 var target_mcpu: ?[]const u8 = null;822 var target_mcpu: ?[]const u8 = null;
812 var target_dynamic_linker: ?[]const u8 = null;
813 var target_ofmt: ?[]const u8 = null;
814 var output_mode: std.builtin.OutputMode = undefined;
815 var emit_h: Emit = .no;823 var emit_h: Emit = .no;
816 var soname: SOName = undefined;824 var soname: SOName = undefined;
817 var ensure_libc_on_non_freestanding = false;
818 var ensure_libcpp_on_non_freestanding = false;
819 var link_libc = false;
820 var link_libcpp = false;
821 var link_libunwind = false;
822 var want_native_include_dirs = false;825 var want_native_include_dirs = false;
823 var want_pic: ?bool = null;
824 var want_pie: ?bool = null;
825 var want_lto: ?bool = null;
826 var want_unwind_tables: ?bool = null;
827 var want_sanitize_c: ?bool = null;
828 var want_stack_check: ?bool = null;
829 var want_stack_protector: ?u32 = null;
830 var want_red_zone: ?bool = null;
831 var omit_frame_pointer: ?bool = null;
832 var want_valgrind: ?bool = null;
833 var want_tsan: ?bool = null;
834 var want_compiler_rt: ?bool = null;826 var want_compiler_rt: ?bool = null;
835 var rdynamic: bool = false;827 var rdynamic: bool = false;
836 var linker_script: ?[]const u8 = null;828 var linker_script: ?[]const u8 = null;
...@@ -841,15 +833,11 @@ fn buildOutputType(...@@ -841,15 +833,11 @@ fn buildOutputType(
841 var linker_compress_debug_sections: ?link.CompressDebugSections = null;833 var linker_compress_debug_sections: ?link.CompressDebugSections = null;
842 var linker_allow_shlib_undefined: ?bool = null;834 var linker_allow_shlib_undefined: ?bool = null;
843 var linker_bind_global_refs_locally: ?bool = null;835 var linker_bind_global_refs_locally: ?bool = null;
844 var linker_import_memory: ?bool = null;
845 var linker_export_memory: ?bool = null;
846 var linker_import_symbols: bool = false;836 var linker_import_symbols: bool = false;
847 var linker_import_table: bool = false;837 var linker_import_table: bool = false;
848 var linker_export_table: bool = false;838 var linker_export_table: bool = false;
849 var linker_force_entry: ?bool = null;
850 var linker_initial_memory: ?u64 = null;839 var linker_initial_memory: ?u64 = null;
851 var linker_max_memory: ?u64 = null;840 var linker_max_memory: ?u64 = null;
852 var linker_shared_memory: bool = false;
853 var linker_global_base: ?u64 = null;841 var linker_global_base: ?u64 = null;
854 var linker_print_gc_sections: bool = false;842 var linker_print_gc_sections: bool = false;
855 var linker_print_icf_sections: bool = false;843 var linker_print_icf_sections: bool = false;
...@@ -869,23 +857,16 @@ fn buildOutputType(...@@ -869,23 +857,16 @@ fn buildOutputType(
869 var linker_dynamicbase = true;857 var linker_dynamicbase = true;
870 var linker_optimization: ?u8 = null;858 var linker_optimization: ?u8 = null;
871 var linker_module_definition_file: ?[]const u8 = null;859 var linker_module_definition_file: ?[]const u8 = null;
872 var test_evented_io = false;
873 var test_no_exec = false;860 var test_no_exec = false;
874 var entry: ?[]const u8 = null;
875 var force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{};861 var force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{};
876 var stack_size_override: ?u64 = null;862 var stack_size_override: ?u64 = null;
877 var image_base_override: ?u64 = null;863 var image_base_override: ?u64 = null;
878 var use_llvm: ?bool = null;
879 var use_lib_llvm: ?bool = null;
880 var use_lld: ?bool = null;
881 var use_clang: ?bool = null;
882 var link_eh_frame_hdr = false;864 var link_eh_frame_hdr = false;
883 var link_emit_relocs = false;865 var link_emit_relocs = false;
884 var each_lib_rpath: ?bool = null;866 var each_lib_rpath: ?bool = null;
885 var build_id: ?std.zig.BuildId = null;867 var build_id: ?std.zig.BuildId = null;
886 var sysroot: ?[]const u8 = null;868 var sysroot: ?[]const u8 = null;
887 var libc_paths_file: ?[]const u8 = try EnvVar.ZIG_LIBC.get(arena);869 var libc_paths_file: ?[]const u8 = try EnvVar.ZIG_LIBC.get(arena);
888 var machine_code_model: std.builtin.CodeModel = .default;
889 var runtime_args_start: ?usize = null;870 var runtime_args_start: ?usize = null;
890 var test_filter: ?[]const u8 = null;871 var test_filter: ?[]const u8 = null;
891 var test_name_prefix: ?[]const u8 = null;872 var test_name_prefix: ?[]const u8 = null;
...@@ -893,12 +874,10 @@ fn buildOutputType(...@@ -893,12 +874,10 @@ fn buildOutputType(
893 var override_local_cache_dir: ?[]const u8 = try EnvVar.ZIG_LOCAL_CACHE_DIR.get(arena);874 var override_local_cache_dir: ?[]const u8 = try EnvVar.ZIG_LOCAL_CACHE_DIR.get(arena);
894 var override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena);875 var override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena);
895 var override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena);876 var override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena);
896 var main_mod_path: ?[]const u8 = null;
897 var clang_preprocessor_mode: Compilation.ClangPreprocessorMode = .no;877 var clang_preprocessor_mode: Compilation.ClangPreprocessorMode = .no;
898 var subsystem: ?std.Target.SubSystem = null;878 var subsystem: ?std.Target.SubSystem = null;
899 var major_subsystem_version: ?u32 = null;879 var major_subsystem_version: ?u32 = null;
900 var minor_subsystem_version: ?u32 = null;880 var minor_subsystem_version: ?u32 = null;
901 var wasi_exec_model: ?std.builtin.WasiExecModel = null;
902 var enable_link_snapshots: bool = false;881 var enable_link_snapshots: bool = false;
903 var debug_incremental: bool = false;882 var debug_incremental: bool = false;
904 var install_name: ?[]const u8 = null;883 var install_name: ?[]const u8 = null;
...@@ -910,63 +889,100 @@ fn buildOutputType(...@@ -910,63 +889,100 @@ fn buildOutputType(
910 var headerpad_size: ?u32 = null;889 var headerpad_size: ?u32 = null;
911 var headerpad_max_install_names: bool = false;890 var headerpad_max_install_names: bool = false;
912 var dead_strip_dylibs: bool = false;891 var dead_strip_dylibs: bool = false;
892 var contains_res_file: bool = false;
913 var reference_trace: ?u32 = null;893 var reference_trace: ?u32 = null;
914 var error_tracing: ?bool = null;
915 var pdb_out_path: ?[]const u8 = null;894 var pdb_out_path: ?[]const u8 = null;
916 var dwarf_format: ?std.dwarf.Format = null;895 var dwarf_format: ?std.dwarf.Format = null;
917 var error_limit: ?Module.ErrorInt = null;896 var error_limit: ?Module.ErrorInt = null;
918 var want_structured_cfg: ?bool = null;897 var want_structured_cfg: ?bool = null;
919 // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.
920 // This array is populated by zig cc frontend and then has to be converted to zig-style
921 // CPU features.
922 var llvm_m_args = std.ArrayList([]const u8).init(arena);
923 var system_libs = std.StringArrayHashMap(SystemLib).init(arena);
924 var wasi_emulated_libs = std.ArrayList(wasi_libc.CRTFile).init(arena);
925 var clang_argv = std.ArrayList([]const u8).init(arena);
926 var extra_cflags = std.ArrayList([]const u8).init(arena);
927 var extra_rcflags = std.ArrayList([]const u8).init(arena);
928 // These are before resolving sysroot.898 // These are before resolving sysroot.
929 var lib_dir_args = std.ArrayList([]const u8).init(arena);899 var lib_dir_args: std.ArrayListUnmanaged([]const u8) = .{};
930 var rpath_list = std.ArrayList([]const u8).init(arena);900 var extra_cflags: std.ArrayListUnmanaged([]const u8) = .{};
901 var extra_rcflags: std.ArrayListUnmanaged([]const u8) = .{};
931 var symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{};902 var symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{};
932 var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena);903 var rpath_list: std.ArrayListUnmanaged([]const u8) = .{};
933 var rc_source_files = std.ArrayList(Compilation.RcSourceFile).init(arena);
934 var rc_includes: Compilation.RcIncludes = .any;904 var rc_includes: Compilation.RcIncludes = .any;
935 var res_files = std.ArrayList(Compilation.LinkObject).init(arena);
936 var manifest_file: ?[]const u8 = null;905 var manifest_file: ?[]const u8 = null;
937 var link_objects = std.ArrayList(Compilation.LinkObject).init(arena);906 var link_objects: std.ArrayListUnmanaged(Compilation.LinkObject) = .{};
938 var framework_dirs = std.ArrayList([]const u8).init(arena);907 var framework_dirs: std.ArrayListUnmanaged([]const u8) = .{};
939 var frameworks: std.StringArrayHashMapUnmanaged(Framework) = .{};908 var frameworks: std.StringArrayHashMapUnmanaged(Framework) = .{};
909 var linker_export_symbol_names: std.ArrayListUnmanaged([]const u8) = .{};
910
911 // Tracks the position in c_source_files which have already their owner populated.
912 var c_source_files_owner_index: usize = 0;
913 // Tracks the position in rc_source_files which have already their owner populated.
914 var rc_source_files_owner_index: usize = 0;
915
940 // null means replace with the test executable binary916 // null means replace with the test executable binary
941 var test_exec_args = std.ArrayList(?[]const u8).init(arena);917 var test_exec_args = std.ArrayList(?[]const u8).init(arena);
942 var linker_export_symbol_names = std.ArrayList([]const u8).init(arena);918
919 // These get set by CLI flags and then snapshotted when a `--mod` flag is
920 // encountered.
921 var mod_opts: Package.Module.CreateOptions.Inherited = .{};
922
923 // These get appended to by CLI flags and then slurped when a `--mod` flag
924 // is encountered.
925 var cssan: ClangSearchSanitizer = .{};
926 var clang_argv: std.ArrayListUnmanaged([]const u8) = .{};
927 var deps: std.ArrayListUnmanaged(CliModule.Dep) = .{};
928
943 // Contains every module specified via --mod. The dependencies are added929 // Contains every module specified via --mod. The dependencies are added
944 // after argument parsing is completed. We use a StringArrayHashMap to make930 // after argument parsing is completed. We use a StringArrayHashMap to make
945 // error output consistent.931 // error output consistent. "root" is special.
946 var modules = std.StringArrayHashMap(CliModule).init(arena);932 var create_module: CreateModule = .{
933 // Populated just before the call to `createModule`.
934 .global_cache_directory = undefined,
935 .object_format = null,
936 .dynamic_linker = null,
937 .modules = .{},
938 .opts = .{
939 .is_test = arg_mode == .zig_test,
940 // Populated while parsing CLI args.
941 .output_mode = undefined,
942 // Populated in the call to `createModule` for the root module.
943 .resolved_target = undefined,
944 .have_zcu = false,
945 // Populated just before the call to `createModule`.
946 .emit_llvm_ir = undefined,
947 // Populated just before the call to `createModule`.
948 .emit_llvm_bc = undefined,
949 // Populated just before the call to `createModule`.
950 .emit_bin = undefined,
951 // Populated just before the call to `createModule`.
952 .c_source_files_len = undefined,
953 },
954 // Populated in the call to `createModule` for the root module.
955 .resolved_options = undefined,
947956
948 // The dependency string for the root package957 .system_libs = .{},
949 var root_deps_str: ?[]const u8 = null;958 .external_system_libs = .{},
959 .resolved_system_libs = .{},
960 .wasi_emulated_libs = .{},
961
962 .c_source_files = .{},
963 .rc_source_files = .{},
964
965 .llvm_m_args = .{},
966 };
950967
951 // before arg parsing, check for the NO_COLOR environment variable968 // before arg parsing, check for the NO_COLOR environment variable
952 // if it exists, default the color setting to .off969 // if it exists, default the color setting to .off
953 // explicit --color arguments will still override this setting.970 // explicit --color arguments will still override this setting.
954 // Disable color on WASI per https://github.com/WebAssembly/WASI/issues/162971 // Disable color on WASI per https://github.com/WebAssembly/WASI/issues/162
955 color = if (builtin.os.tag == .wasi or EnvVar.NO_COLOR.isSet()) .off else .auto;972 var color: Color = if (builtin.os.tag == .wasi or EnvVar.NO_COLOR.isSet()) .off else .auto;
956973
957 switch (arg_mode) {974 switch (arg_mode) {
958 .build, .translate_c, .zig_test, .run => {975 .build, .translate_c, .zig_test, .run => {
959 var optimize_mode_string: ?[]const u8 = null;
960 switch (arg_mode) {976 switch (arg_mode) {
961 .build => |m| {977 .build => |m| {
962 output_mode = m;978 create_module.opts.output_mode = m;
963 },979 },
964 .translate_c => {980 .translate_c => {
965 emit_bin = .no;981 emit_bin = .no;
966 output_mode = .Obj;982 create_module.opts.output_mode = .Obj;
967 },983 },
968 .zig_test, .run => {984 .zig_test, .run => {
969 output_mode = .Exe;985 create_module.opts.output_mode = .Exe;
970 },986 },
971 else => unreachable,987 else => unreachable,
972 }988 }
...@@ -977,9 +993,6 @@ fn buildOutputType(...@@ -977,9 +993,6 @@ fn buildOutputType(
977 .args = all_args[2..],993 .args = all_args[2..],
978 };994 };
979995
980 var cssan = ClangSearchSanitizer.init(gpa, &clang_argv);
981 defer cssan.map.deinit();
982
983 var file_ext: ?Compilation.FileExt = null;996 var file_ext: ?Compilation.FileExt = null;
984 args_loop: while (args_iter.next()) |arg| {997 args_loop: while (args_iter.next()) |arg| {
985 if (mem.startsWith(u8, arg, "@")) {998 if (mem.startsWith(u8, arg, "@")) {
...@@ -1002,49 +1015,73 @@ fn buildOutputType(...@@ -1002,49 +1015,73 @@ fn buildOutputType(
1002 } else {1015 } else {
1003 fatal("unexpected end-of-parameter mark: --", .{});1016 fatal("unexpected end-of-parameter mark: --", .{});
1004 }1017 }
1005 } else if (mem.eql(u8, arg, "--mod")) {1018 } else if (mem.eql(u8, arg, "--dep")) {
1006 const info = args_iter.nextOrFatal();1019 var it = mem.splitScalar(u8, args_iter.nextOrFatal(), '=');
1007 var info_it = mem.splitScalar(u8, info, ':');1020 const key = it.next().?;
1008 const mod_name = info_it.next() orelse fatal("expected non-empty argument after {s}", .{arg});1021 const value = it.next() orelse key;
1009 const deps_str = info_it.next() orelse fatal("expected 'name:deps:path' after {s}", .{arg});1022 if (mem.eql(u8, key, "std") and !mem.eql(u8, value, "std")) {
1010 const root_src_orig = info_it.rest();1023 fatal("unable to import as '{s}': conflicts with builtin module", .{
1011 if (root_src_orig.len == 0) fatal("expected 'name:deps:path' after {s}", .{arg});1024 key,
1012 if (mod_name.len == 0) fatal("empty name for module at '{s}'", .{root_src_orig});1025 });
10131026 }
1014 const root_src = try introspect.resolvePath(arena, root_src_orig);1027 for ([_][]const u8{ "root", "builtin" }) |name| {
10151028 if (mem.eql(u8, key, name)) {
1016 for ([_][]const u8{ "std", "root", "builtin" }) |name| {1029 fatal("unable to import as '{s}': conflicts with builtin module", .{
1017 if (mem.eql(u8, mod_name, name)) {1030 key,
1018 fatal("unable to add module '{s}' -> '{s}': conflicts with builtin module", .{
1019 mod_name, root_src,
1020 });1031 });
1021 }1032 }
1022 }1033 }
1034 try deps.append(arena, .{
1035 .key = key,
1036 .value = value,
1037 });
1038 } else if (mem.eql(u8, arg, "--mod")) {
1039 const mod_name = args_iter.nextOrFatal();
1040 const root_src_orig = args_iter.nextOrFatal();
10231041
1024 if (modules.get(mod_name)) |value| {1042 const gop = try create_module.modules.getOrPut(arena, mod_name);
1025 fatal("unable to add module '{s}' -> '{s}': already exists as '{s}'", .{1043
1026 mod_name, root_src, value.mod.root_src_path,1044 if (gop.found_existing) {
1045 fatal("unable to add module '{s}': already exists as '{s}'", .{
1046 mod_name, gop.value_ptr.paths.root_src_path,
1027 });1047 });
1028 }1048 }
10291049
1030 try modules.put(mod_name, .{1050 // See duplicate logic: ModCreationGlobalFlags
1031 .mod = try Package.Module.create(arena, .{1051 create_module.opts.have_zcu = true;
1052 if (mod_opts.single_threaded == false)
1053 create_module.opts.any_non_single_threaded = true;
1054 if (mod_opts.sanitize_thread == true)
1055 create_module.opts.any_sanitize_thread = true;
1056 if (mod_opts.unwind_tables == true)
1057 create_module.opts.any_unwind_tables = true;
1058
1059 const root_src = try introspect.resolvePath(arena, root_src_orig);
1060 try create_module.modules.put(arena, mod_name, .{
1061 .paths = .{
1032 .root = .{1062 .root = .{
1033 .root_dir = Cache.Directory.cwd(),1063 .root_dir = Cache.Directory.cwd(),
1034 .sub_path = fs.path.dirname(root_src) orelse "",1064 .sub_path = fs.path.dirname(root_src) orelse "",
1035 },1065 },
1036 .root_src_path = fs.path.basename(root_src),1066 .root_src_path = fs.path.basename(root_src),
1037 .fully_qualified_name = mod_name,1067 },
1038 }),1068 .cc_argv = try clang_argv.toOwnedSlice(arena),
1039 .deps_str = deps_str,1069 .inherited = mod_opts,
1070 .target_arch_os_abi = target_arch_os_abi,
1071 .target_mcpu = target_mcpu,
1072 .deps = try deps.toOwnedSlice(arena),
1073 .resolved = null,
1074 .c_source_files_start = c_source_files_owner_index,
1075 .c_source_files_end = create_module.c_source_files.items.len,
1076 .rc_source_files_start = rc_source_files_owner_index,
1077 .rc_source_files_end = create_module.rc_source_files.items.len,
1040 });1078 });
1041 } else if (mem.eql(u8, arg, "--deps")) {1079 cssan.reset();
1042 if (root_deps_str != null) {1080 mod_opts = .{};
1043 fatal("only one --deps argument is allowed", .{});1081 target_arch_os_abi = null;
1044 }1082 target_mcpu = null;
1045 root_deps_str = args_iter.nextOrFatal();1083 c_source_files_owner_index = create_module.c_source_files.items.len;
1046 } else if (mem.eql(u8, arg, "--main-mod-path")) {1084 rc_source_files_owner_index = create_module.rc_source_files.items.len;
1047 main_mod_path = args_iter.nextOrFatal();
1048 } else if (mem.eql(u8, arg, "--error-limit")) {1085 } else if (mem.eql(u8, arg, "--error-limit")) {
1049 const next_arg = args_iter.nextOrFatal();1086 const next_arg = args_iter.nextOrFatal();
1050 error_limit = std.fmt.parseUnsigned(Module.ErrorInt, next_arg, 0) catch |err| {1087 error_limit = std.fmt.parseUnsigned(Module.ErrorInt, next_arg, 0) catch |err| {
...@@ -1057,7 +1094,7 @@ fn buildOutputType(...@@ -1057,7 +1094,7 @@ fn buildOutputType(
1057 fatal("expected -- after -cflags", .{});1094 fatal("expected -- after -cflags", .{});
1058 };1095 };
1059 if (mem.eql(u8, next_arg, "--")) break;1096 if (mem.eql(u8, next_arg, "--")) break;
1060 try extra_cflags.append(next_arg);1097 try extra_cflags.append(arena, next_arg);
1061 }1098 }
1062 } else if (mem.eql(u8, arg, "-rcincludes")) {1099 } else if (mem.eql(u8, arg, "-rcincludes")) {
1063 rc_includes = parseRcIncludes(args_iter.nextOrFatal());1100 rc_includes = parseRcIncludes(args_iter.nextOrFatal());
...@@ -1070,7 +1107,7 @@ fn buildOutputType(...@@ -1070,7 +1107,7 @@ fn buildOutputType(
1070 fatal("expected -- after -rcflags", .{});1107 fatal("expected -- after -rcflags", .{});
1071 };1108 };
1072 if (mem.eql(u8, next_arg, "--")) break;1109 if (mem.eql(u8, next_arg, "--")) break;
1073 try extra_rcflags.append(next_arg);1110 try extra_rcflags.append(arena, next_arg);
1074 }1111 }
1075 } else if (mem.startsWith(u8, arg, "-fstructured-cfg")) {1112 } else if (mem.startsWith(u8, arg, "-fstructured-cfg")) {
1076 want_structured_cfg = true;1113 want_structured_cfg = true;
...@@ -1086,11 +1123,11 @@ fn buildOutputType(...@@ -1086,11 +1123,11 @@ fn buildOutputType(
1086 } else if (mem.eql(u8, arg, "--subsystem")) {1123 } else if (mem.eql(u8, arg, "--subsystem")) {
1087 subsystem = try parseSubSystem(args_iter.nextOrFatal());1124 subsystem = try parseSubSystem(args_iter.nextOrFatal());
1088 } else if (mem.eql(u8, arg, "-O")) {1125 } else if (mem.eql(u8, arg, "-O")) {
1089 optimize_mode_string = args_iter.nextOrFatal();1126 mod_opts.optimize_mode = parseOptimizeMode(args_iter.nextOrFatal());
1090 } else if (mem.startsWith(u8, arg, "-fentry=")) {1127 } else if (mem.startsWith(u8, arg, "-fentry=")) {
1091 entry = arg["-fentry=".len..];1128 create_module.opts.entry = .{ .named = arg["-fentry=".len..] };
1092 } else if (mem.eql(u8, arg, "--force_undefined")) {1129 } else if (mem.eql(u8, arg, "--force_undefined")) {
1093 try force_undefined_symbols.put(gpa, args_iter.nextOrFatal(), {});1130 try force_undefined_symbols.put(arena, args_iter.nextOrFatal(), {});
1094 } else if (mem.eql(u8, arg, "--stack")) {1131 } else if (mem.eql(u8, arg, "--stack")) {
1095 const next_arg = args_iter.nextOrFatal();1132 const next_arg = args_iter.nextOrFatal();
1096 stack_size_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| {1133 stack_size_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| {
...@@ -1106,17 +1143,17 @@ fn buildOutputType(...@@ -1106,17 +1143,17 @@ fn buildOutputType(
1106 if (!mem.eql(u8, provided_name.?, fs.path.basename(provided_name.?)))1143 if (!mem.eql(u8, provided_name.?, fs.path.basename(provided_name.?)))
1107 fatal("invalid package name '{s}': cannot contain folder separators", .{provided_name.?});1144 fatal("invalid package name '{s}': cannot contain folder separators", .{provided_name.?});
1108 } else if (mem.eql(u8, arg, "-rpath")) {1145 } else if (mem.eql(u8, arg, "-rpath")) {
1109 try rpath_list.append(args_iter.nextOrFatal());1146 try rpath_list.append(arena, args_iter.nextOrFatal());
1110 } else if (mem.eql(u8, arg, "--library-directory") or mem.eql(u8, arg, "-L")) {1147 } else if (mem.eql(u8, arg, "--library-directory") or mem.eql(u8, arg, "-L")) {
1111 try lib_dir_args.append(args_iter.nextOrFatal());1148 try lib_dir_args.append(arena, args_iter.nextOrFatal());
1112 } else if (mem.eql(u8, arg, "-F")) {1149 } else if (mem.eql(u8, arg, "-F")) {
1113 try framework_dirs.append(args_iter.nextOrFatal());1150 try framework_dirs.append(arena, args_iter.nextOrFatal());
1114 } else if (mem.eql(u8, arg, "-framework")) {1151 } else if (mem.eql(u8, arg, "-framework")) {
1115 try frameworks.put(gpa, args_iter.nextOrFatal(), .{});1152 try frameworks.put(arena, args_iter.nextOrFatal(), .{});
1116 } else if (mem.eql(u8, arg, "-weak_framework")) {1153 } else if (mem.eql(u8, arg, "-weak_framework")) {
1117 try frameworks.put(gpa, args_iter.nextOrFatal(), .{ .weak = true });1154 try frameworks.put(arena, args_iter.nextOrFatal(), .{ .weak = true });
1118 } else if (mem.eql(u8, arg, "-needed_framework")) {1155 } else if (mem.eql(u8, arg, "-needed_framework")) {
1119 try frameworks.put(gpa, args_iter.nextOrFatal(), .{ .needed = true });1156 try frameworks.put(arena, args_iter.nextOrFatal(), .{ .needed = true });
1120 } else if (mem.eql(u8, arg, "-install_name")) {1157 } else if (mem.eql(u8, arg, "-install_name")) {
1121 install_name = args_iter.nextOrFatal();1158 install_name = args_iter.nextOrFatal();
1122 } else if (mem.startsWith(u8, arg, "--compress-debug-sections=")) {1159 } else if (mem.startsWith(u8, arg, "--compress-debug-sections=")) {
...@@ -1168,7 +1205,7 @@ fn buildOutputType(...@@ -1168,7 +1205,7 @@ fn buildOutputType(
1168 // We don't know whether this library is part of libc1205 // We don't know whether this library is part of libc
1169 // or libc++ until we resolve the target, so we append1206 // or libc++ until we resolve the target, so we append
1170 // to the list for now.1207 // to the list for now.
1171 try system_libs.put(args_iter.nextOrFatal(), .{1208 try create_module.system_libs.put(arena, args_iter.nextOrFatal(), .{
1172 .needed = false,1209 .needed = false,
1173 .weak = false,1210 .weak = false,
1174 .preferred_mode = lib_preferred_mode,1211 .preferred_mode = lib_preferred_mode,
...@@ -1179,38 +1216,37 @@ fn buildOutputType(...@@ -1179,38 +1216,37 @@ fn buildOutputType(
1179 mem.eql(u8, arg, "-needed_library"))1216 mem.eql(u8, arg, "-needed_library"))
1180 {1217 {
1181 const next_arg = args_iter.nextOrFatal();1218 const next_arg = args_iter.nextOrFatal();
1182 try system_libs.put(next_arg, .{1219 try create_module.system_libs.put(arena, next_arg, .{
1183 .needed = true,1220 .needed = true,
1184 .weak = false,1221 .weak = false,
1185 .preferred_mode = lib_preferred_mode,1222 .preferred_mode = lib_preferred_mode,
1186 .search_strategy = lib_search_strategy,1223 .search_strategy = lib_search_strategy,
1187 });1224 });
1188 } else if (mem.eql(u8, arg, "-weak_library") or mem.eql(u8, arg, "-weak-l")) {1225 } else if (mem.eql(u8, arg, "-weak_library") or mem.eql(u8, arg, "-weak-l")) {
1189 try system_libs.put(args_iter.nextOrFatal(), .{1226 try create_module.system_libs.put(arena, args_iter.nextOrFatal(), .{
1190 .needed = false,1227 .needed = false,
1191 .weak = true,1228 .weak = true,
1192 .preferred_mode = lib_preferred_mode,1229 .preferred_mode = lib_preferred_mode,
1193 .search_strategy = lib_search_strategy,1230 .search_strategy = lib_search_strategy,
1194 });1231 });
1195 } else if (mem.eql(u8, arg, "-D")) {1232 } else if (mem.eql(u8, arg, "-D")) {
1196 try clang_argv.append(arg);1233 try clang_argv.appendSlice(arena, &.{ arg, args_iter.nextOrFatal() });
1197 try clang_argv.append(args_iter.nextOrFatal());
1198 } else if (mem.eql(u8, arg, "-I")) {1234 } else if (mem.eql(u8, arg, "-I")) {
1199 try cssan.addIncludePath(.I, arg, args_iter.nextOrFatal(), false);1235 try cssan.addIncludePath(arena, &clang_argv, .I, arg, args_iter.nextOrFatal(), false);
1200 } else if (mem.eql(u8, arg, "-isystem")) {1236 } else if (mem.eql(u8, arg, "-isystem")) {
1201 try cssan.addIncludePath(.isystem, arg, args_iter.nextOrFatal(), false);1237 try cssan.addIncludePath(arena, &clang_argv, .isystem, arg, args_iter.nextOrFatal(), false);
1202 } else if (mem.eql(u8, arg, "-iwithsysroot")) {1238 } else if (mem.eql(u8, arg, "-iwithsysroot")) {
1203 try cssan.addIncludePath(.iwithsysroot, arg, args_iter.nextOrFatal(), false);1239 try cssan.addIncludePath(arena, &clang_argv, .iwithsysroot, arg, args_iter.nextOrFatal(), false);
1204 } else if (mem.eql(u8, arg, "-idirafter")) {1240 } else if (mem.eql(u8, arg, "-idirafter")) {
1205 try cssan.addIncludePath(.idirafter, arg, args_iter.nextOrFatal(), false);1241 try cssan.addIncludePath(arena, &clang_argv, .idirafter, arg, args_iter.nextOrFatal(), false);
1206 } else if (mem.eql(u8, arg, "-iframework")) {1242 } else if (mem.eql(u8, arg, "-iframework")) {
1207 const path = args_iter.nextOrFatal();1243 const path = args_iter.nextOrFatal();
1208 try cssan.addIncludePath(.iframework, arg, path, false);1244 try cssan.addIncludePath(arena, &clang_argv, .iframework, arg, path, false);
1209 try framework_dirs.append(path); // Forward to the backend as -F1245 try framework_dirs.append(arena, path); // Forward to the backend as -F
1210 } else if (mem.eql(u8, arg, "-iframeworkwithsysroot")) {1246 } else if (mem.eql(u8, arg, "-iframeworkwithsysroot")) {
1211 const path = args_iter.nextOrFatal();1247 const path = args_iter.nextOrFatal();
1212 try cssan.addIncludePath(.iframeworkwithsysroot, arg, path, false);1248 try cssan.addIncludePath(arena, &clang_argv, .iframeworkwithsysroot, arg, path, false);
1213 try framework_dirs.append(path); // Forward to the backend as -F1249 try framework_dirs.append(arena, path); // Forward to the backend as -F
1214 } else if (mem.eql(u8, arg, "--version")) {1250 } else if (mem.eql(u8, arg, "--version")) {
1215 const next_arg = args_iter.nextOrFatal();1251 const next_arg = args_iter.nextOrFatal();
1216 version = std.SemanticVersion.parse(next_arg) catch |err| {1252 version = std.SemanticVersion.parse(next_arg) catch |err| {
...@@ -1222,21 +1258,21 @@ fn buildOutputType(...@@ -1222,21 +1258,21 @@ fn buildOutputType(
1222 } else if (mem.eql(u8, arg, "-mcpu")) {1258 } else if (mem.eql(u8, arg, "-mcpu")) {
1223 target_mcpu = args_iter.nextOrFatal();1259 target_mcpu = args_iter.nextOrFatal();
1224 } else if (mem.eql(u8, arg, "-mcmodel")) {1260 } else if (mem.eql(u8, arg, "-mcmodel")) {
1225 machine_code_model = parseCodeModel(args_iter.nextOrFatal());1261 mod_opts.code_model = parseCodeModel(args_iter.nextOrFatal());
1262 } else if (mem.startsWith(u8, arg, "-mcmodel=")) {
1263 mod_opts.code_model = parseCodeModel(arg["-mcmodel=".len..]);
1226 } else if (mem.startsWith(u8, arg, "-ofmt=")) {1264 } else if (mem.startsWith(u8, arg, "-ofmt=")) {
1227 target_ofmt = arg["-ofmt=".len..];1265 create_module.object_format = arg["-ofmt=".len..];
1228 } else if (mem.startsWith(u8, arg, "-mcpu=")) {1266 } else if (mem.startsWith(u8, arg, "-mcpu=")) {
1229 target_mcpu = arg["-mcpu=".len..];1267 target_mcpu = arg["-mcpu=".len..];
1230 } else if (mem.startsWith(u8, arg, "-mcmodel=")) {
1231 machine_code_model = parseCodeModel(arg["-mcmodel=".len..]);
1232 } else if (mem.startsWith(u8, arg, "-O")) {1268 } else if (mem.startsWith(u8, arg, "-O")) {
1233 optimize_mode_string = arg["-O".len..];1269 mod_opts.optimize_mode = parseOptimizeMode(arg["-O".len..]);
1234 } else if (mem.eql(u8, arg, "--dynamic-linker")) {1270 } else if (mem.eql(u8, arg, "--dynamic-linker")) {
1235 target_dynamic_linker = args_iter.nextOrFatal();1271 create_module.dynamic_linker = args_iter.nextOrFatal();
1236 } else if (mem.eql(u8, arg, "--sysroot")) {1272 } else if (mem.eql(u8, arg, "--sysroot")) {
1237 sysroot = args_iter.nextOrFatal();1273 const next_arg = args_iter.nextOrFatal();
1238 try clang_argv.append("-isysroot");1274 sysroot = next_arg;
1239 try clang_argv.append(sysroot.?);1275 try clang_argv.appendSlice(arena, &.{ "-isysroot", next_arg });
1240 } else if (mem.eql(u8, arg, "--libc")) {1276 } else if (mem.eql(u8, arg, "--libc")) {
1241 libc_paths_file = args_iter.nextOrFatal();1277 libc_paths_file = args_iter.nextOrFatal();
1242 } else if (mem.eql(u8, arg, "--test-filter")) {1278 } else if (mem.eql(u8, arg, "--test-filter")) {
...@@ -1258,7 +1294,7 @@ fn buildOutputType(...@@ -1258,7 +1294,7 @@ fn buildOutputType(
1258 warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{});1294 warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{});
1259 _ = args_iter.nextOrFatal();1295 _ = args_iter.nextOrFatal();
1260 } else {1296 } else {
1261 try log_scopes.append(gpa, args_iter.nextOrFatal());1297 try log_scopes.append(arena, args_iter.nextOrFatal());
1262 }1298 }
1263 } else if (mem.eql(u8, arg, "--listen")) {1299 } else if (mem.eql(u8, arg, "--listen")) {
1264 const next_arg = args_iter.nextOrFatal();1300 const next_arg = args_iter.nextOrFatal();
...@@ -1298,7 +1334,7 @@ fn buildOutputType(...@@ -1298,7 +1334,7 @@ fn buildOutputType(
1298 } else if (mem.eql(u8, arg, "--test-cmd-bin")) {1334 } else if (mem.eql(u8, arg, "--test-cmd-bin")) {
1299 try test_exec_args.append(null);1335 try test_exec_args.append(null);
1300 } else if (mem.eql(u8, arg, "--test-evented-io")) {1336 } else if (mem.eql(u8, arg, "--test-evented-io")) {
1301 test_evented_io = true;1337 create_module.opts.test_evented_io = true;
1302 } else if (mem.eql(u8, arg, "--test-no-exec")) {1338 } else if (mem.eql(u8, arg, "--test-no-exec")) {
1303 test_no_exec = true;1339 test_no_exec = true;
1304 } else if (mem.eql(u8, arg, "-ftime-report")) {1340 } else if (mem.eql(u8, arg, "-ftime-report")) {
...@@ -1306,65 +1342,65 @@ fn buildOutputType(...@@ -1306,65 +1342,65 @@ fn buildOutputType(
1306 } else if (mem.eql(u8, arg, "-fstack-report")) {1342 } else if (mem.eql(u8, arg, "-fstack-report")) {
1307 stack_report = true;1343 stack_report = true;
1308 } else if (mem.eql(u8, arg, "-fPIC")) {1344 } else if (mem.eql(u8, arg, "-fPIC")) {
1309 want_pic = true;1345 mod_opts.pic = true;
1310 } else if (mem.eql(u8, arg, "-fno-PIC")) {1346 } else if (mem.eql(u8, arg, "-fno-PIC")) {
1311 want_pic = false;1347 mod_opts.pic = false;
1312 } else if (mem.eql(u8, arg, "-fPIE")) {1348 } else if (mem.eql(u8, arg, "-fPIE")) {
1313 want_pie = true;1349 create_module.opts.pie = true;
1314 } else if (mem.eql(u8, arg, "-fno-PIE")) {1350 } else if (mem.eql(u8, arg, "-fno-PIE")) {
1315 want_pie = false;1351 create_module.opts.pie = false;
1316 } else if (mem.eql(u8, arg, "-flto")) {1352 } else if (mem.eql(u8, arg, "-flto")) {
1317 want_lto = true;1353 create_module.opts.lto = true;
1318 } else if (mem.eql(u8, arg, "-fno-lto")) {1354 } else if (mem.eql(u8, arg, "-fno-lto")) {
1319 want_lto = false;1355 create_module.opts.lto = false;
1320 } else if (mem.eql(u8, arg, "-funwind-tables")) {1356 } else if (mem.eql(u8, arg, "-funwind-tables")) {
1321 want_unwind_tables = true;1357 mod_opts.unwind_tables = true;
1322 } else if (mem.eql(u8, arg, "-fno-unwind-tables")) {1358 } else if (mem.eql(u8, arg, "-fno-unwind-tables")) {
1323 want_unwind_tables = false;1359 mod_opts.unwind_tables = false;
1324 } else if (mem.eql(u8, arg, "-fstack-check")) {1360 } else if (mem.eql(u8, arg, "-fstack-check")) {
1325 want_stack_check = true;1361 mod_opts.stack_check = true;
1326 } else if (mem.eql(u8, arg, "-fno-stack-check")) {1362 } else if (mem.eql(u8, arg, "-fno-stack-check")) {
1327 want_stack_check = false;1363 mod_opts.stack_check = false;
1328 } else if (mem.eql(u8, arg, "-fstack-protector")) {1364 } else if (mem.eql(u8, arg, "-fstack-protector")) {
1329 want_stack_protector = Compilation.default_stack_protector_buffer_size;1365 mod_opts.stack_protector = Compilation.default_stack_protector_buffer_size;
1330 } else if (mem.eql(u8, arg, "-fno-stack-protector")) {1366 } else if (mem.eql(u8, arg, "-fno-stack-protector")) {
1331 want_stack_protector = 0;1367 mod_opts.stack_protector = 0;
1332 } else if (mem.eql(u8, arg, "-mred-zone")) {1368 } else if (mem.eql(u8, arg, "-mred-zone")) {
1333 want_red_zone = true;1369 mod_opts.red_zone = true;
1334 } else if (mem.eql(u8, arg, "-mno-red-zone")) {1370 } else if (mem.eql(u8, arg, "-mno-red-zone")) {
1335 want_red_zone = false;1371 mod_opts.red_zone = false;
1336 } else if (mem.eql(u8, arg, "-fomit-frame-pointer")) {1372 } else if (mem.eql(u8, arg, "-fomit-frame-pointer")) {
1337 omit_frame_pointer = true;1373 mod_opts.omit_frame_pointer = true;
1338 } else if (mem.eql(u8, arg, "-fno-omit-frame-pointer")) {1374 } else if (mem.eql(u8, arg, "-fno-omit-frame-pointer")) {
1339 omit_frame_pointer = false;1375 mod_opts.omit_frame_pointer = false;
1340 } else if (mem.eql(u8, arg, "-fsanitize-c")) {1376 } else if (mem.eql(u8, arg, "-fsanitize-c")) {
1341 want_sanitize_c = true;1377 mod_opts.sanitize_c = true;
1342 } else if (mem.eql(u8, arg, "-fno-sanitize-c")) {1378 } else if (mem.eql(u8, arg, "-fno-sanitize-c")) {
1343 want_sanitize_c = false;1379 mod_opts.sanitize_c = false;
1344 } else if (mem.eql(u8, arg, "-fvalgrind")) {1380 } else if (mem.eql(u8, arg, "-fvalgrind")) {
1345 want_valgrind = true;1381 mod_opts.valgrind = true;
1346 } else if (mem.eql(u8, arg, "-fno-valgrind")) {1382 } else if (mem.eql(u8, arg, "-fno-valgrind")) {
1347 want_valgrind = false;1383 mod_opts.valgrind = false;
1348 } else if (mem.eql(u8, arg, "-fsanitize-thread")) {1384 } else if (mem.eql(u8, arg, "-fsanitize-thread")) {
1349 want_tsan = true;1385 mod_opts.sanitize_thread = true;
1350 } else if (mem.eql(u8, arg, "-fno-sanitize-thread")) {1386 } else if (mem.eql(u8, arg, "-fno-sanitize-thread")) {
1351 want_tsan = false;1387 mod_opts.sanitize_thread = false;
1352 } else if (mem.eql(u8, arg, "-fllvm")) {1388 } else if (mem.eql(u8, arg, "-fllvm")) {
1353 use_llvm = true;1389 create_module.opts.use_llvm = true;
1354 } else if (mem.eql(u8, arg, "-fno-llvm")) {1390 } else if (mem.eql(u8, arg, "-fno-llvm")) {
1355 use_llvm = false;1391 create_module.opts.use_llvm = false;
1356 } else if (mem.eql(u8, arg, "-flibllvm")) {1392 } else if (mem.eql(u8, arg, "-flibllvm")) {
1357 use_lib_llvm = true;1393 create_module.opts.use_lib_llvm = true;
1358 } else if (mem.eql(u8, arg, "-fno-libllvm")) {1394 } else if (mem.eql(u8, arg, "-fno-libllvm")) {
1359 use_lib_llvm = false;1395 create_module.opts.use_lib_llvm = false;
1360 } else if (mem.eql(u8, arg, "-flld")) {1396 } else if (mem.eql(u8, arg, "-flld")) {
1361 use_lld = true;1397 create_module.opts.use_lld = true;
1362 } else if (mem.eql(u8, arg, "-fno-lld")) {1398 } else if (mem.eql(u8, arg, "-fno-lld")) {
1363 use_lld = false;1399 create_module.opts.use_lld = false;
1364 } else if (mem.eql(u8, arg, "-fclang")) {1400 } else if (mem.eql(u8, arg, "-fclang")) {
1365 use_clang = true;1401 create_module.opts.use_clang = true;
1366 } else if (mem.eql(u8, arg, "-fno-clang")) {1402 } else if (mem.eql(u8, arg, "-fno-clang")) {
1367 use_clang = false;1403 create_module.opts.use_clang = false;
1368 } else if (mem.eql(u8, arg, "-freference-trace")) {1404 } else if (mem.eql(u8, arg, "-freference-trace")) {
1369 reference_trace = 256;1405 reference_trace = 256;
1370 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {1406 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {
...@@ -1375,9 +1411,9 @@ fn buildOutputType(...@@ -1375,9 +1411,9 @@ fn buildOutputType(
1375 } else if (mem.eql(u8, arg, "-fno-reference-trace")) {1411 } else if (mem.eql(u8, arg, "-fno-reference-trace")) {
1376 reference_trace = null;1412 reference_trace = null;
1377 } else if (mem.eql(u8, arg, "-ferror-tracing")) {1413 } else if (mem.eql(u8, arg, "-ferror-tracing")) {
1378 error_tracing = true;1414 mod_opts.error_tracing = true;
1379 } else if (mem.eql(u8, arg, "-fno-error-tracing")) {1415 } else if (mem.eql(u8, arg, "-fno-error-tracing")) {
1380 error_tracing = false;1416 mod_opts.error_tracing = false;
1381 } else if (mem.eql(u8, arg, "-rdynamic")) {1417 } else if (mem.eql(u8, arg, "-rdynamic")) {
1382 rdynamic = true;1418 rdynamic = true;
1383 } else if (mem.eql(u8, arg, "-fsoname")) {1419 } else if (mem.eql(u8, arg, "-fsoname")) {
...@@ -1432,11 +1468,11 @@ fn buildOutputType(...@@ -1432,11 +1468,11 @@ fn buildOutputType(
1432 emit_implib = .no;1468 emit_implib = .no;
1433 emit_implib_arg_provided = true;1469 emit_implib_arg_provided = true;
1434 } else if (mem.eql(u8, arg, "-dynamic")) {1470 } else if (mem.eql(u8, arg, "-dynamic")) {
1435 link_mode = .Dynamic;1471 create_module.opts.link_mode = .Dynamic;
1436 lib_preferred_mode = .Dynamic;1472 lib_preferred_mode = .Dynamic;
1437 lib_search_strategy = .mode_first;1473 lib_search_strategy = .mode_first;
1438 } else if (mem.eql(u8, arg, "-static")) {1474 } else if (mem.eql(u8, arg, "-static")) {
1439 link_mode = .Static;1475 create_module.opts.link_mode = .Static;
1440 lib_preferred_mode = .Static;1476 lib_preferred_mode = .Static;
1441 lib_search_strategy = .no_fallback;1477 lib_search_strategy = .no_fallback;
1442 } else if (mem.eql(u8, arg, "-fdll-export-fns")) {1478 } else if (mem.eql(u8, arg, "-fdll-export-fns")) {
...@@ -1447,9 +1483,9 @@ fn buildOutputType(...@@ -1447,9 +1483,9 @@ fn buildOutputType(
1447 show_builtin = true;1483 show_builtin = true;
1448 emit_bin = .no;1484 emit_bin = .no;
1449 } else if (mem.eql(u8, arg, "-fstrip")) {1485 } else if (mem.eql(u8, arg, "-fstrip")) {
1450 strip = true;1486 mod_opts.strip = true;
1451 } else if (mem.eql(u8, arg, "-fno-strip")) {1487 } else if (mem.eql(u8, arg, "-fno-strip")) {
1452 strip = false;1488 mod_opts.strip = false;
1453 } else if (mem.eql(u8, arg, "-gdwarf32")) {1489 } else if (mem.eql(u8, arg, "-gdwarf32")) {
1454 dwarf_format = .@"32";1490 dwarf_format = .@"32";
1455 } else if (mem.eql(u8, arg, "-gdwarf64")) {1491 } else if (mem.eql(u8, arg, "-gdwarf64")) {
...@@ -1459,9 +1495,9 @@ fn buildOutputType(...@@ -1459,9 +1495,9 @@ fn buildOutputType(
1459 } else if (mem.eql(u8, arg, "-fno-formatted-panics")) {1495 } else if (mem.eql(u8, arg, "-fno-formatted-panics")) {
1460 formatted_panics = false;1496 formatted_panics = false;
1461 } else if (mem.eql(u8, arg, "-fsingle-threaded")) {1497 } else if (mem.eql(u8, arg, "-fsingle-threaded")) {
1462 single_threaded = true;1498 mod_opts.single_threaded = true;
1463 } else if (mem.eql(u8, arg, "-fno-single-threaded")) {1499 } else if (mem.eql(u8, arg, "-fno-single-threaded")) {
1464 single_threaded = false;1500 mod_opts.single_threaded = false;
1465 } else if (mem.eql(u8, arg, "-ffunction-sections")) {1501 } else if (mem.eql(u8, arg, "-ffunction-sections")) {
1466 function_sections = true;1502 function_sections = true;
1467 } else if (mem.eql(u8, arg, "-fno-function-sections")) {1503 } else if (mem.eql(u8, arg, "-fno-function-sections")) {
...@@ -1518,13 +1554,16 @@ fn buildOutputType(...@@ -1518,13 +1554,16 @@ fn buildOutputType(
1518 fatal("unsupported linker extension flag: -z {s}", .{z_arg});1554 fatal("unsupported linker extension flag: -z {s}", .{z_arg});
1519 }1555 }
1520 } else if (mem.eql(u8, arg, "--import-memory")) {1556 } else if (mem.eql(u8, arg, "--import-memory")) {
1521 linker_import_memory = true;1557 create_module.opts.import_memory = true;
1522 } else if (mem.eql(u8, arg, "-fentry")) {1558 } else if (mem.eql(u8, arg, "-fentry")) {
1523 linker_force_entry = true;1559 switch (create_module.opts.entry) {
1560 .default, .disabled => create_module.opts.entry = .enabled,
1561 .enabled, .named => {},
1562 }
1524 } else if (mem.eql(u8, arg, "-fno-entry")) {1563 } else if (mem.eql(u8, arg, "-fno-entry")) {
1525 linker_force_entry = false;1564 create_module.opts.entry = .disabled;
1526 } else if (mem.eql(u8, arg, "--export-memory")) {1565 } else if (mem.eql(u8, arg, "--export-memory")) {
1527 linker_export_memory = true;1566 create_module.opts.export_memory = true;
1528 } else if (mem.eql(u8, arg, "--import-symbols")) {1567 } else if (mem.eql(u8, arg, "--import-symbols")) {
1529 linker_import_symbols = true;1568 linker_import_symbols = true;
1530 } else if (mem.eql(u8, arg, "--import-table")) {1569 } else if (mem.eql(u8, arg, "--import-table")) {
...@@ -1536,11 +1575,11 @@ fn buildOutputType(...@@ -1536,11 +1575,11 @@ fn buildOutputType(
1536 } else if (mem.startsWith(u8, arg, "--max-memory=")) {1575 } else if (mem.startsWith(u8, arg, "--max-memory=")) {
1537 linker_max_memory = parseIntSuffix(arg, "--max-memory=".len);1576 linker_max_memory = parseIntSuffix(arg, "--max-memory=".len);
1538 } else if (mem.eql(u8, arg, "--shared-memory")) {1577 } else if (mem.eql(u8, arg, "--shared-memory")) {
1539 linker_shared_memory = true;1578 create_module.opts.shared_memory = true;
1540 } else if (mem.startsWith(u8, arg, "--global-base=")) {1579 } else if (mem.startsWith(u8, arg, "--global-base=")) {
1541 linker_global_base = parseIntSuffix(arg, "--global-base=".len);1580 linker_global_base = parseIntSuffix(arg, "--global-base=".len);
1542 } else if (mem.startsWith(u8, arg, "--export=")) {1581 } else if (mem.startsWith(u8, arg, "--export=")) {
1543 try linker_export_symbol_names.append(arg["--export=".len..]);1582 try linker_export_symbol_names.append(arena, arg["--export=".len..]);
1544 } else if (mem.eql(u8, arg, "-Bsymbolic")) {1583 } else if (mem.eql(u8, arg, "-Bsymbolic")) {
1545 linker_bind_global_refs_locally = true;1584 linker_bind_global_refs_locally = true;
1546 } else if (mem.eql(u8, arg, "--gc-sections")) {1585 } else if (mem.eql(u8, arg, "--gc-sections")) {
...@@ -1585,37 +1624,37 @@ fn buildOutputType(...@@ -1585,37 +1624,37 @@ fn buildOutputType(
1585 } else if (mem.startsWith(u8, arg, "-T")) {1624 } else if (mem.startsWith(u8, arg, "-T")) {
1586 linker_script = arg[2..];1625 linker_script = arg[2..];
1587 } else if (mem.startsWith(u8, arg, "-L")) {1626 } else if (mem.startsWith(u8, arg, "-L")) {
1588 try lib_dir_args.append(arg[2..]);1627 try lib_dir_args.append(arena, arg[2..]);
1589 } else if (mem.startsWith(u8, arg, "-F")) {1628 } else if (mem.startsWith(u8, arg, "-F")) {
1590 try framework_dirs.append(arg[2..]);1629 try framework_dirs.append(arena, arg[2..]);
1591 } else if (mem.startsWith(u8, arg, "-l")) {1630 } else if (mem.startsWith(u8, arg, "-l")) {
1592 // We don't know whether this library is part of libc1631 // We don't know whether this library is part of libc
1593 // or libc++ until we resolve the target, so we append1632 // or libc++ until we resolve the target, so we append
1594 // to the list for now.1633 // to the list for now.
1595 try system_libs.put(arg["-l".len..], .{1634 try create_module.system_libs.put(arena, arg["-l".len..], .{
1596 .needed = false,1635 .needed = false,
1597 .weak = false,1636 .weak = false,
1598 .preferred_mode = lib_preferred_mode,1637 .preferred_mode = lib_preferred_mode,
1599 .search_strategy = lib_search_strategy,1638 .search_strategy = lib_search_strategy,
1600 });1639 });
1601 } else if (mem.startsWith(u8, arg, "-needed-l")) {1640 } else if (mem.startsWith(u8, arg, "-needed-l")) {
1602 try system_libs.put(arg["-needed-l".len..], .{1641 try create_module.system_libs.put(arena, arg["-needed-l".len..], .{
1603 .needed = true,1642 .needed = true,
1604 .weak = false,1643 .weak = false,
1605 .preferred_mode = lib_preferred_mode,1644 .preferred_mode = lib_preferred_mode,
1606 .search_strategy = lib_search_strategy,1645 .search_strategy = lib_search_strategy,
1607 });1646 });
1608 } else if (mem.startsWith(u8, arg, "-weak-l")) {1647 } else if (mem.startsWith(u8, arg, "-weak-l")) {
1609 try system_libs.put(arg["-weak-l".len..], .{1648 try create_module.system_libs.put(arena, arg["-weak-l".len..], .{
1610 .needed = false,1649 .needed = false,
1611 .weak = true,1650 .weak = true,
1612 .preferred_mode = lib_preferred_mode,1651 .preferred_mode = lib_preferred_mode,
1613 .search_strategy = lib_search_strategy,1652 .search_strategy = lib_search_strategy,
1614 });1653 });
1615 } else if (mem.startsWith(u8, arg, "-D")) {1654 } else if (mem.startsWith(u8, arg, "-D")) {
1616 try clang_argv.append(arg);1655 try clang_argv.append(arena, arg);
1617 } else if (mem.startsWith(u8, arg, "-I")) {1656 } else if (mem.startsWith(u8, arg, "-I")) {
1618 try cssan.addIncludePath(.I, arg, arg[2..], true);1657 try cssan.addIncludePath(arena, &clang_argv, .I, arg, arg[2..], true);
1619 } else if (mem.eql(u8, arg, "-x")) {1658 } else if (mem.eql(u8, arg, "-x")) {
1620 const lang = args_iter.nextOrFatal();1659 const lang = args_iter.nextOrFatal();
1621 if (mem.eql(u8, lang, "none")) {1660 if (mem.eql(u8, lang, "none")) {
...@@ -1626,23 +1665,27 @@ fn buildOutputType(...@@ -1626,23 +1665,27 @@ fn buildOutputType(
1626 fatal("language not recognized: '{s}'", .{lang});1665 fatal("language not recognized: '{s}'", .{lang});
1627 }1666 }
1628 } else if (mem.startsWith(u8, arg, "-mexec-model=")) {1667 } else if (mem.startsWith(u8, arg, "-mexec-model=")) {
1629 wasi_exec_model = std.meta.stringToEnum(std.builtin.WasiExecModel, arg["-mexec-model=".len..]) orelse {1668 create_module.opts.wasi_exec_model = parseWasiExecModel(arg["-mexec-model=".len..]);
1630 fatal("expected [command|reactor] for -mexec-mode=[value], found '{s}'", .{arg["-mexec-model=".len..]});
1631 };
1632 } else {1669 } else {
1633 fatal("unrecognized parameter: '{s}'", .{arg});1670 fatal("unrecognized parameter: '{s}'", .{arg});
1634 }1671 }
1635 } else switch (file_ext orelse1672 } else switch (file_ext orelse Compilation.classifyFileExt(arg)) {
1636 Compilation.classifyFileExt(arg)) {1673 .object, .static_library, .shared_library => {
1637 .object, .static_library, .shared_library => try link_objects.append(.{ .path = arg }),1674 try link_objects.append(arena, .{ .path = arg });
1638 .res => try res_files.append(.{ .path = arg }),1675 },
1676 .res => {
1677 try link_objects.append(arena, .{ .path = arg });
1678 contains_res_file = true;
1679 },
1639 .manifest => {1680 .manifest => {
1640 if (manifest_file) |other| {1681 if (manifest_file) |other| {
1641 fatal("only one manifest file can be specified, found '{s}' after '{s}'", .{ arg, other });1682 fatal("only one manifest file can be specified, found '{s}' after '{s}'", .{ arg, other });
1642 } else manifest_file = arg;1683 } else manifest_file = arg;
1643 },1684 },
1644 .assembly, .assembly_with_cpp, .c, .cpp, .h, .ll, .bc, .m, .mm, .cu => {1685 .assembly, .assembly_with_cpp, .c, .cpp, .h, .ll, .bc, .m, .mm, .cu => {
1645 try c_source_files.append(.{1686 try create_module.c_source_files.append(arena, .{
1687 // Populated after module creation.
1688 .owner = undefined,
1646 .src_path = arg,1689 .src_path = arg,
1647 .extra_flags = try arena.dupe([]const u8, extra_cflags.items),1690 .extra_flags = try arena.dupe([]const u8, extra_cflags.items),
1648 // duped when parsing the args.1691 // duped when parsing the args.
...@@ -1650,7 +1693,9 @@ fn buildOutputType(...@@ -1650,7 +1693,9 @@ fn buildOutputType(
1650 });1693 });
1651 },1694 },
1652 .rc => {1695 .rc => {
1653 try rc_source_files.append(.{1696 try create_module.rc_source_files.append(arena, .{
1697 // Populated after module creation.
1698 .owner = undefined,
1654 .src_path = arg,1699 .src_path = arg,
1655 .extra_flags = try arena.dupe([]const u8, extra_rcflags.items),1700 .extra_flags = try arena.dupe([]const u8, extra_rcflags.items),
1656 });1701 });
...@@ -1668,18 +1713,14 @@ fn buildOutputType(...@@ -1668,18 +1713,14 @@ fn buildOutputType(
1668 },1713 },
1669 }1714 }
1670 }1715 }
1671 if (optimize_mode_string) |s| {
1672 optimize_mode = std.meta.stringToEnum(std.builtin.OptimizeMode, s) orelse
1673 fatal("unrecognized optimization mode: '{s}'", .{s});
1674 }
1675 },1716 },
1676 .cc, .cpp => {1717 .cc, .cpp => {
1677 if (build_options.only_c) unreachable;1718 if (build_options.only_c) unreachable;
16781719
1679 emit_h = .no;1720 emit_h = .no;
1680 soname = .no;1721 soname = .no;
1681 ensure_libc_on_non_freestanding = true;1722 create_module.opts.ensure_libc_on_non_freestanding = true;
1682 ensure_libcpp_on_non_freestanding = arg_mode == .cpp;1723 create_module.opts.ensure_libcpp_on_non_freestanding = arg_mode == .cpp;
1683 want_native_include_dirs = true;1724 want_native_include_dirs = true;
1684 // Clang's driver enables this switch unconditionally.1725 // Clang's driver enables this switch unconditionally.
1685 // Disabling the emission of .eh_frame_hdr can unexpectedly break1726 // Disabling the emission of .eh_frame_hdr can unexpectedly break
...@@ -1733,24 +1774,30 @@ fn buildOutputType(...@@ -1733,24 +1774,30 @@ fn buildOutputType(
1733 }1774 }
1734 },1775 },
1735 .other => {1776 .other => {
1736 try clang_argv.appendSlice(it.other_args);1777 try clang_argv.appendSlice(arena, it.other_args);
1737 },1778 },
1738 .positional => switch (file_ext orelse1779 .positional => switch (file_ext orelse Compilation.classifyFileExt(mem.sliceTo(it.only_arg, 0))) {
1739 Compilation.classifyFileExt(mem.sliceTo(it.only_arg, 0))) {
1740 .assembly, .assembly_with_cpp, .c, .cpp, .ll, .bc, .h, .m, .mm, .cu => {1780 .assembly, .assembly_with_cpp, .c, .cpp, .ll, .bc, .h, .m, .mm, .cu => {
1741 try c_source_files.append(.{1781 try create_module.c_source_files.append(arena, .{
1782 // Populated after module creation.
1783 .owner = undefined,
1742 .src_path = it.only_arg,1784 .src_path = it.only_arg,
1743 .ext = file_ext, // duped while parsing the args.1785 .ext = file_ext, // duped while parsing the args.
1744 });1786 });
1745 },1787 },
1746 .unknown, .shared_library, .object, .static_library => try link_objects.append(.{1788 .unknown, .shared_library, .object, .static_library => {
1747 .path = it.only_arg,1789 try link_objects.append(arena, .{
1748 .must_link = must_link,1790 .path = it.only_arg,
1749 }),1791 .must_link = must_link,
1750 .res => try res_files.append(.{1792 });
1751 .path = it.only_arg,1793 },
1752 .must_link = must_link,1794 .res => {
1753 }),1795 try link_objects.append(arena, .{
1796 .path = it.only_arg,
1797 .must_link = must_link,
1798 });
1799 contains_res_file = true;
1800 },
1754 .manifest => {1801 .manifest => {
1755 if (manifest_file) |other| {1802 if (manifest_file) |other| {
1756 fatal("only one manifest file can be specified, found '{s}' after previously specified manifest '{s}'", .{ it.only_arg, other });1803 fatal("only one manifest file can be specified, found '{s}' after previously specified manifest '{s}'", .{ it.only_arg, other });
...@@ -1760,7 +1807,11 @@ fn buildOutputType(...@@ -1760,7 +1807,11 @@ fn buildOutputType(
1760 linker_module_definition_file = it.only_arg;1807 linker_module_definition_file = it.only_arg;
1761 },1808 },
1762 .rc => {1809 .rc => {
1763 try rc_source_files.append(.{ .src_path = it.only_arg });1810 try create_module.rc_source_files.append(arena, .{
1811 // Populated after module creation.
1812 .owner = undefined,
1813 .src_path = it.only_arg,
1814 });
1764 },1815 },
1765 .zig => {1816 .zig => {
1766 if (root_src_file) |other| {1817 if (root_src_file) |other| {
...@@ -1777,13 +1828,13 @@ fn buildOutputType(...@@ -1777,13 +1828,13 @@ fn buildOutputType(
1777 // more control over what's in the resulting1828 // more control over what's in the resulting
1778 // binary: no extra rpaths and DSO filename exactly1829 // binary: no extra rpaths and DSO filename exactly
1779 // as provided. Hello, Go.1830 // as provided. Hello, Go.
1780 try link_objects.append(.{1831 try link_objects.append(arena, .{
1781 .path = it.only_arg,1832 .path = it.only_arg,
1782 .must_link = must_link,1833 .must_link = must_link,
1783 .loption = true,1834 .loption = true,
1784 });1835 });
1785 } else {1836 } else {
1786 try system_libs.put(it.only_arg, .{1837 try create_module.system_libs.put(arena, it.only_arg, .{
1787 .needed = needed,1838 .needed = needed,
1788 .weak = false,1839 .weak = false,
1789 .preferred_mode = lib_preferred_mode,1840 .preferred_mode = lib_preferred_mode,
...@@ -1796,16 +1847,16 @@ fn buildOutputType(...@@ -1796,16 +1847,16 @@ fn buildOutputType(
1796 // Never mind what we're doing, just pass the args directly. For example --help.1847 // Never mind what we're doing, just pass the args directly. For example --help.
1797 return process.exit(try clangMain(arena, all_args));1848 return process.exit(try clangMain(arena, all_args));
1798 },1849 },
1799 .pic => want_pic = true,1850 .pic => mod_opts.pic = true,
1800 .no_pic => want_pic = false,1851 .no_pic => mod_opts.pic = false,
1801 .pie => want_pie = true,1852 .pie => create_module.opts.pie = true,
1802 .no_pie => want_pie = false,1853 .no_pie => create_module.opts.pie = false,
1803 .lto => want_lto = true,1854 .lto => create_module.opts.lto = true,
1804 .no_lto => want_lto = false,1855 .no_lto => create_module.opts.lto = false,
1805 .red_zone => want_red_zone = true,1856 .red_zone => mod_opts.red_zone = true,
1806 .no_red_zone => want_red_zone = false,1857 .no_red_zone => mod_opts.red_zone = false,
1807 .omit_frame_pointer => omit_frame_pointer = true,1858 .omit_frame_pointer => mod_opts.omit_frame_pointer = true,
1808 .no_omit_frame_pointer => omit_frame_pointer = false,1859 .no_omit_frame_pointer => mod_opts.omit_frame_pointer = false,
1809 .function_sections => function_sections = true,1860 .function_sections => function_sections = true,
1810 .no_function_sections => function_sections = false,1861 .no_function_sections => function_sections = false,
1811 .data_sections => data_sections = true,1862 .data_sections => data_sections = true,
...@@ -1814,23 +1865,23 @@ fn buildOutputType(...@@ -1814,23 +1865,23 @@ fn buildOutputType(
1814 .no_builtin => no_builtin = true,1865 .no_builtin => no_builtin = true,
1815 .color_diagnostics => color = .on,1866 .color_diagnostics => color = .on,
1816 .no_color_diagnostics => color = .off,1867 .no_color_diagnostics => color = .off,
1817 .stack_check => want_stack_check = true,1868 .stack_check => mod_opts.stack_check = true,
1818 .no_stack_check => want_stack_check = false,1869 .no_stack_check => mod_opts.stack_check = false,
1819 .stack_protector => {1870 .stack_protector => {
1820 if (want_stack_protector == null) {1871 if (mod_opts.stack_protector == null) {
1821 want_stack_protector = Compilation.default_stack_protector_buffer_size;1872 mod_opts.stack_protector = Compilation.default_stack_protector_buffer_size;
1822 }1873 }
1823 },1874 },
1824 .no_stack_protector => want_stack_protector = 0,1875 .no_stack_protector => mod_opts.stack_protector = 0,
1825 .unwind_tables => want_unwind_tables = true,1876 .unwind_tables => mod_opts.unwind_tables = true,
1826 .no_unwind_tables => want_unwind_tables = false,1877 .no_unwind_tables => mod_opts.unwind_tables = false,
1827 .nostdlib => {1878 .nostdlib => {
1828 ensure_libc_on_non_freestanding = false;1879 create_module.opts.ensure_libc_on_non_freestanding = false;
1829 ensure_libcpp_on_non_freestanding = false;1880 create_module.opts.ensure_libcpp_on_non_freestanding = false;
1830 },1881 },
1831 .nostdlib_cpp => ensure_libcpp_on_non_freestanding = false,1882 .nostdlib_cpp => create_module.opts.ensure_libcpp_on_non_freestanding = false,
1832 .shared => {1883 .shared => {
1833 link_mode = .Dynamic;1884 create_module.opts.link_mode = .Dynamic;
1834 is_shared_lib = true;1885 is_shared_lib = true;
1835 },1886 },
1836 .rdynamic => rdynamic = true,1887 .rdynamic => rdynamic = true,
...@@ -1870,7 +1921,7 @@ fn buildOutputType(...@@ -1870,7 +1921,7 @@ fn buildOutputType(
1870 } else if (mem.eql(u8, linker_arg, "--no-as-needed")) {1921 } else if (mem.eql(u8, linker_arg, "--no-as-needed")) {
1871 needed = true;1922 needed = true;
1872 } else if (mem.eql(u8, linker_arg, "-no-pie")) {1923 } else if (mem.eql(u8, linker_arg, "-no-pie")) {
1873 want_pie = false;1924 create_module.opts.pie = false;
1874 } else if (mem.eql(u8, linker_arg, "--sort-common")) {1925 } else if (mem.eql(u8, linker_arg, "--sort-common")) {
1875 // from ld.lld(1): --sort-common is ignored for GNU compatibility,1926 // from ld.lld(1): --sort-common is ignored for GNU compatibility,
1876 // this ignores plain --sort-common1927 // this ignores plain --sort-common
...@@ -1912,50 +1963,50 @@ fn buildOutputType(...@@ -1912,50 +1963,50 @@ fn buildOutputType(
1912 if (mem.eql(u8, level, "s") or1963 if (mem.eql(u8, level, "s") or
1913 mem.eql(u8, level, "z"))1964 mem.eql(u8, level, "z"))
1914 {1965 {
1915 optimize_mode = .ReleaseSmall;1966 mod_opts.optimize_mode = .ReleaseSmall;
1916 } else if (mem.eql(u8, level, "1") or1967 } else if (mem.eql(u8, level, "1") or
1917 mem.eql(u8, level, "2") or1968 mem.eql(u8, level, "2") or
1918 mem.eql(u8, level, "3") or1969 mem.eql(u8, level, "3") or
1919 mem.eql(u8, level, "4") or1970 mem.eql(u8, level, "4") or
1920 mem.eql(u8, level, "fast"))1971 mem.eql(u8, level, "fast"))
1921 {1972 {
1922 optimize_mode = .ReleaseFast;1973 mod_opts.optimize_mode = .ReleaseFast;
1923 } else if (mem.eql(u8, level, "g") or1974 } else if (mem.eql(u8, level, "g") or
1924 mem.eql(u8, level, "0"))1975 mem.eql(u8, level, "0"))
1925 {1976 {
1926 optimize_mode = .Debug;1977 mod_opts.optimize_mode = .Debug;
1927 } else {1978 } else {
1928 try clang_argv.appendSlice(it.other_args);1979 try clang_argv.appendSlice(arena, it.other_args);
1929 }1980 }
1930 },1981 },
1931 .debug => {1982 .debug => {
1932 strip = false;1983 mod_opts.strip = false;
1933 if (mem.eql(u8, it.only_arg, "g")) {1984 if (mem.eql(u8, it.only_arg, "g")) {
1934 // We handled with strip = false above.1985 // We handled with strip = false above.
1935 } else if (mem.eql(u8, it.only_arg, "g1") or1986 } else if (mem.eql(u8, it.only_arg, "g1") or
1936 mem.eql(u8, it.only_arg, "gline-tables-only"))1987 mem.eql(u8, it.only_arg, "gline-tables-only"))
1937 {1988 {
1938 // We handled with strip = false above. but we also want reduced debug info.1989 // We handled with strip = false above. but we also want reduced debug info.
1939 try clang_argv.append("-gline-tables-only");1990 try clang_argv.append(arena, "-gline-tables-only");
1940 } else {1991 } else {
1941 try clang_argv.appendSlice(it.other_args);1992 try clang_argv.appendSlice(arena, it.other_args);
1942 }1993 }
1943 },1994 },
1944 .gdwarf32 => {1995 .gdwarf32 => {
1945 strip = false;1996 mod_opts.strip = false;
1946 dwarf_format = .@"32";1997 dwarf_format = .@"32";
1947 },1998 },
1948 .gdwarf64 => {1999 .gdwarf64 => {
1949 strip = false;2000 mod_opts.strip = false;
1950 dwarf_format = .@"64";2001 dwarf_format = .@"64";
1951 },2002 },
1952 .sanitize => {2003 .sanitize => {
1953 if (mem.eql(u8, it.only_arg, "undefined")) {2004 if (mem.eql(u8, it.only_arg, "undefined")) {
1954 want_sanitize_c = true;2005 mod_opts.sanitize_c = true;
1955 } else if (mem.eql(u8, it.only_arg, "thread")) {2006 } else if (mem.eql(u8, it.only_arg, "thread")) {
1956 want_tsan = true;2007 mod_opts.sanitize_thread = true;
1957 } else {2008 } else {
1958 try clang_argv.appendSlice(it.other_args);2009 try clang_argv.appendSlice(arena, it.other_args);
1959 }2010 }
1960 },2011 },
1961 .linker_script => linker_script = it.only_arg,2012 .linker_script => linker_script = it.only_arg,
...@@ -1964,59 +2015,57 @@ fn buildOutputType(...@@ -1964,59 +2015,57 @@ fn buildOutputType(
1964 // Have Clang print more infos, some tools such as CMake2015 // Have Clang print more infos, some tools such as CMake
1965 // parse this to discover any implicit include and2016 // parse this to discover any implicit include and
1966 // library dir to look-up into.2017 // library dir to look-up into.
1967 try clang_argv.append("-v");2018 try clang_argv.append(arena, "-v");
1968 },2019 },
1969 .dry_run => {2020 .dry_run => {
1970 // This flag means "dry run". Clang will not actually output anything2021 // This flag means "dry run". Clang will not actually output anything
1971 // to the file system.2022 // to the file system.
1972 verbose_link = true;2023 verbose_link = true;
1973 disable_c_depfile = true;2024 disable_c_depfile = true;
1974 try clang_argv.append("-###");2025 try clang_argv.append(arena, "-###");
1975 },2026 },
1976 .for_linker => try linker_args.append(it.only_arg),2027 .for_linker => try linker_args.append(it.only_arg),
1977 .linker_input_z => {2028 .linker_input_z => {
1978 try linker_args.append("-z");2029 try linker_args.append("-z");
1979 try linker_args.append(it.only_arg);2030 try linker_args.append(it.only_arg);
1980 },2031 },
1981 .lib_dir => try lib_dir_args.append(it.only_arg),2032 .lib_dir => try lib_dir_args.append(arena, it.only_arg),
1982 .mcpu => target_mcpu = it.only_arg,2033 .mcpu => target_mcpu = it.only_arg,
1983 .m => try llvm_m_args.append(it.only_arg),2034 .m => try create_module.llvm_m_args.append(arena, it.only_arg),
1984 .dep_file => {2035 .dep_file => {
1985 disable_c_depfile = true;2036 disable_c_depfile = true;
1986 try clang_argv.appendSlice(it.other_args);2037 try clang_argv.appendSlice(arena, it.other_args);
1987 },2038 },
1988 .dep_file_to_stdout => { // -M, -MM2039 .dep_file_to_stdout => { // -M, -MM
1989 // "Like -MD, but also implies -E and writes to stdout by default"2040 // "Like -MD, but also implies -E and writes to stdout by default"
1990 // "Like -MMD, but also implies -E and writes to stdout by default"2041 // "Like -MMD, but also implies -E and writes to stdout by default"
1991 c_out_mode = .preprocessor;2042 c_out_mode = .preprocessor;
1992 disable_c_depfile = true;2043 disable_c_depfile = true;
1993 try clang_argv.appendSlice(it.other_args);2044 try clang_argv.appendSlice(arena, it.other_args);
1994 },2045 },
1995 .framework_dir => try framework_dirs.append(it.only_arg),2046 .framework_dir => try framework_dirs.append(arena, it.only_arg),
1996 .framework => try frameworks.put(gpa, it.only_arg, .{}),2047 .framework => try frameworks.put(arena, it.only_arg, .{}),
1997 .nostdlibinc => want_native_include_dirs = false,2048 .nostdlibinc => want_native_include_dirs = false,
1998 .strip => strip = true,2049 .strip => mod_opts.strip = true,
1999 .exec_model => {2050 .exec_model => {
2000 wasi_exec_model = std.meta.stringToEnum(std.builtin.WasiExecModel, it.only_arg) orelse {2051 create_module.opts.wasi_exec_model = parseWasiExecModel(it.only_arg);
2001 fatal("expected [command|reactor] for -mexec-mode=[value], found '{s}'", .{it.only_arg});
2002 };
2003 },2052 },
2004 .sysroot => {2053 .sysroot => {
2005 sysroot = it.only_arg;2054 sysroot = it.only_arg;
2006 },2055 },
2007 .entry => {2056 .entry => {
2008 entry = it.only_arg;2057 create_module.opts.entry = .{ .named = it.only_arg };
2009 },2058 },
2010 .force_undefined_symbol => {2059 .force_undefined_symbol => {
2011 try force_undefined_symbols.put(gpa, it.only_arg, {});2060 try force_undefined_symbols.put(arena, it.only_arg, {});
2012 },2061 },
2013 .weak_library => try system_libs.put(it.only_arg, .{2062 .weak_library => try create_module.system_libs.put(arena, it.only_arg, .{
2014 .needed = false,2063 .needed = false,
2015 .weak = true,2064 .weak = true,
2016 .preferred_mode = lib_preferred_mode,2065 .preferred_mode = lib_preferred_mode,
2017 .search_strategy = lib_search_strategy,2066 .search_strategy = lib_search_strategy,
2018 }),2067 }),
2019 .weak_framework => try frameworks.put(gpa, it.only_arg, .{ .weak = true }),2068 .weak_framework => try frameworks.put(arena, it.only_arg, .{ .weak = true }),
2020 .headerpad_max_install_names => headerpad_max_install_names = true,2069 .headerpad_max_install_names => headerpad_max_install_names = true,
2021 .compress_debug_sections => {2070 .compress_debug_sections => {
2022 if (it.only_arg.len == 0) {2071 if (it.only_arg.len == 0) {
...@@ -2077,14 +2126,14 @@ fn buildOutputType(...@@ -2077,14 +2126,14 @@ fn buildOutputType(
2077 }2126 }
2078 provided_name = name[prefix..end];2127 provided_name = name[prefix..end];
2079 } else if (mem.eql(u8, arg, "-rpath")) {2128 } else if (mem.eql(u8, arg, "-rpath")) {
2080 try rpath_list.append(linker_args_it.nextOrFatal());2129 try rpath_list.append(arena, linker_args_it.nextOrFatal());
2081 } else if (mem.eql(u8, arg, "--subsystem")) {2130 } else if (mem.eql(u8, arg, "--subsystem")) {
2082 subsystem = try parseSubSystem(linker_args_it.nextOrFatal());2131 subsystem = try parseSubSystem(linker_args_it.nextOrFatal());
2083 } else if (mem.eql(u8, arg, "-I") or2132 } else if (mem.eql(u8, arg, "-I") or
2084 mem.eql(u8, arg, "--dynamic-linker") or2133 mem.eql(u8, arg, "--dynamic-linker") or
2085 mem.eql(u8, arg, "-dynamic-linker"))2134 mem.eql(u8, arg, "-dynamic-linker"))
2086 {2135 {
2087 target_dynamic_linker = linker_args_it.nextOrFatal();2136 create_module.dynamic_linker = linker_args_it.nextOrFatal();
2088 } else if (mem.eql(u8, arg, "-E") or2137 } else if (mem.eql(u8, arg, "-E") or
2089 mem.eql(u8, arg, "--export-dynamic") or2138 mem.eql(u8, arg, "--export-dynamic") or
2090 mem.eql(u8, arg, "-export-dynamic"))2139 mem.eql(u8, arg, "-export-dynamic"))
...@@ -2145,9 +2194,9 @@ fn buildOutputType(...@@ -2145,9 +2194,9 @@ fn buildOutputType(
2145 } else if (mem.eql(u8, arg, "-Bsymbolic")) {2194 } else if (mem.eql(u8, arg, "-Bsymbolic")) {
2146 linker_bind_global_refs_locally = true;2195 linker_bind_global_refs_locally = true;
2147 } else if (mem.eql(u8, arg, "--import-memory")) {2196 } else if (mem.eql(u8, arg, "--import-memory")) {
2148 linker_import_memory = true;2197 create_module.opts.import_memory = true;
2149 } else if (mem.eql(u8, arg, "--export-memory")) {2198 } else if (mem.eql(u8, arg, "--export-memory")) {
2150 linker_export_memory = true;2199 create_module.opts.export_memory = true;
2151 } else if (mem.eql(u8, arg, "--import-symbols")) {2200 } else if (mem.eql(u8, arg, "--import-symbols")) {
2152 linker_import_symbols = true;2201 linker_import_symbols = true;
2153 } else if (mem.eql(u8, arg, "--import-table")) {2202 } else if (mem.eql(u8, arg, "--import-table")) {
...@@ -2155,7 +2204,7 @@ fn buildOutputType(...@@ -2155,7 +2204,7 @@ fn buildOutputType(
2155 } else if (mem.eql(u8, arg, "--export-table")) {2204 } else if (mem.eql(u8, arg, "--export-table")) {
2156 linker_export_table = true;2205 linker_export_table = true;
2157 } else if (mem.eql(u8, arg, "--no-entry")) {2206 } else if (mem.eql(u8, arg, "--no-entry")) {
2158 linker_force_entry = false;2207 create_module.opts.entry = .disabled;
2159 } else if (mem.eql(u8, arg, "--initial-memory")) {2208 } else if (mem.eql(u8, arg, "--initial-memory")) {
2160 const next_arg = linker_args_it.nextOrFatal();2209 const next_arg = linker_args_it.nextOrFatal();
2161 linker_initial_memory = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| {2210 linker_initial_memory = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| {
...@@ -2167,14 +2216,14 @@ fn buildOutputType(...@@ -2167,14 +2216,14 @@ fn buildOutputType(
2167 fatal("unable to parse max memory size '{s}': {s}", .{ next_arg, @errorName(err) });2216 fatal("unable to parse max memory size '{s}': {s}", .{ next_arg, @errorName(err) });
2168 };2217 };
2169 } else if (mem.eql(u8, arg, "--shared-memory")) {2218 } else if (mem.eql(u8, arg, "--shared-memory")) {
2170 linker_shared_memory = true;2219 create_module.opts.shared_memory = true;
2171 } else if (mem.eql(u8, arg, "--global-base")) {2220 } else if (mem.eql(u8, arg, "--global-base")) {
2172 const next_arg = linker_args_it.nextOrFatal();2221 const next_arg = linker_args_it.nextOrFatal();
2173 linker_global_base = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| {2222 linker_global_base = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| {
2174 fatal("unable to parse global base '{s}': {s}", .{ next_arg, @errorName(err) });2223 fatal("unable to parse global base '{s}': {s}", .{ next_arg, @errorName(err) });
2175 };2224 };
2176 } else if (mem.eql(u8, arg, "--export")) {2225 } else if (mem.eql(u8, arg, "--export")) {
2177 try linker_export_symbol_names.append(linker_args_it.nextOrFatal());2226 try linker_export_symbol_names.append(arena, linker_args_it.nextOrFatal());
2178 } else if (mem.eql(u8, arg, "--compress-debug-sections")) {2227 } else if (mem.eql(u8, arg, "--compress-debug-sections")) {
2179 const arg1 = linker_args_it.nextOrFatal();2228 const arg1 = linker_args_it.nextOrFatal();
2180 linker_compress_debug_sections = std.meta.stringToEnum(link.CompressDebugSections, arg1) orelse {2229 linker_compress_debug_sections = std.meta.stringToEnum(link.CompressDebugSections, arg1) orelse {
...@@ -2232,9 +2281,9 @@ fn buildOutputType(...@@ -2232,9 +2281,9 @@ fn buildOutputType(
2232 };2281 };
2233 have_version = true;2282 have_version = true;
2234 } else if (mem.eql(u8, arg, "-e") or mem.eql(u8, arg, "--entry")) {2283 } else if (mem.eql(u8, arg, "-e") or mem.eql(u8, arg, "--entry")) {
2235 entry = linker_args_it.nextOrFatal();2284 create_module.opts.entry = .{ .named = linker_args_it.nextOrFatal() };
2236 } else if (mem.eql(u8, arg, "-u")) {2285 } else if (mem.eql(u8, arg, "-u")) {
2237 try force_undefined_symbols.put(gpa, linker_args_it.nextOrFatal(), {});2286 try force_undefined_symbols.put(arena, linker_args_it.nextOrFatal(), {});
2238 } else if (mem.eql(u8, arg, "--stack") or mem.eql(u8, arg, "-stack_size")) {2287 } else if (mem.eql(u8, arg, "--stack") or mem.eql(u8, arg, "-stack_size")) {
2239 const stack_size = linker_args_it.nextOrFatal();2288 const stack_size = linker_args_it.nextOrFatal();
2240 stack_size_override = std.fmt.parseUnsigned(u64, stack_size, 0) catch |err| {2289 stack_size_override = std.fmt.parseUnsigned(u64, stack_size, 0) catch |err| {
...@@ -2276,7 +2325,7 @@ fn buildOutputType(...@@ -2276,7 +2325,7 @@ fn buildOutputType(
2276 {2325 {
2277 // -s, --strip-all Strip all symbols2326 // -s, --strip-all Strip all symbols
2278 // -S, --strip-debug Strip debugging symbols2327 // -S, --strip-debug Strip debugging symbols
2279 strip = true;2328 mod_opts.strip = true;
2280 } else if (mem.eql(u8, arg, "--start-group") or2329 } else if (mem.eql(u8, arg, "--start-group") or
2281 mem.eql(u8, arg, "--end-group"))2330 mem.eql(u8, arg, "--end-group"))
2282 {2331 {
...@@ -2307,27 +2356,27 @@ fn buildOutputType(...@@ -2307,27 +2356,27 @@ fn buildOutputType(
2307 fatal("unable to parse minor subsystem version '{s}': {s}", .{ minor, @errorName(err) });2356 fatal("unable to parse minor subsystem version '{s}': {s}", .{ minor, @errorName(err) });
2308 };2357 };
2309 } else if (mem.eql(u8, arg, "-framework")) {2358 } else if (mem.eql(u8, arg, "-framework")) {
2310 try frameworks.put(gpa, linker_args_it.nextOrFatal(), .{});2359 try frameworks.put(arena, linker_args_it.nextOrFatal(), .{});
2311 } else if (mem.eql(u8, arg, "-weak_framework")) {2360 } else if (mem.eql(u8, arg, "-weak_framework")) {
2312 try frameworks.put(gpa, linker_args_it.nextOrFatal(), .{ .weak = true });2361 try frameworks.put(arena, linker_args_it.nextOrFatal(), .{ .weak = true });
2313 } else if (mem.eql(u8, arg, "-needed_framework")) {2362 } else if (mem.eql(u8, arg, "-needed_framework")) {
2314 try frameworks.put(gpa, linker_args_it.nextOrFatal(), .{ .needed = true });2363 try frameworks.put(arena, linker_args_it.nextOrFatal(), .{ .needed = true });
2315 } else if (mem.eql(u8, arg, "-needed_library")) {2364 } else if (mem.eql(u8, arg, "-needed_library")) {
2316 try system_libs.put(linker_args_it.nextOrFatal(), .{2365 try create_module.system_libs.put(arena, linker_args_it.nextOrFatal(), .{
2317 .weak = false,2366 .weak = false,
2318 .needed = true,2367 .needed = true,
2319 .preferred_mode = lib_preferred_mode,2368 .preferred_mode = lib_preferred_mode,
2320 .search_strategy = lib_search_strategy,2369 .search_strategy = lib_search_strategy,
2321 });2370 });
2322 } else if (mem.startsWith(u8, arg, "-weak-l")) {2371 } else if (mem.startsWith(u8, arg, "-weak-l")) {
2323 try system_libs.put(arg["-weak-l".len..], .{2372 try create_module.system_libs.put(arena, arg["-weak-l".len..], .{
2324 .weak = true,2373 .weak = true,
2325 .needed = false,2374 .needed = false,
2326 .preferred_mode = lib_preferred_mode,2375 .preferred_mode = lib_preferred_mode,
2327 .search_strategy = lib_search_strategy,2376 .search_strategy = lib_search_strategy,
2328 });2377 });
2329 } else if (mem.eql(u8, arg, "-weak_library")) {2378 } else if (mem.eql(u8, arg, "-weak_library")) {
2330 try system_libs.put(linker_args_it.nextOrFatal(), .{2379 try create_module.system_libs.put(arena, linker_args_it.nextOrFatal(), .{
2331 .weak = true,2380 .weak = true,
2332 .needed = false,2381 .needed = false,
2333 .preferred_mode = lib_preferred_mode,2382 .preferred_mode = lib_preferred_mode,
...@@ -2361,7 +2410,7 @@ fn buildOutputType(...@@ -2361,7 +2410,7 @@ fn buildOutputType(
2361 } else if (mem.eql(u8, arg, "-install_name")) {2410 } else if (mem.eql(u8, arg, "-install_name")) {
2362 install_name = linker_args_it.nextOrFatal();2411 install_name = linker_args_it.nextOrFatal();
2363 } else if (mem.eql(u8, arg, "-force_load")) {2412 } else if (mem.eql(u8, arg, "-force_load")) {
2364 try link_objects.append(.{2413 try link_objects.append(arena, .{
2365 .path = linker_args_it.nextOrFatal(),2414 .path = linker_args_it.nextOrFatal(),
2366 .must_link = true,2415 .must_link = true,
2367 });2416 });
...@@ -2402,22 +2451,22 @@ fn buildOutputType(...@@ -2402,22 +2451,22 @@ fn buildOutputType(
2402 }2451 }
2403 }2452 }
24042453
2405 if (want_sanitize_c) |wsc| {2454 if (mod_opts.sanitize_c) |wsc| {
2406 if (wsc and optimize_mode == .ReleaseFast) {2455 if (wsc and mod_opts.optimize_mode == .ReleaseFast) {
2407 optimize_mode = .ReleaseSafe;2456 mod_opts.optimize_mode = .ReleaseSafe;
2408 }2457 }
2409 }2458 }
24102459
2411 switch (c_out_mode) {2460 switch (c_out_mode) {
2412 .link => {2461 .link => {
2413 output_mode = if (is_shared_lib) .Lib else .Exe;2462 create_module.opts.output_mode = if (is_shared_lib) .Lib else .Exe;
2414 emit_bin = if (out_path) |p| .{ .yes = p } else EmitBin.yes_a_out;2463 emit_bin = if (out_path) |p| .{ .yes = p } else EmitBin.yes_a_out;
2415 if (emit_llvm) {2464 if (emit_llvm) {
2416 fatal("-emit-llvm cannot be used when linking", .{});2465 fatal("-emit-llvm cannot be used when linking", .{});
2417 }2466 }
2418 },2467 },
2419 .object => {2468 .object => {
2420 output_mode = .Obj;2469 create_module.opts.output_mode = .Obj;
2421 if (emit_llvm) {2470 if (emit_llvm) {
2422 emit_bin = .no;2471 emit_bin = .no;
2423 if (out_path) |p| {2472 if (out_path) |p| {
...@@ -2434,7 +2483,7 @@ fn buildOutputType(...@@ -2434,7 +2483,7 @@ fn buildOutputType(
2434 }2483 }
2435 },2484 },
2436 .assembly => {2485 .assembly => {
2437 output_mode = .Obj;2486 create_module.opts.output_mode = .Obj;
2438 emit_bin = .no;2487 emit_bin = .no;
2439 if (emit_llvm) {2488 if (emit_llvm) {
2440 if (out_path) |p| {2489 if (out_path) |p| {
...@@ -2451,9 +2500,9 @@ fn buildOutputType(...@@ -2451,9 +2500,9 @@ fn buildOutputType(
2451 }2500 }
2452 },2501 },
2453 .preprocessor => {2502 .preprocessor => {
2454 output_mode = .Obj;2503 create_module.opts.output_mode = .Obj;
2455 // An error message is generated when there is more than 1 C source file.2504 // An error message is generated when there is more than 1 C source file.
2456 if (c_source_files.items.len != 1) {2505 if (create_module.c_source_files.items.len != 1) {
2457 // For example `zig cc` and no args should print the "no input files" message.2506 // For example `zig cc` and no args should print the "no input files" message.
2458 return process.exit(try clangMain(arena, all_args));2507 return process.exit(try clangMain(arena, all_args));
2459 }2508 }
...@@ -2465,7 +2514,7 @@ fn buildOutputType(...@@ -2465,7 +2514,7 @@ fn buildOutputType(
2465 }2514 }
2466 },2515 },
2467 }2516 }
2468 if (c_source_files.items.len == 0 and2517 if (create_module.c_source_files.items.len == 0 and
2469 link_objects.items.len == 0 and2518 link_objects.items.len == 0 and
2470 root_src_file == null)2519 root_src_file == null)
2471 {2520 {
...@@ -2476,258 +2525,72 @@ fn buildOutputType(...@@ -2476,258 +2525,72 @@ fn buildOutputType(
2476 },2525 },
2477 }2526 }
24782527
2479 {2528 if (arg_mode == .translate_c and create_module.c_source_files.items.len != 1) {
2480 // Resolve module dependencies2529 fatal("translate-c expects exactly 1 source file (found {d})", .{create_module.c_source_files.items.len});
2481 var it = modules.iterator();
2482 while (it.next()) |kv| {
2483 const deps_str = kv.value_ptr.deps_str;
2484 var deps_it = ModuleDepIterator.init(deps_str);
2485 while (deps_it.next()) |dep| {
2486 if (dep.expose.len == 0) {
2487 fatal("module '{s}' depends on '{s}' with a blank name", .{
2488 kv.key_ptr.*, dep.name,
2489 });
2490 }
2491
2492 for ([_][]const u8{ "std", "root", "builtin" }) |name| {
2493 if (mem.eql(u8, dep.expose, name)) {
2494 fatal("unable to add module '{s}' under name '{s}': conflicts with builtin module", .{
2495 dep.name, dep.expose,
2496 });
2497 }
2498 }
2499
2500 const dep_mod = modules.get(dep.name) orelse {
2501 fatal("module '{s}' depends on module '{s}' which does not exist", .{
2502 kv.key_ptr.*, dep.name,
2503 });
2504 };
2505
2506 try kv.value_ptr.mod.deps.put(arena, dep.expose, dep_mod.mod);
2507 }
2508 }
2509 }
2510
2511 if (arg_mode == .build and optimize_mode == .ReleaseSmall and strip == null)
2512 strip = true;
2513
2514 if (arg_mode == .translate_c and c_source_files.items.len != 1) {
2515 fatal("translate-c expects exactly 1 source file (found {d})", .{c_source_files.items.len});
2516 }2530 }
25172531
2518 if (root_src_file == null and arg_mode == .zig_test) {2532 if (root_src_file == null and arg_mode == .zig_test) {
2519 fatal("`zig test` expects a zig source file argument", .{});2533 fatal("`zig test` expects a zig source file argument", .{});
2520 }2534 }
25212535
2522 const root_name = if (provided_name) |n| n else blk: {2536 if (root_src_file) |unresolved_src_path| {
2523 if (arg_mode == .zig_test) {2537 if (create_module.modules.count() != 0) {
2524 break :blk "test";2538 fatal("main module provided both by '--mod {s} {}{s}' and by positional argument '{s}'", .{
2525 } else if (root_src_file) |file| {2539 create_module.modules.keys()[0],
2526 const basename = fs.path.basename(file);2540 create_module.modules.values()[0].paths.root,
2527 break :blk basename[0 .. basename.len - fs.path.extension(basename).len];2541 create_module.modules.values()[0].paths.root_src_path,
2528 } else if (c_source_files.items.len >= 1) {2542 unresolved_src_path,
2529 const basename = fs.path.basename(c_source_files.items[0].src_path);2543 });
2530 break :blk basename[0 .. basename.len - fs.path.extension(basename).len];
2531 } else if (link_objects.items.len >= 1) {
2532 const basename = fs.path.basename(link_objects.items[0].path);
2533 break :blk basename[0 .. basename.len - fs.path.extension(basename).len];
2534 } else if (emit_bin == .yes) {
2535 const basename = fs.path.basename(emit_bin.yes);
2536 break :blk basename[0 .. basename.len - fs.path.extension(basename).len];
2537 } else if (rc_source_files.items.len >= 1) {
2538 const basename = fs.path.basename(rc_source_files.items[0].src_path);
2539 break :blk basename[0 .. basename.len - fs.path.extension(basename).len];
2540 } else if (res_files.items.len >= 1) {
2541 const basename = fs.path.basename(res_files.items[0].path);
2542 break :blk basename[0 .. basename.len - fs.path.extension(basename).len];
2543 } else if (show_builtin) {
2544 break :blk "builtin";
2545 } else if (arg_mode == .run) {
2546 fatal("`zig run` expects at least one positional argument", .{});
2547 // TODO once the attempt to unwrap error: LinkingWithoutZigSourceUnimplemented
2548 // is solved, remove the above fatal() and uncomment the `break` below.
2549 //break :blk "run";
2550 } else {
2551 fatal("expected a positional argument, -femit-bin=[path], --show-builtin, or --name [name]", .{});
2552 }
2553 };
2554
2555 var target_parse_options: std.Target.Query.ParseOptions = .{
2556 .arch_os_abi = target_arch_os_abi,
2557 .cpu_features = target_mcpu,
2558 .dynamic_linker = target_dynamic_linker,
2559 .object_format = target_ofmt,
2560 };
2561
2562 // Before passing the mcpu string in for parsing, we convert any -m flags that were
2563 // passed in via zig cc to zig-style.
2564 if (llvm_m_args.items.len != 0) {
2565 // If this returns null, we let it fall through to the case below which will
2566 // run the full parse function and do proper error handling.
2567 if (std.Target.Query.parseCpuArch(target_parse_options)) |cpu_arch| {
2568 var llvm_to_zig_name = std.StringHashMap([]const u8).init(gpa);
2569 defer llvm_to_zig_name.deinit();
2570
2571 for (cpu_arch.allFeaturesList()) |feature| {
2572 const llvm_name = feature.llvm_name orelse continue;
2573 try llvm_to_zig_name.put(llvm_name, feature.name);
2574 }
2575
2576 var mcpu_buffer = std.ArrayList(u8).init(gpa);
2577 defer mcpu_buffer.deinit();
2578
2579 try mcpu_buffer.appendSlice(target_mcpu orelse "baseline");
2580
2581 for (llvm_m_args.items) |llvm_m_arg| {
2582 if (mem.startsWith(u8, llvm_m_arg, "mno-")) {
2583 const llvm_name = llvm_m_arg["mno-".len..];
2584 const zig_name = llvm_to_zig_name.get(llvm_name) orelse {
2585 fatal("target architecture {s} has no LLVM CPU feature named '{s}'", .{
2586 @tagName(cpu_arch), llvm_name,
2587 });
2588 };
2589 try mcpu_buffer.append('-');
2590 try mcpu_buffer.appendSlice(zig_name);
2591 } else if (mem.startsWith(u8, llvm_m_arg, "m")) {
2592 const llvm_name = llvm_m_arg["m".len..];
2593 const zig_name = llvm_to_zig_name.get(llvm_name) orelse {
2594 fatal("target architecture {s} has no LLVM CPU feature named '{s}'", .{
2595 @tagName(cpu_arch), llvm_name,
2596 });
2597 };
2598 try mcpu_buffer.append('+');
2599 try mcpu_buffer.appendSlice(zig_name);
2600 } else {
2601 unreachable;
2602 }
2603 }
2604
2605 const adjusted_target_mcpu = try arena.dupe(u8, mcpu_buffer.items);
2606 std.log.debug("adjusted target_mcpu: {s}", .{adjusted_target_mcpu});
2607 target_parse_options.cpu_features = adjusted_target_mcpu;
2608 }
2609 }
2610
2611 const target_query = try parseTargetQueryOrReportFatalError(arena, target_parse_options);
2612 const target = try std.zig.system.resolveTargetQuery(target_query);
2613
2614 if (target.os.tag != .freestanding) {
2615 if (ensure_libc_on_non_freestanding)
2616 link_libc = true;
2617 if (ensure_libcpp_on_non_freestanding)
2618 link_libcpp = true;
2619 }
2620
2621 if (linker_force_entry) |force| {
2622 if (!force) {
2623 entry = null;
2624 } else if (entry == null and output_mode == .Exe) {
2625 entry = switch (target.ofmt) {
2626 .coff => "wWinMainCRTStartup",
2627 .macho => "_main",
2628 .elf, .plan9 => "_start",
2629 .wasm => defaultWasmEntryName(wasi_exec_model),
2630 else => |tag| fatal("No default entry point available for output format {s}", .{@tagName(tag)}),
2631 };
2632 }
2633 } else if (entry == null and target.isWasm() and output_mode == .Exe) {
2634 // For WebAssembly the compiler defaults to setting the entry name when no flags are set.
2635 entry = defaultWasmEntryName(wasi_exec_model);
2636 }
2637
2638 if (target.ofmt == .coff) {
2639 // Now that we know the target supports resources,
2640 // we can add the res files as link objects.
2641 for (res_files.items) |res_file| {
2642 try link_objects.append(res_file);
2643 }
2644 } else {
2645 if (manifest_file != null) {
2646 fatal("manifest file is not allowed unless the target object format is coff (Windows/UEFI)", .{});
2647 }
2648 if (rc_source_files.items.len != 0) {
2649 fatal("rc files are not allowed unless the target object format is coff (Windows/UEFI)", .{});
2650 }
2651 if (res_files.items.len != 0) {
2652 fatal("res files are not allowed unless the target object format is coff (Windows/UEFI)", .{});
2653 }
2654 }
2655
2656 if (target.cpu.arch.isWasm()) blk: {
2657 if (single_threaded == null) {
2658 single_threaded = true;
2659 }
2660 if (link_mode) |mode| {
2661 if (mode == .Dynamic) {
2662 if (linker_export_memory != null and linker_export_memory.?) {
2663 fatal("flags '-dynamic' and '--export-memory' are incompatible", .{});
2664 }
2665 // User did not supply `--export-memory` which is incompatible with -dynamic, therefore
2666 // set the flag to false to ensure it does not get enabled by default.
2667 linker_export_memory = false;
2668 }
2669 }
2670 if (wasi_exec_model != null and wasi_exec_model.? == .reactor) {
2671 if (entry) |entry_name| {
2672 if (!mem.eql(u8, "_initialize", entry_name)) {
2673 fatal("the entry symbol of the reactor model must be '_initialize', but found '{s}'", .{entry_name});
2674 }
2675 }
2676 }
2677 if (linker_shared_memory) {
2678 if (output_mode == .Obj) {
2679 fatal("shared memory is not allowed in object files", .{});
2680 }
2681
2682 if (!target.cpu.features.isEnabled(@intFromEnum(std.Target.wasm.Feature.atomics)) or
2683 !target.cpu.features.isEnabled(@intFromEnum(std.Target.wasm.Feature.bulk_memory)))
2684 {
2685 fatal("'atomics' and 'bulk-memory' features must be enabled to use shared memory", .{});
2686 }
2687 break :blk;
2688 }
2689
2690 // Single-threaded is the default for WebAssembly, so only when the user specified `-fno_single-threaded`
2691 // can they enable multithreaded WebAssembly builds.
2692 const is_single_threaded = single_threaded.?;
2693 if (!is_single_threaded) {
2694 fatal("'-fno-single-threaded' requires the linker feature shared-memory to be enabled using '--shared-memory'", .{});
2695 }2544 }
2696 }
26972545
2698 if (use_lld) |opt| {2546 // See duplicate logic: ModCreationGlobalFlags
2699 if (opt and target.isDarwin()) {2547 create_module.opts.have_zcu = true;
2700 fatal("LLD requested with Mach-O object format. Only the self-hosted linker is supported for this target.", .{});2548 if (mod_opts.single_threaded == false)
2701 }2549 create_module.opts.any_non_single_threaded = true;
2702 }2550 if (mod_opts.sanitize_thread == true)
2551 create_module.opts.any_sanitize_thread = true;
2552 if (mod_opts.unwind_tables == true)
2553 create_module.opts.any_unwind_tables = true;
27032554
2704 if (want_lto) |opt| {2555 const src_path = try introspect.resolvePath(arena, unresolved_src_path);
2705 if (opt and target.isDarwin()) {2556 try create_module.modules.put(arena, "main", .{
2706 fatal("LTO is not yet supported with the Mach-O object format. More details: https://github.com/ziglang/zig/issues/8680", .{});2557 .paths = .{
2707 }2558 .root = .{
2559 .root_dir = Cache.Directory.cwd(),
2560 .sub_path = fs.path.dirname(src_path) orelse "",
2561 },
2562 .root_src_path = fs.path.basename(src_path),
2563 },
2564 .cc_argv = try clang_argv.toOwnedSlice(arena),
2565 .inherited = mod_opts,
2566 .target_arch_os_abi = target_arch_os_abi,
2567 .target_mcpu = target_mcpu,
2568 .deps = try deps.toOwnedSlice(arena),
2569 .resolved = null,
2570 .c_source_files_start = c_source_files_owner_index,
2571 .c_source_files_end = create_module.c_source_files.items.len,
2572 .rc_source_files_start = rc_source_files_owner_index,
2573 .rc_source_files_end = create_module.rc_source_files.items.len,
2574 });
2575 cssan.reset();
2576 mod_opts = .{};
2577 target_arch_os_abi = null;
2578 target_mcpu = null;
2579 c_source_files_owner_index = create_module.c_source_files.items.len;
2580 rc_source_files_owner_index = create_module.rc_source_files.items.len;
2708 }2581 }
27092582
2710 if (comptime builtin.target.isDarwin()) {2583 if (c_source_files_owner_index != create_module.c_source_files.items.len) {
2711 // If we want to link against frameworks, we need system headers.2584 fatal("C source file '{s}' has no parent module", .{
2712 if (framework_dirs.items.len > 0 or frameworks.count() > 0)2585 create_module.c_source_files.items[c_source_files_owner_index].src_path,
2713 want_native_include_dirs = true;2586 });
2714 }2587 }
27152588
2716 // Resolve the library path arguments with respect to sysroot.2589 if (rc_source_files_owner_index != create_module.rc_source_files.items.len) {
2717 var lib_dirs = std.ArrayList([]const u8).init(arena);2590 fatal("resource file '{s}' has no parent module", .{
2718 if (sysroot) |root| {2591 create_module.rc_source_files.items[rc_source_files_owner_index].src_path,
2719 for (lib_dir_args.items) |dir| {2592 });
2720 if (fs.path.isAbsolute(dir)) {
2721 const stripped_dir = dir[fs.path.diskDesignator(dir).len..];
2722 const full_path = try fs.path.join(arena, &[_][]const u8{ root, stripped_dir });
2723 try lib_dirs.append(full_path);
2724 }
2725 try lib_dirs.append(dir);
2726 }
2727 } else {
2728 lib_dirs = lib_dir_args;
2729 }2593 }
2730 lib_dir_args = undefined; // From here we use lib_dirs instead.
27312594
2732 const self_exe_path: ?[]const u8 = if (!process.can_spawn)2595 const self_exe_path: ?[]const u8 = if (!process.can_spawn)
2733 null2596 null
...@@ -2757,87 +2620,185 @@ fn buildOutputType(...@@ -2757,87 +2620,185 @@ fn buildOutputType(
2757 };2620 };
2758 defer zig_lib_directory.handle.close();2621 defer zig_lib_directory.handle.close();
27592622
2760 // First, remove libc, libc++, and compiler_rt libraries from the system libraries list.2623 var global_cache_directory: Compilation.Directory = l: {
2761 // We need to know whether the set of system libraries contains anything besides these2624 if (override_global_cache_dir) |p| {
2762 // to decide whether to trigger native path detection logic.2625 break :l .{
2763 var external_system_libs: std.MultiArrayList(struct {2626 .handle = try fs.cwd().makeOpenPath(p, .{}),
2764 name: []const u8,2627 .path = p,
2765 info: SystemLib,2628 };
2766 }) = .{};2629 }
2630 if (builtin.os.tag == .wasi) {
2631 break :l getWasiPreopen("/cache");
2632 }
2633 const p = try introspect.resolveGlobalCacheDir(arena);
2634 break :l .{
2635 .handle = try fs.cwd().makeOpenPath(p, .{}),
2636 .path = p,
2637 };
2638 };
2639 defer global_cache_directory.handle.close();
27672640
2768 var resolved_system_libs: std.MultiArrayList(struct {2641 create_module.global_cache_directory = global_cache_directory;
2769 name: []const u8,2642 create_module.opts.emit_llvm_ir = emit_llvm_ir != .no;
2770 lib: Compilation.SystemLib,2643 create_module.opts.emit_llvm_bc = emit_llvm_bc != .no;
2771 }) = .{};2644 create_module.opts.emit_bin = emit_bin != .no;
2645 create_module.opts.c_source_files_len = create_module.c_source_files.items.len;
27722646
2773 var libc_installation: ?LibCInstallation = null;2647 const main_mod = try createModule(gpa, arena, &create_module, 0, null, zig_lib_directory);
2774 if (libc_paths_file) |paths_file| {2648 for (create_module.modules.keys(), create_module.modules.values()) |key, cli_mod| {
2775 libc_installation = LibCInstallation.parse(arena, paths_file, target) catch |err| {2649 if (cli_mod.resolved == null)
2776 fatal("unable to parse libc paths file at path {s}: {s}", .{ paths_file, @errorName(err) });2650 fatal("module '{s}' declared but not used", .{key});
2777 };
2778 }2651 }
27792652
2780 for (system_libs.keys(), system_libs.values()) |lib_name, info| {2653 // When you're testing std, the main module is std. In that case,
2781 if (target.is_libc_lib_name(lib_name)) {2654 // we'll just set the std module to the main one, since avoiding
2782 link_libc = true;2655 // the errors caused by duplicating it is more effort than it's
2783 continue;2656 // worth.
2784 }2657 const main_mod_is_std = m: {
2785 if (target.is_libcpp_lib_name(lib_name)) {2658 const std_path = try fs.path.resolve(arena, &.{
2786 link_libcpp = true;2659 zig_lib_directory.path orelse ".", "std", "std.zig",
2787 continue;2660 });
2788 }2661 const main_path = try fs.path.resolve(arena, &.{
2789 switch (target_util.classifyCompilerRtLibName(target, lib_name)) {2662 main_mod.root.root_dir.path orelse ".",
2790 .none => {},2663 main_mod.root.sub_path,
2791 .only_libunwind, .both => {2664 main_mod.root_src_path,
2792 link_libunwind = true;2665 });
2793 continue;2666 break :m mem.eql(u8, main_path, std_path);
2794 },2667 };
2795 .only_compiler_rt => {2668
2796 warn("ignoring superfluous library '{s}': this dependency is fulfilled instead by compiler-rt which zig unconditionally provides", .{lib_name});2669 const std_mod = m: {
2797 continue;2670 if (main_mod_is_std) break :m main_mod;
2671 if (create_module.modules.get("std")) |cli_mod| break :m cli_mod.resolved.?;
2672
2673 break :m try Package.Module.create(arena, .{
2674 .global_cache_directory = global_cache_directory,
2675 .paths = .{
2676 .root = .{
2677 .root_dir = zig_lib_directory,
2678 .sub_path = "std",
2679 },
2680 .root_src_path = "std.zig",
2798 },2681 },
2799 }2682 .fully_qualified_name = "std",
2683 .cc_argv = &.{},
2684 .inherited = .{},
2685 .global = create_module.resolved_options,
2686 .parent = main_mod,
2687 .builtin_mod = main_mod.getBuiltinDependency(),
2688 });
2689 };
28002690
2801 if (target.isMinGW()) {2691 const root_mod = if (arg_mode == .zig_test) root_mod: {
2802 const exists = mingw.libExists(arena, target, zig_lib_directory, lib_name) catch |err| {2692 const test_mod = if (test_runner_path) |test_runner| test_mod: {
2803 fatal("failed to check zig installation for DLL import libs: {s}", .{2693 const test_mod = try Package.Module.create(arena, .{
2804 @errorName(err),2694 .global_cache_directory = global_cache_directory,
2805 });2695 .paths = .{
2806 };2696 .root = .{
2807 if (exists) {2697 .root_dir = Cache.Directory.cwd(),
2808 try resolved_system_libs.append(arena, .{2698 .sub_path = fs.path.dirname(test_runner) orelse "",
2809 .name = lib_name,
2810 .lib = .{
2811 .needed = true,
2812 .weak = false,
2813 .path = null,
2814 },2699 },
2815 });2700 .root_src_path = fs.path.basename(test_runner),
2816 continue;2701 },
2817 }2702 .fully_qualified_name = "root",
2703 .cc_argv = &.{},
2704 .inherited = .{},
2705 .global = create_module.resolved_options,
2706 .parent = main_mod,
2707 .builtin_mod = main_mod.getBuiltinDependency(),
2708 });
2709 test_mod.deps = try main_mod.deps.clone(arena);
2710 break :test_mod test_mod;
2711 } else try Package.Module.create(arena, .{
2712 .global_cache_directory = global_cache_directory,
2713 .paths = .{
2714 .root = .{
2715 .root_dir = zig_lib_directory,
2716 },
2717 .root_src_path = "test_runner.zig",
2718 },
2719 .fully_qualified_name = "root",
2720 .cc_argv = &.{},
2721 .inherited = .{},
2722 .global = create_module.resolved_options,
2723 .parent = main_mod,
2724 .builtin_mod = main_mod.getBuiltinDependency(),
2725 });
2726
2727 break :root_mod test_mod;
2728 } else main_mod;
2729
2730 const target = main_mod.resolved_target.result;
2731
2732 if (target.ofmt != .coff) {
2733 if (manifest_file != null) {
2734 fatal("manifest file is not allowed unless the target object format is coff (Windows/UEFI)", .{});
2735 }
2736 if (create_module.rc_source_files.items.len != 0) {
2737 fatal("rc files are not allowed unless the target object format is coff (Windows/UEFI)", .{});
2818 }2738 }
2739 if (contains_res_file) {
2740 fatal("res files are not allowed unless the target object format is coff (Windows/UEFI)", .{});
2741 }
2742 }
28192743
2820 if (fs.path.isAbsolute(lib_name)) {2744 const root_name = if (provided_name) |n| n else blk: {
2821 fatal("cannot use absolute path as a system library: {s}", .{lib_name});2745 if (arg_mode == .zig_test) {
2746 break :blk "test";
2747 } else if (root_src_file) |file| {
2748 const basename = fs.path.basename(file);
2749 break :blk basename[0 .. basename.len - fs.path.extension(basename).len];
2750 } else if (create_module.c_source_files.items.len >= 1) {
2751 const basename = fs.path.basename(create_module.c_source_files.items[0].src_path);
2752 break :blk basename[0 .. basename.len - fs.path.extension(basename).len];
2753 } else if (link_objects.items.len >= 1) {
2754 const basename = fs.path.basename(link_objects.items[0].path);
2755 break :blk basename[0 .. basename.len - fs.path.extension(basename).len];
2756 } else if (emit_bin == .yes) {
2757 const basename = fs.path.basename(emit_bin.yes);
2758 break :blk basename[0 .. basename.len - fs.path.extension(basename).len];
2759 } else if (create_module.rc_source_files.items.len >= 1) {
2760 const basename = fs.path.basename(create_module.rc_source_files.items[0].src_path);
2761 break :blk basename[0 .. basename.len - fs.path.extension(basename).len];
2762 } else if (show_builtin) {
2763 break :blk "builtin";
2764 } else if (arg_mode == .run) {
2765 fatal("`zig run` expects at least one positional argument", .{});
2766 // TODO once the attempt to unwrap error: LinkingWithoutZigSourceUnimplemented
2767 // is solved, remove the above fatal() and uncomment the `break` below.
2768 //break :blk "run";
2769 } else {
2770 fatal("expected a positional argument, -femit-bin=[path], --show-builtin, or --name [name]", .{});
2822 }2771 }
2772 };
28232773
2824 if (target.os.tag == .wasi) {2774 // Resolve the library path arguments with respect to sysroot.
2825 if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| {2775 var lib_dirs: std.ArrayListUnmanaged([]const u8) = .{};
2826 try wasi_emulated_libs.append(crt_file);2776 if (sysroot) |root| {
2827 continue;2777 try lib_dirs.ensureUnusedCapacity(arena, lib_dir_args.items.len * 2);
2778 for (lib_dir_args.items) |dir| {
2779 if (fs.path.isAbsolute(dir)) {
2780 const stripped_dir = dir[fs.path.diskDesignator(dir).len..];
2781 const full_path = try fs.path.join(arena, &[_][]const u8{ root, stripped_dir });
2782 lib_dirs.appendAssumeCapacity(full_path);
2828 }2783 }
2784 lib_dirs.appendAssumeCapacity(dir);
2829 }2785 }
2786 } else {
2787 lib_dirs = lib_dir_args;
2788 }
2789 lib_dir_args = undefined; // From here we use lib_dirs instead.
28302790
2831 try external_system_libs.append(arena, .{2791 if (main_mod.resolved_target.is_native_os and target.isDarwin()) {
2832 .name = lib_name,2792 // If we want to link against frameworks, we need system headers.
2833 .info = info,2793 if (framework_dirs.items.len > 0 or frameworks.count() > 0)
2834 });2794 want_native_include_dirs = true;
2835 }2795 }
2836 // After this point, external_system_libs is used instead of system_libs.
28372796
2838 // Trigger native system library path detection if necessary.2797 // Trigger native system library path detection if necessary.
2839 if (sysroot == null and target_query.isNativeOs() and target_query.isNativeAbi() and2798 if (sysroot == null and
2840 (external_system_libs.len != 0 or want_native_include_dirs))2799 main_mod.resolved_target.is_native_os and
2800 main_mod.resolved_target.is_native_abi and
2801 (create_module.external_system_libs.len != 0 or want_native_include_dirs))
2841 {2802 {
2842 const paths = std.zig.system.NativePaths.detect(arena, target) catch |err| {2803 const paths = std.zig.system.NativePaths.detect(arena, target) catch |err| {
2843 fatal("unable to detect native system paths: {s}", .{@errorName(err)});2804 fatal("unable to detect native system paths: {s}", .{@errorName(err)});
...@@ -2846,20 +2807,27 @@ fn buildOutputType(...@@ -2846,20 +2807,27 @@ fn buildOutputType(
2846 warn("{s}", .{warning});2807 warn("{s}", .{warning});
2847 }2808 }
28482809
2849 try clang_argv.ensureUnusedCapacity(paths.include_dirs.items.len * 2);2810 try clang_argv.ensureUnusedCapacity(arena, paths.include_dirs.items.len * 2);
2850 for (paths.include_dirs.items) |include_dir| {2811 for (paths.include_dirs.items) |include_dir| {
2851 clang_argv.appendAssumeCapacity("-isystem");2812 clang_argv.appendAssumeCapacity("-isystem");
2852 clang_argv.appendAssumeCapacity(include_dir);2813 clang_argv.appendAssumeCapacity(include_dir);
2853 }2814 }
28542815
2855 try framework_dirs.appendSlice(paths.framework_dirs.items);2816 try framework_dirs.appendSlice(arena, paths.framework_dirs.items);
2856 try lib_dirs.appendSlice(paths.lib_dirs.items);2817 try lib_dirs.appendSlice(arena, paths.lib_dirs.items);
2857 try rpath_list.appendSlice(paths.rpaths.items);2818 try rpath_list.appendSlice(arena, paths.rpaths.items);
2819 }
2820
2821 var libc_installation: ?LibCInstallation = null;
2822 if (libc_paths_file) |paths_file| {
2823 libc_installation = LibCInstallation.parse(arena, paths_file, target) catch |err| {
2824 fatal("unable to parse libc paths file at path {s}: {s}", .{ paths_file, @errorName(err) });
2825 };
2858 }2826 }
28592827
2860 if (builtin.target.os.tag == .windows and2828 if (builtin.target.os.tag == .windows and
2861 target.abi == .msvc and2829 target.abi == .msvc and
2862 external_system_libs.len != 0)2830 create_module.external_system_libs.len != 0)
2863 {2831 {
2864 if (libc_installation == null) {2832 if (libc_installation == null) {
2865 libc_installation = try LibCInstallation.findNative(.{2833 libc_installation = try LibCInstallation.findNative(.{
...@@ -2868,7 +2836,10 @@ fn buildOutputType(...@@ -2868,7 +2836,10 @@ fn buildOutputType(
2868 .target = target,2836 .target = target,
2869 });2837 });
28702838
2871 try lib_dirs.appendSlice(&.{ libc_installation.?.msvc_lib_dir.?, libc_installation.?.kernel32_lib_dir.? });2839 try lib_dirs.appendSlice(arena, &.{
2840 libc_installation.?.msvc_lib_dir.?,
2841 libc_installation.?.kernel32_lib_dir.?,
2842 });
2872 }2843 }
2873 }2844 }
28742845
...@@ -2888,7 +2859,7 @@ fn buildOutputType(...@@ -2888,7 +2859,7 @@ fn buildOutputType(
2888 preferred_mode: std.builtin.LinkMode,2859 preferred_mode: std.builtin.LinkMode,
2889 }).init(arena);2860 }).init(arena);
28902861
2891 syslib: for (external_system_libs.items(.name), external_system_libs.items(.info)) |lib_name, info| {2862 syslib: for (create_module.external_system_libs.items(.name), create_module.external_system_libs.items(.info)) |lib_name, info| {
2892 // Checked in the first pass above while looking for libc libraries.2863 // Checked in the first pass above while looking for libc libraries.
2893 assert(!fs.path.isAbsolute(lib_name));2864 assert(!fs.path.isAbsolute(lib_name));
28942865
...@@ -2908,8 +2879,8 @@ fn buildOutputType(...@@ -2908,8 +2879,8 @@ fn buildOutputType(
2908 )) {2879 )) {
2909 const path = try arena.dupe(u8, test_path.items);2880 const path = try arena.dupe(u8, test_path.items);
2910 switch (info.preferred_mode) {2881 switch (info.preferred_mode) {
2911 .Static => try link_objects.append(.{ .path = path }),2882 .Static => try link_objects.append(arena, .{ .path = path }),
2912 .Dynamic => try resolved_system_libs.append(arena, .{2883 .Dynamic => try create_module.resolved_system_libs.append(arena, .{
2913 .name = lib_name,2884 .name = lib_name,
2914 .lib = .{2885 .lib = .{
2915 .needed = info.needed,2886 .needed = info.needed,
...@@ -2942,8 +2913,8 @@ fn buildOutputType(...@@ -2942,8 +2913,8 @@ fn buildOutputType(
2942 )) {2913 )) {
2943 const path = try arena.dupe(u8, test_path.items);2914 const path = try arena.dupe(u8, test_path.items);
2944 switch (info.fallbackMode()) {2915 switch (info.fallbackMode()) {
2945 .Static => try link_objects.append(.{ .path = path }),2916 .Static => try link_objects.append(arena, .{ .path = path }),
2946 .Dynamic => try resolved_system_libs.append(arena, .{2917 .Dynamic => try create_module.resolved_system_libs.append(arena, .{
2947 .name = lib_name,2918 .name = lib_name,
2948 .lib = .{2919 .lib = .{
2949 .needed = info.needed,2920 .needed = info.needed,
...@@ -2976,8 +2947,8 @@ fn buildOutputType(...@@ -2976,8 +2947,8 @@ fn buildOutputType(
2976 )) {2947 )) {
2977 const path = try arena.dupe(u8, test_path.items);2948 const path = try arena.dupe(u8, test_path.items);
2978 switch (info.preferred_mode) {2949 switch (info.preferred_mode) {
2979 .Static => try link_objects.append(.{ .path = path }),2950 .Static => try link_objects.append(arena, .{ .path = path }),
2980 .Dynamic => try resolved_system_libs.append(arena, .{2951 .Dynamic => try create_module.resolved_system_libs.append(arena, .{
2981 .name = lib_name,2952 .name = lib_name,
2982 .lib = .{2953 .lib = .{
2983 .needed = info.needed,2954 .needed = info.needed,
...@@ -3000,8 +2971,8 @@ fn buildOutputType(...@@ -3000,8 +2971,8 @@ fn buildOutputType(
3000 )) {2971 )) {
3001 const path = try arena.dupe(u8, test_path.items);2972 const path = try arena.dupe(u8, test_path.items);
3002 switch (info.fallbackMode()) {2973 switch (info.fallbackMode()) {
3003 .Static => try link_objects.append(.{ .path = path }),2974 .Static => try link_objects.append(arena, .{ .path = path }),
3004 .Dynamic => try resolved_system_libs.append(arena, .{2975 .Dynamic => try create_module.resolved_system_libs.append(arena, .{
3005 .name = lib_name,2976 .name = lib_name,
3006 .lib = .{2977 .lib = .{
3007 .needed = info.needed,2978 .needed = info.needed,
...@@ -3035,7 +3006,8 @@ fn buildOutputType(...@@ -3035,7 +3006,8 @@ fn buildOutputType(
3035 process.exit(1);3006 process.exit(1);
3036 }3007 }
3037 }3008 }
3038 // After this point, resolved_system_libs is used instead of external_system_libs.3009 // After this point, create_module.resolved_system_libs is used instead of
3010 // create_module.external_system_libs.
30393011
3040 // We now repeat part of the process for frameworks.3012 // We now repeat part of the process for frameworks.
3041 var resolved_frameworks = std.ArrayList(Compilation.Framework).init(arena);3013 var resolved_frameworks = std.ArrayList(Compilation.Framework).init(arena);
...@@ -3090,10 +3062,10 @@ fn buildOutputType(...@@ -3090,10 +3062,10 @@ fn buildOutputType(
3090 }3062 }
3091 // After this point, resolved_frameworks is used instead of frameworks.3063 // After this point, resolved_frameworks is used instead of frameworks.
30923064
3093 if (output_mode == .Obj and (target.ofmt == .coff or target.ofmt == .macho)) {3065 if (create_module.opts.output_mode == .Obj and (target.ofmt == .coff or target.ofmt == .macho)) {
3094 const total_obj_count = c_source_files.items.len +3066 const total_obj_count = create_module.c_source_files.items.len +
3095 @intFromBool(root_src_file != null) +3067 @intFromBool(root_src_file != null) +
3096 rc_source_files.items.len +3068 create_module.rc_source_files.items.len +
3097 link_objects.items.len;3069 link_objects.items.len;
3098 if (total_obj_count > 1) {3070 if (total_obj_count > 1) {
3099 fatal("{s} does not support linking multiple objects into one", .{@tagName(target.ofmt)});3071 fatal("{s} does not support linking multiple objects into one", .{@tagName(target.ofmt)});
...@@ -3141,8 +3113,8 @@ fn buildOutputType(...@@ -3141,8 +3113,8 @@ fn buildOutputType(
3141 .basename = try std.zig.binNameAlloc(arena, .{3113 .basename = try std.zig.binNameAlloc(arena, .{
3142 .root_name = root_name,3114 .root_name = root_name,
3143 .target = target,3115 .target = target,
3144 .output_mode = output_mode,3116 .output_mode = create_module.opts.output_mode,
3145 .link_mode = link_mode,3117 .link_mode = create_module.opts.link_mode,
3146 .version = optional_version,3118 .version = optional_version,
3147 }),3119 }),
3148 },3120 },
...@@ -3260,9 +3232,9 @@ fn buildOutputType(...@@ -3260,9 +3232,9 @@ fn buildOutputType(
3260 };3232 };
3261 defer emit_docs_resolved.deinit();3233 defer emit_docs_resolved.deinit();
32623234
3263 const is_exe_or_dyn_lib = switch (output_mode) {3235 const is_exe_or_dyn_lib = switch (create_module.opts.output_mode) {
3264 .Obj => false,3236 .Obj => false,
3265 .Lib => (link_mode orelse .Static) == .Dynamic,3237 .Lib => (create_module.opts.link_mode orelse .Static) == .Dynamic,
3266 .Exe => true,3238 .Exe => true,
3267 };3239 };
3268 // Note that cmake when targeting Windows will try to execute3240 // Note that cmake when targeting Windows will try to execute
...@@ -3294,76 +3266,10 @@ fn buildOutputType(...@@ -3294,76 +3266,10 @@ fn buildOutputType(
3294 };3266 };
3295 defer emit_implib_resolved.deinit();3267 defer emit_implib_resolved.deinit();
32963268
3297 const main_mod: ?*Package.Module = if (root_src_file) |unresolved_src_path| blk: {
3298 const src_path = try introspect.resolvePath(arena, unresolved_src_path);
3299 if (main_mod_path) |unresolved_main_mod_path| {
3300 const p = try introspect.resolvePath(arena, unresolved_main_mod_path);
3301 break :blk try Package.Module.create(arena, .{
3302 .root = .{
3303 .root_dir = Cache.Directory.cwd(),
3304 .sub_path = p,
3305 },
3306 .root_src_path = if (p.len == 0)
3307 src_path
3308 else
3309 try fs.path.relative(arena, p, src_path),
3310 .fully_qualified_name = "root",
3311 });
3312 } else {
3313 break :blk try Package.Module.create(arena, .{
3314 .root = .{
3315 .root_dir = Cache.Directory.cwd(),
3316 .sub_path = fs.path.dirname(src_path) orelse "",
3317 },
3318 .root_src_path = fs.path.basename(src_path),
3319 .fully_qualified_name = "root",
3320 });
3321 }
3322 } else null;
3323
3324 // Transfer packages added with --deps to the root package
3325 if (main_mod) |mod| {
3326 var it = ModuleDepIterator.init(root_deps_str orelse "");
3327 while (it.next()) |dep| {
3328 if (dep.expose.len == 0) {
3329 fatal("root module depends on '{s}' with a blank name", .{dep.name});
3330 }
3331
3332 for ([_][]const u8{ "std", "root", "builtin" }) |name| {
3333 if (mem.eql(u8, dep.expose, name)) {
3334 fatal("unable to add module '{s}' under name '{s}': conflicts with builtin module", .{ dep.name, dep.expose });
3335 }
3336 }
3337
3338 const dep_mod = modules.get(dep.name) orelse
3339 fatal("root module depends on module '{s}' which does not exist", .{dep.name});
3340
3341 try mod.deps.put(arena, dep.expose, dep_mod.mod);
3342 }
3343 }
3344
3345 var thread_pool: ThreadPool = undefined;3269 var thread_pool: ThreadPool = undefined;
3346 try thread_pool.init(.{ .allocator = gpa });3270 try thread_pool.init(.{ .allocator = gpa });
3347 defer thread_pool.deinit();3271 defer thread_pool.deinit();
33483272
3349 var global_cache_directory: Compilation.Directory = l: {
3350 if (override_global_cache_dir) |p| {
3351 break :l .{
3352 .handle = try fs.cwd().makeOpenPath(p, .{}),
3353 .path = p,
3354 };
3355 }
3356 if (builtin.os.tag == .wasi) {
3357 break :l getWasiPreopen("/cache");
3358 }
3359 const p = try introspect.resolveGlobalCacheDir(arena);
3360 break :l .{
3361 .handle = try fs.cwd().makeOpenPath(p, .{}),
3362 .path = p,
3363 };
3364 };
3365 defer global_cache_directory.handle.close();
3366
3367 var cleanup_local_cache_dir: ?fs.Dir = null;3273 var cleanup_local_cache_dir: ?fs.Dir = null;
3368 defer if (cleanup_local_cache_dir) |*dir| dir.close();3274 defer if (cleanup_local_cache_dir) |*dir| dir.close();
33693275
...@@ -3379,37 +3285,37 @@ fn buildOutputType(...@@ -3379,37 +3285,37 @@ fn buildOutputType(
3379 if (arg_mode == .run) {3285 if (arg_mode == .run) {
3380 break :l global_cache_directory;3286 break :l global_cache_directory;
3381 }3287 }
3382 if (main_mod != null) {3288
3383 // search upwards from cwd until we find directory with build.zig3289 // search upwards from cwd until we find directory with build.zig
3384 const cwd_path = try process.getCwdAlloc(arena);3290 const cwd_path = try process.getCwdAlloc(arena);
3385 const zig_cache = "zig-cache";3291 const zig_cache = "zig-cache";
3386 var dirname: []const u8 = cwd_path;3292 var dirname: []const u8 = cwd_path;
3387 while (true) {3293 while (true) {
3388 const joined_path = try fs.path.join(arena, &.{3294 const joined_path = try fs.path.join(arena, &.{
3389 dirname, Package.build_zig_basename,3295 dirname, Package.build_zig_basename,
3390 });3296 });
3391 if (fs.cwd().access(joined_path, .{})) |_| {3297 if (fs.cwd().access(joined_path, .{})) |_| {
3392 const cache_dir_path = try fs.path.join(arena, &.{ dirname, zig_cache });3298 const cache_dir_path = try fs.path.join(arena, &.{ dirname, zig_cache });
3393 const dir = try fs.cwd().makeOpenPath(cache_dir_path, .{});3299 const dir = try fs.cwd().makeOpenPath(cache_dir_path, .{});
3394 cleanup_local_cache_dir = dir;3300 cleanup_local_cache_dir = dir;
3395 break :l .{ .handle = dir, .path = cache_dir_path };3301 break :l .{ .handle = dir, .path = cache_dir_path };
3396 } else |err| switch (err) {3302 } else |err| switch (err) {
3397 error.FileNotFound => {3303 error.FileNotFound => {
3398 dirname = fs.path.dirname(dirname) orelse {3304 dirname = fs.path.dirname(dirname) orelse {
3399 break :l global_cache_directory;3305 break :l global_cache_directory;
3400 };3306 };
3401 continue;3307 continue;
3402 },3308 },
3403 else => break :l global_cache_directory,3309 else => break :l global_cache_directory,
3404 }
3405 }3310 }
3406 }3311 }
3312
3407 // Otherwise we really don't have a reasonable place to put the local cache directory,3313 // Otherwise we really don't have a reasonable place to put the local cache directory,
3408 // so we utilize the global one.3314 // so we utilize the global one.
3409 break :l global_cache_directory;3315 break :l global_cache_directory;
3410 };3316 };
34113317
3412 for (c_source_files.items) |*src| {3318 for (create_module.c_source_files.items) |*src| {
3413 if (!mem.eql(u8, src.src_path, "-")) continue;3319 if (!mem.eql(u8, src.src_path, "-")) continue;
34143320
3415 const ext = src.ext orelse3321 const ext = src.ext orelse
...@@ -3452,13 +3358,14 @@ fn buildOutputType(...@@ -3452,13 +3358,14 @@ fn buildOutputType(
3452 .zig_lib_directory = zig_lib_directory,3358 .zig_lib_directory = zig_lib_directory,
3453 .local_cache_directory = local_cache_directory,3359 .local_cache_directory = local_cache_directory,
3454 .global_cache_directory = global_cache_directory,3360 .global_cache_directory = global_cache_directory,
3361 .thread_pool = &thread_pool,
3362 .self_exe_path = self_exe_path,
3363 .config = create_module.resolved_options,
3455 .root_name = root_name,3364 .root_name = root_name,
3456 .target = target,
3457 .is_native_os = target_query.isNativeOs(),
3458 .is_native_abi = target_query.isNativeAbi(),
3459 .sysroot = sysroot,3365 .sysroot = sysroot,
3460 .output_mode = output_mode,
3461 .main_mod = main_mod,3366 .main_mod = main_mod,
3367 .root_mod = root_mod,
3368 .std_mod = std_mod,
3462 .emit_bin = emit_bin_loc,3369 .emit_bin = emit_bin_loc,
3463 .emit_h = emit_h_resolved.data,3370 .emit_h = emit_h_resolved.data,
3464 .emit_asm = emit_asm_resolved.data,3371 .emit_asm = emit_asm_resolved.data,
...@@ -3466,43 +3373,22 @@ fn buildOutputType(...@@ -3466,43 +3373,22 @@ fn buildOutputType(
3466 .emit_llvm_bc = emit_llvm_bc_resolved.data,3373 .emit_llvm_bc = emit_llvm_bc_resolved.data,
3467 .emit_docs = emit_docs_resolved.data,3374 .emit_docs = emit_docs_resolved.data,
3468 .emit_implib = emit_implib_resolved.data,3375 .emit_implib = emit_implib_resolved.data,
3469 .link_mode = link_mode,
3470 .dll_export_fns = dll_export_fns,3376 .dll_export_fns = dll_export_fns,
3471 .optimize_mode = optimize_mode,
3472 .keep_source_files_loaded = false,3377 .keep_source_files_loaded = false,
3473 .clang_argv = clang_argv.items,
3474 .lib_dirs = lib_dirs.items,3378 .lib_dirs = lib_dirs.items,
3475 .rpath_list = rpath_list.items,3379 .rpath_list = rpath_list.items,
3476 .symbol_wrap_set = symbol_wrap_set,3380 .symbol_wrap_set = symbol_wrap_set,
3477 .c_source_files = c_source_files.items,3381 .c_source_files = create_module.c_source_files.items,
3478 .rc_source_files = rc_source_files.items,3382 .rc_source_files = create_module.rc_source_files.items,
3479 .manifest_file = manifest_file,3383 .manifest_file = manifest_file,
3480 .rc_includes = rc_includes,3384 .rc_includes = rc_includes,
3481 .link_objects = link_objects.items,3385 .link_objects = link_objects.items,
3482 .framework_dirs = framework_dirs.items,3386 .framework_dirs = framework_dirs.items,
3483 .frameworks = resolved_frameworks.items,3387 .frameworks = resolved_frameworks.items,
3484 .system_lib_names = resolved_system_libs.items(.name),3388 .system_lib_names = create_module.resolved_system_libs.items(.name),
3485 .system_lib_infos = resolved_system_libs.items(.lib),3389 .system_lib_infos = create_module.resolved_system_libs.items(.lib),
3486 .wasi_emulated_libs = wasi_emulated_libs.items,3390 .wasi_emulated_libs = create_module.wasi_emulated_libs.items,
3487 .link_libc = link_libc,
3488 .link_libcpp = link_libcpp,
3489 .link_libunwind = link_libunwind,
3490 .want_pic = want_pic,
3491 .want_pie = want_pie,
3492 .want_lto = want_lto,
3493 .want_unwind_tables = want_unwind_tables,
3494 .want_sanitize_c = want_sanitize_c,
3495 .want_stack_check = want_stack_check,
3496 .want_stack_protector = want_stack_protector,
3497 .want_red_zone = want_red_zone,
3498 .omit_frame_pointer = omit_frame_pointer,
3499 .want_valgrind = want_valgrind,
3500 .want_tsan = want_tsan,
3501 .want_compiler_rt = want_compiler_rt,3391 .want_compiler_rt = want_compiler_rt,
3502 .use_llvm = use_llvm,
3503 .use_lib_llvm = use_lib_llvm,
3504 .use_lld = use_lld,
3505 .use_clang = use_clang,
3506 .hash_style = hash_style,3392 .hash_style = hash_style,
3507 .rdynamic = rdynamic,3393 .rdynamic = rdynamic,
3508 .linker_script = linker_script,3394 .linker_script = linker_script,
...@@ -3513,14 +3399,11 @@ fn buildOutputType(...@@ -3513,14 +3399,11 @@ fn buildOutputType(
3513 .linker_gc_sections = linker_gc_sections,3399 .linker_gc_sections = linker_gc_sections,
3514 .linker_allow_shlib_undefined = linker_allow_shlib_undefined,3400 .linker_allow_shlib_undefined = linker_allow_shlib_undefined,
3515 .linker_bind_global_refs_locally = linker_bind_global_refs_locally,3401 .linker_bind_global_refs_locally = linker_bind_global_refs_locally,
3516 .linker_import_memory = linker_import_memory,
3517 .linker_export_memory = linker_export_memory,
3518 .linker_import_symbols = linker_import_symbols,3402 .linker_import_symbols = linker_import_symbols,
3519 .linker_import_table = linker_import_table,3403 .linker_import_table = linker_import_table,
3520 .linker_export_table = linker_export_table,3404 .linker_export_table = linker_export_table,
3521 .linker_initial_memory = linker_initial_memory,3405 .linker_initial_memory = linker_initial_memory,
3522 .linker_max_memory = linker_max_memory,3406 .linker_max_memory = linker_max_memory,
3523 .linker_shared_memory = linker_shared_memory,
3524 .linker_print_gc_sections = linker_print_gc_sections,3407 .linker_print_gc_sections = linker_print_gc_sections,
3525 .linker_print_icf_sections = linker_print_icf_sections,3408 .linker_print_icf_sections = linker_print_icf_sections,
3526 .linker_print_map = linker_print_map,3409 .linker_print_map = linker_print_map,
...@@ -3546,18 +3429,13 @@ fn buildOutputType(...@@ -3546,18 +3429,13 @@ fn buildOutputType(
3546 .minor_subsystem_version = minor_subsystem_version,3429 .minor_subsystem_version = minor_subsystem_version,
3547 .link_eh_frame_hdr = link_eh_frame_hdr,3430 .link_eh_frame_hdr = link_eh_frame_hdr,
3548 .link_emit_relocs = link_emit_relocs,3431 .link_emit_relocs = link_emit_relocs,
3549 .entry = entry,
3550 .force_undefined_symbols = force_undefined_symbols,3432 .force_undefined_symbols = force_undefined_symbols,
3551 .stack_size_override = stack_size_override,3433 .stack_size_override = stack_size_override,
3552 .image_base_override = image_base_override,3434 .image_base_override = image_base_override,
3553 .strip = strip,
3554 .formatted_panics = formatted_panics,3435 .formatted_panics = formatted_panics,
3555 .single_threaded = single_threaded,
3556 .function_sections = function_sections,3436 .function_sections = function_sections,
3557 .data_sections = data_sections,3437 .data_sections = data_sections,
3558 .no_builtin = no_builtin,3438 .no_builtin = no_builtin,
3559 .self_exe_path = self_exe_path,
3560 .thread_pool = &thread_pool,
3561 .clang_passthrough_mode = clang_passthrough_mode,3439 .clang_passthrough_mode = clang_passthrough_mode,
3562 .clang_preprocessor_mode = clang_preprocessor_mode,3440 .clang_preprocessor_mode = clang_preprocessor_mode,
3563 .version = optional_version,3441 .version = optional_version,
...@@ -3571,21 +3449,17 @@ fn buildOutputType(...@@ -3571,21 +3449,17 @@ fn buildOutputType(
3571 .verbose_llvm_bc = verbose_llvm_bc,3449 .verbose_llvm_bc = verbose_llvm_bc,
3572 .verbose_cimport = verbose_cimport,3450 .verbose_cimport = verbose_cimport,
3573 .verbose_llvm_cpu_features = verbose_llvm_cpu_features,3451 .verbose_llvm_cpu_features = verbose_llvm_cpu_features,
3574 .machine_code_model = machine_code_model,
3575 .color = color,3452 .color = color,
3576 .time_report = time_report,3453 .time_report = time_report,
3577 .stack_report = stack_report,3454 .stack_report = stack_report,
3578 .is_test = arg_mode == .zig_test,
3579 .each_lib_rpath = each_lib_rpath,3455 .each_lib_rpath = each_lib_rpath,
3580 .build_id = build_id,3456 .build_id = build_id,
3581 .test_evented_io = test_evented_io,
3582 .test_filter = test_filter,3457 .test_filter = test_filter,
3583 .test_name_prefix = test_name_prefix,3458 .test_name_prefix = test_name_prefix,
3584 .test_runner_path = test_runner_path,3459 .test_runner_path = test_runner_path,
3585 .disable_lld_caching = !output_to_cache,3460 .disable_lld_caching = !output_to_cache,
3586 .subsystem = subsystem,3461 .subsystem = subsystem,
3587 .dwarf_format = dwarf_format,3462 .dwarf_format = dwarf_format,
3588 .wasi_exec_model = wasi_exec_model,
3589 .debug_compile_errors = debug_compile_errors,3463 .debug_compile_errors = debug_compile_errors,
3590 .enable_link_snapshots = enable_link_snapshots,3464 .enable_link_snapshots = enable_link_snapshots,
3591 .install_name = install_name,3465 .install_name = install_name,
...@@ -3595,7 +3469,6 @@ fn buildOutputType(...@@ -3595,7 +3469,6 @@ fn buildOutputType(
3595 .headerpad_max_install_names = headerpad_max_install_names,3469 .headerpad_max_install_names = headerpad_max_install_names,
3596 .dead_strip_dylibs = dead_strip_dylibs,3470 .dead_strip_dylibs = dead_strip_dylibs,
3597 .reference_trace = reference_trace,3471 .reference_trace = reference_trace,
3598 .error_tracing = error_tracing,
3599 .pdb_out_path = pdb_out_path,3472 .pdb_out_path = pdb_out_path,
3600 .error_limit = error_limit,3473 .error_limit = error_limit,
3601 .want_structured_cfg = want_structured_cfg,3474 .want_structured_cfg = want_structured_cfg,
...@@ -3702,7 +3575,7 @@ fn buildOutputType(...@@ -3702,7 +3575,7 @@ fn buildOutputType(
3702 try test_exec_args.appendSlice(&.{ "-I", p });3575 try test_exec_args.appendSlice(&.{ "-I", p });
3703 }3576 }
37043577
3705 if (link_libc) {3578 if (create_module.resolved_options.link_libc) {
3706 try test_exec_args.append("-lc");3579 try test_exec_args.append("-lc");
3707 } else if (target.os.tag == .windows) {3580 } else if (target.os.tag == .windows) {
3708 try test_exec_args.appendSlice(&.{3581 try test_exec_args.appendSlice(&.{
...@@ -3711,14 +3584,15 @@ fn buildOutputType(...@@ -3711,14 +3584,15 @@ fn buildOutputType(
3711 });3584 });
3712 }3585 }
37133586
3714 if (!mem.eql(u8, target_arch_os_abi, "native")) {3587 const first_cli_mod = create_module.modules.values()[0];
3588 if (first_cli_mod.target_arch_os_abi) |triple| {
3715 try test_exec_args.append("-target");3589 try test_exec_args.append("-target");
3716 try test_exec_args.append(target_arch_os_abi);3590 try test_exec_args.append(triple);
3717 }3591 }
3718 if (target_mcpu) |mcpu| {3592 if (first_cli_mod.target_mcpu) |mcpu| {
3719 try test_exec_args.append(try std.fmt.allocPrint(arena, "-mcpu={s}", .{mcpu}));3593 try test_exec_args.append(try std.fmt.allocPrint(arena, "-mcpu={s}", .{mcpu}));
3720 }3594 }
3721 if (target_dynamic_linker) |dl| {3595 if (create_module.dynamic_linker) |dl| {
3722 try test_exec_args.append("--dynamic-linker");3596 try test_exec_args.append("--dynamic-linker");
3723 try test_exec_args.append(dl);3597 try test_exec_args.append(dl);
3724 }3598 }
...@@ -3742,7 +3616,7 @@ fn buildOutputType(...@@ -3742,7 +3616,7 @@ fn buildOutputType(
3742 &comp_destroyed,3616 &comp_destroyed,
3743 all_args,3617 all_args,
3744 runtime_args_start,3618 runtime_args_start,
3745 link_libc,3619 create_module.resolved_options.link_libc,
3746 );3620 );
3747 }3621 }
37483622
...@@ -3750,6 +3624,243 @@ fn buildOutputType(...@@ -3750,6 +3624,243 @@ fn buildOutputType(
3750 return cleanExit();3624 return cleanExit();
3751}3625}
37523626
3627const CreateModule = struct {
3628 global_cache_directory: Cache.Directory,
3629 modules: std.StringArrayHashMapUnmanaged(CliModule),
3630 opts: Compilation.Config.Options,
3631 dynamic_linker: ?[]const u8,
3632 object_format: ?[]const u8,
3633 /// undefined until createModule() for the root module is called.
3634 resolved_options: Compilation.Config,
3635
3636 /// This one is used while collecting CLI options. The set of libs is used
3637 /// directly after computing the target and used to compute link_libc,
3638 /// link_libcpp, and then the libraries are filtered into
3639 /// `external_system_libs` and `resolved_system_libs`.
3640 system_libs: std.StringArrayHashMapUnmanaged(SystemLib),
3641 external_system_libs: std.MultiArrayList(struct {
3642 name: []const u8,
3643 info: SystemLib,
3644 }),
3645 resolved_system_libs: std.MultiArrayList(struct {
3646 name: []const u8,
3647 lib: Compilation.SystemLib,
3648 }),
3649 wasi_emulated_libs: std.ArrayListUnmanaged(wasi_libc.CRTFile),
3650
3651 c_source_files: std.ArrayListUnmanaged(Compilation.CSourceFile),
3652 rc_source_files: std.ArrayListUnmanaged(Compilation.RcSourceFile),
3653
3654 // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.
3655 // This array is populated by zig cc frontend and then has to be converted to zig-style
3656 // CPU features.
3657 llvm_m_args: std.ArrayListUnmanaged([]const u8),
3658};
3659
3660fn createModule(
3661 gpa: Allocator,
3662 arena: Allocator,
3663 create_module: *CreateModule,
3664 index: usize,
3665 parent: ?*Package.Module,
3666 zig_lib_directory: Cache.Directory,
3667) Allocator.Error!*Package.Module {
3668 const cli_mod = &create_module.modules.values()[index];
3669 if (cli_mod.resolved) |m| return m;
3670
3671 const name = create_module.modules.keys()[index];
3672
3673 cli_mod.inherited.resolved_target = t: {
3674 // If the target is not overridden, use the parent's target. Of course,
3675 // if this is the root module then we need to proceed to resolve the
3676 // target.
3677 if (cli_mod.target_arch_os_abi == null and
3678 cli_mod.target_mcpu == null and
3679 create_module.dynamic_linker == null and
3680 create_module.object_format == null)
3681 {
3682 if (parent) |p| break :t p.resolved_target;
3683 }
3684
3685 var target_parse_options: std.Target.Query.ParseOptions = .{
3686 .arch_os_abi = cli_mod.target_arch_os_abi orelse "native",
3687 .cpu_features = cli_mod.target_mcpu,
3688 .dynamic_linker = create_module.dynamic_linker,
3689 .object_format = create_module.object_format,
3690 };
3691
3692 // Before passing the mcpu string in for parsing, we convert any -m flags that were
3693 // passed in via zig cc to zig-style.
3694 if (create_module.llvm_m_args.items.len != 0) {
3695 // If this returns null, we let it fall through to the case below which will
3696 // run the full parse function and do proper error handling.
3697 if (std.Target.Query.parseCpuArch(target_parse_options)) |cpu_arch| {
3698 var llvm_to_zig_name = std.StringHashMap([]const u8).init(gpa);
3699 defer llvm_to_zig_name.deinit();
3700
3701 for (cpu_arch.allFeaturesList()) |feature| {
3702 const llvm_name = feature.llvm_name orelse continue;
3703 try llvm_to_zig_name.put(llvm_name, feature.name);
3704 }
3705
3706 var mcpu_buffer = std.ArrayList(u8).init(gpa);
3707 defer mcpu_buffer.deinit();
3708
3709 try mcpu_buffer.appendSlice(cli_mod.target_mcpu orelse "baseline");
3710
3711 for (create_module.llvm_m_args.items) |llvm_m_arg| {
3712 if (mem.startsWith(u8, llvm_m_arg, "mno-")) {
3713 const llvm_name = llvm_m_arg["mno-".len..];
3714 const zig_name = llvm_to_zig_name.get(llvm_name) orelse {
3715 fatal("target architecture {s} has no LLVM CPU feature named '{s}'", .{
3716 @tagName(cpu_arch), llvm_name,
3717 });
3718 };
3719 try mcpu_buffer.append('-');
3720 try mcpu_buffer.appendSlice(zig_name);
3721 } else if (mem.startsWith(u8, llvm_m_arg, "m")) {
3722 const llvm_name = llvm_m_arg["m".len..];
3723 const zig_name = llvm_to_zig_name.get(llvm_name) orelse {
3724 fatal("target architecture {s} has no LLVM CPU feature named '{s}'", .{
3725 @tagName(cpu_arch), llvm_name,
3726 });
3727 };
3728 try mcpu_buffer.append('+');
3729 try mcpu_buffer.appendSlice(zig_name);
3730 } else {
3731 unreachable;
3732 }
3733 }
3734
3735 const adjusted_target_mcpu = try arena.dupe(u8, mcpu_buffer.items);
3736 std.log.debug("adjusted target_mcpu: {s}", .{adjusted_target_mcpu});
3737 target_parse_options.cpu_features = adjusted_target_mcpu;
3738 }
3739 }
3740
3741 const target_query = parseTargetQueryOrReportFatalError(arena, target_parse_options);
3742 const target = resolveTargetQueryOrFatal(target_query);
3743 break :t .{
3744 .result = target,
3745 .is_native_os = target_query.isNativeOs(),
3746 .is_native_abi = target_query.isNativeAbi(),
3747 };
3748 };
3749
3750 if (parent == null) {
3751 // This block is for initializing the fields of
3752 // `Compilation.Config.Options` that require knowledge of the
3753 // target (which was just now resolved for the root module above).
3754 const resolved_target = cli_mod.inherited.resolved_target.?;
3755 create_module.opts.resolved_target = resolved_target;
3756 create_module.opts.root_optimize_mode = cli_mod.inherited.optimize_mode;
3757 const target = resolved_target.result;
3758
3759 // First, remove libc, libc++, and compiler_rt libraries from the system libraries list.
3760 // We need to know whether the set of system libraries contains anything besides these
3761 // to decide whether to trigger native path detection logic.
3762 for (create_module.system_libs.keys(), create_module.system_libs.values()) |lib_name, info| {
3763 if (target.is_libc_lib_name(lib_name)) {
3764 create_module.opts.link_libc = true;
3765 continue;
3766 }
3767 if (target.is_libcpp_lib_name(lib_name)) {
3768 create_module.opts.link_libcpp = true;
3769 continue;
3770 }
3771 switch (target_util.classifyCompilerRtLibName(target, lib_name)) {
3772 .none => {},
3773 .only_libunwind, .both => {
3774 create_module.opts.link_libunwind = true;
3775 continue;
3776 },
3777 .only_compiler_rt => {
3778 warn("ignoring superfluous library '{s}': this dependency is fulfilled instead by compiler-rt which zig unconditionally provides", .{lib_name});
3779 continue;
3780 },
3781 }
3782
3783 if (target.isMinGW()) {
3784 const exists = mingw.libExists(arena, target, zig_lib_directory, lib_name) catch |err| {
3785 fatal("failed to check zig installation for DLL import libs: {s}", .{
3786 @errorName(err),
3787 });
3788 };
3789 if (exists) {
3790 try create_module.resolved_system_libs.append(arena, .{
3791 .name = lib_name,
3792 .lib = .{
3793 .needed = true,
3794 .weak = false,
3795 .path = null,
3796 },
3797 });
3798 continue;
3799 }
3800 }
3801
3802 if (fs.path.isAbsolute(lib_name)) {
3803 fatal("cannot use absolute path as a system library: {s}", .{lib_name});
3804 }
3805
3806 if (target.os.tag == .wasi) {
3807 if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| {
3808 try create_module.wasi_emulated_libs.append(arena, crt_file);
3809 continue;
3810 }
3811 }
3812
3813 try create_module.external_system_libs.append(arena, .{
3814 .name = lib_name,
3815 .info = info,
3816 });
3817 }
3818 // After this point, external_system_libs is used instead of system_libs.
3819
3820 create_module.resolved_options = Compilation.Config.resolve(create_module.opts) catch |err| switch (err) {
3821 else => fatal("unable to resolve compilation options: {s}", .{@errorName(err)}),
3822 };
3823 }
3824
3825 const mod = Package.Module.create(arena, .{
3826 .global_cache_directory = create_module.global_cache_directory,
3827 .paths = cli_mod.paths,
3828 .fully_qualified_name = name,
3829
3830 .cc_argv = cli_mod.cc_argv,
3831 .inherited = cli_mod.inherited,
3832 .global = create_module.resolved_options,
3833 .parent = parent,
3834 .builtin_mod = null,
3835 }) catch |err| switch (err) {
3836 error.ValgrindUnsupportedOnTarget => fatal("unable to create module '{s}': valgrind does not support the selected target CPU architecture", .{name}),
3837 error.TargetRequiresSingleThreaded => fatal("unable to create module '{s}': the selected target does not support multithreading", .{name}),
3838 error.BackendRequiresSingleThreaded => fatal("unable to create module '{s}': the selected machine code backend is limited to single-threaded applications", .{name}),
3839 error.TargetRequiresPic => fatal("unable to create module '{s}': the selected target requires position independent code", .{name}),
3840 error.PieRequiresPic => fatal("unable to create module '{s}': making a Position Independent Executable requires enabling Position Independent Code", .{name}),
3841 error.DynamicLinkingRequiresPic => fatal("unable to create module '{s}': dynamic linking requires enabling Position Independent Code", .{name}),
3842 error.TargetHasNoRedZone => fatal("unable to create module '{s}': the selected target does not have a red zone", .{name}),
3843 error.StackCheckUnsupportedByTarget => fatal("unable to create module '{s}': the selected target does not support stack checking", .{name}),
3844 error.StackProtectorUnsupportedByTarget => fatal("unable to create module '{s}': the selected target does not support stack protection", .{name}),
3845 error.StackProtectorUnavailableWithoutLibC => fatal("unable to create module '{s}': enabling stack protection requires libc", .{name}),
3846 error.OutOfMemory => return error.OutOfMemory,
3847 };
3848 cli_mod.resolved = mod;
3849
3850 for (create_module.c_source_files.items[cli_mod.c_source_files_start..cli_mod.c_source_files_end]) |*item| item.owner = mod;
3851
3852 for (create_module.rc_source_files.items[cli_mod.rc_source_files_start..cli_mod.rc_source_files_end]) |*item| item.owner = mod;
3853
3854 for (cli_mod.deps) |dep| {
3855 const dep_index = create_module.modules.getIndex(dep.key) orelse
3856 fatal("module '{s}' depends on non-existent module '{s}'", .{ name, dep.key });
3857 const dep_mod = try createModule(gpa, arena, create_module, dep_index, mod, zig_lib_directory);
3858 try mod.deps.put(arena, dep.key, dep_mod);
3859 }
3860
3861 return mod;
3862}
3863
3753fn saveState(comp: *Compilation, debug_incremental: bool) void {3864fn saveState(comp: *Compilation, debug_incremental: bool) void {
3754 if (debug_incremental) {3865 if (debug_incremental) {
3755 comp.saveState() catch |err| {3866 comp.saveState() catch |err| {
...@@ -3984,36 +4095,10 @@ fn serveUpdateResults(s: *Server, comp: *Compilation) !void {...@@ -3984,36 +4095,10 @@ fn serveUpdateResults(s: *Server, comp: *Compilation) !void {
3984 }4095 }
3985}4096}
39864097
3987const ModuleDepIterator = struct {
3988 split: mem.SplitIterator(u8, .scalar),
3989
3990 fn init(deps_str: []const u8) ModuleDepIterator {
3991 return .{ .split = mem.splitScalar(u8, deps_str, ',') };
3992 }
3993
3994 const Dependency = struct {
3995 expose: []const u8,
3996 name: []const u8,
3997 };
3998
3999 fn next(it: *ModuleDepIterator) ?Dependency {
4000 if (it.split.buffer.len == 0) return null; // don't return "" for the first iteration on ""
4001 const str = it.split.next() orelse return null;
4002 if (mem.indexOfScalar(u8, str, '=')) |i| {
4003 return .{
4004 .expose = str[0..i],
4005 .name = str[i + 1 ..],
4006 };
4007 } else {
4008 return .{ .expose = str, .name = str };
4009 }
4010 }
4011};
4012
4013fn parseTargetQueryOrReportFatalError(4098fn parseTargetQueryOrReportFatalError(
4014 allocator: Allocator,4099 allocator: Allocator,
4015 opts: std.Target.Query.ParseOptions,4100 opts: std.Target.Query.ParseOptions,
4016) !std.Target.Query {4101) std.Target.Query {
4017 var opts_with_diags = opts;4102 var opts_with_diags = opts;
4018 var diags: std.Target.Query.ParseOptions.Diagnostics = .{};4103 var diags: std.Target.Query.ParseOptions.Diagnostics = .{};
4019 if (opts_with_diags.diagnostics == null) {4104 if (opts_with_diags.diagnostics == null) {
...@@ -4057,7 +4142,9 @@ fn parseTargetQueryOrReportFatalError(...@@ -4057,7 +4142,9 @@ fn parseTargetQueryOrReportFatalError(
4057 }4142 }
4058 fatal("unknown object format: '{s}'", .{opts.object_format.?});4143 fatal("unknown object format: '{s}'", .{opts.object_format.?});
4059 },4144 },
4060 else => |e| return e,4145 else => |e| fatal("unable to parse target query '{s}': {s}", .{
4146 opts.arch_os_abi, @errorName(e),
4147 }),
4061 };4148 };
4062}4149}
40634150
...@@ -4667,7 +4754,7 @@ fn detectRcIncludeDirs(arena: Allocator, zig_lib_dir: []const u8, auto_includes:...@@ -4667,7 +4754,7 @@ fn detectRcIncludeDirs(arena: Allocator, zig_lib_dir: []const u8, auto_includes:
4667 .os_tag = .windows,4754 .os_tag = .windows,
4668 .abi = .msvc,4755 .abi = .msvc,
4669 };4756 };
4670 const target = try std.zig.system.resolveTargetQuery(target_query);4757 const target = resolveTargetQueryOrFatal(target_query);
4671 const is_native_abi = target_query.isNativeAbi();4758 const is_native_abi = target_query.isNativeAbi();
4672 const detected_libc = Compilation.detectLibCIncludeDirs(arena, zig_lib_dir, target, is_native_abi, true, null) catch |err| {4759 const detected_libc = Compilation.detectLibCIncludeDirs(arena, zig_lib_dir, target, is_native_abi, true, null) catch |err| {
4673 if (cur_includes == .any) {4760 if (cur_includes == .any) {
...@@ -4695,7 +4782,7 @@ fn detectRcIncludeDirs(arena: Allocator, zig_lib_dir: []const u8, auto_includes:...@@ -4695,7 +4782,7 @@ fn detectRcIncludeDirs(arena: Allocator, zig_lib_dir: []const u8, auto_includes:
4695 .os_tag = .windows,4782 .os_tag = .windows,
4696 .abi = .gnu,4783 .abi = .gnu,
4697 };4784 };
4698 const target = try std.zig.system.resolveTargetQuery(target_query);4785 const target = resolveTargetQueryOrFatal(target_query);
4699 const is_native_abi = target_query.isNativeAbi();4786 const is_native_abi = target_query.isNativeAbi();
4700 const detected_libc = try Compilation.detectLibCIncludeDirs(arena, zig_lib_dir, target, is_native_abi, true, null);4787 const detected_libc = try Compilation.detectLibCIncludeDirs(arena, zig_lib_dir, target, is_native_abi, true, null);
4701 return .{4788 return .{
...@@ -4757,10 +4844,10 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void {...@@ -4757,10 +4844,10 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void {
4757 }4844 }
4758 }4845 }
47594846
4760 const target_query = try parseTargetQueryOrReportFatalError(gpa, .{4847 const target_query = parseTargetQueryOrReportFatalError(gpa, .{
4761 .arch_os_abi = target_arch_os_abi,4848 .arch_os_abi = target_arch_os_abi,
4762 });4849 });
4763 const target = try std.zig.system.resolveTargetQuery(target_query);4850 const target = resolveTargetQueryOrFatal(target_query);
47644851
4765 if (print_includes) {4852 if (print_includes) {
4766 var arena_state = std.heap.ArenaAllocator.init(gpa);4853 var arena_state = std.heap.ArenaAllocator.init(gpa);
...@@ -5024,7 +5111,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi...@@ -5024,7 +5111,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
5024 if (!build_options.enable_logging) {5111 if (!build_options.enable_logging) {
5025 warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{});5112 warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{});
5026 } else {5113 } else {
5027 try log_scopes.append(gpa, args[i]);5114 try log_scopes.append(arena, args[i]);
5028 }5115 }
5029 continue;5116 continue;
5030 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {5117 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {
...@@ -5115,7 +5202,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi...@@ -5115,7 +5202,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
5115 gimmeMoreOfThoseSweetSweetFileDescriptors();5202 gimmeMoreOfThoseSweetSweetFileDescriptors();
51165203
5117 const target_query: std.Target.Query = .{};5204 const target_query: std.Target.Query = .{};
5118 const target = try std.zig.system.resolveTargetQuery(target_query);5205 const target = resolveTargetQueryOrFatal(target_query);
51195206
5120 const exe_basename = try std.zig.binNameAlloc(arena, .{5207 const exe_basename = try std.zig.binNameAlloc(arena, .{
5121 .root_name = "build",5208 .root_name = "build",
...@@ -5130,29 +5217,80 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi...@@ -5130,29 +5217,80 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
5130 try thread_pool.init(.{ .allocator = gpa });5217 try thread_pool.init(.{ .allocator = gpa });
5131 defer thread_pool.deinit();5218 defer thread_pool.deinit();
51325219
5133 var main_mod: Package.Module = if (override_build_runner) |build_runner_path|5220 const main_mod_paths: Package.Module.CreateOptions.Paths = if (override_build_runner) |runner| .{
5134 .{5221 .root = .{
5222 .root_dir = Cache.Directory.cwd(),
5223 .sub_path = fs.path.dirname(runner) orelse "",
5224 },
5225 .root_src_path = fs.path.basename(runner),
5226 } else .{
5227 .root = .{ .root_dir = zig_lib_directory },
5228 .root_src_path = "build_runner.zig",
5229 };
5230
5231 const config = try Compilation.Config.resolve(.{
5232 .output_mode = .Exe,
5233 .resolved_target = .{
5234 .result = target,
5235 .is_native_os = true,
5236 .is_native_abi = true,
5237 },
5238 .have_zcu = true,
5239 .emit_bin = true,
5240 .is_test = false,
5241 });
5242
5243 const root_mod = try Package.Module.create(arena, .{
5244 .global_cache_directory = global_cache_directory,
5245 .paths = main_mod_paths,
5246 .fully_qualified_name = "root",
5247 .cc_argv = &.{},
5248 .inherited = .{},
5249 .global = config,
5250 .parent = null,
5251 .builtin_mod = null,
5252 });
5253
5254 const builtin_mod = root_mod.getBuiltinDependency();
5255 const std_mod = try Package.Module.create(arena, .{
5256 .global_cache_directory = global_cache_directory,
5257 .paths = .{
5135 .root = .{5258 .root = .{
5136 .root_dir = Cache.Directory.cwd(),5259 .root_dir = zig_lib_directory,
5137 .sub_path = fs.path.dirname(build_runner_path) orelse "",5260 .sub_path = "std",
5138 },5261 },
5139 .root_src_path = fs.path.basename(build_runner_path),5262 .root_src_path = "std.zig",
5140 .fully_qualified_name = "root",5263 },
5141 }5264 .fully_qualified_name = "std",
5142 else5265 .cc_argv = &.{},
5143 .{5266 .inherited = .{},
5144 .root = .{ .root_dir = zig_lib_directory },5267 .global = config,
5145 .root_src_path = "build_runner.zig",5268 .parent = root_mod,
5146 .fully_qualified_name = "root",5269 .builtin_mod = builtin_mod,
5147 };5270 });
51485271
5149 var build_mod: Package.Module = .{5272 const build_mod = try Package.Module.create(arena, .{
5150 .root = .{ .root_dir = build_root.directory },5273 .global_cache_directory = global_cache_directory,
5151 .root_src_path = build_root.build_zig_basename,5274 .paths = .{
5275 .root = .{ .root_dir = build_root.directory },
5276 .root_src_path = build_root.build_zig_basename,
5277 },
5152 .fully_qualified_name = "root.@build",5278 .fully_qualified_name = "root.@build",
5153 };5279 .cc_argv = &.{},
5280 .inherited = .{},
5281 .global = config,
5282 .parent = root_mod,
5283 .builtin_mod = builtin_mod,
5284 });
5154 if (build_options.only_core_functionality) {5285 if (build_options.only_core_functionality) {
5155 try createEmptyDependenciesModule(arena, &main_mod, local_cache_directory);5286 try createEmptyDependenciesModule(
5287 arena,
5288 root_mod,
5289 global_cache_directory,
5290 local_cache_directory,
5291 builtin_mod,
5292 config,
5293 );
5156 } else {5294 } else {
5157 var http_client: std.http.Client = .{ .allocator = gpa };5295 var http_client: std.http.Client = .{ .allocator = gpa };
5158 defer http_client.deinit();5296 defer http_client.deinit();
...@@ -5196,7 +5334,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi...@@ -5196,7 +5334,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
5196 .has_build_zig = true,5334 .has_build_zig = true,
5197 .oom_flag = false,5335 .oom_flag = false,
51985336
5199 .module = &build_mod,5337 .module = build_mod,
5200 };5338 };
5201 job_queue.all_fetches.appendAssumeCapacity(&fetch);5339 job_queue.all_fetches.appendAssumeCapacity(&fetch);
52025340
...@@ -5225,8 +5363,11 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi...@@ -5225,8 +5363,11 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
5225 const deps_mod = try createDependenciesModule(5363 const deps_mod = try createDependenciesModule(
5226 arena,5364 arena,
5227 source_buf.items,5365 source_buf.items,
5228 &main_mod,5366 root_mod,
5367 global_cache_directory,
5229 local_cache_directory,5368 local_cache_directory,
5369 builtin_mod,
5370 config,
5230 );5371 );
52315372
5232 {5373 {
...@@ -5242,13 +5383,21 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi...@@ -5242,13 +5383,21 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
5242 if (!f.has_build_zig)5383 if (!f.has_build_zig)
5243 continue;5384 continue;
5244 const m = try Package.Module.create(arena, .{5385 const m = try Package.Module.create(arena, .{
5245 .root = try f.package_root.clone(arena),5386 .global_cache_directory = global_cache_directory,
5246 .root_src_path = Package.build_zig_basename,5387 .paths = .{
5388 .root = try f.package_root.clone(arena),
5389 .root_src_path = Package.build_zig_basename,
5390 },
5247 .fully_qualified_name = try std.fmt.allocPrint(5391 .fully_qualified_name = try std.fmt.allocPrint(
5248 arena,5392 arena,
5249 "root.@dependencies.{s}",5393 "root.@dependencies.{s}",
5250 .{&hash},5394 .{&hash},
5251 ),5395 ),
5396 .cc_argv = &.{},
5397 .inherited = .{},
5398 .global = config,
5399 .parent = root_mod,
5400 .builtin_mod = builtin_mod,
5252 });5401 });
5253 const hash_cloned = try arena.dupe(u8, &hash);5402 const hash_cloned = try arena.dupe(u8, &hash);
5254 deps_mod.deps.putAssumeCapacityNoClobber(hash_cloned, m);5403 deps_mod.deps.putAssumeCapacityNoClobber(hash_cloned, m);
...@@ -5276,21 +5425,19 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi...@@ -5276,21 +5425,19 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
5276 }5425 }
5277 }5426 }
52785427
5279 try main_mod.deps.put(arena, "@build", &build_mod);5428 try root_mod.deps.put(arena, "@build", build_mod);
52805429
5281 const comp = Compilation.create(gpa, .{5430 const comp = Compilation.create(gpa, .{
5282 .zig_lib_directory = zig_lib_directory,5431 .zig_lib_directory = zig_lib_directory,
5283 .local_cache_directory = local_cache_directory,5432 .local_cache_directory = local_cache_directory,
5284 .global_cache_directory = global_cache_directory,5433 .global_cache_directory = global_cache_directory,
5285 .root_name = "build",5434 .root_name = "build",
5286 .target = target,5435 .config = config,
5287 .is_native_os = target_query.isNativeOs(),5436 .root_mod = root_mod,
5288 .is_native_abi = target_query.isNativeAbi(),5437 .main_mod = build_mod,
5289 .output_mode = .Exe,5438 .std_mod = std_mod,
5290 .main_mod = &main_mod,
5291 .emit_bin = emit_bin,5439 .emit_bin = emit_bin,
5292 .emit_h = null,5440 .emit_h = null,
5293 .optimize_mode = .Debug,
5294 .self_exe_path = self_exe_path,5441 .self_exe_path = self_exe_path,
5295 .thread_pool = &thread_pool,5442 .thread_pool = &thread_pool,
5296 .verbose_cc = verbose_cc,5443 .verbose_cc = verbose_cc,
...@@ -5514,7 +5661,7 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void...@@ -5514,7 +5661,7 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void
5514 .root_decl = .none,5661 .root_decl = .none,
5515 };5662 };
55165663
5517 file.mod = try Package.Module.create(arena, .{5664 file.mod = try Package.Module.createLimited(arena, .{
5518 .root = Package.Path.cwd(),5665 .root = Package.Path.cwd(),
5519 .root_src_path = file.sub_file_path,5666 .root_src_path = file.sub_file_path,
5520 .fully_qualified_name = "root",5667 .fully_qualified_name = "root",
...@@ -5724,7 +5871,7 @@ fn fmtPathFile(...@@ -5724,7 +5871,7 @@ fn fmtPathFile(
5724 .root_decl = .none,5871 .root_decl = .none,
5725 };5872 };
57265873
5727 file.mod = try Package.Module.create(fmt.arena, .{5874 file.mod = try Package.Module.createLimited(fmt.arena, .{
5728 .root = Package.Path.cwd(),5875 .root = Package.Path.cwd(),
5729 .root_src_path = file.sub_file_path,5876 .root_src_path = file.sub_file_path,
5730 .fully_qualified_name = "root",5877 .fully_qualified_name = "root",
...@@ -5804,15 +5951,13 @@ pub fn putAstErrorsIntoBundle(...@@ -5804,15 +5951,13 @@ pub fn putAstErrorsIntoBundle(
5804 .tree = tree,5951 .tree = tree,
5805 .tree_loaded = true,5952 .tree_loaded = true,
5806 .zir = undefined,5953 .zir = undefined,
5807 .mod = undefined,5954 .mod = try Package.Module.createLimited(gpa, .{
5955 .root = Package.Path.cwd(),
5956 .root_src_path = path,
5957 .fully_qualified_name = "root",
5958 }),
5808 .root_decl = .none,5959 .root_decl = .none,
5809 };5960 };
5810
5811 file.mod = try Package.Module.create(gpa, .{
5812 .root = Package.Path.cwd(),
5813 .root_src_path = file.sub_file_path,
5814 .fully_qualified_name = "root",
5815 });
5816 defer gpa.destroy(file.mod);5961 defer gpa.destroy(file.mod);
58175962
5818 file.zir = try AstGen.generate(gpa, file.tree);5963 file.zir = try AstGen.generate(gpa, file.tree);
...@@ -6373,7 +6518,7 @@ pub fn cmdAstCheck(...@@ -6373,7 +6518,7 @@ pub fn cmdAstCheck(
6373 file.stat.size = source.len;6518 file.stat.size = source.len;
6374 }6519 }
63756520
6376 file.mod = try Package.Module.create(arena, .{6521 file.mod = try Package.Module.createLimited(arena, .{
6377 .root = Package.Path.cwd(),6522 .root = Package.Path.cwd(),
6378 .root_src_path = file.sub_file_path,6523 .root_src_path = file.sub_file_path,
6379 .fully_qualified_name = "root",6524 .fully_qualified_name = "root",
...@@ -6546,7 +6691,7 @@ pub fn cmdChangelist(...@@ -6546,7 +6691,7 @@ pub fn cmdChangelist(
6546 .root_decl = .none,6691 .root_decl = .none,
6547 };6692 };
65486693
6549 file.mod = try Package.Module.create(arena, .{6694 file.mod = try Package.Module.createLimited(arena, .{
6550 .root = Package.Path.cwd(),6695 .root = Package.Path.cwd(),
6551 .root_src_path = file.sub_file_path,6696 .root_src_path = file.sub_file_path,
6552 .fully_qualified_name = "root",6697 .fully_qualified_name = "root",
...@@ -6669,7 +6814,7 @@ fn warnAboutForeignBinaries(...@@ -6669,7 +6814,7 @@ fn warnAboutForeignBinaries(
6669 link_libc: bool,6814 link_libc: bool,
6670) !void {6815) !void {
6671 const host_query: std.Target.Query = .{};6816 const host_query: std.Target.Query = .{};
6672 const host_target = try std.zig.system.resolveTargetQuery(host_query);6817 const host_target = resolveTargetQueryOrFatal(host_query);
66736818
6674 switch (std.zig.system.getExternalExecutor(host_target, target, .{ .link_libc = link_libc })) {6819 switch (std.zig.system.getExternalExecutor(host_target, target, .{ .link_libc = link_libc })) {
6675 .native => return,6820 .native => return,
...@@ -6809,18 +6954,22 @@ fn parseSubSystem(next_arg: []const u8) !std.Target.SubSystem {...@@ -6809,18 +6954,22 @@ fn parseSubSystem(next_arg: []const u8) !std.Target.SubSystem {
6809/// Silently ignore superfluous search dirs.6954/// Silently ignore superfluous search dirs.
6810/// Warn when a dir is added to multiple searchlists.6955/// Warn when a dir is added to multiple searchlists.
6811const ClangSearchSanitizer = struct {6956const ClangSearchSanitizer = struct {
6812 argv: *std.ArrayList([]const u8),6957 map: std.StringHashMapUnmanaged(Membership) = .{},
6813 map: std.StringHashMap(Membership),
68146958
6815 fn init(gpa: Allocator, argv: *std.ArrayList([]const u8)) @This() {6959 fn reset(self: *@This()) void {
6816 return .{6960 self.map.clearRetainingCapacity();
6817 .argv = argv,
6818 .map = std.StringHashMap(Membership).init(gpa),
6819 };
6820 }6961 }
68216962
6822 fn addIncludePath(self: *@This(), group: Group, arg: []const u8, dir: []const u8, joined: bool) !void {6963 fn addIncludePath(
6823 const gopr = try self.map.getOrPut(dir);6964 self: *@This(),
6965 ally: Allocator,
6966 argv: *std.ArrayListUnmanaged([]const u8),
6967 group: Group,
6968 arg: []const u8,
6969 dir: []const u8,
6970 joined: bool,
6971 ) !void {
6972 const gopr = try self.map.getOrPut(ally, dir);
6824 const m = gopr.value_ptr;6973 const m = gopr.value_ptr;
6825 if (!gopr.found_existing) {6974 if (!gopr.found_existing) {
6826 // init empty membership6975 // init empty membership
...@@ -6867,8 +7016,9 @@ const ClangSearchSanitizer = struct {...@@ -6867,8 +7016,9 @@ const ClangSearchSanitizer = struct {
6867 if (m.iwithsysroot) warn(wtxt, .{ dir, "iframeworkwithsysroot", "iwithsysroot" });7016 if (m.iwithsysroot) warn(wtxt, .{ dir, "iframeworkwithsysroot", "iwithsysroot" });
6868 },7017 },
6869 }7018 }
6870 try self.argv.append(arg);7019 try argv.ensureUnusedCapacity(ally, 2);
6871 if (!joined) try self.argv.append(dir);7020 argv.appendAssumeCapacity(arg);
7021 if (!joined) argv.appendAssumeCapacity(dir);
6872 }7022 }
68737023
6874 const Group = enum { I, isystem, iwithsysroot, idirafter, iframework, iframeworkwithsysroot };7024 const Group = enum { I, isystem, iwithsysroot, idirafter, iframework, iframeworkwithsysroot };
...@@ -7244,11 +7394,22 @@ fn cmdFetch(...@@ -7244,11 +7394,22 @@ fn cmdFetch(
7244fn createEmptyDependenciesModule(7394fn createEmptyDependenciesModule(
7245 arena: Allocator,7395 arena: Allocator,
7246 main_mod: *Package.Module,7396 main_mod: *Package.Module,
7397 global_cache_directory: Cache.Directory,
7247 local_cache_directory: Cache.Directory,7398 local_cache_directory: Cache.Directory,
7399 builtin_mod: *Package.Module,
7400 global_options: Compilation.Config,
7248) !void {7401) !void {
7249 var source = std.ArrayList(u8).init(arena);7402 var source = std.ArrayList(u8).init(arena);
7250 try Package.Fetch.JobQueue.createEmptyDependenciesSource(&source);7403 try Package.Fetch.JobQueue.createEmptyDependenciesSource(&source);
7251 _ = try createDependenciesModule(arena, source.items, main_mod, local_cache_directory);7404 _ = try createDependenciesModule(
7405 arena,
7406 source.items,
7407 main_mod,
7408 global_cache_directory,
7409 local_cache_directory,
7410 builtin_mod,
7411 global_options,
7412 );
7252}7413}
72537414
7254/// Creates the dependencies.zig file and corresponding `Package.Module` for the7415/// Creates the dependencies.zig file and corresponding `Package.Module` for the
...@@ -7257,7 +7418,10 @@ fn createDependenciesModule(...@@ -7257,7 +7418,10 @@ fn createDependenciesModule(
7257 arena: Allocator,7418 arena: Allocator,
7258 source: []const u8,7419 source: []const u8,
7259 main_mod: *Package.Module,7420 main_mod: *Package.Module,
7421 global_cache_directory: Cache.Directory,
7260 local_cache_directory: Cache.Directory,7422 local_cache_directory: Cache.Directory,
7423 builtin_mod: *Package.Module,
7424 global_options: Compilation.Config,
7261) !*Package.Module {7425) !*Package.Module {
7262 // Atomically create the file in a directory named after the hash of its contents.7426 // Atomically create the file in a directory named after the hash of its contents.
7263 const basename = "dependencies.zig";7427 const basename = "dependencies.zig";
...@@ -7283,25 +7447,25 @@ fn createDependenciesModule(...@@ -7283,25 +7447,25 @@ fn createDependenciesModule(
7283 );7447 );
72847448
7285 const deps_mod = try Package.Module.create(arena, .{7449 const deps_mod = try Package.Module.create(arena, .{
7286 .root = .{7450 .global_cache_directory = global_cache_directory,
7287 .root_dir = local_cache_directory,7451 .paths = .{
7288 .sub_path = o_dir_sub_path,7452 .root = .{
7453 .root_dir = local_cache_directory,
7454 .sub_path = o_dir_sub_path,
7455 },
7456 .root_src_path = basename,
7289 },7457 },
7290 .root_src_path = basename,
7291 .fully_qualified_name = "root.@dependencies",7458 .fully_qualified_name = "root.@dependencies",
7459 .parent = main_mod,
7460 .builtin_mod = builtin_mod,
7461 .cc_argv = &.{},
7462 .inherited = .{},
7463 .global = global_options,
7292 });7464 });
7293 try main_mod.deps.put(arena, "@dependencies", deps_mod);7465 try main_mod.deps.put(arena, "@dependencies", deps_mod);
7294 return deps_mod;7466 return deps_mod;
7295}7467}
72967468
7297fn defaultWasmEntryName(exec_model: ?std.builtin.WasiExecModel) []const u8 {
7298 const model = exec_model orelse .command;
7299 if (model == .reactor) {
7300 return "_initialize";
7301 }
7302 return "_start";
7303}
7304
7305const BuildRoot = struct {7469const BuildRoot = struct {
7306 directory: Cache.Directory,7470 directory: Cache.Directory,
7307 build_zig_basename: []const u8,7471 build_zig_basename: []const u8,
...@@ -7509,3 +7673,18 @@ fn findTemplates(gpa: Allocator, arena: Allocator) Templates {...@@ -7509,3 +7673,18 @@ fn findTemplates(gpa: Allocator, arena: Allocator) Templates {
7509 .buffer = std.ArrayList(u8).init(gpa),7673 .buffer = std.ArrayList(u8).init(gpa),
7510 };7674 };
7511}7675}
7676
7677fn parseOptimizeMode(s: []const u8) std.builtin.OptimizeMode {
7678 return std.meta.stringToEnum(std.builtin.OptimizeMode, s) orelse
7679 fatal("unrecognized optimization mode: '{s}'", .{s});
7680}
7681
7682fn parseWasiExecModel(s: []const u8) std.builtin.WasiExecModel {
7683 return std.meta.stringToEnum(std.builtin.WasiExecModel, s) orelse
7684 fatal("expected [command|reactor] for -mexec-mode=[value], found '{s}'", .{s});
7685}
7686
7687fn resolveTargetQueryOrFatal(target_query: std.Target.Query) std.Target {
7688 return std.zig.system.resolveTargetQuery(target_query) catch |err|
7689 fatal("unable to resolve target: {s}", .{@errorName(err)});
7690}
src/target.zig+54-7
...@@ -3,6 +3,8 @@ const Type = @import("type.zig").Type;...@@ -3,6 +3,8 @@ const Type = @import("type.zig").Type;
3const AddressSpace = std.builtin.AddressSpace;3const AddressSpace = std.builtin.AddressSpace;
4const Alignment = @import("InternPool.zig").Alignment;4const Alignment = @import("InternPool.zig").Alignment;
55
6pub const default_stack_protector_buffer_size = 4;
7
6pub const ArchOsAbi = struct {8pub const ArchOsAbi = struct {
7 arch: std.Target.Cpu.Arch,9 arch: std.Target.Cpu.Arch,
8 os: std.Target.Os.Tag,10 os: std.Target.Os.Tag,
...@@ -204,11 +206,18 @@ pub fn supports_fpic(target: std.Target) bool {...@@ -204,11 +206,18 @@ pub fn supports_fpic(target: std.Target) bool {
204 return target.os.tag != .windows and target.os.tag != .uefi;206 return target.os.tag != .windows and target.os.tag != .uefi;
205}207}
206208
207pub fn isSingleThreaded(target: std.Target) bool {209pub fn alwaysSingleThreaded(target: std.Target) bool {
208 _ = target;210 _ = target;
209 return false;211 return false;
210}212}
211213
214pub fn defaultSingleThreaded(target: std.Target) bool {
215 return switch (target.cpu.arch) {
216 .wasm32, .wasm64 => true,
217 else => false,
218 };
219}
220
212/// Valgrind supports more, but Zig does not support them yet.221/// Valgrind supports more, but Zig does not support them yet.
213pub fn hasValgrindSupport(target: std.Target) bool {222pub fn hasValgrindSupport(target: std.Target) bool {
214 switch (target.cpu.arch) {223 switch (target.cpu.arch) {
...@@ -375,12 +384,17 @@ pub fn classifyCompilerRtLibName(target: std.Target, name: []const u8) CompilerR...@@ -375,12 +384,17 @@ pub fn classifyCompilerRtLibName(target: std.Target, name: []const u8) CompilerR
375}384}
376385
377pub fn hasDebugInfo(target: std.Target) bool {386pub fn hasDebugInfo(target: std.Target) bool {
378 if (target.cpu.arch.isNvptx()) {387 return switch (target.cpu.arch) {
379 // TODO: not sure how to test "ptx >= 7.5" with featureset388 .nvptx, .nvptx64 => std.Target.nvptx.featureSetHas(target.cpu.features, .ptx75) or
380 return std.Target.nvptx.featureSetHas(target.cpu.features, .ptx75);389 std.Target.nvptx.featureSetHas(target.cpu.features, .ptx76) or
381 }390 std.Target.nvptx.featureSetHas(target.cpu.features, .ptx77) or
382391 std.Target.nvptx.featureSetHas(target.cpu.features, .ptx78) or
383 return true;392 std.Target.nvptx.featureSetHas(target.cpu.features, .ptx80) or
393 std.Target.nvptx.featureSetHas(target.cpu.features, .ptx81),
394 .wasm32, .wasm64 => false,
395 .bpfel, .bpfeb => false,
396 else => true,
397 };
384}398}
385399
386pub fn defaultCompilerRtOptimizeMode(target: std.Target) std.builtin.OptimizeMode {400pub fn defaultCompilerRtOptimizeMode(target: std.Target) std.builtin.OptimizeMode {
...@@ -619,3 +633,36 @@ pub fn fnCallConvAllowsZigTypes(target: std.Target, cc: std.builtin.CallingConve...@@ -619,3 +633,36 @@ pub fn fnCallConvAllowsZigTypes(target: std.Target, cc: std.builtin.CallingConve
619 else => false,633 else => false,
620 };634 };
621}635}
636
637pub fn zigBackend(target: std.Target, use_llvm: bool) std.builtin.CompilerBackend {
638 if (use_llvm) return .stage2_llvm;
639 if (target.ofmt == .c) return .stage2_c;
640 return switch (target.cpu.arch) {
641 .wasm32, .wasm64 => std.builtin.CompilerBackend.stage2_wasm,
642 .arm, .armeb, .thumb, .thumbeb => .stage2_arm,
643 .x86_64 => .stage2_x86_64,
644 .x86 => .stage2_x86,
645 .aarch64, .aarch64_be, .aarch64_32 => .stage2_aarch64,
646 .riscv64 => .stage2_riscv64,
647 .sparc64 => .stage2_sparc64,
648 .spirv64 => .stage2_spirv64,
649 else => .other,
650 };
651}
652
653pub fn defaultEntrySymbolName(
654 target: std.Target,
655 /// May be `undefined` when `target` is not WASI.
656 wasi_exec_model: std.builtin.WasiExecModel,
657) ?[]const u8 {
658 return switch (target.ofmt) {
659 .coff => "wWinMainCRTStartup",
660 .macho => "_main",
661 .elf, .plan9 => "_start",
662 .wasm => switch (wasi_exec_model) {
663 .reactor => "_initialize",
664 .command => "_start",
665 },
666 else => null,
667 };
668}