| author | |
| committer | |
| log | 845c906e6a2ed9206840bd189d85bf9525687102 |
| tree | c0e620efdcf386af5d459aacb05cb4e0183d2d87 |
| parent | 3bfde76cff60a0d9c70d8e660dd633bed17a314f |
in self-hosted compiler.2 files changed, 37 insertions(+), 72 deletions(-)
src/codegen.zig+30-21| ... | ... | @@ -2506,7 +2506,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2506 | 2506 | }) orelse unreachable; |
| 2507 | 2507 | break :blk got.addr + got_index * @sizeOf(u64); |
| 2508 | 2508 | }; |
| 2509 | log.debug("got_addr = 0x{x}", .{got_addr}); | |
| 2510 | 2509 | switch (arch) { |
| 2511 | 2510 | .x86_64 => { |
| 2512 | 2511 | try self.genSetReg(inst.base.src, Type.initTag(.u64), .rax, .{ .memory = got_addr }); |
| ... | ... | @@ -3864,19 +3863,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3864 | 3863 | .memory => |addr| { |
| 3865 | 3864 | if (self.bin_file.options.pie) { |
| 3866 | 3865 | // PC-relative displacement to the entry in the GOT table. |
| 3867 | // TODO we should come up with our own, backend independent relocation types | |
| 3868 | // which each backend (Elf, MachO, etc.) would then translate into an actual | |
| 3869 | // fixup when linking. | |
| 3870 | // adrp reg, pages | |
| 3871 | if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 3872 | try macho_file.pie_fixups.append(self.bin_file.allocator, .{ | |
| 3873 | .target_addr = addr, | |
| 3874 | .offset = self.code.items.len, | |
| 3875 | .size = 4, | |
| 3876 | }); | |
| 3877 | } else { | |
| 3878 | return self.fail(src, "TODO implement genSetReg for PIE GOT indirection on this platform", .{}); | |
| 3879 | } | |
| 3866 | // adrp | |
| 3867 | const offset = @intCast(u32, self.code.items.len); | |
| 3880 | 3868 | mem.writeIntLittle( |
| 3881 | 3869 | u32, |
| 3882 | 3870 | try self.code.addManyAsArray(4), |
| ... | ... | @@ -3889,6 +3877,26 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3889 | 3877 | .offset = Instruction.LoadStoreOffset.imm(0), |
| 3890 | 3878 | }, |
| 3891 | 3879 | }).toU32()); |
| 3880 | ||
| 3881 | if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 3882 | const decl = macho_file.active_decl.?; | |
| 3883 | // Page reloc for adrp instruction. | |
| 3884 | try decl.link.macho.relocs.append(self.bin_file.allocator, .{ | |
| 3885 | .offset = offset, | |
| 3886 | .where = .local, | |
| 3887 | .where_index = decl.link.macho.local_sym_index, | |
| 3888 | .payload = .{ .page = .{ .kind = .got } }, | |
| 3889 | }); | |
| 3890 | // Pageoff reloc for adrp instruction. | |
| 3891 | try decl.link.macho.relocs.append(self.bin_file.allocator, .{ | |
| 3892 | .offset = offset + 4, | |
| 3893 | .where = .local, | |
| 3894 | .where_index = decl.link.macho.local_sym_index, | |
| 3895 | .payload = .{ .page_off = .{ .kind = .got } }, | |
| 3896 | }); | |
| 3897 | } else { | |
| 3898 | return self.fail(src, "TODO implement genSetReg for PIE GOT indirection on this platform", .{}); | |
| 3899 | } | |
| 3892 | 3900 | } else { |
| 3893 | 3901 | // The value is in memory at a hard-coded address. |
| 3894 | 3902 | // If the type is a pointer, it means the pointer address is at this memory location. |
| ... | ... | @@ -4128,6 +4136,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 4128 | 4136 | const abi_size = ty.abiSize(self.target.*); |
| 4129 | 4137 | const encoder = try X8664Encoder.init(self.code, 10); |
| 4130 | 4138 | |
| 4139 | const offset = @intCast(u32, self.code.items.len); | |
| 4131 | 4140 | // LEA reg, [<offset>] |
| 4132 | 4141 | |
| 4133 | 4142 | // We encode the instruction FIRST because prefixes may or may not appear. |
| ... | ... | @@ -4141,14 +4150,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 4141 | 4150 | encoder.modRm_RIPDisp32(reg.low_id()); |
| 4142 | 4151 | encoder.disp32(0); |
| 4143 | 4152 | |
| 4144 | // TODO we should come up with our own, backend independent relocation types | |
| 4145 | // which each backend (Elf, MachO, etc.) would then translate into an actual | |
| 4146 | // fixup when linking. | |
| 4147 | 4153 | if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 4148 | try macho_file.pie_fixups.append(self.bin_file.allocator, .{ | |
| 4149 | .target_addr = x, | |
| 4150 | .offset = self.code.items.len - 4, | |
| 4151 | .size = 4, | |
| 4154 | const decl = macho_file.active_decl.?; | |
| 4155 | // Load reloc for LEA instruction. | |
| 4156 | try decl.link.macho.relocs.append(self.bin_file.allocator, .{ | |
| 4157 | .offset = offset, | |
| 4158 | .where = .local, | |
| 4159 | .where_index = decl.link.macho.local_sym_index, | |
| 4160 | .payload = .{ .load = .{ .kind = .got } }, | |
| 4152 | 4161 | }); |
| 4153 | 4162 | } else { |
| 4154 | 4163 | return self.fail(src, "TODO implement genSetReg for PIE GOT indirection on this platform", .{}); |
src/link/MachO.zig+7-51| ... | ... | @@ -203,14 +203,11 @@ blocks: std.AutoHashMapUnmanaged(MatchingSection, *TextBlock) = .{}, |
| 203 | 203 | /// TODO consolidate this. |
| 204 | 204 | decls: std.ArrayListUnmanaged(*Module.Decl) = .{}, |
| 205 | 205 | |
| 206 | /// A list of all PIE fixups required for this run of the linker. | |
| 207 | /// Warning, this is currently NOT thread-safe. See the TODO below. | |
| 208 | /// TODO Move this list inside `updateDecl` where it should be allocated | |
| 209 | /// prior to calling `generateSymbol`, and then immediately deallocated | |
| 210 | /// rather than sitting in the global scope. | |
| 211 | /// TODO We should also rewrite this using generic relocations common to all | |
| 212 | /// backends. | |
| 213 | pie_fixups: std.ArrayListUnmanaged(PIEFixup) = .{}, | |
| 206 | /// Currently active Module.Decl. | |
| 207 | /// TODO this might not be necessary if we figure out how to pass Module.Decl instance | |
| 208 | /// to codegen.genSetReg() or alterntively move PIE displacement for MCValue{ .memory = x } | |
| 209 | /// somewhere else in the codegen. | |
| 210 | active_decl: ?*Module.Decl = null, | |
| 214 | 211 | |
| 215 | 212 | const StringIndexContext = struct { |
| 216 | 213 | strtab: *std.ArrayListUnmanaged(u8), |
| ... | ... | @@ -3279,7 +3276,6 @@ pub fn deinit(self: *MachO) void { |
| 3279 | 3276 | } |
| 3280 | 3277 | |
| 3281 | 3278 | self.pending_updates.deinit(self.base.allocator); |
| 3282 | self.pie_fixups.deinit(self.base.allocator); | |
| 3283 | 3279 | self.got_entries.deinit(self.base.allocator); |
| 3284 | 3280 | self.got_entries_map.deinit(self.base.allocator); |
| 3285 | 3281 | self.got_entries_free_list.deinit(self.base.allocator); |
| ... | ... | @@ -3497,6 +3493,8 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 3497 | 3493 | } |
| 3498 | 3494 | } |
| 3499 | 3495 | |
| 3496 | self.active_decl = decl; | |
| 3497 | ||
| 3500 | 3498 | const res = if (debug_buffers) |*dbg| |
| 3501 | 3499 | try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ |
| 3502 | 3500 | .ty = decl.ty, |
| ... | ... | @@ -3522,8 +3520,6 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 3522 | 3520 | break :blk decl.link.macho.code; |
| 3523 | 3521 | }, |
| 3524 | 3522 | .fail => |em| { |
| 3525 | // Clear any PIE fixups for this decl. | |
| 3526 | self.pie_fixups.shrinkRetainingCapacity(0); | |
| 3527 | 3523 | decl.analysis = .codegen_failure; |
| 3528 | 3524 | try module.failed_decls.put(module.gpa, decl, em); |
| 3529 | 3525 | return; |
| ... | ... | @@ -3600,46 +3596,6 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 3600 | 3596 | try self.writeGotEntry(got_index); |
| 3601 | 3597 | } |
| 3602 | 3598 | |
| 3603 | // Calculate displacements to target addr (if any). | |
| 3604 | while (self.pie_fixups.popOrNull()) |fixup| { | |
| 3605 | assert(fixup.size == 4); | |
| 3606 | const this_addr = symbol.n_value + fixup.offset; | |
| 3607 | const target_addr = fixup.target_addr; | |
| 3608 | ||
| 3609 | switch (self.base.options.target.cpu.arch) { | |
| 3610 | .x86_64 => { | |
| 3611 | const displacement = try math.cast(u32, target_addr - this_addr - 4); | |
| 3612 | mem.writeIntLittle(u32, decl.link.macho.code[fixup.offset..][0..4], displacement); | |
| 3613 | }, | |
| 3614 | .aarch64 => { | |
| 3615 | // TODO optimize instruction based on jump length (use ldr(literal) + nop if possible). | |
| 3616 | { | |
| 3617 | const inst = decl.link.macho.code[fixup.offset..][0..4]; | |
| 3618 | var parsed = mem.bytesAsValue(meta.TagPayload( | |
| 3619 | aarch64.Instruction, | |
| 3620 | aarch64.Instruction.pc_relative_address, | |
| 3621 | ), inst); | |
| 3622 | const this_page = @intCast(i32, this_addr >> 12); | |
| 3623 | const target_page = @intCast(i32, target_addr >> 12); | |
| 3624 | const pages = @bitCast(u21, @intCast(i21, target_page - this_page)); | |
| 3625 | parsed.immhi = @truncate(u19, pages >> 2); | |
| 3626 | parsed.immlo = @truncate(u2, pages); | |
| 3627 | } | |
| 3628 | { | |
| 3629 | const inst = decl.link.macho.code[fixup.offset + 4 ..][0..4]; | |
| 3630 | var parsed = mem.bytesAsValue(meta.TagPayload( | |
| 3631 | aarch64.Instruction, | |
| 3632 | aarch64.Instruction.load_store_register, | |
| 3633 | ), inst); | |
| 3634 | const narrowed = @truncate(u12, target_addr); | |
| 3635 | const offset = try math.divExact(u12, narrowed, 8); | |
| 3636 | parsed.offset = offset; | |
| 3637 | } | |
| 3638 | }, | |
| 3639 | else => unreachable, // unsupported target architecture | |
| 3640 | } | |
| 3641 | } | |
| 3642 | ||
| 3643 | 3599 | // Resolve relocations |
| 3644 | 3600 | try decl.link.macho.resolveRelocs(self); |
| 3645 | 3601 |