From d107ef86973692123892bcd5e47ce1b17982283a Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Wed, 2 Feb 2022 20:59:17 +0100 Subject: [PATCH] Merge pull request #10769 from ziglang/link-lib-fixes stage2: handle name-qualified imports in sema, add a zerofill sections workaround to incremental macho --- src/Sema.zig | 16 +++++++++++----- src/link/MachO.zig | 22 ++++++++++++++-------- test/stage2/aarch64.zig | 12 ++++++------ test/stage2/x86_64.zig | 26 +++++++++++++------------- 4 files changed, 44 insertions(+), 32 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 044084a349..67dbcb6e99 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5145,11 +5145,6 @@ fn funcCommon( if (opt_lib_name) |lib_name| blk: { const lib_name_src: LazySrcLoc = .{ .node_offset_lib_name = src_node_offset }; log.debug("extern fn symbol expected in lib '{s}'", .{lib_name}); - mod.comp.stage1AddLinkLib(lib_name) catch |err| { - return sema.fail(block, lib_name_src, "unable to add link lib '{s}': {s}", .{ - lib_name, @errorName(err), - }); - }; const target = mod.getTarget(); if (target_util.is_libc_lib_name(target, lib_name)) { if (!mod.comp.bin_file.options.link_libc) { @@ -5160,6 +5155,7 @@ fn funcCommon( .{}, ); } + mod.comp.bin_file.options.link_libc = true; break :blk; } if (target_util.is_libcpp_lib_name(target, lib_name)) { @@ -5171,6 +5167,11 @@ fn funcCommon( .{}, ); } + mod.comp.bin_file.options.link_libcpp = true; + break :blk; + } + if (mem.eql(u8, lib_name, "unwind")) { + mod.comp.bin_file.options.link_libunwind = true; break :blk; } if (!target.isWasm() and !mod.comp.bin_file.options.pic) { @@ -5181,6 +5182,11 @@ fn funcCommon( .{ lib_name, lib_name }, ); } + mod.comp.stage1AddLinkLib(lib_name) catch |err| { + return sema.fail(block, lib_name_src, "unable to add link lib '{s}': {s}", .{ + lib_name, @errorName(err), + }); + }; } if (is_extern) { diff --git a/src/link/MachO.zig b/src/link/MachO.zig index e9732be258..b27c54fd34 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -143,9 +143,6 @@ objc_data_section_index: ?u16 = null, rustc_section_index: ?u16 = null, rustc_section_size: u64 = 0, -bss_file_offset: u32 = 0, -tlv_bss_file_offset: u32 = 0, - locals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, globals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{}, @@ -384,7 +381,8 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO { // Adhoc code signature is required when targeting aarch64-macos either directly or indirectly via the simulator // ABI such as aarch64-ios-simulator, etc. const requires_adhoc_codesig = cpu_arch == .aarch64 and (os_tag == .macos or abi == .simulator); - const needs_prealloc = !(build_options.is_stage1 and options.use_stage1); + const use_stage1 = build_options.is_stage1 and options.use_stage1; + const needs_prealloc = !(use_stage1 or options.cache_mode == .whole); self.* = .{ .base = .{ @@ -2129,7 +2127,8 @@ fn writeAtoms(self: *MachO) !void { const sect = seg.sections.items[match.sect]; var atom: *Atom = entry.value_ptr.*; - if (sect.flags == macho.S_ZEROFILL or sect.flags == macho.S_THREAD_LOCAL_ZEROFILL) continue; + // TODO handle zerofill in stage2 + // if (sect.flags == macho.S_ZEROFILL or sect.flags == macho.S_THREAD_LOCAL_ZEROFILL) continue; log.debug("writing atoms in {s},{s}", .{ sect.segName(), sect.sectName() }); @@ -4566,9 +4565,12 @@ fn allocateSegment(self: *MachO, index: u16, offset: u64) !void { var start: u64 = offset; for (seg.sections.items) |*sect, sect_id| { const is_zerofill = sect.flags == macho.S_ZEROFILL or sect.flags == macho.S_THREAD_LOCAL_ZEROFILL; + const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1; const alignment = try math.powi(u32, 2, sect.@"align"); const start_aligned = mem.alignForwardGeneric(u64, start, alignment); - sect.offset = if (is_zerofill) 0 else @intCast(u32, seg.inner.fileoff + start_aligned); + + // TODO handle zerofill sections in stage2 + sect.offset = if (is_zerofill and use_stage1) 0 else @intCast(u32, seg.inner.fileoff + start_aligned); sect.addr = seg.inner.vmaddr + start_aligned; // Recalculate section size given the allocated start address @@ -4596,7 +4598,7 @@ fn allocateSegment(self: *MachO, index: u16, offset: u64) !void { start = start_aligned + sect.size; - if (!is_zerofill) { + if (!(is_zerofill and use_stage1)) { seg.inner.filesize = start; } seg.inner.vmsize = start; @@ -4644,7 +4646,11 @@ fn initSection( sect.addr = seg.inner.vmaddr + off - seg.inner.fileoff; - if (opts.flags != macho.S_ZEROFILL and opts.flags != macho.S_THREAD_LOCAL_ZEROFILL) { + const is_zerofill = opts.flags == macho.S_ZEROFILL or opts.flags == macho.S_THREAD_LOCAL_ZEROFILL; + const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1; + + // TODO handle zerofill in stage2 + if (!(is_zerofill and use_stage1)) { sect.offset = @intCast(u32, off); } } diff --git a/test/stage2/aarch64.zig b/test/stage2/aarch64.zig index db4539eca9..64e6f95a84 100644 --- a/test/stage2/aarch64.zig +++ b/test/stage2/aarch64.zig @@ -121,8 +121,8 @@ pub fn addCases(ctx: *TestContext) !void { // Regular old hello world case.addCompareOutput( - \\extern fn write(usize, usize, usize) usize; - \\extern fn exit(usize) noreturn; + \\extern "c" fn write(usize, usize, usize) usize; + \\extern "c" fn exit(usize) noreturn; \\ \\pub export fn main() noreturn { \\ print(); @@ -141,7 +141,7 @@ pub fn addCases(ctx: *TestContext) !void { // Now using start.zig without an explicit extern exit fn case.addCompareOutput( - \\extern fn write(usize, usize, usize) usize; + \\extern "c" fn write(usize, usize, usize) usize; \\ \\pub fn main() void { \\ print(); @@ -158,7 +158,7 @@ pub fn addCases(ctx: *TestContext) !void { // Print it 4 times and force growth and realloc. case.addCompareOutput( - \\extern fn write(usize, usize, usize) usize; + \\extern "c" fn write(usize, usize, usize) usize; \\ \\pub fn main() void { \\ print(); @@ -182,7 +182,7 @@ pub fn addCases(ctx: *TestContext) !void { // Print it once, and change the message. case.addCompareOutput( - \\extern fn write(usize, usize, usize) usize; + \\extern "c" fn write(usize, usize, usize) usize; \\ \\pub fn main() void { \\ print(); @@ -199,7 +199,7 @@ pub fn addCases(ctx: *TestContext) !void { // Now we print it twice. case.addCompareOutput( - \\extern fn write(usize, usize, usize) usize; + \\extern "c" fn write(usize, usize, usize) usize; \\ \\pub fn main() void { \\ print(); diff --git a/test/stage2/x86_64.zig b/test/stage2/x86_64.zig index 2725767e95..20bf2264bf 100644 --- a/test/stage2/x86_64.zig +++ b/test/stage2/x86_64.zig @@ -328,7 +328,7 @@ pub fn addCases(ctx: *TestContext) !void { .macos => { // While loops case.addCompareOutput( - \\extern fn write(usize, usize, usize) usize; + \\extern "c" fn write(usize, usize, usize) usize; \\ \\pub fn main() void { \\ var i: u32 = 0; @@ -349,7 +349,7 @@ pub fn addCases(ctx: *TestContext) !void { // inline while requires the condition to be comptime known. case.addError( - \\extern fn write(usize, usize, usize) usize; + \\extern "c" fn write(usize, usize, usize) usize; \\ \\pub fn main() void { \\ var i: u32 = 0; @@ -652,7 +652,7 @@ pub fn addCases(ctx: *TestContext) !void { .macos => { // Basic for loop case.addCompareOutput( - \\extern fn write(usize, usize, usize) usize; + \\extern "c" fn write(usize, usize, usize) usize; \\ \\pub fn main() void { \\ for ("hello") |_| print(); @@ -736,7 +736,7 @@ pub fn addCases(ctx: *TestContext) !void { }), .macos => try case.files.append(.{ .src = - \\extern fn write(usize, usize, usize) usize; + \\extern "c" fn write(usize, usize, usize) usize; \\ \\pub fn print() void { \\ _ = write(1, @ptrToInt("Hello, World!\n"), 14); @@ -814,7 +814,7 @@ pub fn addCases(ctx: *TestContext) !void { }), .macos => try case.files.append(.{ .src = - \\extern fn write(usize, usize, usize) usize; + \\extern "c" fn write(usize, usize, usize) usize; \\fn print() void { \\ _ = write(1, @ptrToInt("Hello, World!\n"), 14); \\} @@ -1478,7 +1478,7 @@ pub fn addCases(ctx: *TestContext) !void { \\} , "HelloHello, World!\n"), .macos => case.addCompareOutput( - \\extern fn write(usize, usize, usize) usize; + \\extern "c" fn write(usize, usize, usize) usize; \\ \\pub fn main() void { \\ comptime var len: u32 = 5; @@ -1550,7 +1550,7 @@ pub fn addCases(ctx: *TestContext) !void { \\} , "HeHelHellHello"), .macos => case.addCompareOutput( - \\extern fn write(usize, usize, usize) usize; + \\extern "c" fn write(usize, usize, usize) usize; \\ \\pub fn main() void { \\ comptime var i: u64 = 2; @@ -1877,8 +1877,8 @@ fn addMacOsTestCases(ctx: *TestContext) !void { // Regular old hello world case.addCompareOutput( - \\extern fn write(usize, usize, usize) usize; - \\extern fn exit(usize) noreturn; + \\extern "c" fn write(usize, usize, usize) usize; + \\extern "c" fn exit(usize) noreturn; \\ \\pub export fn main() noreturn { \\ print(); @@ -1897,7 +1897,7 @@ fn addMacOsTestCases(ctx: *TestContext) !void { // Now using start.zig without an explicit extern exit fn case.addCompareOutput( - \\extern fn write(usize, usize, usize) usize; + \\extern "c" fn write(usize, usize, usize) usize; \\ \\pub fn main() void { \\ print(); @@ -1914,7 +1914,7 @@ fn addMacOsTestCases(ctx: *TestContext) !void { // Print it 4 times and force growth and realloc. case.addCompareOutput( - \\extern fn write(usize, usize, usize) usize; + \\extern "c" fn write(usize, usize, usize) usize; \\ \\pub fn main() void { \\ print(); @@ -1938,7 +1938,7 @@ fn addMacOsTestCases(ctx: *TestContext) !void { // Print it once, and change the message. case.addCompareOutput( - \\extern fn write(usize, usize, usize) usize; + \\extern "c" fn write(usize, usize, usize) usize; \\ \\pub fn main() void { \\ print(); @@ -1955,7 +1955,7 @@ fn addMacOsTestCases(ctx: *TestContext) !void { // Now we print it twice. case.addCompareOutput( - \\extern fn write(usize, usize, usize) usize; + \\extern "c" fn write(usize, usize, usize) usize; \\ \\pub fn main() void { \\ print();