authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-13 16:09:47+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-13 16:35:45+02:00
log3f35d6984fa7e90a86cae3d6769cc2f1036bbdde
treeb27744b59fa8979ea258d72375c334e45a706546
parent887da399eb266b166d1a109bdfe631f4533ead64

x86_64: make TLV a separate MCValue


6 files changed, 72 insertions(+), 69 deletions(-)

src/arch/aarch64/CodeGen.zig+1-4
......@@ -3982,7 +3982,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
39823982 .got => .load_memory_ptr_got,
39833983 .direct => .load_memory_ptr_direct,
39843984 .import => unreachable,
3985 .tlv => @panic("TODO TLV support"),
39863985 };
39873986 const atom_index = switch (self.bin_file.tag) {
39883987 .macho => blk: {
......@@ -5511,7 +5510,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
55115510 .got => .load_memory_ptr_got,
55125511 .direct => .load_memory_ptr_direct,
55135512 .import => unreachable,
5514 .tlv => @panic("TODO TLV support"),
55155513 };
55165514 const atom_index = switch (self.bin_file.tag) {
55175515 .macho => blk: {
......@@ -5632,7 +5630,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
56325630 .got => .load_memory_got,
56335631 .direct => .load_memory_direct,
56345632 .import => .load_memory_import,
5635 .tlv => @panic("TODO TLV support"),
56365633 };
56375634 const atom_index = switch (self.bin_file.tag) {
56385635 .macho => blk: {
......@@ -5833,7 +5830,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
58335830 .got => .load_memory_ptr_got,
58345831 .direct => .load_memory_ptr_direct,
58355832 .import => unreachable,
5836 .tlv => @panic("TODO TLV support"),
58375833 };
58385834 const atom_index = switch (self.bin_file.tag) {
58395835 .macho => blk: {
......@@ -6175,6 +6171,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
61756171 .linker_load => |ll| .{ .linker_load = ll },
61766172 .immediate => |imm| .{ .immediate = imm },
61776173 .memory => |addr| .{ .memory = addr },
6174 .tlv_reloc => unreachable, // TODO
61786175 },
61796176 .fail => |msg| {
61806177 self.err_msg = msg;
src/arch/arm/CodeGen.zig+1-1
......@@ -6114,7 +6114,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
61146114 .mcv => |mcv| switch (mcv) {
61156115 .none => .none,
61166116 .undef => .undef,
6117 .linker_load => unreachable, // TODO
6117 .tlv_reloc, .linker_load => unreachable, // TODO
61186118 .immediate => |imm| .{ .immediate = @truncate(u32, imm) },
61196119 .memory => |addr| .{ .memory = addr },
61206120 },
src/arch/riscv64/CodeGen.zig+1-1
......@@ -2572,7 +2572,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
25722572 .mcv => |mcv| switch (mcv) {
25732573 .none => .none,
25742574 .undef => .undef,
2575 .linker_load => unreachable, // TODO
2575 .tlv_reloc, .linker_load => unreachable, // TODO
25762576 .immediate => |imm| .{ .immediate = imm },
25772577 .memory => |addr| .{ .memory = addr },
25782578 },
src/arch/sparc64/CodeGen.zig+1-1
......@@ -3931,7 +3931,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
39313931 .mcv => |mcv| switch (mcv) {
39323932 .none => .none,
39333933 .undef => .undef,
3934 .linker_load => unreachable, // TODO
3934 .tlv_reloc, .linker_load => unreachable, // TODO
39353935 .immediate => |imm| .{ .immediate = imm },
39363936 .memory => |addr| .{ .memory = addr },
39373937 },
src/arch/x86_64/CodeGen.zig+60-59
......@@ -132,6 +132,10 @@ pub const MCValue = union(enum) {
132132 memory: u64,
133133 /// The value is in memory but requires a linker relocation fixup.
134134 linker_load: codegen.LinkerLoad,
135 /// Pointer to a threadlocal variable.
136 /// The address resolution will be deferred until the linker allocates everything in virtual memory.
137 /// Payload is a symbol index.
138 tlv_reloc: u32,
135139 /// The value is one of the stack variables.
136140 /// If the type is a pointer, it means the pointer address is in the stack at this offset.
137141 stack_offset: i32,
......@@ -146,6 +150,7 @@ pub const MCValue = union(enum) {
146150 .stack_offset,
147151 .ptr_stack_offset,
148152 .linker_load,
153 .tlv_reloc,
149154 => true,
150155 else => false,
151156 };
......@@ -736,7 +741,6 @@ fn asmMovLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege
736741 .got => .got_reloc,
737742 .direct => .direct_reloc,
738743 .import => .import_reloc,
739 .tlv => .tlv_reloc,
740744 };
741745 _ = try self.addInst(.{
742746 .tag = .mov_linker,
......@@ -754,7 +758,6 @@ fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege
754758 .got => .got_reloc,
755759 .direct => .direct_reloc,
756760 .import => .import_reloc,
757 .tlv => .tlv_reloc,
758761 };
759762 _ = try self.addInst(.{
760763 .tag = .lea_linker,
......@@ -767,15 +770,6 @@ fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege
767770 });
768771}
769772
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
779773fn gen(self: *Self) InnerError!void {
780774 const cc = self.fn_type.fnCallingConvention();
781775 if (cc != .Naked) {
......@@ -2929,6 +2923,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
29292923 }));
29302924 },
29312925 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),
2926 .tlv_reloc => try self.genSetReg(array_ty, addr_reg, array),
29322927 .linker_load => |load_struct| {
29332928 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
29342929 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
......@@ -2942,7 +2937,6 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
29422937 .import => unreachable,
29432938 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
29442939 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
2945 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
29462940 }
29472941 },
29482942 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
......@@ -3656,7 +3650,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
36563650 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),
36573651 }
36583652 },
3659 .memory => {
3653 .memory, .tlv_reloc => {
36603654 const reg = try self.copyToTmpRegister(ptr_ty, ptr);
36613655 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
36623656 },
......@@ -3676,7 +3670,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
36763670 switch (load_struct.type) {
36773671 .import => unreachable,
36783672 .got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct),
3679 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
36803673 }
36813674
36823675 try self.load(dst_mcv, .{ .register = addr_reg }, ptr_ty);
......@@ -3838,7 +3831,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
38383831 .import => unreachable,
38393832 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
38403833 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
3841 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
38423834 }
38433835 },
38443836 else => unreachable,
......@@ -3863,7 +3855,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
38633855 .{ .immediate = abi_size },
38643856 .{},
38653857 ),
3866 .ptr_stack_offset => {
3858 .ptr_stack_offset, .tlv_reloc => {
38673859 const tmp_reg = try self.copyToTmpRegister(value_ty, value);
38683860 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
38693861 defer self.register_manager.unlockReg(tmp_lock);
......@@ -3900,12 +3892,19 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
39003892 switch (load_struct.type) {
39013893 .import => unreachable,
39023894 .got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct),
3903 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
39043895 }
39053896 },
39063897 else => unreachable,
39073898 }
39083899
3900 const new_ptr = MCValue{ .register = addr_reg };
3901 try self.store(new_ptr, value, ptr_ty, value_ty);
3902 },
3903 .tlv_reloc => {
3904 const addr_reg = try self.copyToTmpRegister(Type.usize, ptr);
3905 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
3906 defer self.register_manager.unlockReg(addr_reg_lock);
3907
39093908 const new_ptr = MCValue{ .register = addr_reg };
39103909 try self.store(new_ptr, value, ptr_ty, value_ty);
39113910 },
......@@ -3954,7 +3953,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32
39543953
39553954 const dst_mcv: MCValue = result: {
39563955 switch (mcv) {
3957 .stack_offset => {
3956 .stack_offset, .tlv_reloc => {
39583957 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{
39593958 .immediate = field_offset,
39603959 });
......@@ -4236,6 +4235,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue
42364235 }));
42374236 },
42384237 .ptr_stack_offset => unreachable,
4238 .tlv_reloc => unreachable,
42394239 .memory, .linker_load => {
42404240 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
42414241 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
......@@ -4256,7 +4256,6 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue
42564256 .import => unreachable,
42574257 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
42584258 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
4259 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
42604259 }
42614260 },
42624261 else => unreachable,
......@@ -4898,6 +4897,7 @@ fn genBinOp(
48984897 .eflags,
48994898 .register_overflow,
49004899 .ptr_stack_offset,
4900 .tlv_reloc,
49014901 => unreachable,
49024902 .register => |src_reg| try self.asmCmovccRegisterRegister(
49034903 registerAlias(tmp_reg, cmov_abi_size),
......@@ -4932,7 +4932,6 @@ fn genBinOp(
49324932 .import => unreachable,
49334933 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
49344934 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
4935 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
49364935 }
49374936 },
49384937 else => unreachable,
......@@ -4983,7 +4982,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
49834982 .undef => unreachable,
49844983 .dead, .unreach => unreachable,
49854984 .register_overflow => unreachable,
4986 .ptr_stack_offset => {
4985 .ptr_stack_offset, .tlv_reloc => {
49874986 const dst_reg_lock = self.register_manager.lockReg(dst_reg);
49884987 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
49894988
......@@ -5079,7 +5078,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
50795078 .import => unreachable,
50805079 .got => try self.asmMovLinker(dst_addr_reg, atom_index, load_struct),
50815080 .direct => try self.asmLeaLinker(dst_addr_reg, atom_index, load_struct),
5082 .tlv => try self.genTlvPtr(dst_addr_reg, atom_index, load_struct),
50835081 }
50845082 },
50855083 else => unreachable,
......@@ -5125,7 +5123,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
51255123 .import => unreachable,
51265124 .got => try self.asmMovLinker(src_addr_reg, atom_index, load_struct),
51275125 .direct => try self.asmLeaLinker(src_addr_reg, atom_index, load_struct),
5128 .tlv => try self.genTlvPtr(src_addr_reg, atom_index, load_struct),
51295126 }
51305127 },
51315128 else => unreachable,
......@@ -5236,7 +5233,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
52365233 else => unreachable,
52375234 }
52385235 },
5239 .memory, .linker_load => {
5236 .memory, .linker_load, .tlv_reloc => {
52405237 try self.asmRegisterMemory(
52415238 .mov,
52425239 registerAlias(src.?.limb_reg, limb_abi_size),
......@@ -5275,6 +5272,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
52755272 }
52765273 },
52775274 .ptr_stack_offset => unreachable,
5275 .tlv_reloc => unreachable,
52785276 }
52795277}
52805278
......@@ -5288,6 +5286,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
52885286 .dead, .unreach, .immediate => unreachable,
52895287 .eflags => unreachable,
52905288 .ptr_stack_offset => unreachable,
5289 .tlv_reloc => unreachable,
52915290 .register_overflow => unreachable,
52925291 .register => |dst_reg| {
52935292 const dst_alias = registerAlias(dst_reg, abi_size);
......@@ -5299,6 +5298,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
52995298 .undef => try self.genSetReg(dst_ty, dst_reg, .undef),
53005299 .dead, .unreach => unreachable,
53015300 .ptr_stack_offset => unreachable,
5301 .tlv_reloc => unreachable,
53025302 .register_overflow => unreachable,
53035303 .register => |src_reg| try self.asmRegisterRegister(
53045304 .imul,
......@@ -5342,6 +5342,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
53425342 .undef => return self.genSetStack(dst_ty, off, .undef, .{}),
53435343 .dead, .unreach => unreachable,
53445344 .ptr_stack_offset => unreachable,
5345 .tlv_reloc => unreachable,
53455346 .register_overflow => unreachable,
53465347 .register => |src_reg| {
53475348 // copy dst to a register
......@@ -5564,6 +5565,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
55645565 .linker_load => unreachable,
55655566 .eflags => unreachable,
55665567 .register_overflow => unreachable,
5568 .tlv_reloc => unreachable,
55675569 }
55685570 }
55695571
......@@ -5602,6 +5604,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
56025604 .linker_load => unreachable,
56035605 .eflags => unreachable,
56045606 .register_overflow => unreachable,
5607 .tlv_reloc => unreachable,
56055608 }
56065609 }
56075610
......@@ -6123,6 +6126,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
61236126 .register_overflow,
61246127 .ptr_stack_offset,
61256128 .eflags,
6129 .tlv_reloc,
61266130 => unreachable,
61276131
61286132 .register => |opt_reg| {
......@@ -6163,7 +6167,6 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
61636167 .import => unreachable,
61646168 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
61656169 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
6166 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
61676170 }
61686171 },
61696172 else => unreachable,
......@@ -7121,7 +7124,6 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
71217124 .import => unreachable,
71227125 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
71237126 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
7124 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
71257127 }
71267128 },
71277129 else => unreachable,
......@@ -7168,7 +7170,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
71687170 },
71697171 }
71707172 },
7171 .ptr_stack_offset => {
7173 .ptr_stack_offset, .tlv_reloc => {
71727174 const reg = try self.copyToTmpRegister(ty, mcv);
71737175 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
71747176 },
......@@ -7349,7 +7351,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
73497351 .import => unreachable,
73507352 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
73517353 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
7352 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
73537354 }
73547355 },
73557356 else => unreachable,
......@@ -7374,7 +7375,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
73747375 .{ .immediate = abi_size },
73757376 .{},
73767377 ),
7377 .ptr_stack_offset => {
7378 .ptr_stack_offset, .tlv_reloc => {
73787379 const tmp_reg = try self.copyToTmpRegister(ty, mcv);
73797380 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
73807381 defer self.register_manager.unlockReg(tmp_lock);
......@@ -7481,13 +7482,9 @@ fn genInlineMemcpy(
74817482 switch (load_struct.type) {
74827483 .import => unreachable,
74837484 .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),
7484 .tlv => {
7485 try self.genTlvPtr(.rdi, atom_index, load_struct);
7486 // Load the pointer, which is stored in memory
7487 try self.asmRegisterMemory(.mov, .rdi, Memory.sib(.qword, .{ .base = .rdi }));
7488 },
74897485 }
74907486 },
7487 .tlv_reloc => try self.genSetReg(Type.usize, .rdi, dst_ptr),
74917488 .stack_offset, .ptr_stack_offset => |off| {
74927489 try self.asmRegisterMemory(switch (dst_ptr) {
74937490 .stack_offset => .mov,
......@@ -7528,13 +7525,9 @@ fn genInlineMemcpy(
75287525 switch (load_struct.type) {
75297526 .import => unreachable,
75307527 .got, .direct => try self.asmMovLinker(.rsi, atom_index, load_struct),
7531 .tlv => {
7532 try self.genTlvPtr(.rsi, atom_index, load_struct);
7533 // Load the pointer, which is stored in memory
7534 try self.asmRegisterMemory(.mov, .rsi, Memory.sib(.qword, .{ .base = .rsi }));
7535 },
75367528 }
75377529 },
7530 .tlv_reloc => try self.genSetReg(Type.usize, .rsi, src_ptr),
75387531 .stack_offset, .ptr_stack_offset => |off| {
75397532 try self.asmRegisterMemory(switch (src_ptr) {
75407533 .stack_offset => .mov,
......@@ -7598,13 +7591,9 @@ fn genInlineMemset(
75987591 switch (load_struct.type) {
75997592 .import => unreachable,
76007593 .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),
7601 .tlv => {
7602 try self.genTlvPtr(.rdi, atom_index, load_struct);
7603 // Load the pointer, which is stored in memory
7604 try self.asmRegisterMemory(.mov, .rdi, Memory.sib(.qword, .{ .base = .rdi }));
7605 },
76067594 }
76077595 },
7596 .tlv_reloc => try self.genSetReg(Type.usize, .rdi, dst_ptr),
76087597 .stack_offset, .ptr_stack_offset => |off| {
76097598 try self.asmRegisterMemory(switch (dst_ptr) {
76107599 .stack_offset => .mov,
......@@ -7780,6 +7769,30 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
77807769 }
77817770 },
77827771 },
7772 .tlv_reloc => |sym_index| {
7773 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
7774 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
7775 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
7776 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {
7777 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
7778 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
7779 } else unreachable;
7780
7781 if (self.bin_file.cast(link.File.MachO)) |_| {
7782 _ = try self.addInst(.{
7783 .tag = .mov_linker,
7784 .ops = .tlv_reloc,
7785 .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{
7786 .reg = @enumToInt(Register.rdi),
7787 .atom_index = atom_index,
7788 .sym_index = sym_index,
7789 }) },
7790 });
7791 // TODO: spill registers before calling
7792 try self.asmMemory(.call, Memory.sib(.qword, .{ .base = .rdi }));
7793 try self.genSetReg(Type.usize, reg, .{ .register = .rax });
7794 } else return self.fail("TODO emit ptr to TLV sequence on {s}", .{@tagName(self.bin_file.tag)});
7795 },
77837796 .linker_load => |load_struct| {
77847797 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
77857798 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
......@@ -7792,10 +7805,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
77927805 switch (ty.zigTypeTag()) {
77937806 .Float => {
77947807 const base_reg = (try self.register_manager.allocReg(null, gp)).to64();
7795 switch (load_struct.type) {
7796 .tlv => try self.genTlvPtr(base_reg, atom_index, load_struct),
7797 else => try self.asmLeaLinker(base_reg, atom_index, load_struct),
7798 }
7808 try self.asmLeaLinker(base_reg, atom_index, load_struct);
77997809
78007810 if (intrinsicsAllowed(self.target.*, ty)) {
78017811 return self.asmRegisterMemory(
......@@ -7813,17 +7823,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
78137823
78147824 return self.fail("TODO genSetReg from memory for float with no intrinsics", .{});
78157825 },
7816 else => switch (load_struct.type) {
7817 .tlv => {
7818 try self.genTlvPtr(reg.to64(), atom_index, load_struct);
7819 try self.asmRegisterMemory(
7820 .mov,
7821 registerAlias(reg, abi_size),
7822 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }),
7823 );
7824 },
7825 else => try self.asmMovLinker(registerAlias(reg, abi_size), atom_index, load_struct),
7826 },
7826 else => try self.asmMovLinker(registerAlias(reg, abi_size), atom_index, load_struct),
78277827 }
78287828 },
78297829 .stack_offset => |off| {
......@@ -8779,6 +8779,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
87798779 .linker_load => |ll| .{ .linker_load = ll },
87808780 .immediate => |imm| .{ .immediate = imm },
87818781 .memory => |addr| .{ .memory = addr },
8782 .tlv_reloc => |sym_index| .{ .tlv_reloc = sym_index },
87828783 },
87838784 .fail => |msg| {
87848785 self.err_msg = msg;
src/codegen.zig+8-3
......@@ -912,13 +912,11 @@ fn lowerDeclRef(
912912/// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
913913/// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
914914/// * 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)
916915pub const LinkerLoad = struct {
917916 type: enum {
918917 got,
919918 direct,
920919 import,
921 tlv,
922920 },
923921 sym_index: u32,
924922};
......@@ -934,6 +932,10 @@ pub const GenResult = union(enum) {
934932 /// such as ARM, the immediate will never exceed 32-bits.
935933 immediate: u64,
936934 linker_load: LinkerLoad,
935 /// Pointer to a threadlocal variable.
936 /// The address resolution will be deferred until the linker allocates everything in virtual memory.
937 /// Payload is a symbol index.
938 tlv_reloc: u32,
937939 /// Direct by-address reference to memory location.
938940 memory: u64,
939941 };
......@@ -1002,8 +1004,11 @@ fn genDeclRef(
10021004 } else if (bin_file.cast(link.File.MachO)) |macho_file| {
10031005 const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);
10041006 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
1007 if (is_threadlocal) {
1008 return GenResult.mcv(.{ .tlv_reloc = sym_index });
1009 }
10051010 return GenResult.mcv(.{ .linker_load = .{
1006 .type = if (is_threadlocal) .tlv else .got,
1011 .type = .got,
10071012 .sym_index = sym_index,
10081013 } });
10091014 } else if (bin_file.cast(link.File.Coff)) |coff_file| {