authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-11 12:16:32+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-11 12:16:32+01:00
log066758b1a296aa6f01d505f7b90d5aee2f387d30
tree50c15027ca05182f8f47e55d2891d9b9d318db66
parentb9b1ab024063105a9adfe3828692867c91015dc6

macho: correctly lower slices incl reloc and rebase tracking

Match changes required to `Elf` linker, which enable lowering of const slices on `MachO` targets. Expand `Mir` instructions requiring the knowledge of the containing atom - pass the symbol index into the linker's table from codegen via mir to emitter, to then utilise it in the linker.

9 files changed, 130 insertions(+), 61 deletions(-)

src/arch/aarch64/CodeGen.zig+15-1
...@@ -1617,7 +1617,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -1617,7 +1617,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
16171617
1618 _ = try self.addInst(.{1618 _ = try self.addInst(.{
1619 .tag = .call_extern,1619 .tag = .call_extern,
1620 .data = .{ .extern_fn = n_strx },1620 .data = .{
1621 .extern_fn = .{
1622 .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index,
1623 .sym_name = n_strx,
1624 },
1625 },
1621 });1626 });
1622 } else {1627 } else {
1623 return self.fail("TODO implement calling bitcasted functions", .{});1628 return self.fail("TODO implement calling bitcasted functions", .{});
...@@ -2485,9 +2490,18 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -2485,9 +2490,18 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
2485 });2490 });
2486 },2491 },
2487 .memory => |addr| {2492 .memory => |addr| {
2493 const owner_decl = self.mod_fn.owner_decl;
2494 // TODO when refactoring LinkBlock, make this into a generic function.
2495 const atom_index = switch (self.bin_file.tag) {
2496 .macho => owner_decl.link.macho.local_sym_index,
2497 .elf => owner_decl.link.elf.local_sym_index,
2498 .plan9 => @intCast(u32, owner_decl.link.plan9.sym_index orelse 0),
2499 else => return self.fail("TODO handle aarch64 load memory in {}", .{self.bin_file.tag}),
2500 };
2488 _ = try self.addInst(.{2501 _ = try self.addInst(.{
2489 .tag = .load_memory,2502 .tag = .load_memory,
2490 .data = .{ .payload = try self.addExtra(Mir.LoadMemory{2503 .data = .{ .payload = try self.addExtra(Mir.LoadMemory{
2504 .atom_index = atom_index,
2491 .register = @enumToInt(reg),2505 .register = @enumToInt(reg),
2492 .addr = @intCast(u32, addr),2506 .addr = @intCast(u32, addr),
2493 }) },2507 }) },
src/arch/aarch64/Emit.zig+7-7
...@@ -537,7 +537,7 @@ fn mirDebugEpilogueBegin(self: *Emit) !void {...@@ -537,7 +537,7 @@ fn mirDebugEpilogueBegin(self: *Emit) !void {
537537
538fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {538fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {
539 assert(emit.mir.instructions.items(.tag)[inst] == .call_extern);539 assert(emit.mir.instructions.items(.tag)[inst] == .call_extern);
540 const n_strx = emit.mir.instructions.items(.data)[inst].extern_fn;540 const extern_fn = emit.mir.instructions.items(.data)[inst].extern_fn;
541541
542 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {542 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
543 const offset = blk: {543 const offset = blk: {
...@@ -547,9 +547,10 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -547,9 +547,10 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {
547 break :blk offset;547 break :blk offset;
548 };548 };
549 // Add relocation to the decl.549 // Add relocation to the decl.
550 try macho_file.active_decl.?.link.macho.relocs.append(emit.bin_file.allocator, .{550 const atom = macho_file.atom_by_index_table.get(extern_fn.atom_index).?;
551 try atom.relocs.append(emit.bin_file.allocator, .{
551 .offset = offset,552 .offset = offset,
552 .target = .{ .global = n_strx },553 .target = .{ .global = extern_fn.sym_name },
553 .addend = 0,554 .addend = 0,
554 .subtractor = null,555 .subtractor = null,
555 .pcrel = true,556 .pcrel = true,
...@@ -613,10 +614,9 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -613,10 +614,9 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void {
613 ));614 ));
614615
615 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {616 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
616 // TODO I think the reloc might be in the wrong place.617 const atom = macho_file.atom_by_index_table.get(load_memory.atom_index).?;
617 const decl = macho_file.active_decl.?;
618 // Page reloc for adrp instruction.618 // Page reloc for adrp instruction.
619 try decl.link.macho.relocs.append(emit.bin_file.allocator, .{619 try atom.relocs.append(emit.bin_file.allocator, .{
620 .offset = offset,620 .offset = offset,
621 .target = .{ .local = addr },621 .target = .{ .local = addr },
622 .addend = 0,622 .addend = 0,
...@@ -626,7 +626,7 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -626,7 +626,7 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void {
626 .@"type" = @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21),626 .@"type" = @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21),
627 });627 });
628 // Pageoff reloc for adrp instruction.628 // Pageoff reloc for adrp instruction.
629 try decl.link.macho.relocs.append(emit.bin_file.allocator, .{629 try atom.relocs.append(emit.bin_file.allocator, .{
630 .offset = offset + 4,630 .offset = offset + 4,
631 .target = .{ .local = addr },631 .target = .{ .local = addr },
632 .addend = 0,632 .addend = 0,
src/arch/aarch64/Mir.zig+7-1
...@@ -134,7 +134,12 @@ pub const Inst = struct {...@@ -134,7 +134,12 @@ pub const Inst = struct {
134 /// An extern function134 /// An extern function
135 ///135 ///
136 /// Used by e.g. call_extern136 /// Used by e.g. call_extern
137 extern_fn: u32,137 extern_fn: struct {
138 /// Index of the containing atom.
139 atom_index: u32,
140 /// Index into the linker's string table.
141 sym_name: u32,
142 },
138 /// A 16-bit immediate value.143 /// A 16-bit immediate value.
139 ///144 ///
140 /// Used by e.g. svc145 /// Used by e.g. svc
...@@ -278,6 +283,7 @@ pub fn extraData(mir: Mir, comptime T: type, index: usize) struct { data: T, end...@@ -278,6 +283,7 @@ pub fn extraData(mir: Mir, comptime T: type, index: usize) struct { data: T, end
278}283}
279284
280pub const LoadMemory = struct {285pub const LoadMemory = struct {
286 atom_index: u32,
281 register: u32,287 register: u32,
282 addr: u32,288 addr: u32,
283};289};
src/arch/x86_64/CodeGen.zig+48-4
...@@ -1897,7 +1897,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -1897,7 +1897,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
1897 .reg1 = addr_reg.to64(),1897 .reg1 = addr_reg.to64(),
1898 .flags = flags,1898 .flags = flags,
1899 }).encode(),1899 }).encode(),
1900 .data = .{ .linker_sym_index = sym_index },1900 .data = .{
1901 .load_reloc = .{
1902 .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index,
1903 .sym_index = sym_index,
1904 },
1905 },
1901 });1906 });
1902 break :blk addr_reg;1907 break :blk addr_reg;
1903 },1908 },
...@@ -2670,7 +2675,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -2670,7 +2675,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
2670 _ = try self.addInst(.{2675 _ = try self.addInst(.{
2671 .tag = .call_extern,2676 .tag = .call_extern,
2672 .ops = undefined,2677 .ops = undefined,
2673 .data = .{ .extern_fn = n_strx },2678 .data = .{
2679 .extern_fn = .{
2680 .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index,
2681 .sym_name = n_strx,
2682 },
2683 },
2674 });2684 });
2675 } else {2685 } else {
2676 return self.fail("TODO implement calling bitcasted functions", .{});2686 return self.fail("TODO implement calling bitcasted functions", .{});
...@@ -3550,7 +3560,12 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE...@@ -3550,7 +3560,12 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
3550 .reg1 = addr_reg.to64(),3560 .reg1 = addr_reg.to64(),
3551 .flags = flags,3561 .flags = flags,
3552 }).encode(),3562 }).encode(),
3553 .data = .{ .linker_sym_index = sym_index },3563 .data = .{
3564 .load_reloc = .{
3565 .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index,
3566 .sym_index = sym_index,
3567 },
3568 },
3554 });3569 });
3555 break :blk addr_reg;3570 break :blk addr_reg;
3556 },3571 },
...@@ -3767,6 +3782,30 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro...@@ -3767,6 +3782,30 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
3767 const reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = addr });3782 const reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = addr });
3768 break :blk reg;3783 break :blk reg;
3769 },3784 },
3785 .direct_load,
3786 .got_load,
3787 => |sym_index| {
3788 const flags: u2 = switch (mcv) {
3789 .got_load => 0b00,
3790 .direct_load => 0b01,
3791 else => unreachable,
3792 };
3793 const addr_reg = try self.register_manager.allocReg(null);
3794 _ = try self.addInst(.{
3795 .tag = .lea_pie,
3796 .ops = (Mir.Ops{
3797 .reg1 = addr_reg.to64(),
3798 .flags = flags,
3799 }).encode(),
3800 .data = .{
3801 .load_reloc = .{
3802 .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index,
3803 .sym_index = sym_index,
3804 },
3805 },
3806 });
3807 break :blk addr_reg;
3808 },
3770 else => {3809 else => {
3771 return self.fail("TODO implement memcpy for setting stack from {}", .{mcv});3810 return self.fail("TODO implement memcpy for setting stack from {}", .{mcv});
3772 },3811 },
...@@ -4202,7 +4241,12 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -4202,7 +4241,12 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
4202 .reg1 = reg,4241 .reg1 = reg,
4203 .flags = flags,4242 .flags = flags,
4204 }).encode(),4243 }).encode(),
4205 .data = .{ .linker_sym_index = sym_index },4244 .data = .{
4245 .load_reloc = .{
4246 .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index,
4247 .sym_index = sym_index,
4248 },
4249 },
4206 });4250 });
4207 // MOV reg, [reg]4251 // MOV reg, [reg]
4208 _ = try self.addInst(.{4252 _ = try self.addInst(.{
src/arch/x86_64/Emit.zig+12-7
...@@ -763,6 +763,7 @@ fn mirLeaPie(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {...@@ -763,6 +763,7 @@ fn mirLeaPie(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
763 const tag = emit.mir.instructions.items(.tag)[inst];763 const tag = emit.mir.instructions.items(.tag)[inst];
764 assert(tag == .lea_pie);764 assert(tag == .lea_pie);
765 const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);765 const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
766 const load_reloc = emit.mir.instructions.items(.data)[inst].load_reloc;
766767
767 // lea reg1, [rip + reloc]768 // lea reg1, [rip + reloc]
768 // RM769 // RM
...@@ -772,18 +773,19 @@ fn mirLeaPie(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {...@@ -772,18 +773,19 @@ fn mirLeaPie(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
772 RegisterOrMemory.rip(Memory.PtrSize.fromBits(ops.reg1.size()), 0),773 RegisterOrMemory.rip(Memory.PtrSize.fromBits(ops.reg1.size()), 0),
773 emit.code,774 emit.code,
774 );775 );
776
775 const end_offset = emit.code.items.len;777 const end_offset = emit.code.items.len;
776 const sym_index = emit.mir.instructions.items(.data)[inst].linker_sym_index;778
777 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {779 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
778 const reloc_type = switch (ops.flags) {780 const reloc_type = switch (ops.flags) {
779 0b00 => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_GOT),781 0b00 => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_GOT),
780 0b01 => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),782 0b01 => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),
781 else => return emit.fail("TODO unused LEA PIE variants 0b10 and 0b11", .{}),783 else => return emit.fail("TODO unused LEA PIE variants 0b10 and 0b11", .{}),
782 };784 };
783 const decl = macho_file.active_decl.?;785 const atom = macho_file.atom_by_index_table.get(load_reloc.atom_index).?;
784 try decl.link.macho.relocs.append(emit.bin_file.allocator, .{786 try atom.relocs.append(emit.bin_file.allocator, .{
785 .offset = @intCast(u32, end_offset - 4),787 .offset = @intCast(u32, end_offset - 4),
786 .target = .{ .local = sym_index },788 .target = .{ .local = load_reloc.sym_index },
787 .addend = 0,789 .addend = 0,
788 .subtractor = null,790 .subtractor = null,
789 .pcrel = true,791 .pcrel = true,
...@@ -801,17 +803,20 @@ fn mirLeaPie(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {...@@ -801,17 +803,20 @@ fn mirLeaPie(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
801fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {803fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
802 const tag = emit.mir.instructions.items(.tag)[inst];804 const tag = emit.mir.instructions.items(.tag)[inst];
803 assert(tag == .call_extern);805 assert(tag == .call_extern);
804 const n_strx = emit.mir.instructions.items(.data)[inst].extern_fn;806 const extern_fn = emit.mir.instructions.items(.data)[inst].extern_fn;
807
805 const offset = blk: {808 const offset = blk: {
806 // callq809 // callq
807 try lowerToDEnc(.call_near, 0, emit.code);810 try lowerToDEnc(.call_near, 0, emit.code);
808 break :blk @intCast(u32, emit.code.items.len) - 4;811 break :blk @intCast(u32, emit.code.items.len) - 4;
809 };812 };
813
810 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {814 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
811 // Add relocation to the decl.815 // Add relocation to the decl.
812 try macho_file.active_decl.?.link.macho.relocs.append(emit.bin_file.allocator, .{816 const atom = macho_file.atom_by_index_table.get(extern_fn.atom_index).?;
817 try atom.relocs.append(emit.bin_file.allocator, .{
813 .offset = offset,818 .offset = offset,
814 .target = .{ .global = n_strx },819 .target = .{ .global = extern_fn.sym_name },
815 .addend = 0,820 .addend = 0,
816 .subtractor = null,821 .subtractor = null,
817 .pcrel = true,822 .pcrel = true,
src/arch/x86_64/Mir.zig+15-6
...@@ -185,7 +185,7 @@ pub const Inst = struct {...@@ -185,7 +185,7 @@ pub const Inst = struct {
185 /// 0b00 reg1, [rip + reloc] // via GOT emits X86_64_RELOC_GOT relocation185 /// 0b00 reg1, [rip + reloc] // via GOT emits X86_64_RELOC_GOT relocation
186 /// 0b01 reg1, [rip + reloc] // direct load emits X86_64_RELOC_SIGNED relocation186 /// 0b01 reg1, [rip + reloc] // direct load emits X86_64_RELOC_SIGNED relocation
187 /// Notes:187 /// Notes:
188 /// * `Data` contains `linker_sym_index` 188 /// * `Data` contains `load_reloc`
189 lea_pie,189 lea_pie,
190190
191 /// ops flags: form:191 /// ops flags: form:
...@@ -350,10 +350,19 @@ pub const Inst = struct {...@@ -350,10 +350,19 @@ pub const Inst = struct {
350 /// A 32-bit immediate value.350 /// A 32-bit immediate value.
351 imm: u32,351 imm: u32,
352 /// An extern function.352 /// An extern function.
353 /// Index into the linker's string table.353 extern_fn: struct {
354 extern_fn: u32,354 /// Index of the containing atom.
355 /// Entry in the linker's symbol table.355 atom_index: u32,
356 linker_sym_index: u32,356 /// Index into the linker's string table.
357 sym_name: u32,
358 },
359 /// PIE load relocation.
360 load_reloc: struct {
361 /// Index of the containing atom.
362 atom_index: u32,
363 /// Index into the linker's symbol table.
364 sym_index: u32,
365 },
357 /// Index into `extra`. Meaning of what can be found there is context-dependent.366 /// Index into `extra`. Meaning of what can be found there is context-dependent.
358 payload: u32,367 payload: u32,
359 };368 };
...@@ -362,7 +371,7 @@ pub const Inst = struct {...@@ -362,7 +371,7 @@ pub const Inst = struct {
362 // Note that in Debug builds, Zig is allowed to insert a secret field for safety checks.371 // Note that in Debug builds, Zig is allowed to insert a secret field for safety checks.
363 comptime {372 comptime {
364 if (builtin.mode != .Debug) {373 if (builtin.mode != .Debug) {
365 assert(@sizeOf(Inst) == 8);374 assert(@sizeOf(Data) == 8);
366 }375 }
367 }376 }
368};377};
src/arch/x86_64/PrintMir.zig+2-2
...@@ -450,6 +450,7 @@ fn mirLea(print: *const Print, inst: Mir.Inst.Index, w: anytype) !void {...@@ -450,6 +450,7 @@ fn mirLea(print: *const Print, inst: Mir.Inst.Index, w: anytype) !void {
450450
451fn mirLeaPie(print: *const Print, inst: Mir.Inst.Index, w: anytype) !void {451fn mirLeaPie(print: *const Print, inst: Mir.Inst.Index, w: anytype) !void {
452 const ops = Mir.Ops.decode(print.mir.instructions.items(.ops)[inst]);452 const ops = Mir.Ops.decode(print.mir.instructions.items(.ops)[inst]);
453 const load_reloc = print.mir.instructions.items(.data)[inst].load_reloc;
453 try w.print("lea {s}, ", .{@tagName(ops.reg1)});454 try w.print("lea {s}, ", .{@tagName(ops.reg1)});
454 switch (ops.reg1.size()) {455 switch (ops.reg1.size()) {
455 8 => try w.print("byte ptr ", .{}),456 8 => try w.print("byte ptr ", .{}),
...@@ -459,9 +460,8 @@ fn mirLeaPie(print: *const Print, inst: Mir.Inst.Index, w: anytype) !void {...@@ -459,9 +460,8 @@ fn mirLeaPie(print: *const Print, inst: Mir.Inst.Index, w: anytype) !void {
459 else => unreachable,460 else => unreachable,
460 }461 }
461 try w.print("[rip + 0x0] ", .{});462 try w.print("[rip + 0x0] ", .{});
462 const sym_index = print.mir.instructions.items(.data)[inst].linker_sym_index;
463 if (print.bin_file.cast(link.File.MachO)) |macho_file| {463 if (print.bin_file.cast(link.File.MachO)) |macho_file| {
464 const target = macho_file.locals.items[sym_index];464 const target = macho_file.locals.items[load_reloc.sym_index];
465 const target_name = macho_file.getString(target.n_strx);465 const target_name = macho_file.getString(target.n_strx);
466 try w.print("target@{s}", .{target_name});466 try w.print("target@{s}", .{target_name});
467 } else {467 } else {
src/link/MachO.zig+21-32
...@@ -40,6 +40,7 @@ const StringIndexContext = std.hash_map.StringIndexContext;...@@ -40,6 +40,7 @@ const StringIndexContext = std.hash_map.StringIndexContext;
40const Trie = @import("MachO/Trie.zig");40const Trie = @import("MachO/Trie.zig");
41const Type = @import("../type.zig").Type;41const Type = @import("../type.zig").Type;
42const TypedValue = @import("../TypedValue.zig");42const TypedValue = @import("../TypedValue.zig");
43const Value = @import("../value.zig").Value;
4344
44pub const TextBlock = Atom;45pub const TextBlock = Atom;
4546
...@@ -220,6 +221,7 @@ atoms: std.AutoHashMapUnmanaged(MatchingSection, *Atom) = .{},...@@ -220,6 +221,7 @@ atoms: std.AutoHashMapUnmanaged(MatchingSection, *Atom) = .{},
220/// at present owned by Module.Decl.221/// at present owned by Module.Decl.
221/// TODO consolidate this.222/// TODO consolidate this.
222managed_atoms: std.ArrayListUnmanaged(*Atom) = .{},223managed_atoms: std.ArrayListUnmanaged(*Atom) = .{},
224atom_by_index_table: std.AutoHashMapUnmanaged(u32, *Atom) = .{},
223225
224/// Table of unnamed constants associated with a parent `Decl`.226/// Table of unnamed constants associated with a parent `Decl`.
225/// We store them here so that we can free the constants whenever the `Decl`227/// We store them here so that we can free the constants whenever the `Decl`
...@@ -248,12 +250,6 @@ unnamed_const_atoms: UnnamedConstTable = .{},...@@ -248,12 +250,6 @@ unnamed_const_atoms: UnnamedConstTable = .{},
248/// TODO consolidate this.250/// TODO consolidate this.
249decls: std.AutoArrayHashMapUnmanaged(*Module.Decl, ?MatchingSection) = .{},251decls: std.AutoArrayHashMapUnmanaged(*Module.Decl, ?MatchingSection) = .{},
250252
251/// Currently active Module.Decl.
252/// TODO this might not be necessary if we figure out how to pass Module.Decl instance
253/// to codegen.genSetReg() or alternatively move PIE displacement for MCValue{ .memory = x }
254/// somewhere else in the codegen.
255active_decl: ?*Module.Decl = null,
256
257const Entry = struct {253const Entry = struct {
258 target: Atom.Relocation.Target,254 target: Atom.Relocation.Target,
259 atom: *Atom,255 atom: *Atom,
...@@ -3441,6 +3437,8 @@ pub fn deinit(self: *MachO) void {...@@ -3441,6 +3437,8 @@ pub fn deinit(self: *MachO) void {
3441 }3437 }
3442 self.unnamed_const_atoms.deinit(self.base.allocator);3438 self.unnamed_const_atoms.deinit(self.base.allocator);
3443 }3439 }
3440
3441 self.atom_by_index_table.deinit(self.base.allocator);
3444}3442}
34453443
3446pub fn closeFiles(self: MachO) void {3444pub fn closeFiles(self: MachO) void {
...@@ -3647,6 +3645,7 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {...@@ -3647,6 +3645,7 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {
3647 if (decl.link.macho.local_sym_index != 0) return;3645 if (decl.link.macho.local_sym_index != 0) return;
36483646
3649 decl.link.macho.local_sym_index = try self.allocateLocalSymbol();3647 decl.link.macho.local_sym_index = try self.allocateLocalSymbol();
3648 try self.atom_by_index_table.putNoClobber(self.base.allocator, decl.link.macho.local_sym_index, &decl.link.macho);
3650 try self.decls.putNoClobber(self.base.allocator, decl, null);3649 try self.decls.putNoClobber(self.base.allocator, decl, null);
36513650
3652 const got_target = .{ .local = decl.link.macho.local_sym_index };3651 const got_target = .{ .local = decl.link.macho.local_sym_index };
...@@ -3693,8 +3692,6 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv...@@ -3693,8 +3692,6 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
3693 }3692 }
3694 }3693 }
36953694
3696 self.active_decl = decl;
3697
3698 const res = if (debug_buffers) |dbg|3695 const res = if (debug_buffers) |dbg|
3699 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{3696 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{
3700 .dwarf = .{3697 .dwarf = .{
...@@ -3756,14 +3753,9 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De...@@ -3756,14 +3753,9 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De
3756 log.debug("allocating symbol indexes for {s}", .{name});3753 log.debug("allocating symbol indexes for {s}", .{name});
37573754
3758 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);3755 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);
3759 const match = (try self.getMatchingSection(.{
3760 .segname = makeStaticString("__TEXT"),
3761 .sectname = makeStaticString("__const"),
3762 .size = @sizeOf(u64),
3763 .@"align" = math.log2(required_alignment),
3764 })).?;
3765 const local_sym_index = try self.allocateLocalSymbol();3756 const local_sym_index = try self.allocateLocalSymbol();
3766 const atom = try self.createEmptyAtom(local_sym_index, @sizeOf(u64), math.log2(required_alignment));3757 const atom = try self.createEmptyAtom(local_sym_index, @sizeOf(u64), math.log2(required_alignment));
3758 try self.atom_by_index_table.putNoClobber(self.base.allocator, local_sym_index, atom);
37673759
3768 const res = try codegen.generateSymbol(&self.base, local_sym_index, decl.srcLoc(), typed_value, &code_buffer, .{3760 const res = try codegen.generateSymbol(&self.base, local_sym_index, decl.srcLoc(), typed_value, &code_buffer, .{
3769 .none = .{},3761 .none = .{},
...@@ -3780,6 +3772,8 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De...@@ -3780,6 +3772,8 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De
37803772
3781 atom.code.clearRetainingCapacity();3773 atom.code.clearRetainingCapacity();
3782 try atom.code.appendSlice(self.base.allocator, code);3774 try atom.code.appendSlice(self.base.allocator, code);
3775
3776 const match = try self.getMatchingSectionAtom(atom, typed_value.ty, typed_value.val);
3783 const addr = try self.allocateAtom(atom, code.len, required_alignment, match);3777 const addr = try self.allocateAtom(atom, code.len, required_alignment, match);
37843778
3785 log.debug("allocated atom for {s} at 0x{x}", .{ name, addr });3779 log.debug("allocated atom for {s} at 0x{x}", .{ name, addr });
...@@ -3839,11 +3833,9 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -3839,11 +3833,9 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
3839 }3833 }
3840 }3834 }
38413835
3842 self.active_decl = decl;
3843
3844 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;3836 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
3845 const res = if (debug_buffers) |dbg|3837 const res = if (debug_buffers) |dbg|
3846 try codegen.generateSymbol(&self.base, decl.link.elf.local_sym_index, decl.srcLoc(), .{3838 try codegen.generateSymbol(&self.base, decl.link.macho.local_sym_index, decl.srcLoc(), .{
3847 .ty = decl.ty,3839 .ty = decl.ty,
3848 .val = decl_val,3840 .val = decl_val,
3849 }, &code_buffer, .{3841 }, &code_buffer, .{
...@@ -3854,7 +3846,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -3854,7 +3846,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
3854 },3846 },
3855 })3847 })
3856 else3848 else
3857 try codegen.generateSymbol(&self.base, decl.link.elf.local_sym_index, decl.srcLoc(), .{3849 try codegen.generateSymbol(&self.base, decl.link.macho.local_sym_index, decl.srcLoc(), .{
3858 .ty = decl.ty,3850 .ty = decl.ty,
3859 .val = decl_val,3851 .val = decl_val,
3860 }, &code_buffer, .none);3852 }, &code_buffer, .none);
...@@ -3908,13 +3900,11 @@ fn isElemTyPointer(ty: Type) bool {...@@ -3908,13 +3900,11 @@ fn isElemTyPointer(ty: Type) bool {
3908 }3900 }
3909}3901}
39103902
3911fn getMatchingSectionDecl(self: *MachO, decl: *Module.Decl) !MatchingSection {3903fn getMatchingSectionAtom(self: *MachO, atom: *Atom, ty: Type, val: Value) !MatchingSection {
3912 const code = decl.link.macho.code.items;3904 const code = atom.code.items;
3913 const alignment = decl.ty.abiAlignment(self.base.options.target);3905 const alignment = ty.abiAlignment(self.base.options.target);
3914 const align_log_2 = math.log2(alignment);3906 const align_log_2 = math.log2(alignment);
3915 const ty = decl.ty;
3916 const zig_ty = ty.zigTypeTag();3907 const zig_ty = ty.zigTypeTag();
3917 const val = decl.val;
3918 const mode = self.base.options.optimize_mode;3908 const mode = self.base.options.optimize_mode;
3919 const match: MatchingSection = blk: {3909 const match: MatchingSection = blk: {
3920 // TODO finish and audit this function3910 // TODO finish and audit this function
...@@ -4023,9 +4013,11 @@ fn getMatchingSectionDecl(self: *MachO, decl: *Module.Decl) !MatchingSection {...@@ -4023,9 +4013,11 @@ fn getMatchingSectionDecl(self: *MachO, decl: *Module.Decl) !MatchingSection {
4023 },4013 },
4024 }4014 }
4025 };4015 };
4016 const local = self.locals.items[atom.local_sym_index];
4026 const seg = self.load_commands.items[match.seg].segment;4017 const seg = self.load_commands.items[match.seg].segment;
4027 const sect = seg.sections.items[match.sect];4018 const sect = seg.sections.items[match.sect];
4028 log.debug(" allocating atom in '{s},{s}' ({d},{d})", .{4019 log.debug(" allocating atom '{s}' in '{s},{s}' ({d},{d})", .{
4020 self.getString(local.n_strx),
4029 sect.segName(),4021 sect.segName(),
4030 sect.sectName(),4022 sect.sectName(),
4031 match.seg,4023 match.seg,
...@@ -4041,7 +4033,7 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64...@@ -4041,7 +4033,7 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64
40414033
4042 const decl_ptr = self.decls.getPtr(decl).?;4034 const decl_ptr = self.decls.getPtr(decl).?;
4043 if (decl_ptr.* == null) {4035 if (decl_ptr.* == null) {
4044 decl_ptr.* = try self.getMatchingSectionDecl(decl);4036 decl_ptr.* = try self.getMatchingSectionAtom(&decl.link.macho, decl.ty, decl.val);
4045 }4037 }
4046 const match = decl_ptr.*.?;4038 const match = decl_ptr.*.?;
40474039
...@@ -4290,6 +4282,8 @@ fn freeUnnamedConsts(self: *MachO, decl: *Module.Decl) void {...@@ -4290,6 +4282,8 @@ fn freeUnnamedConsts(self: *MachO, decl: *Module.Decl) void {
4290 }, true);4282 }, true);
4291 self.locals_free_list.append(self.base.allocator, atom.local_sym_index) catch {};4283 self.locals_free_list.append(self.base.allocator, atom.local_sym_index) catch {};
4292 self.locals.items[atom.local_sym_index].n_type = 0;4284 self.locals.items[atom.local_sym_index].n_type = 0;
4285 _ = self.atom_by_index_table.remove(atom.local_sym_index);
4286 atom.local_sym_index = 0;
4293 }4287 }
4294 unnamed_consts.clearAndFree(self.base.allocator);4288 unnamed_consts.clearAndFree(self.base.allocator);
4295}4289}
...@@ -4316,6 +4310,7 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {...@@ -4316,6 +4310,7 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {
4316 }4310 }
43174311
4318 self.locals.items[decl.link.macho.local_sym_index].n_type = 0;4312 self.locals.items[decl.link.macho.local_sym_index].n_type = 0;
4313 _ = self.atom_by_index_table.remove(decl.link.macho.local_sym_index);
4319 decl.link.macho.local_sym_index = 0;4314 decl.link.macho.local_sym_index = 0;
4320 }4315 }
4321 if (self.d_sym) |*ds| {4316 if (self.d_sym) |*ds| {
...@@ -4347,13 +4342,7 @@ pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl, parent_atom_index: u...@@ -4347,13 +4342,7 @@ pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl, parent_atom_index: u
4347 assert(self.llvm_object == null);4342 assert(self.llvm_object == null);
4348 assert(decl.link.macho.local_sym_index != 0);4343 assert(decl.link.macho.local_sym_index != 0);
43494344
4350 // TODO cache local_sym_index => atom!!!4345 const atom = self.atom_by_index_table.get(parent_atom_index).?;
4351 const atom: *Atom = blk: for (self.managed_atoms.items) |atom| {
4352 if (atom.local_sym_index == parent_atom_index) {
4353 break :blk atom;
4354 }
4355 } else unreachable;
4356
4357 try atom.relocs.append(self.base.allocator, .{4346 try atom.relocs.append(self.base.allocator, .{
4358 .offset = @intCast(u32, offset),4347 .offset = @intCast(u32, offset),
4359 .target = .{ .local = decl.link.macho.local_sym_index },4348 .target = .{ .local = decl.link.macho.local_sym_index },
src/link/Plan9.zig+3-1
...@@ -302,7 +302,9 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl: *Module.Decl) !void {...@@ -302,7 +302,9 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl: *Module.Decl) !void {
302 var code_buffer = std.ArrayList(u8).init(self.base.allocator);302 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
303 defer code_buffer.deinit();303 defer code_buffer.deinit();
304 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;304 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
305 const res = try codegen.generateSymbol(&self.base, @intCast(u32, decl.link.plan9.sym_index.?), decl.srcLoc(), .{305 // TODO we need the symbol index for symbol in the table of locals for the containing atom
306 const sym_index = decl.link.plan9.sym_index orelse 0;
307 const res = try codegen.generateSymbol(&self.base, @intCast(u32, sym_index), decl.srcLoc(), .{
306 .ty = decl.ty,308 .ty = decl.ty,
307 .val = decl_val,309 .val = decl_val,
308 }, &code_buffer, .{ .none = .{} });310 }, &code_buffer, .{ .none = .{} });