authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-15 00:57:17+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-15 00:57:23+02:00
log179117c114ca44d977f794961762e110c1955911
tree61295bfab6c963c1d1935345896fb0a45351c41c
parent0733c8c5ca03f55fe8f65f74cea89dfccf6079b4

x86_64: split MCValue.tlv_reloc into .load_tlv and .lea_tlv

`.load_tlv` signifies we want to load the value of a TLV `.lea_tlv` signifies we want to load effective address of a TLV

6 files changed, 126 insertions(+), 63 deletions(-)

src/arch/aarch64/CodeGen.zig+1-1
......@@ -6171,7 +6171,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
61716171 .linker_load => |ll| .{ .linker_load = ll },
61726172 .immediate => |imm| .{ .immediate = imm },
61736173 .memory => |addr| .{ .memory = addr },
6174 .tlv_reloc => unreachable, // TODO
6174 .load_tlv => unreachable, // TODO
61756175 },
61766176 .fail => |msg| {
61776177 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 .tlv_reloc, .linker_load => unreachable, // TODO
6117 .load_tlv, .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 .tlv_reloc, .linker_load => unreachable, // TODO
2575 .load_tlv, .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 .tlv_reloc, .linker_load => unreachable, // TODO
3934 .load_tlv, .linker_load => unreachable, // TODO
39353935 .immediate => |imm| .{ .immediate = imm },
39363936 .memory => |addr| .{ .memory = addr },
39373937 },
src/arch/x86_64/CodeGen.zig+118-55
......@@ -132,10 +132,12 @@ 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.
135 /// The value is a threadlocal variable.
137136 /// Payload is a symbol index.
138 tlv_reloc: u32,
137 load_tlv: u32,
138 /// The value is a pointer to threadlocal variable.
139 /// Payload is a symbol index.
140 lea_tlv: u32,
139141 /// The value is one of the stack variables.
140142 /// If the type is a pointer, it means the pointer address is in the stack at this offset.
141143 stack_offset: i32,
......@@ -150,7 +152,8 @@ pub const MCValue = union(enum) {
150152 .stack_offset,
151153 .ptr_stack_offset,
152154 .linker_load,
153 .tlv_reloc,
155 .load_tlv,
156 .lea_tlv,
154157 => true,
155158 else => false,
156159 };
......@@ -2923,7 +2926,8 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
29232926 }));
29242927 },
29252928 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),
2926 .tlv_reloc => try self.genSetReg(array_ty, addr_reg, array),
2929 .lea_tlv => unreachable,
2930 .load_tlv => |sym_index| try self.genSetReg(array_ty, addr_reg, .{ .lea_tlv = sym_index }),
29272931 .linker_load => |load_struct| {
29282932 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
29292933 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
......@@ -3650,7 +3654,8 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
36503654 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),
36513655 }
36523656 },
3653 .memory, .tlv_reloc => {
3657 .load_tlv => |sym_index| try self.load(dst_mcv, .{ .lea_tlv = sym_index }, ptr_ty),
3658 .memory, .lea_tlv => {
36543659 const reg = try self.copyToTmpRegister(ptr_ty, ptr);
36553660 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
36563661 },
......@@ -3806,7 +3811,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
38063811 -@intCast(i32, overflow_bit_offset),
38073812 );
38083813 },
3809 .memory, .linker_load => if (abi_size <= 8) {
3814 .memory, .load_tlv, .linker_load => if (abi_size <= 8) {
38103815 const tmp_reg = try self.copyToTmpRegister(value_ty, value);
38113816 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
38123817 defer self.register_manager.unlockReg(tmp_lock);
......@@ -3819,6 +3824,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
38193824
38203825 switch (value) {
38213826 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),
3827 .load_tlv => |sym_index| try self.genSetReg(Type.usize, addr_reg, .{ .lea_tlv = sym_index }),
38223828 .linker_load => |load_struct| {
38233829 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
38243830 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
......@@ -3855,7 +3861,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
38553861 .{ .immediate = abi_size },
38563862 .{},
38573863 ),
3858 .ptr_stack_offset, .tlv_reloc => {
3864 .ptr_stack_offset, .lea_tlv => {
38593865 const tmp_reg = try self.copyToTmpRegister(value_ty, value);
38603866 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
38613867 defer self.register_manager.unlockReg(tmp_lock);
......@@ -3864,7 +3870,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
38643870 },
38653871 }
38663872 },
3867 .memory, .linker_load => {
3873 .memory, .load_tlv, .linker_load => {
38683874 const value_lock: ?RegisterLock = switch (value) {
38693875 .register => |reg| self.register_manager.lockReg(reg),
38703876 else => null,
......@@ -3881,6 +3887,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
38813887 // Load the pointer, which is stored in memory
38823888 try self.asmRegisterMemory(.mov, addr_reg, Memory.sib(.qword, .{ .base = addr_reg }));
38833889 },
3890 .load_tlv => |sym_index| try self.genSetReg(ptr_ty, addr_reg, .{ .lea_tlv = sym_index }),
38843891 .linker_load => |load_struct| {
38853892 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
38863893 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
......@@ -3900,8 +3907,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
39003907 const new_ptr = MCValue{ .register = addr_reg };
39013908 try self.store(new_ptr, value, ptr_ty, value_ty);
39023909 },
3903 .tlv_reloc => {
3904 const addr_reg = try self.copyToTmpRegister(Type.usize, ptr);
3910 .lea_tlv => {
3911 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr);
39053912 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
39063913 defer self.register_manager.unlockReg(addr_reg_lock);
39073914
......@@ -3953,14 +3960,17 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32
39533960
39543961 const dst_mcv: MCValue = result: {
39553962 switch (mcv) {
3956 .stack_offset, .tlv_reloc => {
3963 .stack_offset, .lea_tlv, .load_tlv => {
39573964 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{
39583965 .immediate = field_offset,
39593966 });
39603967 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
39613968 defer self.register_manager.unlockReg(offset_reg_lock);
39623969
3963 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, mcv);
3970 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, switch (mcv) {
3971 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
3972 else => mcv,
3973 });
39643974 try self.genBinOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });
39653975 break :result dst_mcv;
39663976 },
......@@ -4235,14 +4245,15 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue
42354245 }));
42364246 },
42374247 .ptr_stack_offset => unreachable,
4238 .tlv_reloc => unreachable,
4239 .memory, .linker_load => {
4248 .lea_tlv => unreachable,
4249 .memory, .load_tlv, .linker_load => {
42404250 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
42414251 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
42424252 defer self.register_manager.unlockReg(addr_reg_lock);
42434253
42444254 switch (dst_mcv) {
42454255 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),
4256 .load_tlv => |sym_index| try self.genSetReg(Type.usize, addr_reg, .{ .lea_tlv = sym_index }),
42464257 .linker_load => |load_struct| {
42474258 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
42484259 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
......@@ -4756,7 +4767,10 @@ fn genBinOp(
47564767 }
47574768 }
47584769 const dst_mcv = try self.allocRegOrMemAdvanced(lhs_ty, maybe_inst, true);
4759 try self.setRegOrMem(lhs_ty, dst_mcv, lhs);
4770 try self.setRegOrMem(lhs_ty, dst_mcv, switch (lhs) {
4771 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
4772 else => lhs,
4773 });
47604774 break :dst dst_mcv;
47614775 };
47624776 const dst_mcv_lock: ?RegisterLock = switch (dst_mcv) {
......@@ -4897,7 +4911,7 @@ fn genBinOp(
48974911 .eflags,
48984912 .register_overflow,
48994913 .ptr_stack_offset,
4900 .tlv_reloc,
4914 .lea_tlv,
49014915 => unreachable,
49024916 .register => |src_reg| try self.asmCmovccRegisterRegister(
49034917 registerAlias(tmp_reg, cmov_abi_size),
......@@ -4912,13 +4926,14 @@ fn genBinOp(
49124926 }),
49134927 cc,
49144928 ),
4915 .memory, .linker_load => {
4929 .memory, .load_tlv, .linker_load => {
49164930 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
49174931 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
49184932 defer self.register_manager.unlockReg(addr_reg_lock);
49194933
49204934 switch (mat_src_mcv) {
49214935 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),
4936 .load_tlv => |sym_index| try self.genSetReg(Type.usize, addr_reg, .{ .lea_tlv = sym_index }),
49224937 .linker_load => |load_struct| {
49234938 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
49244939 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
......@@ -4982,13 +4997,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
49824997 .undef => unreachable,
49834998 .dead, .unreach => unreachable,
49844999 .register_overflow => unreachable,
4985 .ptr_stack_offset, .tlv_reloc => {
4986 const dst_reg_lock = self.register_manager.lockReg(dst_reg);
4987 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
4988
4989 const reg = try self.copyToTmpRegister(ty, src_mcv);
4990 return self.genBinOpMir(mir_tag, ty, dst_mcv, .{ .register = reg });
4991 },
49925000 .register => |src_reg| switch (ty.zigTypeTag()) {
49935001 .Float => {
49945002 if (intrinsicsAllowed(self.target.*, ty)) {
......@@ -5037,7 +5045,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
50375045 )),
50385046 else => unreachable,
50395047 },
5040 .memory, .linker_load, .eflags => {
5048 .ptr_stack_offset, .memory, .lea_tlv, .load_tlv, .linker_load, .eflags => {
50415049 assert(abi_size <= 8);
50425050 const dst_reg_lock = self.register_manager.lockReg(dst_reg);
50435051 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
......@@ -5052,19 +5060,20 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
50525060 ),
50535061 }
50545062 },
5055 .memory, .linker_load, .stack_offset => {
5063 .memory, .load_tlv, .linker_load, .stack_offset => {
50565064 const dst: ?struct {
50575065 addr_reg: Register,
50585066 addr_lock: RegisterLock,
50595067 } = switch (dst_mcv) {
50605068 else => unreachable,
5061 .memory, .linker_load => dst: {
5069 .memory, .load_tlv, .linker_load => dst: {
50625070 const dst_addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
50635071 const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);
50645072 errdefer self.register_manager.unlockReg(dst_addr_lock);
50655073
50665074 switch (dst_mcv) {
50675075 .memory => |addr| try self.genSetReg(Type.usize, dst_addr_reg, .{ .immediate = addr }),
5076 .load_tlv => |sym_index| try self.genSetReg(Type.usize, dst_addr_reg, .{ .lea_tlv = sym_index }),
50685077 .linker_load => |load_struct| {
50695078 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
50705079 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
......@@ -5099,7 +5108,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
50995108 addr_lock: RegisterLock,
51005109 } = switch (src_mcv) {
51015110 else => null,
5102 .memory, .linker_load => src: {
5111 .memory, .load_tlv, .linker_load => src: {
51035112 const src_limb_reg = try self.register_manager.allocReg(null, gp);
51045113 const src_limb_lock = self.register_manager.lockRegAssumeUnused(src_limb_reg);
51055114 errdefer self.register_manager.unlockReg(src_limb_lock);
......@@ -5110,6 +5119,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
51105119
51115120 switch (src_mcv) {
51125121 .memory => |addr| try self.genSetReg(Type.usize, src_addr_reg, .{ .immediate = addr }),
5122 .load_tlv => |sym_index| try self.genSetReg(Type.usize, src_addr_reg, .{ .lea_tlv = sym_index }),
51135123 .linker_load => |load_struct| {
51145124 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
51155125 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
......@@ -5233,7 +5243,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
52335243 else => unreachable,
52345244 }
52355245 },
5236 .memory, .linker_load, .tlv_reloc => {
5246 .memory, .linker_load, .lea_tlv, .load_tlv => {
52375247 try self.asmRegisterMemory(
52385248 .mov,
52395249 registerAlias(src.?.limb_reg, limb_abi_size),
......@@ -5272,7 +5282,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
52725282 }
52735283 },
52745284 .ptr_stack_offset => unreachable,
5275 .tlv_reloc => unreachable,
5285 .lea_tlv => unreachable,
52765286 }
52775287}
52785288
......@@ -5286,7 +5296,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
52865296 .dead, .unreach, .immediate => unreachable,
52875297 .eflags => unreachable,
52885298 .ptr_stack_offset => unreachable,
5289 .tlv_reloc => unreachable,
5299 .lea_tlv => unreachable,
52905300 .register_overflow => unreachable,
52915301 .register => |dst_reg| {
52925302 const dst_alias = registerAlias(dst_reg, abi_size);
......@@ -5298,7 +5308,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
52985308 .undef => try self.genSetReg(dst_ty, dst_reg, .undef),
52995309 .dead, .unreach => unreachable,
53005310 .ptr_stack_offset => unreachable,
5301 .tlv_reloc => unreachable,
5311 .lea_tlv => unreachable,
53025312 .register_overflow => unreachable,
53035313 .register => |src_reg| try self.asmRegisterRegister(
53045314 .imul,
......@@ -5325,7 +5335,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
53255335 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .rbp, .disp = -off }),
53265336 );
53275337 },
5328 .memory => {
5338 .memory, .load_tlv => {
53295339 return self.fail("TODO implement x86 multiply source memory", .{});
53305340 },
53315341 .linker_load => {
......@@ -5342,7 +5352,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
53425352 .undef => return self.genSetStack(dst_ty, off, .undef, .{}),
53435353 .dead, .unreach => unreachable,
53445354 .ptr_stack_offset => unreachable,
5345 .tlv_reloc => unreachable,
5355 .lea_tlv => unreachable,
53465356 .register_overflow => unreachable,
53475357 .register => |src_reg| {
53485358 // copy dst to a register
......@@ -5365,7 +5375,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
53655375
53665376 return self.genSetStack(dst_ty, off, .{ .register = dst_reg }, .{});
53675377 },
5368 .memory, .stack_offset => {
5378 .memory, .load_tlv, .stack_offset => {
53695379 return self.fail("TODO implement x86 multiply source memory", .{});
53705380 },
53715381 .linker_load => {
......@@ -5376,7 +5386,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
53765386 },
53775387 }
53785388 },
5379 .memory => {
5389 .memory, .load_tlv => {
53805390 return self.fail("TODO implement x86 multiply destination memory", .{});
53815391 },
53825392 .linker_load => {
......@@ -5565,7 +5575,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
55655575 .linker_load => unreachable,
55665576 .eflags => unreachable,
55675577 .register_overflow => unreachable,
5568 .tlv_reloc => unreachable,
5578 .lea_tlv => unreachable,
5579 .load_tlv => unreachable,
55695580 }
55705581 }
55715582
......@@ -5604,7 +5615,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
56045615 .linker_load => unreachable,
56055616 .eflags => unreachable,
56065617 .register_overflow => unreachable,
5607 .tlv_reloc => unreachable,
5618 .lea_tlv => unreachable,
5619 .load_tlv => unreachable,
56085620 }
56095621 }
56105622
......@@ -6126,7 +6138,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
61266138 .register_overflow,
61276139 .ptr_stack_offset,
61286140 .eflags,
6129 .tlv_reloc,
6141 .lea_tlv,
61306142 => unreachable,
61316143
61326144 .register => |opt_reg| {
......@@ -6147,13 +6159,14 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
61476159 return .{ .eflags = .nc };
61486160 },
61496161
6150 .memory, .linker_load => {
6162 .memory, .load_tlv, .linker_load => {
61516163 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
61526164 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
61536165 defer self.register_manager.unlockReg(addr_reg_lock);
61546166
61556167 switch (opt_mcv) {
61566168 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),
6169 .load_tlv => |sym_index| try self.genSetReg(Type.usize, addr_reg, .{ .lea_tlv = sym_index }),
61576170 .linker_load => |load_struct| {
61586171 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
61596172 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
......@@ -7099,7 +7112,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
70997112 else => return self.fail("TODO implement inputs on stack for {} with abi size > 8", .{mcv}),
71007113 }
71017114 },
7102 .memory, .linker_load => {
7115 .memory, .load_tlv, .linker_load => {
71037116 if (abi_size <= 8) {
71047117 const reg = try self.copyToTmpRegister(ty, mcv);
71057118 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
......@@ -7111,6 +7124,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
71117124
71127125 switch (mcv) {
71137126 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),
7127 .load_tlv => |sym_index| try self.genSetReg(Type.usize, addr_reg, .{ .lea_tlv = sym_index }),
71147128 .linker_load => |load_struct| {
71157129 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
71167130 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
......@@ -7170,7 +7184,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
71707184 },
71717185 }
71727186 },
7173 .ptr_stack_offset, .tlv_reloc => {
7187 .ptr_stack_offset, .lea_tlv => {
71747188 const reg = try self.copyToTmpRegister(ty, mcv);
71757189 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
71767190 },
......@@ -7328,7 +7342,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
73287342 },
73297343 }
73307344 },
7331 .memory, .linker_load => if (abi_size <= 8) {
7345 .memory, .load_tlv, .linker_load => if (abi_size <= 8) {
73327346 const reg = try self.copyToTmpRegister(ty, mcv);
73337347 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts);
73347348 } else {
......@@ -7338,6 +7352,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
73387352
73397353 switch (mcv) {
73407354 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),
7355 .load_tlv => |sym_index| try self.genSetReg(Type.usize, addr_reg, .{ .lea_tlv = sym_index }),
73417356 .linker_load => |load_struct| {
73427357 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
73437358 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
......@@ -7375,7 +7390,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
73757390 .{ .immediate = abi_size },
73767391 .{},
73777392 ),
7378 .ptr_stack_offset, .tlv_reloc => {
7393 .ptr_stack_offset, .lea_tlv => {
73797394 const tmp_reg = try self.copyToTmpRegister(ty, mcv);
73807395 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
73817396 defer self.register_manager.unlockReg(tmp_lock);
......@@ -7484,7 +7499,10 @@ fn genInlineMemcpy(
74847499 .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),
74857500 }
74867501 },
7487 .tlv_reloc => try self.genSetReg(Type.usize, .rdi, dst_ptr),
7502 .lea_tlv, .load_tlv => try self.genSetReg(Type.usize, .rdi, switch (dst_ptr) {
7503 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
7504 else => dst_ptr,
7505 }),
74887506 .stack_offset, .ptr_stack_offset => |off| {
74897507 try self.asmRegisterMemory(switch (dst_ptr) {
74907508 .stack_offset => .mov,
......@@ -7527,7 +7545,10 @@ fn genInlineMemcpy(
75277545 .got, .direct => try self.asmMovLinker(.rsi, atom_index, load_struct),
75287546 }
75297547 },
7530 .tlv_reloc => try self.genSetReg(Type.usize, .rsi, src_ptr),
7548 .lea_tlv, .load_tlv => try self.genSetReg(Type.usize, .rsi, switch (src_ptr) {
7549 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
7550 else => src_ptr,
7551 }),
75317552 .stack_offset, .ptr_stack_offset => |off| {
75327553 try self.asmRegisterMemory(switch (src_ptr) {
75337554 .stack_offset => .mov,
......@@ -7593,7 +7614,10 @@ fn genInlineMemset(
75937614 .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),
75947615 }
75957616 },
7596 .tlv_reloc => try self.genSetReg(Type.usize, .rdi, dst_ptr),
7617 .lea_tlv, .load_tlv => try self.genSetReg(Type.usize, .rdi, switch (dst_ptr) {
7618 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
7619 else => dst_ptr,
7620 }),
75977621 .stack_offset, .ptr_stack_offset => |off| {
75987622 try self.asmRegisterMemory(switch (dst_ptr) {
75997623 .stack_offset => .mov,
......@@ -7769,7 +7793,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
77697793 }
77707794 },
77717795 },
7772 .tlv_reloc => |sym_index| {
7796 .lea_tlv => |sym_index| {
77737797 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
77747798 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
77757799 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
......@@ -7793,6 +7817,33 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
77937817 try self.genSetReg(Type.usize, reg, .{ .register = .rax });
77947818 } else return self.fail("TODO emit ptr to TLV sequence on {s}", .{@tagName(self.bin_file.tag)});
77957819 },
7820 .load_tlv => |sym_index| {
7821 const base_reg = switch (ty.zigTypeTag()) {
7822 .Float => (try self.register_manager.allocReg(null, gp)).to64(),
7823 else => reg.to64(),
7824 };
7825 try self.genSetReg(Type.usize, base_reg, .{ .lea_tlv = sym_index });
7826 switch (ty.zigTypeTag()) {
7827 .Float => if (intrinsicsAllowed(self.target.*, ty)) {
7828 return self.asmRegisterMemory(
7829 switch (ty.tag()) {
7830 .f32 => .movss,
7831 .f64 => .movsd,
7832 else => return self.fail("TODO genSetReg from memory for {}", .{
7833 ty.fmt(self.bin_file.options.module.?),
7834 }),
7835 },
7836 reg.to128(),
7837 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base_reg }),
7838 );
7839 } else return self.fail("TODO genSetReg from memory for float with no intrinsics", .{}),
7840 else => try self.asmRegisterMemory(
7841 .mov,
7842 registerAlias(reg, abi_size),
7843 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base_reg }),
7844 ),
7845 }
7846 },
77967847 .linker_load => |load_struct| {
77977848 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
77987849 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
......@@ -8586,7 +8637,11 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
85868637 const elem_byte_off = @intCast(i32, elem_off / elem_abi_bits * elem_abi_size);
85878638 const elem_bit_off = elem_off % elem_abi_bits;
85888639 const elem_mcv = try self.resolveInst(elem);
8589 const elem_lock = switch (elem_mcv) {
8640 const mat_elem_mcv = switch (elem_mcv) {
8641 .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index },
8642 else => elem_mcv,
8643 };
8644 const elem_lock = switch (mat_elem_mcv) {
85908645 .register => |reg| self.register_manager.lockReg(reg),
85918646 .immediate => |imm| lock: {
85928647 if (imm == 0) continue;
......@@ -8596,7 +8651,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
85968651 };
85978652 defer if (elem_lock) |lock| self.register_manager.unlockReg(lock);
85988653 const elem_reg = registerAlias(
8599 try self.copyToTmpRegister(elem_ty, elem_mcv),
8654 try self.copyToTmpRegister(elem_ty, mat_elem_mcv),
86008655 elem_abi_size,
86018656 );
86028657 const elem_extra_bits = self.regExtraBits(elem_ty);
......@@ -8616,7 +8671,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
86168671 .{ .register = elem_reg },
86178672 );
86188673 if (elem_bit_off > elem_extra_bits) {
8619 const reg = try self.copyToTmpRegister(elem_ty, elem_mcv);
8674 const reg = try self.copyToTmpRegister(elem_ty, mat_elem_mcv);
86208675 if (elem_extra_bits > 0) {
86218676 try self.truncateRegister(elem_ty, registerAlias(reg, elem_abi_size));
86228677 }
......@@ -8641,7 +8696,11 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
86418696 const elem_ty = result_ty.structFieldType(elem_i);
86428697 const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, self.target.*));
86438698 const elem_mcv = try self.resolveInst(elem);
8644 try self.genSetStack(elem_ty, stack_offset - elem_off, elem_mcv, .{});
8699 const mat_elem_mcv = switch (elem_mcv) {
8700 .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index },
8701 else => elem_mcv,
8702 };
8703 try self.genSetStack(elem_ty, stack_offset - elem_off, mat_elem_mcv, .{});
86458704 }
86468705 break :res .{ .stack_offset = stack_offset };
86478706 },
......@@ -8652,8 +8711,12 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
86528711
86538712 for (elements, 0..) |elem, elem_i| {
86548713 const elem_mcv = try self.resolveInst(elem);
8714 const mat_elem_mcv = switch (elem_mcv) {
8715 .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index },
8716 else => elem_mcv,
8717 };
86558718 const elem_off = @intCast(i32, elem_size * elem_i);
8656 try self.genSetStack(elem_ty, stack_offset - elem_off, elem_mcv, .{});
8719 try self.genSetStack(elem_ty, stack_offset - elem_off, mat_elem_mcv, .{});
86578720 }
86588721 break :res MCValue{ .stack_offset = stack_offset };
86598722 },
......@@ -8779,7 +8842,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
87798842 .linker_load => |ll| .{ .linker_load = ll },
87808843 .immediate => |imm| .{ .immediate = imm },
87818844 .memory => |addr| .{ .memory = addr },
8782 .tlv_reloc => |sym_index| .{ .tlv_reloc = sym_index },
8845 .load_tlv => |sym_index| .{ .load_tlv = sym_index },
87838846 },
87848847 .fail => |msg| {
87858848 self.err_msg = msg;
src/codegen.zig+4-4
......@@ -932,10 +932,10 @@ pub const GenResult = union(enum) {
932932 /// such as ARM, the immediate will never exceed 32-bits.
933933 immediate: u64,
934934 linker_load: LinkerLoad,
935 /// Pointer to a threadlocal variable.
936 /// The address resolution will be deferred until the linker allocates everything in virtual memory.
935 /// Threadlocal variable with address deferred until the linker allocates
936 /// everything in virtual memory.
937937 /// Payload is a symbol index.
938 tlv_reloc: u32,
938 load_tlv: u32,
939939 /// Direct by-address reference to memory location.
940940 memory: u64,
941941 };
......@@ -1005,7 +1005,7 @@ fn genDeclRef(
10051005 const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);
10061006 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
10071007 if (is_threadlocal) {
1008 return GenResult.mcv(.{ .tlv_reloc = sym_index });
1008 return GenResult.mcv(.{ .load_tlv = sym_index });
10091009 }
10101010 return GenResult.mcv(.{ .linker_load = .{
10111011 .type = .got,