Commit bdbb1dbe15
Changed files (4)
src
src/link/MachO/Archive.zig
@@ -144,8 +144,32 @@ pub fn parse(self: *Archive, macho_file: *MachO, path: []const u8, handle_index:
}
pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {
- _ = comp;
- _ = module_obj_path;
+ const gpa = comp.gpa;
+
+ var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);
+ defer positionals.deinit();
+
+ try positionals.ensureUnusedCapacity(comp.objects.len);
+ positionals.appendSliceAssumeCapacity(comp.objects);
+
+ for (comp.c_object_table.keys()) |key| {
+ try positionals.append(.{ .path = key.status.success.object_path });
+ }
+
+ if (module_obj_path) |path| try positionals.append(.{ .path = path });
+
+ for (positionals.items) |obj| {
+ // TODO: parse for archive meaning don't unpack objects
+ _ = obj;
+ }
+
+ if (comp.link_errors.items.len > 0) return error.FlushFailure;
+
+ // First, we flush relocatable object file generated with our backends.
+ if (macho_file.getZigObject()) |zo| {
+ zo.resolveSymbols(macho_file);
+ zo.asFile().claimUnresolvedRelocatable(macho_file);
+ }
var err = try macho_file.addErrorWithNotes(0);
try err.addMsg(macho_file, "TODO implement flushStaticLib", .{});
@@ -158,6 +182,7 @@ const link = @import("../../link.zig");
const log = std.log.scoped(.link);
const macho = std.macho;
const mem = std.mem;
+const relocatable = @import("relocatable.zig");
const std = @import("std");
const Allocator = mem.Allocator;
src/link/MachO/file.zig
@@ -44,6 +44,97 @@ pub const File = union(enum) {
}
}
+ pub fn claimUnresolved(file: File, macho_file: *MachO) error{OutOfMemory}!void {
+ assert(file == .object or file == .zig_object);
+
+ for (file.getSymbols(), 0..) |sym_index, i| {
+ const nlist_idx = @as(Symbol.Index, @intCast(i));
+ const nlist = switch (file) {
+ .object => |x| x.symtab.items(.nlist)[nlist_idx],
+ .zig_object => |x| x.symtab.items(.nlist)[nlist_idx],
+ else => unreachable,
+ };
+ if (!nlist.ext()) continue;
+ if (!nlist.undf()) continue;
+
+ const sym = macho_file.getSymbol(sym_index);
+ if (sym.getFile(macho_file) != null) continue;
+
+ const is_import = switch (macho_file.undefined_treatment) {
+ .@"error" => false,
+ .warn, .suppress => nlist.weakRef(),
+ .dynamic_lookup => true,
+ };
+ if (is_import) {
+ sym.value = 0;
+ sym.atom = 0;
+ sym.nlist_idx = 0;
+ sym.file = macho_file.internal_object.?;
+ sym.flags.weak = false;
+ sym.flags.weak_ref = nlist.weakRef();
+ sym.flags.import = is_import;
+ sym.visibility = .global;
+ try macho_file.getInternalObject().?.symbols.append(macho_file.base.comp.gpa, sym_index);
+ }
+ }
+ }
+
+ pub fn claimUnresolvedRelocatable(file: File, macho_file: *MachO) void {
+ assert(file == .object or file == .zig_object);
+
+ for (file.getSymbols(), 0..) |sym_index, i| {
+ const nlist_idx = @as(Symbol.Index, @intCast(i));
+ const nlist = switch (file) {
+ .object => |x| x.symtab.items(.nlist)[nlist_idx],
+ .zig_object => |x| x.symtab.items(.nlist)[nlist_idx],
+ else => unreachable,
+ };
+ if (!nlist.ext()) continue;
+ if (!nlist.undf()) continue;
+
+ const sym = macho_file.getSymbol(sym_index);
+ if (sym.getFile(macho_file) != null) continue;
+
+ sym.value = 0;
+ sym.atom = 0;
+ sym.nlist_idx = nlist_idx;
+ sym.file = file.getIndex();
+ sym.flags.weak_ref = nlist.weakRef();
+ sym.flags.import = true;
+ sym.visibility = .global;
+ }
+ }
+
+ pub fn markImportsExports(file: File, macho_file: *MachO) void {
+ assert(file == .object or file == .zig_object);
+
+ for (file.getSymbols()) |sym_index| {
+ const sym = macho_file.getSymbol(sym_index);
+ const other_file = sym.getFile(macho_file) orelse continue;
+ if (sym.visibility != .global) continue;
+ if (other_file == .dylib and !sym.flags.abs) {
+ sym.flags.import = true;
+ continue;
+ }
+ if (other_file.getIndex() == file.getIndex()) {
+ sym.flags.@"export" = true;
+ }
+ }
+ }
+
+ pub fn markExportsRelocatable(file: File, macho_file: *MachO) void {
+ assert(file == .object or file == .zig_object);
+
+ for (file.getSymbols()) |sym_index| {
+ const sym = macho_file.getSymbol(sym_index);
+ const other_file = sym.getFile(macho_file) orelse continue;
+ if (sym.visibility != .global) continue;
+ if (other_file.getIndex() == file.getIndex()) {
+ sym.flags.@"export" = true;
+ }
+ }
+ }
+
/// Encodes symbol rank so that the following ordering applies:
/// * strong in object
/// * weak in object
@@ -110,6 +201,7 @@ pub const File = union(enum) {
pub const HandleIndex = Index;
};
+const assert = std.debug.assert;
const macho = std.macho;
const std = @import("std");
src/link/MachO/relocatable.zig
@@ -46,8 +46,8 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
try macho_file.addUndefinedGlobals();
try macho_file.resolveSymbols();
- try markExports(macho_file);
- try claimUnresolved(macho_file);
+ markExports(macho_file);
+ claimUnresolved(macho_file);
try initOutputSections(macho_file);
try macho_file.sortSections();
try macho_file.addAtomsToSections();
@@ -86,54 +86,21 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
try writeHeader(macho_file, ncmds, sizeofcmds);
}
-fn markExports(macho_file: *MachO) error{OutOfMemory}!void {
- var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1);
- defer objects.deinit();
- if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index);
- objects.appendSliceAssumeCapacity(macho_file.objects.items);
-
- for (objects.items) |index| {
- for (macho_file.getFile(index).?.getSymbols()) |sym_index| {
- const sym = macho_file.getSymbol(sym_index);
- const file = sym.getFile(macho_file) orelse continue;
- if (sym.visibility != .global) continue;
- if (file.getIndex() == index) {
- sym.flags.@"export" = true;
- }
- }
+fn markExports(macho_file: *MachO) void {
+ if (macho_file.getZigObject()) |zo| {
+ zo.asFile().markExportsRelocatable(macho_file);
+ }
+ for (macho_file.objects.items) |index| {
+ macho_file.getFile(index).?.markExportsRelocatable(macho_file);
}
}
-fn claimUnresolved(macho_file: *MachO) error{OutOfMemory}!void {
- var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1);
- defer objects.deinit();
- if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index);
- objects.appendSliceAssumeCapacity(macho_file.objects.items);
-
- for (objects.items) |index| {
- const file = macho_file.getFile(index).?;
-
- for (file.getSymbols(), 0..) |sym_index, i| {
- const nlist_idx = @as(Symbol.Index, @intCast(i));
- const nlist = switch (file) {
- .object => |x| x.symtab.items(.nlist)[nlist_idx],
- .zig_object => |x| x.symtab.items(.nlist)[nlist_idx],
- else => unreachable,
- };
- if (!nlist.ext()) continue;
- if (!nlist.undf()) continue;
-
- const sym = macho_file.getSymbol(sym_index);
- if (sym.getFile(macho_file) != null) continue;
-
- sym.value = 0;
- sym.atom = 0;
- sym.nlist_idx = nlist_idx;
- sym.file = index;
- sym.flags.weak_ref = nlist.weakRef();
- sym.flags.import = true;
- sym.visibility = .global;
- }
+pub fn claimUnresolved(macho_file: *MachO) void {
+ if (macho_file.getZigObject()) |zo| {
+ zo.asFile().claimUnresolvedRelocatable(macho_file);
+ }
+ for (macho_file.objects.items) |index| {
+ macho_file.getFile(index).?.claimUnresolvedRelocatable(macho_file);
}
}
src/link/MachO.zig
@@ -379,6 +379,10 @@ pub fn deinit(self: *MachO) void {
}
pub fn flush(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
+ // TODO: I think this is just a temp and can be removed once we can emit static archives
+ if (self.base.isStaticLib() and build_options.have_llvm) {
+ return self.base.linkAsArchive(arena, prog_node);
+ }
try self.flushModule(arena, prog_node);
}
@@ -391,6 +395,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
if (self.llvm_object) |llvm_object| {
try self.base.emitLlvmObject(arena, llvm_object, prog_node);
+ // TODO: I think this is just a temp and can be removed once we can emit static archives
+ if (self.base.isStaticLib() and build_options.have_llvm) return;
}
var sub_prog_node = prog_node.start("MachO Flush", 0);
@@ -571,7 +577,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
},
};
- try self.markImportsAndExports();
+ self.markImportsAndExports();
self.deadStripDylibs();
for (self.dylibs.items, 1..) |index, ord| {
@@ -1509,46 +1515,11 @@ fn createObjcSections(self: *MachO) !void {
}
fn claimUnresolved(self: *MachO) error{OutOfMemory}!void {
- const gpa = self.base.comp.gpa;
-
- var objects = try std.ArrayList(File.Index).initCapacity(gpa, self.objects.items.len + 1);
- defer objects.deinit();
- if (self.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index);
- objects.appendSliceAssumeCapacity(self.objects.items);
-
- for (objects.items) |index| {
- const file = self.getFile(index).?;
-
- for (file.getSymbols(), 0..) |sym_index, i| {
- const nlist_idx = @as(Symbol.Index, @intCast(i));
- const nlist = switch (file) {
- .object => |x| x.symtab.items(.nlist)[nlist_idx],
- .zig_object => |x| x.symtab.items(.nlist)[nlist_idx],
- else => unreachable,
- };
- if (!nlist.ext()) continue;
- if (!nlist.undf()) continue;
-
- const sym = self.getSymbol(sym_index);
- if (sym.getFile(self) != null) continue;
-
- const is_import = switch (self.undefined_treatment) {
- .@"error" => false,
- .warn, .suppress => nlist.weakRef(),
- .dynamic_lookup => true,
- };
- if (is_import) {
- sym.value = 0;
- sym.atom = 0;
- sym.nlist_idx = 0;
- sym.file = self.internal_object.?;
- sym.flags.weak = false;
- sym.flags.weak_ref = nlist.weakRef();
- sym.flags.import = is_import;
- sym.visibility = .global;
- try self.getInternalObject().?.symbols.append(self.base.comp.gpa, sym_index);
- }
- }
+ if (self.getZigObject()) |zo| {
+ try zo.asFile().claimUnresolved(self);
+ }
+ for (self.objects.items) |index| {
+ try self.getFile(index).?.claimUnresolved(self);
}
}
@@ -1574,26 +1545,12 @@ fn checkDuplicates(self: *MachO) !void {
try self.reportDuplicates(dupes);
}
-fn markImportsAndExports(self: *MachO) error{OutOfMemory}!void {
- const gpa = self.base.comp.gpa;
- var objects = try std.ArrayList(File.Index).initCapacity(gpa, self.objects.items.len + 1);
- defer objects.deinit();
- if (self.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index);
- objects.appendSliceAssumeCapacity(self.objects.items);
-
- for (objects.items) |index| {
- for (self.getFile(index).?.getSymbols()) |sym_index| {
- const sym = self.getSymbol(sym_index);
- const file = sym.getFile(self) orelse continue;
- if (sym.visibility != .global) continue;
- if (file == .dylib and !sym.flags.abs) {
- sym.flags.import = true;
- continue;
- }
- if (file.getIndex() == index) {
- sym.flags.@"export" = true;
- }
- }
+fn markImportsAndExports(self: *MachO) void {
+ if (self.getZigObject()) |zo| {
+ zo.asFile().markImportsExports(self);
+ }
+ for (self.objects.items) |index| {
+ self.getFile(index).?.markImportsExports(self);
}
for (self.undefined_symbols.items) |index| {