authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-09-30 23:17:40+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-10-04 15:31:47+02:00
logf8dd48bcd257a5a6a893c11b89af21b7e2ca9a79
treefc8edef1c994776860a533ce44954da99eedda45
parent5a7105401cda94fa82f07630672559659d875854

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.

3 files changed, 52 insertions(+), 10 deletions(-)

src/codegen.zig+6-6
......@@ -1532,12 +1532,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
15321532 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
15331533 const func = func_val.func;
15341534 const got = &macho_file.sections.items[macho_file.got_section_index.?];
1535 const ptr_bytes = 8;
1536 const got_addr = @intCast(u32, got.addr + func.owner_decl.link.macho.offset_table_index.? * ptr_bytes);
1537 // ff 14 25 xx xx xx xx call [addr]
1538 try self.code.ensureCapacity(self.code.items.len + 7);
1539 self.code.appendSliceAssumeCapacity(&[3]u8{ 0xff, 0x14, 0x25 });
1540 mem.writeIntLittle(u32, self.code.addManyAsArrayAssumeCapacity(4), got_addr);
1535 const got_addr = got.addr + func.owner_decl.link.macho.offset_table_index.? * @sizeOf(u64);
1536 // Here, we store the got address in %rax, and then call %rax
1537 // movabsq [addr], %rax
1538 try self.genSetReg(inst.base.src, .rax, .{ .memory = got_addr });
1539 // callq *%rax
1540 self.code.appendSliceAssumeCapacity(&[2]u8{ 0xff, 0xd0 });
15411541 } else {
15421542 return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});
15431543 }
src/link/MachO.zig+7-4
......@@ -262,11 +262,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
262262 dysymtab.iundefsym = nlocals + nglobals;
263263 dysymtab.nundefsym = nundefs;
264264 }
265 {
265 if (self.entry_addr) |addr| {
266266 // update LC_MAIN with entry offset
267267 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
268268 const main_cmd = &self.load_commands.items[self.main_cmd_index.?].EntryPoint;
269 main_cmd.entryoff = self.entry_addr.? - text_segment.vmaddr;
269 main_cmd.entryoff = addr - text_segment.vmaddr;
270270 }
271271 {
272272 var last_cmd_offset: usize = @sizeOf(macho.mach_header_64);
......@@ -709,6 +709,7 @@ fn darwinArchString(arch: std.Target.Cpu.Arch) []const u8 {
709709pub fn deinit(self: *MachO) void {
710710 self.offset_table.deinit(self.base.allocator);
711711 self.string_table.deinit(self.base.allocator);
712 self.undef_symbols.deinit(self.base.allocator);
712713 self.global_symbols.deinit(self.base.allocator);
713714 self.local_symbols.deinit(self.base.allocator);
714715 self.sections.deinit(self.base.allocator);
......@@ -813,7 +814,7 @@ pub fn updateDeclExports(
813814 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
814815 module.failed_exports.putAssumeCapacityNoClobber(
815816 exp,
816 try Module.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: ExportOptions.section", .{}),
817 try Compilation.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: ExportOptions.section", .{}),
817818 );
818819 continue;
819820 }
......@@ -831,7 +832,7 @@ pub fn updateDeclExports(
831832 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
832833 module.failed_exports.putAssumeCapacityNoClobber(
833834 exp,
834 try Module.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: GlobalLinkage.LinkOnce", .{}),
835 try Compilation.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: GlobalLinkage.LinkOnce", .{}),
835836 );
836837 continue;
837838 },
......@@ -1405,6 +1406,8 @@ fn writeAllUndefSymbols(self: *MachO) !void {
14051406}
14061407
14071408fn writeExportTrie(self: *MachO) !void {
1409 if (self.entry_addr == null) return;
1410
14081411 // TODO implement mechanism for generating a prefix tree of the exported symbols
14091412 // single branch export trie
14101413 var buf = [_]u8{0} ** 24;
test/stage2/test.zig+39
......@@ -151,6 +151,45 @@ pub fn addCases(ctx: *TestContext) !void {
151151 {
152152 var case = ctx.exe("hello world", macosx_x64);
153153 case.addError("", &[_][]const u8{":1:1: error: no entry point found"});
154
155 // Incorrect return type
156 case.addError(
157 \\export fn _start() noreturn {
158 \\}
159 , &[_][]const u8{":2:1: error: expected noreturn, found void"});
160
161 // Regular old hello world
162 case.addCompareOutput(
163 \\export fn _start() noreturn {
164 \\ print();
165 \\
166 \\ exit();
167 \\}
168 \\
169 \\fn print() void {
170 \\ asm volatile ("syscall"
171 \\ :
172 \\ : [number] "{rax}" (0x2000004),
173 \\ [arg1] "{rdi}" (1),
174 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
175 \\ [arg3] "{rdx}" (14)
176 \\ : "memory"
177 \\ );
178 \\ return;
179 \\}
180 \\
181 \\fn exit() noreturn {
182 \\ asm volatile ("syscall"
183 \\ :
184 \\ : [number] "{rax}" (0x2000001),
185 \\ [arg1] "{rdi}" (0)
186 \\ : "memory"
187 \\ );
188 \\ unreachable;
189 \\}
190 ,
191 "Hello, World!\n",
192 );
154193 }
155194
156195 {