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...@@ -3982,7 +3982,6 @@ 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"),
3986 };3985 };
3987 const atom_index = switch (self.bin_file.tag) {3986 const atom_index = switch (self.bin_file.tag) {
3988 .macho => blk: {3987 .macho => blk: {
...@@ -5511,7 +5510,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -5511,7 +5510,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5511 .got => .load_memory_ptr_got,5510 .got => .load_memory_ptr_got,
5512 .direct => .load_memory_ptr_direct,5511 .direct => .load_memory_ptr_direct,
5513 .import => unreachable,5512 .import => unreachable,
5514 .tlv => @panic("TODO TLV support"),
5515 };5513 };
5516 const atom_index = switch (self.bin_file.tag) {5514 const atom_index = switch (self.bin_file.tag) {
5517 .macho => blk: {5515 .macho => blk: {
...@@ -5632,7 +5630,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -5632,7 +5630,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
5632 .got => .load_memory_got,5630 .got => .load_memory_got,
5633 .direct => .load_memory_direct,5631 .direct => .load_memory_direct,
5634 .import => .load_memory_import,5632 .import => .load_memory_import,
5635 .tlv => @panic("TODO TLV support"),
5636 };5633 };
5637 const atom_index = switch (self.bin_file.tag) {5634 const atom_index = switch (self.bin_file.tag) {
5638 .macho => blk: {5635 .macho => blk: {
...@@ -5833,7 +5830,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -5833,7 +5830,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5833 .got => .load_memory_ptr_got,5830 .got => .load_memory_ptr_got,
5834 .direct => .load_memory_ptr_direct,5831 .direct => .load_memory_ptr_direct,
5835 .import => unreachable,5832 .import => unreachable,
5836 .tlv => @panic("TODO TLV support"),
5837 };5833 };
5838 const atom_index = switch (self.bin_file.tag) {5834 const atom_index = switch (self.bin_file.tag) {
5839 .macho => blk: {5835 .macho => blk: {
...@@ -6175,6 +6171,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -6175,6 +6171,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6175 .linker_load => |ll| .{ .linker_load = ll },6171 .linker_load => |ll| .{ .linker_load = ll },
6176 .immediate => |imm| .{ .immediate = imm },6172 .immediate => |imm| .{ .immediate = imm },
6177 .memory => |addr| .{ .memory = addr },6173 .memory => |addr| .{ .memory = addr },
6174 .tlv_reloc => unreachable, // TODO
6178 },6175 },
6179 .fail => |msg| {6176 .fail => |msg| {
6180 self.err_msg = msg;6177 self.err_msg = msg;
src/arch/arm/CodeGen.zig+1-1
...@@ -6114,7 +6114,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -6114,7 +6114,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6114 .mcv => |mcv| switch (mcv) {6114 .mcv => |mcv| switch (mcv) {
6115 .none => .none,6115 .none => .none,
6116 .undef => .undef,6116 .undef => .undef,
6117 .linker_load => unreachable, // TODO6117 .tlv_reloc, .linker_load => unreachable, // TODO
6118 .immediate => |imm| .{ .immediate = @truncate(u32, imm) },6118 .immediate => |imm| .{ .immediate = @truncate(u32, imm) },
6119 .memory => |addr| .{ .memory = addr },6119 .memory => |addr| .{ .memory = addr },
6120 },6120 },
src/arch/riscv64/CodeGen.zig+1-1
...@@ -2572,7 +2572,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -2572,7 +2572,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
2572 .mcv => |mcv| switch (mcv) {2572 .mcv => |mcv| switch (mcv) {
2573 .none => .none,2573 .none => .none,
2574 .undef => .undef,2574 .undef => .undef,
2575 .linker_load => unreachable, // TODO2575 .tlv_reloc, .linker_load => unreachable, // TODO
2576 .immediate => |imm| .{ .immediate = imm },2576 .immediate => |imm| .{ .immediate = imm },
2577 .memory => |addr| .{ .memory = addr },2577 .memory => |addr| .{ .memory = addr },
2578 },2578 },
src/arch/sparc64/CodeGen.zig+1-1
...@@ -3931,7 +3931,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -3931,7 +3931,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
3931 .mcv => |mcv| switch (mcv) {3931 .mcv => |mcv| switch (mcv) {
3932 .none => .none,3932 .none => .none,
3933 .undef => .undef,3933 .undef => .undef,
3934 .linker_load => unreachable, // TODO3934 .tlv_reloc, .linker_load => unreachable, // TODO
3935 .immediate => |imm| .{ .immediate = imm },3935 .immediate => |imm| .{ .immediate = imm },
3936 .memory => |addr| .{ .memory = addr },3936 .memory => |addr| .{ .memory = addr },
3937 },3937 },
src/arch/x86_64/CodeGen.zig+60-59
...@@ -132,6 +132,10 @@ pub const MCValue = union(enum) {...@@ -132,6 +132,10 @@ pub const MCValue = union(enum) {
132 memory: u64,132 memory: u64,
133 /// The value is in memory but requires a linker relocation fixup.133 /// The value is in memory but requires a linker relocation fixup.
134 linker_load: codegen.LinkerLoad,134 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,
135 /// The value is one of the stack variables.139 /// The value is one of the stack variables.
136 /// If the type is a pointer, it means the pointer address is in the stack at this offset.140 /// If the type is a pointer, it means the pointer address is in the stack at this offset.
137 stack_offset: i32,141 stack_offset: i32,
...@@ -146,6 +150,7 @@ pub const MCValue = union(enum) {...@@ -146,6 +150,7 @@ pub const MCValue = union(enum) {
146 .stack_offset,150 .stack_offset,
147 .ptr_stack_offset,151 .ptr_stack_offset,
148 .linker_load,152 .linker_load,
153 .tlv_reloc,
149 => true,154 => true,
150 else => false,155 else => false,
151 };156 };
...@@ -736,7 +741,6 @@ fn asmMovLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege...@@ -736,7 +741,6 @@ fn asmMovLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege
736 .got => .got_reloc,741 .got => .got_reloc,
737 .direct => .direct_reloc,742 .direct => .direct_reloc,
738 .import => .import_reloc,743 .import => .import_reloc,
739 .tlv => .tlv_reloc,
740 };744 };
741 _ = try self.addInst(.{745 _ = try self.addInst(.{
742 .tag = .mov_linker,746 .tag = .mov_linker,
...@@ -754,7 +758,6 @@ fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege...@@ -754,7 +758,6 @@ fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege
754 .got => .got_reloc,758 .got => .got_reloc,
755 .direct => .direct_reloc,759 .direct => .direct_reloc,
756 .import => .import_reloc,760 .import => .import_reloc,
757 .tlv => .tlv_reloc,
758 };761 };
759 _ = try self.addInst(.{762 _ = try self.addInst(.{
760 .tag = .lea_linker,763 .tag = .lea_linker,
...@@ -767,15 +770,6 @@ fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege...@@ -767,15 +770,6 @@ fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege
767 });770 });
768}771}
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
779fn gen(self: *Self) InnerError!void {773fn gen(self: *Self) InnerError!void {
780 const cc = self.fn_type.fnCallingConvention();774 const cc = self.fn_type.fnCallingConvention();
781 if (cc != .Naked) {775 if (cc != .Naked) {
...@@ -2929,6 +2923,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2929,6 +2923,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
2929 }));2923 }));
2930 },2924 },
2931 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),2925 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),
2926 .tlv_reloc => try self.genSetReg(array_ty, addr_reg, array),
2932 .linker_load => |load_struct| {2927 .linker_load => |load_struct| {
2933 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {2928 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
2934 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);2929 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
...@@ -2942,7 +2937,6 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2942,7 +2937,6 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
2942 .import => unreachable,2937 .import => unreachable,
2943 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),2938 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
2944 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),2939 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
2945 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
2946 }2940 }
2947 },2941 },
2948 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),2942 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...@@ -3656,7 +3650,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
3656 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),3650 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),
3657 }3651 }
3658 },3652 },
3659 .memory => {3653 .memory, .tlv_reloc => {
3660 const reg = try self.copyToTmpRegister(ptr_ty, ptr);3654 const reg = try self.copyToTmpRegister(ptr_ty, ptr);
3661 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);3655 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
3662 },3656 },
...@@ -3676,7 +3670,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -3676,7 +3670,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
3676 switch (load_struct.type) {3670 switch (load_struct.type) {
3677 .import => unreachable,3671 .import => unreachable,
3678 .got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct),3672 .got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct),
3679 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
3680 }3673 }
36813674
3682 try self.load(dst_mcv, .{ .register = addr_reg }, ptr_ty);3675 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...@@ -3838,7 +3831,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3838 .import => unreachable,3831 .import => unreachable,
3839 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),3832 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
3840 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),3833 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
3841 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
3842 }3834 }
3843 },3835 },
3844 else => unreachable,3836 else => unreachable,
...@@ -3863,7 +3855,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -3863,7 +3855,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3863 .{ .immediate = abi_size },3855 .{ .immediate = abi_size },
3864 .{},3856 .{},
3865 ),3857 ),
3866 .ptr_stack_offset => {3858 .ptr_stack_offset, .tlv_reloc => {
3867 const tmp_reg = try self.copyToTmpRegister(value_ty, value);3859 const tmp_reg = try self.copyToTmpRegister(value_ty, value);
3868 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);3860 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
3869 defer self.register_manager.unlockReg(tmp_lock);3861 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...@@ -3900,12 +3892,19 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3900 switch (load_struct.type) {3892 switch (load_struct.type) {
3901 .import => unreachable,3893 .import => unreachable,
3902 .got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct),3894 .got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct),
3903 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
3904 }3895 }
3905 },3896 },
3906 else => unreachable,3897 else => unreachable,
3907 }3898 }
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
3909 const new_ptr = MCValue{ .register = addr_reg };3908 const new_ptr = MCValue{ .register = addr_reg };
3910 try self.store(new_ptr, value, ptr_ty, value_ty);3909 try self.store(new_ptr, value, ptr_ty, value_ty);
3911 },3910 },
...@@ -3954,7 +3953,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32...@@ -3954,7 +3953,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32
39543953
3955 const dst_mcv: MCValue = result: {3954 const dst_mcv: MCValue = result: {
3956 switch (mcv) {3955 switch (mcv) {
3957 .stack_offset => {3956 .stack_offset, .tlv_reloc => {
3958 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{3957 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{
3959 .immediate = field_offset,3958 .immediate = field_offset,
3960 });3959 });
...@@ -4236,6 +4235,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue...@@ -4236,6 +4235,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue
4236 }));4235 }));
4237 },4236 },
4238 .ptr_stack_offset => unreachable,4237 .ptr_stack_offset => unreachable,
4238 .tlv_reloc => unreachable,
4239 .memory, .linker_load => {4239 .memory, .linker_load => {
4240 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();4240 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
4241 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);4241 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...@@ -4256,7 +4256,6 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue
4256 .import => unreachable,4256 .import => unreachable,
4257 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),4257 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
4258 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),4258 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
4259 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
4260 }4259 }
4261 },4260 },
4262 else => unreachable,4261 else => unreachable,
...@@ -4898,6 +4897,7 @@ fn genBinOp(...@@ -4898,6 +4897,7 @@ fn genBinOp(
4898 .eflags,4897 .eflags,
4899 .register_overflow,4898 .register_overflow,
4900 .ptr_stack_offset,4899 .ptr_stack_offset,
4900 .tlv_reloc,
4901 => unreachable,4901 => unreachable,
4902 .register => |src_reg| try self.asmCmovccRegisterRegister(4902 .register => |src_reg| try self.asmCmovccRegisterRegister(
4903 registerAlias(tmp_reg, cmov_abi_size),4903 registerAlias(tmp_reg, cmov_abi_size),
...@@ -4932,7 +4932,6 @@ fn genBinOp(...@@ -4932,7 +4932,6 @@ fn genBinOp(
4932 .import => unreachable,4932 .import => unreachable,
4933 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),4933 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
4934 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),4934 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
4935 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
4936 }4935 }
4937 },4936 },
4938 else => unreachable,4937 else => unreachable,
...@@ -4983,7 +4982,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s...@@ -4983,7 +4982,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
4983 .undef => unreachable,4982 .undef => unreachable,
4984 .dead, .unreach => unreachable,4983 .dead, .unreach => unreachable,
4985 .register_overflow => unreachable,4984 .register_overflow => unreachable,
4986 .ptr_stack_offset => {4985 .ptr_stack_offset, .tlv_reloc => {
4987 const dst_reg_lock = self.register_manager.lockReg(dst_reg);4986 const dst_reg_lock = self.register_manager.lockReg(dst_reg);
4988 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);4987 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...@@ -5079,7 +5078,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5079 .import => unreachable,5078 .import => unreachable,
5080 .got => try self.asmMovLinker(dst_addr_reg, atom_index, load_struct),5079 .got => try self.asmMovLinker(dst_addr_reg, atom_index, load_struct),
5081 .direct => try self.asmLeaLinker(dst_addr_reg, atom_index, load_struct),5080 .direct => try self.asmLeaLinker(dst_addr_reg, atom_index, load_struct),
5082 .tlv => try self.genTlvPtr(dst_addr_reg, atom_index, load_struct),
5083 }5081 }
5084 },5082 },
5085 else => unreachable,5083 else => unreachable,
...@@ -5125,7 +5123,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s...@@ -5125,7 +5123,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5125 .import => unreachable,5123 .import => unreachable,
5126 .got => try self.asmMovLinker(src_addr_reg, atom_index, load_struct),5124 .got => try self.asmMovLinker(src_addr_reg, atom_index, load_struct),
5127 .direct => try self.asmLeaLinker(src_addr_reg, atom_index, load_struct),5125 .direct => try self.asmLeaLinker(src_addr_reg, atom_index, load_struct),
5128 .tlv => try self.genTlvPtr(src_addr_reg, atom_index, load_struct),
5129 }5126 }
5130 },5127 },
5131 else => unreachable,5128 else => unreachable,
...@@ -5236,7 +5233,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s...@@ -5236,7 +5233,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5236 else => unreachable,5233 else => unreachable,
5237 }5234 }
5238 },5235 },
5239 .memory, .linker_load => {5236 .memory, .linker_load, .tlv_reloc => {
5240 try self.asmRegisterMemory(5237 try self.asmRegisterMemory(
5241 .mov,5238 .mov,
5242 registerAlias(src.?.limb_reg, limb_abi_size),5239 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...@@ -5275,6 +5272,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5275 }5272 }
5276 },5273 },
5277 .ptr_stack_offset => unreachable,5274 .ptr_stack_offset => unreachable,
5275 .tlv_reloc => unreachable,
5278 }5276 }
5279}5277}
52805278
...@@ -5288,6 +5286,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -5288,6 +5286,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
5288 .dead, .unreach, .immediate => unreachable,5286 .dead, .unreach, .immediate => unreachable,
5289 .eflags => unreachable,5287 .eflags => unreachable,
5290 .ptr_stack_offset => unreachable,5288 .ptr_stack_offset => unreachable,
5289 .tlv_reloc => unreachable,
5291 .register_overflow => unreachable,5290 .register_overflow => unreachable,
5292 .register => |dst_reg| {5291 .register => |dst_reg| {
5293 const dst_alias = registerAlias(dst_reg, abi_size);5292 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...@@ -5299,6 +5298,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
5299 .undef => try self.genSetReg(dst_ty, dst_reg, .undef),5298 .undef => try self.genSetReg(dst_ty, dst_reg, .undef),
5300 .dead, .unreach => unreachable,5299 .dead, .unreach => unreachable,
5301 .ptr_stack_offset => unreachable,5300 .ptr_stack_offset => unreachable,
5301 .tlv_reloc => unreachable,
5302 .register_overflow => unreachable,5302 .register_overflow => unreachable,
5303 .register => |src_reg| try self.asmRegisterRegister(5303 .register => |src_reg| try self.asmRegisterRegister(
5304 .imul,5304 .imul,
...@@ -5342,6 +5342,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -5342,6 +5342,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
5342 .undef => return self.genSetStack(dst_ty, off, .undef, .{}),5342 .undef => return self.genSetStack(dst_ty, off, .undef, .{}),
5343 .dead, .unreach => unreachable,5343 .dead, .unreach => unreachable,
5344 .ptr_stack_offset => unreachable,5344 .ptr_stack_offset => unreachable,
5345 .tlv_reloc => unreachable,
5345 .register_overflow => unreachable,5346 .register_overflow => unreachable,
5346 .register => |src_reg| {5347 .register => |src_reg| {
5347 // copy dst to a register5348 // copy dst to a register
...@@ -5564,6 +5565,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -5564,6 +5565,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
5564 .linker_load => unreachable,5565 .linker_load => unreachable,
5565 .eflags => unreachable,5566 .eflags => unreachable,
5566 .register_overflow => unreachable,5567 .register_overflow => unreachable,
5568 .tlv_reloc => unreachable,
5567 }5569 }
5568 }5570 }
55695571
...@@ -5602,6 +5604,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -5602,6 +5604,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
5602 .linker_load => unreachable,5604 .linker_load => unreachable,
5603 .eflags => unreachable,5605 .eflags => unreachable,
5604 .register_overflow => unreachable,5606 .register_overflow => unreachable,
5607 .tlv_reloc => unreachable,
5605 }5608 }
5606 }5609 }
56075610
...@@ -6123,6 +6126,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -6123,6 +6126,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
6123 .register_overflow,6126 .register_overflow,
6124 .ptr_stack_offset,6127 .ptr_stack_offset,
6125 .eflags,6128 .eflags,
6129 .tlv_reloc,
6126 => unreachable,6130 => unreachable,
61276131
6128 .register => |opt_reg| {6132 .register => |opt_reg| {
...@@ -6163,7 +6167,6 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -6163,7 +6167,6 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
6163 .import => unreachable,6167 .import => unreachable,
6164 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),6168 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
6165 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),6169 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
6166 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
6167 }6170 }
6168 },6171 },
6169 else => unreachable,6172 else => unreachable,
...@@ -7121,7 +7124,6 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE...@@ -7121,7 +7124,6 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
7121 .import => unreachable,7124 .import => unreachable,
7122 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),7125 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
7123 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),7126 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
7124 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
7125 }7127 }
7126 },7128 },
7127 else => unreachable,7129 else => unreachable,
...@@ -7168,7 +7170,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE...@@ -7168,7 +7170,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
7168 },7170 },
7169 }7171 }
7170 },7172 },
7171 .ptr_stack_offset => {7173 .ptr_stack_offset, .tlv_reloc => {
7172 const reg = try self.copyToTmpRegister(ty, mcv);7174 const reg = try self.copyToTmpRegister(ty, mcv);
7173 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });7175 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
7174 },7176 },
...@@ -7349,7 +7351,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl...@@ -7349,7 +7351,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
7349 .import => unreachable,7351 .import => unreachable,
7350 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),7352 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
7351 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),7353 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
7352 .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
7353 }7354 }
7354 },7355 },
7355 else => unreachable,7356 else => unreachable,
...@@ -7374,7 +7375,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl...@@ -7374,7 +7375,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
7374 .{ .immediate = abi_size },7375 .{ .immediate = abi_size },
7375 .{},7376 .{},
7376 ),7377 ),
7377 .ptr_stack_offset => {7378 .ptr_stack_offset, .tlv_reloc => {
7378 const tmp_reg = try self.copyToTmpRegister(ty, mcv);7379 const tmp_reg = try self.copyToTmpRegister(ty, mcv);
7379 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);7380 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7380 defer self.register_manager.unlockReg(tmp_lock);7381 defer self.register_manager.unlockReg(tmp_lock);
...@@ -7481,13 +7482,9 @@ fn genInlineMemcpy(...@@ -7481,13 +7482,9 @@ fn genInlineMemcpy(
7481 switch (load_struct.type) {7482 switch (load_struct.type) {
7482 .import => unreachable,7483 .import => unreachable,
7483 .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),7484 .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 },
7489 }7485 }
7490 },7486 },
7487 .tlv_reloc => try self.genSetReg(Type.usize, .rdi, dst_ptr),
7491 .stack_offset, .ptr_stack_offset => |off| {7488 .stack_offset, .ptr_stack_offset => |off| {
7492 try self.asmRegisterMemory(switch (dst_ptr) {7489 try self.asmRegisterMemory(switch (dst_ptr) {
7493 .stack_offset => .mov,7490 .stack_offset => .mov,
...@@ -7528,13 +7525,9 @@ fn genInlineMemcpy(...@@ -7528,13 +7525,9 @@ fn genInlineMemcpy(
7528 switch (load_struct.type) {7525 switch (load_struct.type) {
7529 .import => unreachable,7526 .import => unreachable,
7530 .got, .direct => try self.asmMovLinker(.rsi, atom_index, load_struct),7527 .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 },
7536 }7528 }
7537 },7529 },
7530 .tlv_reloc => try self.genSetReg(Type.usize, .rsi, src_ptr),
7538 .stack_offset, .ptr_stack_offset => |off| {7531 .stack_offset, .ptr_stack_offset => |off| {
7539 try self.asmRegisterMemory(switch (src_ptr) {7532 try self.asmRegisterMemory(switch (src_ptr) {
7540 .stack_offset => .mov,7533 .stack_offset => .mov,
...@@ -7598,13 +7591,9 @@ fn genInlineMemset(...@@ -7598,13 +7591,9 @@ fn genInlineMemset(
7598 switch (load_struct.type) {7591 switch (load_struct.type) {
7599 .import => unreachable,7592 .import => unreachable,
7600 .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),7593 .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 },
7606 }7594 }
7607 },7595 },
7596 .tlv_reloc => try self.genSetReg(Type.usize, .rdi, dst_ptr),
7608 .stack_offset, .ptr_stack_offset => |off| {7597 .stack_offset, .ptr_stack_offset => |off| {
7609 try self.asmRegisterMemory(switch (dst_ptr) {7598 try self.asmRegisterMemory(switch (dst_ptr) {
7610 .stack_offset => .mov,7599 .stack_offset => .mov,
...@@ -7780,6 +7769,30 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -7780,6 +7769,30 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
7780 }7769 }
7781 },7770 },
7782 },7771 },
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 },
7783 .linker_load => |load_struct| {7796 .linker_load => |load_struct| {
7784 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {7797 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
7785 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);7798 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...@@ -7792,10 +7805,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
7792 switch (ty.zigTypeTag()) {7805 switch (ty.zigTypeTag()) {
7793 .Float => {7806 .Float => {
7794 const base_reg = (try self.register_manager.allocReg(null, gp)).to64();7807 const base_reg = (try self.register_manager.allocReg(null, gp)).to64();
7795 switch (load_struct.type) {7808 try self.asmLeaLinker(base_reg, atom_index, load_struct);
7796 .tlv => try self.genTlvPtr(base_reg, atom_index, load_struct),
7797 else => try self.asmLeaLinker(base_reg, atom_index, load_struct),
7798 }
77997809
7800 if (intrinsicsAllowed(self.target.*, ty)) {7810 if (intrinsicsAllowed(self.target.*, ty)) {
7801 return self.asmRegisterMemory(7811 return self.asmRegisterMemory(
...@@ -7813,17 +7823,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -7813,17 +7823,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
78137823
7814 return self.fail("TODO genSetReg from memory for float with no intrinsics", .{});7824 return self.fail("TODO genSetReg from memory for float with no intrinsics", .{});
7815 },7825 },
7816 else => switch (load_struct.type) {7826 else => try self.asmMovLinker(registerAlias(reg, abi_size), atom_index, load_struct),
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 },
7827 }7827 }
7828 },7828 },
7829 .stack_offset => |off| {7829 .stack_offset => |off| {
...@@ -8779,6 +8779,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -8779,6 +8779,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
8779 .linker_load => |ll| .{ .linker_load = ll },8779 .linker_load => |ll| .{ .linker_load = ll },
8780 .immediate => |imm| .{ .immediate = imm },8780 .immediate => |imm| .{ .immediate = imm },
8781 .memory => |addr| .{ .memory = addr },8781 .memory => |addr| .{ .memory = addr },
8782 .tlv_reloc => |sym_index| .{ .tlv_reloc = sym_index },
8782 },8783 },
8783 .fail => |msg| {8784 .fail => |msg| {
8784 self.err_msg = msg;8785 self.err_msg = msg;
src/codegen.zig+8-3
...@@ -912,13 +912,11 @@ fn lowerDeclRef(...@@ -912,13 +912,11 @@ 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)
916pub const LinkerLoad = struct {915pub const LinkerLoad = struct {
917 type: enum {916 type: enum {
918 got,917 got,
919 direct,918 direct,
920 import,919 import,
921 tlv,
922 },920 },
923 sym_index: u32,921 sym_index: u32,
924};922};
...@@ -934,6 +932,10 @@ pub const GenResult = union(enum) {...@@ -934,6 +932,10 @@ pub const GenResult = union(enum) {
934 /// such as ARM, the immediate will never exceed 32-bits.932 /// such as ARM, the immediate will never exceed 32-bits.
935 immediate: u64,933 immediate: u64,
936 linker_load: LinkerLoad,934 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,
937 /// Direct by-address reference to memory location.939 /// Direct by-address reference to memory location.
938 memory: u64,940 memory: u64,
939 };941 };
...@@ -1002,8 +1004,11 @@ fn genDeclRef(...@@ -1002,8 +1004,11 @@ fn genDeclRef(
1002 } else if (bin_file.cast(link.File.MachO)) |macho_file| {1004 } else if (bin_file.cast(link.File.MachO)) |macho_file| {
1003 const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);1005 const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);
1004 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;1006 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
1007 if (is_threadlocal) {
1008 return GenResult.mcv(.{ .tlv_reloc = sym_index });
1009 }
1005 return GenResult.mcv(.{ .linker_load = .{1010 return GenResult.mcv(.{ .linker_load = .{
1006 .type = if (is_threadlocal) .tlv else .got,1011 .type = .got,
1007 .sym_index = sym_index,1012 .sym_index = sym_index,
1008 } });1013 } });
1009 } else if (bin_file.cast(link.File.Coff)) |coff_file| {1014 } else if (bin_file.cast(link.File.Coff)) |coff_file| {