From f8dd48bcd257a5a6a893c11b89af21b7e2ca9a79 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Wed, 30 Sep 2020 23:17:40 +0200 Subject: [PATCH] Fix after rebase and enable stage2 tests for macOS Also, rewrites codegen section to store symbol address in a register to then later invoke `callq` on the register. --- src/codegen.zig | 12 ++++++------ src/link/MachO.zig | 11 +++++++---- test/stage2/test.zig | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/codegen.zig b/src/codegen.zig index a1d3cc2fc4..919d1ef457 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -1532,12 +1532,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { if (func_inst.val.cast(Value.Payload.Function)) |func_val| { const func = func_val.func; const got = &macho_file.sections.items[macho_file.got_section_index.?]; - const ptr_bytes = 8; - const got_addr = @intCast(u32, got.addr + func.owner_decl.link.macho.offset_table_index.? * ptr_bytes); - // ff 14 25 xx xx xx xx call [addr] - try self.code.ensureCapacity(self.code.items.len + 7); - self.code.appendSliceAssumeCapacity(&[3]u8{ 0xff, 0x14, 0x25 }); - mem.writeIntLittle(u32, self.code.addManyAsArrayAssumeCapacity(4), got_addr); + const got_addr = got.addr + func.owner_decl.link.macho.offset_table_index.? * @sizeOf(u64); + // Here, we store the got address in %rax, and then call %rax + // movabsq [addr], %rax + try self.genSetReg(inst.base.src, .rax, .{ .memory = got_addr }); + // callq *%rax + self.code.appendSliceAssumeCapacity(&[2]u8{ 0xff, 0xd0 }); } else { return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{}); } diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 342a73ca36..9a58a35dc9 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -262,11 +262,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { dysymtab.iundefsym = nlocals + nglobals; dysymtab.nundefsym = nundefs; } - { + if (self.entry_addr) |addr| { // update LC_MAIN with entry offset const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment; const main_cmd = &self.load_commands.items[self.main_cmd_index.?].EntryPoint; - main_cmd.entryoff = self.entry_addr.? - text_segment.vmaddr; + main_cmd.entryoff = addr - text_segment.vmaddr; } { var last_cmd_offset: usize = @sizeOf(macho.mach_header_64); @@ -709,6 +709,7 @@ fn darwinArchString(arch: std.Target.Cpu.Arch) []const u8 { pub fn deinit(self: *MachO) void { self.offset_table.deinit(self.base.allocator); self.string_table.deinit(self.base.allocator); + self.undef_symbols.deinit(self.base.allocator); self.global_symbols.deinit(self.base.allocator); self.local_symbols.deinit(self.base.allocator); self.sections.deinit(self.base.allocator); @@ -813,7 +814,7 @@ pub fn updateDeclExports( try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); module.failed_exports.putAssumeCapacityNoClobber( exp, - try Module.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: ExportOptions.section", .{}), + try Compilation.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: ExportOptions.section", .{}), ); continue; } @@ -831,7 +832,7 @@ pub fn updateDeclExports( try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); module.failed_exports.putAssumeCapacityNoClobber( exp, - try Module.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: GlobalLinkage.LinkOnce", .{}), + try Compilation.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: GlobalLinkage.LinkOnce", .{}), ); continue; }, @@ -1405,6 +1406,8 @@ fn writeAllUndefSymbols(self: *MachO) !void { } fn writeExportTrie(self: *MachO) !void { + if (self.entry_addr == null) return; + // TODO implement mechanism for generating a prefix tree of the exported symbols // single branch export trie var buf = [_]u8{0} ** 24; diff --git a/test/stage2/test.zig b/test/stage2/test.zig index a22dc23d36..281bd0a6e8 100644 --- a/test/stage2/test.zig +++ b/test/stage2/test.zig @@ -151,6 +151,45 @@ pub fn addCases(ctx: *TestContext) !void { { var case = ctx.exe("hello world", macosx_x64); case.addError("", &[_][]const u8{":1:1: error: no entry point found"}); + + // Incorrect return type + case.addError( + \\export fn _start() noreturn { + \\} + , &[_][]const u8{":2:1: error: expected noreturn, found void"}); + + // Regular old hello world + case.addCompareOutput( + \\export fn _start() noreturn { + \\ print(); + \\ + \\ exit(); + \\} + \\ + \\fn print() void { + \\ asm volatile ("syscall" + \\ : + \\ : [number] "{rax}" (0x2000004), + \\ [arg1] "{rdi}" (1), + \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")), + \\ [arg3] "{rdx}" (14) + \\ : "memory" + \\ ); + \\ return; + \\} + \\ + \\fn exit() noreturn { + \\ asm volatile ("syscall" + \\ : + \\ : [number] "{rax}" (0x2000001), + \\ [arg1] "{rdi}" (0) + \\ : "memory" + \\ ); + \\ unreachable; + \\} + , + "Hello, World!\n", + ); } {