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 {...@@ -1532,12 +1532,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1532 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {1532 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
1533 const func = func_val.func;1533 const func = func_val.func;
1534 const got = &macho_file.sections.items[macho_file.got_section_index.?];1534 const got = &macho_file.sections.items[macho_file.got_section_index.?];
1535 const ptr_bytes = 8;1535 const got_addr = got.addr + func.owner_decl.link.macho.offset_table_index.? * @sizeOf(u64);
1536 const got_addr = @intCast(u32, got.addr + func.owner_decl.link.macho.offset_table_index.? * ptr_bytes);1536 // Here, we store the got address in %rax, and then call %rax
1537 // ff 14 25 xx xx xx xx call [addr]1537 // movabsq [addr], %rax
1538 try self.code.ensureCapacity(self.code.items.len + 7);1538 try self.genSetReg(inst.base.src, .rax, .{ .memory = got_addr });
1539 self.code.appendSliceAssumeCapacity(&[3]u8{ 0xff, 0x14, 0x25 });1539 // callq *%rax
1540 mem.writeIntLittle(u32, self.code.addManyAsArrayAssumeCapacity(4), got_addr);1540 self.code.appendSliceAssumeCapacity(&[2]u8{ 0xff, 0xd0 });
1541 } else {1541 } else {
1542 return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});1542 return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});
1543 }1543 }
src/link/MachO.zig+7-4
...@@ -262,11 +262,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -262,11 +262,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
262 dysymtab.iundefsym = nlocals + nglobals;262 dysymtab.iundefsym = nlocals + nglobals;
263 dysymtab.nundefsym = nundefs;263 dysymtab.nundefsym = nundefs;
264 }264 }
265 {265 if (self.entry_addr) |addr| {
266 // update LC_MAIN with entry offset266 // update LC_MAIN with entry offset
267 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;267 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
268 const main_cmd = &self.load_commands.items[self.main_cmd_index.?].EntryPoint;268 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;
270 }270 }
271 {271 {
272 var last_cmd_offset: usize = @sizeOf(macho.mach_header_64);272 var last_cmd_offset: usize = @sizeOf(macho.mach_header_64);
...@@ -709,6 +709,7 @@ fn darwinArchString(arch: std.Target.Cpu.Arch) []const u8 {...@@ -709,6 +709,7 @@ fn darwinArchString(arch: std.Target.Cpu.Arch) []const u8 {
709pub fn deinit(self: *MachO) void {709pub fn deinit(self: *MachO) void {
710 self.offset_table.deinit(self.base.allocator);710 self.offset_table.deinit(self.base.allocator);
711 self.string_table.deinit(self.base.allocator);711 self.string_table.deinit(self.base.allocator);
712 self.undef_symbols.deinit(self.base.allocator);
712 self.global_symbols.deinit(self.base.allocator);713 self.global_symbols.deinit(self.base.allocator);
713 self.local_symbols.deinit(self.base.allocator);714 self.local_symbols.deinit(self.base.allocator);
714 self.sections.deinit(self.base.allocator);715 self.sections.deinit(self.base.allocator);
...@@ -813,7 +814,7 @@ pub fn updateDeclExports(...@@ -813,7 +814,7 @@ pub fn updateDeclExports(
813 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);814 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
814 module.failed_exports.putAssumeCapacityNoClobber(815 module.failed_exports.putAssumeCapacityNoClobber(
815 exp,816 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", .{}),
817 );818 );
818 continue;819 continue;
819 }820 }
...@@ -831,7 +832,7 @@ pub fn updateDeclExports(...@@ -831,7 +832,7 @@ pub fn updateDeclExports(
831 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);832 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
832 module.failed_exports.putAssumeCapacityNoClobber(833 module.failed_exports.putAssumeCapacityNoClobber(
833 exp,834 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", .{}),
835 );836 );
836 continue;837 continue;
837 },838 },
...@@ -1405,6 +1406,8 @@ fn writeAllUndefSymbols(self: *MachO) !void {...@@ -1405,6 +1406,8 @@ fn writeAllUndefSymbols(self: *MachO) !void {
1405}1406}
14061407
1407fn writeExportTrie(self: *MachO) !void {1408fn writeExportTrie(self: *MachO) !void {
1409 if (self.entry_addr == null) return;
1410
1408 // TODO implement mechanism for generating a prefix tree of the exported symbols1411 // TODO implement mechanism for generating a prefix tree of the exported symbols
1409 // single branch export trie1412 // single branch export trie
1410 var buf = [_]u8{0} ** 24;1413 var buf = [_]u8{0} ** 24;
test/stage2/test.zig+39
...@@ -151,6 +151,45 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -151,6 +151,45 @@ pub fn addCases(ctx: *TestContext) !void {
151 {151 {
152 var case = ctx.exe("hello world", macosx_x64);152 var case = ctx.exe("hello world", macosx_x64);
153 case.addError("", &[_][]const u8{":1:1: error: no entry point found"});153 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 );
154 }193 }
155194
156 {195 {