| author | |
| committer | |
| log | f8dd48bcd257a5a6a893c11b89af21b7e2ca9a79 |
| tree | fc8edef1c994776860a533ce44954da99eedda45 |
| parent | 5a7105401cda94fa82f07630672559659d875854 |
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 | 1532 | if (func_inst.val.cast(Value.Payload.Function)) |func_val| { |
| 1533 | 1533 | const func = func_val.func; |
| 1534 | 1534 | 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 }); | |
| 1541 | 1541 | } else { |
| 1542 | 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 | 262 | dysymtab.iundefsym = nlocals + nglobals; |
| 263 | 263 | dysymtab.nundefsym = nundefs; |
| 264 | 264 | } |
| 265 | { | |
| 265 | if (self.entry_addr) |addr| { | |
| 266 | 266 | // update LC_MAIN with entry offset |
| 267 | 267 | const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 268 | 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 | 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 | 709 | pub fn deinit(self: *MachO) void { |
| 710 | 710 | self.offset_table.deinit(self.base.allocator); |
| 711 | 711 | self.string_table.deinit(self.base.allocator); |
| 712 | self.undef_symbols.deinit(self.base.allocator); | |
| 712 | 713 | self.global_symbols.deinit(self.base.allocator); |
| 713 | 714 | self.local_symbols.deinit(self.base.allocator); |
| 714 | 715 | self.sections.deinit(self.base.allocator); |
| ... | ... | @@ -813,7 +814,7 @@ pub fn updateDeclExports( |
| 813 | 814 | try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); |
| 814 | 815 | module.failed_exports.putAssumeCapacityNoClobber( |
| 815 | 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 | 819 | continue; |
| 819 | 820 | } |
| ... | ... | @@ -831,7 +832,7 @@ pub fn updateDeclExports( |
| 831 | 832 | try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); |
| 832 | 833 | module.failed_exports.putAssumeCapacityNoClobber( |
| 833 | 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 | 837 | continue; |
| 837 | 838 | }, |
| ... | ... | @@ -1405,6 +1406,8 @@ fn writeAllUndefSymbols(self: *MachO) !void { |
| 1405 | 1406 | } |
| 1406 | 1407 | |
| 1407 | 1408 | fn writeExportTrie(self: *MachO) !void { |
| 1409 | if (self.entry_addr == null) return; | |
| 1410 | ||
| 1408 | 1411 | // TODO implement mechanism for generating a prefix tree of the exported symbols |
| 1409 | 1412 | // single branch export trie |
| 1410 | 1413 | var buf = [_]u8{0} ** 24; |
test/stage2/test.zig+39| ... | ... | @@ -151,6 +151,45 @@ pub fn addCases(ctx: *TestContext) !void { |
| 151 | 151 | { |
| 152 | 152 | var case = ctx.exe("hello world", macosx_x64); |
| 153 | 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 | } |
| 155 | 194 | |
| 156 | 195 | { |