authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-12 12:06:49+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-13 11:47:51+02:00
logfd52d4537a86fc312e4491206228ab3aeabe0f2c
treed36e275293e26a30b623ceb2440a8826060f203e
parent1f6165f6211885d3f5392cdfcc15f990284159de

x86_64: emit pointer to TLV for macho


5 files changed, 68 insertions(+), 3 deletions(-)

src/arch/aarch64/CodeGen.zig+4
...@@ -3982,6 +3982,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -3982,6 +3982,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3982 .got => .load_memory_ptr_got,3982 .got => .load_memory_ptr_got,
3983 .direct => .load_memory_ptr_direct,3983 .direct => .load_memory_ptr_direct,
3984 .import => unreachable,3984 .import => unreachable,
3985 .tlv => @panic("TODO TLV support"),
3985 };3986 };
3986 const atom_index = switch (self.bin_file.tag) {3987 const atom_index = switch (self.bin_file.tag) {
3987 .macho => blk: {3988 .macho => blk: {
...@@ -5510,6 +5511,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -5510,6 +5511,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5510 .got => .load_memory_ptr_got,5511 .got => .load_memory_ptr_got,
5511 .direct => .load_memory_ptr_direct,5512 .direct => .load_memory_ptr_direct,
5512 .import => unreachable,5513 .import => unreachable,
5514 .tlv => @panic("TODO TLV support"),
5513 };5515 };
5514 const atom_index = switch (self.bin_file.tag) {5516 const atom_index = switch (self.bin_file.tag) {
5515 .macho => blk: {5517 .macho => blk: {
...@@ -5630,6 +5632,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -5630,6 +5632,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
5630 .got => .load_memory_got,5632 .got => .load_memory_got,
5631 .direct => .load_memory_direct,5633 .direct => .load_memory_direct,
5632 .import => .load_memory_import,5634 .import => .load_memory_import,
5635 .tlv => @panic("TODO TLV support"),
5633 };5636 };
5634 const atom_index = switch (self.bin_file.tag) {5637 const atom_index = switch (self.bin_file.tag) {
5635 .macho => blk: {5638 .macho => blk: {
...@@ -5830,6 +5833,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -5830,6 +5833,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5830 .got => .load_memory_ptr_got,5833 .got => .load_memory_ptr_got,
5831 .direct => .load_memory_ptr_direct,5834 .direct => .load_memory_ptr_direct,
5832 .import => unreachable,5835 .import => unreachable,
5836 .tlv => @panic("TODO TLV support"),
5833 };5837 };
5834 const atom_index = switch (self.bin_file.tag) {5838 const atom_index = switch (self.bin_file.tag) {
5835 .macho => blk: {5839 .macho => blk: {
src/arch/x86_64/CodeGen.zig+55-2
...@@ -736,6 +736,7 @@ fn asmMovLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege...@@ -736,6 +736,7 @@ fn asmMovLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege
736 .got => .got_reloc,736 .got => .got_reloc,
737 .direct => .direct_reloc,737 .direct => .direct_reloc,
738 .import => .import_reloc,738 .import => .import_reloc,
739 .tlv => .tlv_reloc,
739 };740 };
740 _ = try self.addInst(.{741 _ = try self.addInst(.{
741 .tag = .mov_linker,742 .tag = .mov_linker,
...@@ -753,6 +754,7 @@ fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege...@@ -753,6 +754,7 @@ fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege
753 .got => .got_reloc,754 .got => .got_reloc,
754 .direct => .direct_reloc,755 .direct => .direct_reloc,
755 .import => .import_reloc,756 .import => .import_reloc,
757 .tlv => .tlv_reloc,
756 };758 };
757 _ = try self.addInst(.{759 _ = try self.addInst(.{
758 .tag = .lea_linker,760 .tag = .lea_linker,
...@@ -765,6 +767,15 @@ fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege...@@ -765,6 +767,15 @@ fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege
765 });767 });
766}768}
767769
770fn genTlvPtr(self: *Self, reg: Register, atom_index: u32, linker_load: codegen.LinkerLoad) !void {
771 assert(linker_load.type == .tlv);
772 if (self.bin_file.cast(link.File.MachO)) |_| {
773 try self.asmMovLinker(.rdi, atom_index, linker_load);
774 try self.asmMemory(.call, Memory.sib(.qword, .{ .base = .rdi }));
775 try self.genSetReg(Type.usize, reg, .{ .register = .rax });
776 } else return self.fail("TODO emit ptr-to-TLV sequence on {s}", .{@tagName(self.bin_file.tag)});
777}
778
768fn gen(self: *Self) InnerError!void {779fn gen(self: *Self) InnerError!void {
769 const cc = self.fn_type.fnCallingConvention();780 const cc = self.fn_type.fnCallingConvention();
770 if (cc != .Naked) {781 if (cc != .Naked) {
...@@ -2931,6 +2942,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2931,6 +2942,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
2931 .import => unreachable,2942 .import => unreachable,
2932 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),2943 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
2933 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),2944 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
2945 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
2934 }2946 }
2935 },2947 },
2936 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),2948 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
...@@ -3805,6 +3817,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -3805,6 +3817,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3805 .import => unreachable,3817 .import => unreachable,
3806 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),3818 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
3807 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),3819 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
3820 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
3808 }3821 }
3809 },3822 },
3810 else => unreachable,3823 else => unreachable,
...@@ -3866,6 +3879,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -3866,6 +3879,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3866 switch (load_struct.type) {3879 switch (load_struct.type) {
3867 .import => unreachable,3880 .import => unreachable,
3868 .got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct),3881 .got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct),
3882 .tlv => {
3883 try self.genTlvPtr(addr_reg, atom_index, load_struct);
3884 // Load the pointer, which is stored in memory
3885 try self.asmRegisterMemory(.mov, addr_reg, Memory.sib(.qword, .{ .base = addr_reg }));
3886 },
3869 }3887 }
3870 },3888 },
3871 else => unreachable,3889 else => unreachable,
...@@ -4221,6 +4239,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue...@@ -4221,6 +4239,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue
4221 .import => unreachable,4239 .import => unreachable,
4222 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),4240 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
4223 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),4241 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
4242 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
4224 }4243 }
4225 },4244 },
4226 else => unreachable,4245 else => unreachable,
...@@ -4896,6 +4915,7 @@ fn genBinOp(...@@ -4896,6 +4915,7 @@ fn genBinOp(
4896 .import => unreachable,4915 .import => unreachable,
4897 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),4916 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
4898 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),4917 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
4918 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
4899 }4919 }
4900 },4920 },
4901 else => unreachable,4921 else => unreachable,
...@@ -5042,6 +5062,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s...@@ -5042,6 +5062,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5042 .import => unreachable,5062 .import => unreachable,
5043 .got => try self.asmMovLinker(dst_addr_reg, atom_index, load_struct),5063 .got => try self.asmMovLinker(dst_addr_reg, atom_index, load_struct),
5044 .direct => try self.asmLeaLinker(dst_addr_reg, atom_index, load_struct),5064 .direct => try self.asmLeaLinker(dst_addr_reg, atom_index, load_struct),
5065 .tlv => try self.genTlvPtr(dst_addr_reg, atom_index, load_struct),
5045 }5066 }
5046 },5067 },
5047 else => unreachable,5068 else => unreachable,
...@@ -5087,6 +5108,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s...@@ -5087,6 +5108,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5087 .import => unreachable,5108 .import => unreachable,
5088 .got => try self.asmMovLinker(src_addr_reg, atom_index, load_struct),5109 .got => try self.asmMovLinker(src_addr_reg, atom_index, load_struct),
5089 .direct => try self.asmLeaLinker(src_addr_reg, atom_index, load_struct),5110 .direct => try self.asmLeaLinker(src_addr_reg, atom_index, load_struct),
5111 .tlv => try self.genTlvPtr(src_addr_reg, atom_index, load_struct),
5090 }5112 }
5091 },5113 },
5092 else => unreachable,5114 else => unreachable,
...@@ -6124,6 +6146,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -6124,6 +6146,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
6124 .import => unreachable,6146 .import => unreachable,
6125 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),6147 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
6126 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),6148 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
6149 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
6127 }6150 }
6128 },6151 },
6129 else => unreachable,6152 else => unreachable,
...@@ -7081,6 +7104,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE...@@ -7081,6 +7104,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
7081 .import => unreachable,7104 .import => unreachable,
7082 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),7105 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
7083 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),7106 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
7107 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
7084 }7108 }
7085 },7109 },
7086 else => unreachable,7110 else => unreachable,
...@@ -7308,6 +7332,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl...@@ -7308,6 +7332,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
7308 .import => unreachable,7332 .import => unreachable,
7309 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),7333 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
7310 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),7334 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
7335 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
7311 }7336 }
7312 },7337 },
7313 else => unreachable,7338 else => unreachable,
...@@ -7439,6 +7464,11 @@ fn genInlineMemcpy(...@@ -7439,6 +7464,11 @@ fn genInlineMemcpy(
7439 switch (load_struct.type) {7464 switch (load_struct.type) {
7440 .import => unreachable,7465 .import => unreachable,
7441 .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),7466 .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),
7467 .tlv => {
7468 try self.genTlvPtr(.rdi, atom_index, load_struct);
7469 // Load the pointer, which is stored in memory
7470 try self.asmRegisterMemory(.mov, .rdi, Memory.sib(.qword, .{ .base = .rdi }));
7471 },
7442 }7472 }
7443 },7473 },
7444 .stack_offset, .ptr_stack_offset => |off| {7474 .stack_offset, .ptr_stack_offset => |off| {
...@@ -7481,6 +7511,11 @@ fn genInlineMemcpy(...@@ -7481,6 +7511,11 @@ fn genInlineMemcpy(
7481 switch (load_struct.type) {7511 switch (load_struct.type) {
7482 .import => unreachable,7512 .import => unreachable,
7483 .got, .direct => try self.asmMovLinker(.rsi, atom_index, load_struct),7513 .got, .direct => try self.asmMovLinker(.rsi, atom_index, load_struct),
7514 .tlv => {
7515 try self.genTlvPtr(.rsi, atom_index, load_struct);
7516 // Load the pointer, which is stored in memory
7517 try self.asmRegisterMemory(.mov, .rsi, Memory.sib(.qword, .{ .base = .rsi }));
7518 },
7484 }7519 }
7485 },7520 },
7486 .stack_offset, .ptr_stack_offset => |off| {7521 .stack_offset, .ptr_stack_offset => |off| {
...@@ -7546,6 +7581,11 @@ fn genInlineMemset(...@@ -7546,6 +7581,11 @@ fn genInlineMemset(
7546 switch (load_struct.type) {7581 switch (load_struct.type) {
7547 .import => unreachable,7582 .import => unreachable,
7548 .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),7583 .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),
7584 .tlv => {
7585 try self.genTlvPtr(.rdi, atom_index, load_struct);
7586 // Load the pointer, which is stored in memory
7587 try self.asmRegisterMemory(.mov, .rdi, Memory.sib(.qword, .{ .base = .rdi }));
7588 },
7549 }7589 }
7550 },7590 },
7551 .stack_offset, .ptr_stack_offset => |off| {7591 .stack_offset, .ptr_stack_offset => |off| {
...@@ -7735,7 +7775,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -7735,7 +7775,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
7735 switch (ty.zigTypeTag()) {7775 switch (ty.zigTypeTag()) {
7736 .Float => {7776 .Float => {
7737 const base_reg = (try self.register_manager.allocReg(null, gp)).to64();7777 const base_reg = (try self.register_manager.allocReg(null, gp)).to64();
7738 try self.asmLeaLinker(base_reg, atom_index, load_struct);7778 switch (load_struct.type) {
7779 .tlv => try self.genTlvPtr(base_reg, atom_index, load_struct),
7780 else => try self.asmLeaLinker(base_reg, atom_index, load_struct),
7781 }
77397782
7740 if (intrinsicsAllowed(self.target.*, ty)) {7783 if (intrinsicsAllowed(self.target.*, ty)) {
7741 return self.asmRegisterMemory(7784 return self.asmRegisterMemory(
...@@ -7753,7 +7796,17 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -7753,7 +7796,17 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
77537796
7754 return self.fail("TODO genSetReg from memory for float with no intrinsics", .{});7797 return self.fail("TODO genSetReg from memory for float with no intrinsics", .{});
7755 },7798 },
7756 else => try self.asmMovLinker(registerAlias(reg, abi_size), atom_index, load_struct),7799 else => switch (load_struct.type) {
7800 .tlv => {
7801 try self.genTlvPtr(reg.to64(), atom_index, load_struct);
7802 try self.asmRegisterMemory(
7803 .mov,
7804 registerAlias(reg, abi_size),
7805 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }),
7806 );
7807 },
7808 else => try self.asmMovLinker(registerAlias(reg, abi_size), atom_index, load_struct),
7809 },
7757 }7810 }
7758 },7811 },
7759 .stack_offset => |off| {7812 .stack_offset => |off| {
src/arch/x86_64/Emit.zig+1
...@@ -76,6 +76,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -76,6 +76,7 @@ pub fn emitMir(emit: *Emit) Error!void {
76 .type = switch (inst.ops) {76 .type = switch (inst.ops) {
77 .got_reloc => .got,77 .got_reloc => .got,
78 .direct_reloc => .signed,78 .direct_reloc => .signed,
79 .tlv_reloc => .tlv,
79 else => unreachable,80 else => unreachable,
80 },81 },
81 .target = .{ .sym_index = metadata.sym_index, .file = null },82 .target = .{ .sym_index = metadata.sym_index, .file = null },
src/arch/x86_64/Mir.zig+3
...@@ -404,6 +404,9 @@ pub const Inst = struct {...@@ -404,6 +404,9 @@ pub const Inst = struct {
404 /// Linker relocation - imports table indirection (binding).404 /// Linker relocation - imports table indirection (binding).
405 /// Uses `payload` payload with extra data of type `LeaRegisterReloc`.405 /// Uses `payload` payload with extra data of type `LeaRegisterReloc`.
406 import_reloc,406 import_reloc,
407 /// Linker relocation - threadlocal variable via GOT indirection.
408 /// Uses `payload` payload with extra data of type `LeaRegisterReloc`.
409 tlv_reloc,
407 };410 };
408411
409 pub const Data = union {412 pub const Data = union {
src/codegen.zig+5-1
...@@ -912,11 +912,13 @@ fn lowerDeclRef(...@@ -912,11 +912,13 @@ fn lowerDeclRef(
912/// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)912/// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
913/// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)913/// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
914/// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)914/// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
915/// * tlv - the value is a threadlocal variable referenced indirectly via GOT (the linker emits a got-type reloc)
915pub const LinkerLoad = struct {916pub const LinkerLoad = struct {
916 type: enum {917 type: enum {
917 got,918 got,
918 direct,919 direct,
919 import,920 import,
921 tlv,
920 },922 },
921 sym_index: u32,923 sym_index: u32,
922};924};
...@@ -991,6 +993,8 @@ fn genDeclRef(...@@ -991,6 +993,8 @@ fn genDeclRef(
991993
992 module.markDeclAlive(decl);994 module.markDeclAlive(decl);
993995
996 const is_threadlocal = tv.val.isPtrToThreadLocal(module) and !bin_file.options.single_threaded;
997
994 if (bin_file.cast(link.File.Elf)) |elf_file| {998 if (bin_file.cast(link.File.Elf)) |elf_file| {
995 const atom_index = try elf_file.getOrCreateAtomForDecl(decl_index);999 const atom_index = try elf_file.getOrCreateAtomForDecl(decl_index);
996 const atom = elf_file.getAtom(atom_index);1000 const atom = elf_file.getAtom(atom_index);
...@@ -999,7 +1003,7 @@ fn genDeclRef(...@@ -999,7 +1003,7 @@ fn genDeclRef(
999 const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);1003 const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);
1000 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;1004 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
1001 return GenResult.mcv(.{ .linker_load = .{1005 return GenResult.mcv(.{ .linker_load = .{
1002 .type = .got,1006 .type = if (is_threadlocal) .tlv else .got,
1003 .sym_index = sym_index,1007 .sym_index = sym_index,
1004 } });1008 } });
1005 } else if (bin_file.cast(link.File.Coff)) |coff_file| {1009 } else if (bin_file.cast(link.File.Coff)) |coff_file| {