authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-18 19:05:06+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-18 19:05:06+01:00
log46171bf6c89dc2c2b8f155c8511b62e5cd52e3bc
tree7ae0f3662be1266e37bb8ef4ede4fe5ebe5c4b6f
parentee705e3ac71205142a4457acd2677f7be921d62b

macho+zld: clean up how to interface with link.zig and openPath()


1 files changed, 42 insertions(+), 27 deletions(-)

src/link/MachO.zig+42-27
......@@ -60,6 +60,17 @@ pub const SearchStrategy = enum {
6060 dylibs_first,
6161};
6262
63/// Mode of operation of the linker.
64pub const Mode = enum {
65 /// Incremental mode will preallocate segments/sections and is compatible with
66 /// watch and HCS modes of operation.
67 incremental,
68 /// Zld mode will link relocatables in a traditional, one-shot
69 /// fashion (default for LLVM backend). It acts as a drop-in replacement for
70 /// LLD.
71 zld,
72};
73
6374const Section = struct {
6475 header: macho.section_64,
6576 segment_index: u8,
......@@ -98,10 +109,7 @@ d_sym: ?DebugSymbols = null,
98109/// For x86_64 that's 4KB, whereas for aarch64, that's 16KB.
99110page_size: u16,
100111
101/// Mode of operation: incremental - will preallocate segments/sections and is compatible with
102/// watch and HCS modes of operation; one_shot - will link relocatables in a traditional, one-shot
103/// fashion (default for LLVM backend).
104mode: enum { incremental, one_shot },
112mode: Mode,
105113
106114dyld_info_cmd: macho.dyld_info_command = .{},
107115symtab_cmd: macho.symtab_command = .{},
......@@ -314,33 +322,42 @@ pub const default_headerpad_size: u32 = 0x1000;
314322pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
315323 assert(options.target.ofmt == .macho);
316324
317 if (options.emit == null or options.module == null) {
325 if (options.emit == null) {
318326 return createEmpty(allocator, options);
319327 }
320328
321329 const emit = options.emit.?;
330 const mode: Mode = mode: {
331 if (options.use_llvm or options.module == null or options.cache_mode == .whole)
332 break :mode .zld;
333 break :mode .incremental;
334 };
335 const sub_path = if (mode == .zld) blk: {
336 if (options.module == null) {
337 // No point in opening a file, we would not write anything to it.
338 // Initialize with empty.
339 return createEmpty(allocator, options);
340 }
341 // Open a temporary object file, not the final output file because we
342 // want to link with LLD.
343 break :blk try std.fmt.allocPrint(allocator, "{s}{s}", .{
344 emit.sub_path, options.target.ofmt.fileExt(options.target.cpu.arch),
345 });
346 } else emit.sub_path;
347 errdefer if (mode == .zld) allocator.free(sub_path);
348
322349 const self = try createEmpty(allocator, options);
323 errdefer {
324 self.base.file = null;
325 self.base.destroy();
326 }
350 errdefer self.base.destroy();
327351
328 if (build_options.have_llvm and options.use_llvm and options.module != null) {
352 if (mode == .zld) {
329353 // TODO this intermediary_basename isn't enough; in the case of `zig build-exe`,
330354 // we also want to put the intermediary object file in the cache while the
331355 // main emit directory is the cwd.
332 self.base.intermediary_basename = try std.fmt.allocPrint(allocator, "{s}{s}", .{
333 emit.sub_path, options.target.ofmt.fileExt(options.target.cpu.arch),
334 });
356 self.base.intermediary_basename = sub_path;
357 return self;
335358 }
336359
337 if (self.base.intermediary_basename != null) switch (options.output_mode) {
338 .Obj => return self,
339 .Lib => if (options.link_mode == .Static) return self,
340 else => {},
341 };
342
343 const file = try emit.directory.handle.createFile(emit.sub_path, .{
360 const file = try emit.directory.handle.createFile(sub_path, .{
344361 .truncate = false,
345362 .read = true,
346363 .mode = link.determineMode(options),
......@@ -348,23 +365,21 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
348365 errdefer file.close();
349366 self.base.file = file;
350367
351 if (self.mode == .one_shot) return self;
352
353368 if (!options.strip and options.module != null) {
354369 // Create dSYM bundle.
355 log.debug("creating {s}.dSYM bundle", .{emit.sub_path});
370 log.debug("creating {s}.dSYM bundle", .{sub_path});
356371
357372 const d_sym_path = try fmt.allocPrint(
358373 allocator,
359374 "{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF",
360 .{emit.sub_path},
375 .{sub_path},
361376 );
362377 defer allocator.free(d_sym_path);
363378
364379 var d_sym_bundle = try emit.directory.handle.makeOpenPath(d_sym_path, .{});
365380 defer d_sym_bundle.close();
366381
367 const d_sym_file = try d_sym_bundle.createFile(emit.sub_path, .{
382 const d_sym_file = try d_sym_bundle.createFile(sub_path, .{
368383 .truncate = false,
369384 .read = true,
370385 });
......@@ -413,7 +428,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO {
413428 },
414429 .page_size = page_size,
415430 .mode = if (use_llvm or options.module == null or options.cache_mode == .whole)
416 .one_shot
431 .zld
417432 else
418433 .incremental,
419434 };
......@@ -447,7 +462,7 @@ pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) li
447462 }
448463
449464 switch (self.mode) {
450 .one_shot => return zld.linkWithZld(self, comp, prog_node),
465 .zld => return zld.linkWithZld(self, comp, prog_node),
451466 .incremental => return self.flushModule(comp, prog_node),
452467 }
453468}