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 {...@@ -6171,7 +6171,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6171 .linker_load => |ll| .{ .linker_load = ll },6171 .linker_load => |ll| .{ .linker_load = ll },
6172 .immediate => |imm| .{ .immediate = imm },6172 .immediate => |imm| .{ .immediate = imm },
6173 .memory => |addr| .{ .memory = addr },6173 .memory => |addr| .{ .memory = addr },
6174 .tlv_reloc => unreachable, // TODO6174 .load_tlv => unreachable, // TODO
6175 },6175 },
6176 .fail => |msg| {6176 .fail => |msg| {
6177 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 .tlv_reloc, .linker_load => unreachable, // TODO6117 .load_tlv, .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 .tlv_reloc, .linker_load => unreachable, // TODO2575 .load_tlv, .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 .tlv_reloc, .linker_load => unreachable, // TODO3934 .load_tlv, .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+118-55
...@@ -132,10 +132,12 @@ pub const MCValue = union(enum) {...@@ -132,10 +132,12 @@ 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.135 /// The value is a threadlocal variable.
136 /// The address resolution will be deferred until the linker allocates everything in virtual memory.
137 /// Payload is a symbol index.136 /// 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,
139 /// The value is one of the stack variables.141 /// The value is one of the stack variables.
140 /// If the type is a pointer, it means the pointer address is in the stack at this offset.142 /// If the type is a pointer, it means the pointer address is in the stack at this offset.
141 stack_offset: i32,143 stack_offset: i32,
...@@ -150,7 +152,8 @@ pub const MCValue = union(enum) {...@@ -150,7 +152,8 @@ pub const MCValue = union(enum) {
150 .stack_offset,152 .stack_offset,
151 .ptr_stack_offset,153 .ptr_stack_offset,
152 .linker_load,154 .linker_load,
153 .tlv_reloc,155 .load_tlv,
156 .lea_tlv,
154 => true,157 => true,
155 else => false,158 else => false,
156 };159 };
...@@ -2923,7 +2926,8 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2923,7 +2926,8 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
2923 }));2926 }));
2924 },2927 },
2925 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),2928 .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 }),
2927 .linker_load => |load_struct| {2931 .linker_load => |load_struct| {
2928 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {2932 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
2929 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);2933 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...@@ -3650,7 +3654,8 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
3650 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),3654 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),
3651 }3655 }
3652 },3656 },
3653 .memory, .tlv_reloc => {3657 .load_tlv => |sym_index| try self.load(dst_mcv, .{ .lea_tlv = sym_index }, ptr_ty),
3658 .memory, .lea_tlv => {
3654 const reg = try self.copyToTmpRegister(ptr_ty, ptr);3659 const reg = try self.copyToTmpRegister(ptr_ty, ptr);
3655 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);3660 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
3656 },3661 },
...@@ -3806,7 +3811,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -3806,7 +3811,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3806 -@intCast(i32, overflow_bit_offset),3811 -@intCast(i32, overflow_bit_offset),
3807 );3812 );
3808 },3813 },
3809 .memory, .linker_load => if (abi_size <= 8) {3814 .memory, .load_tlv, .linker_load => if (abi_size <= 8) {
3810 const tmp_reg = try self.copyToTmpRegister(value_ty, value);3815 const tmp_reg = try self.copyToTmpRegister(value_ty, value);
3811 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);3816 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
3812 defer self.register_manager.unlockReg(tmp_lock);3817 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...@@ -3819,6 +3824,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
38193824
3820 switch (value) {3825 switch (value) {
3821 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),3826 .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 }),
3822 .linker_load => |load_struct| {3828 .linker_load => |load_struct| {
3823 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {3829 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
3824 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);3830 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...@@ -3855,7 +3861,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3855 .{ .immediate = abi_size },3861 .{ .immediate = abi_size },
3856 .{},3862 .{},
3857 ),3863 ),
3858 .ptr_stack_offset, .tlv_reloc => {3864 .ptr_stack_offset, .lea_tlv => {
3859 const tmp_reg = try self.copyToTmpRegister(value_ty, value);3865 const tmp_reg = try self.copyToTmpRegister(value_ty, value);
3860 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);3866 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
3861 defer self.register_manager.unlockReg(tmp_lock);3867 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...@@ -3864,7 +3870,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3864 },3870 },
3865 }3871 }
3866 },3872 },
3867 .memory, .linker_load => {3873 .memory, .load_tlv, .linker_load => {
3868 const value_lock: ?RegisterLock = switch (value) {3874 const value_lock: ?RegisterLock = switch (value) {
3869 .register => |reg| self.register_manager.lockReg(reg),3875 .register => |reg| self.register_manager.lockReg(reg),
3870 else => null,3876 else => null,
...@@ -3881,6 +3887,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -3881,6 +3887,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3881 // Load the pointer, which is stored in memory3887 // Load the pointer, which is stored in memory
3882 try self.asmRegisterMemory(.mov, addr_reg, Memory.sib(.qword, .{ .base = addr_reg }));3888 try self.asmRegisterMemory(.mov, addr_reg, Memory.sib(.qword, .{ .base = addr_reg }));
3883 },3889 },
3890 .load_tlv => |sym_index| try self.genSetReg(ptr_ty, addr_reg, .{ .lea_tlv = sym_index }),
3884 .linker_load => |load_struct| {3891 .linker_load => |load_struct| {
3885 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {3892 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
3886 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);3893 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...@@ -3900,8 +3907,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3900 const new_ptr = MCValue{ .register = addr_reg };3907 const new_ptr = MCValue{ .register = addr_reg };
3901 try self.store(new_ptr, value, ptr_ty, value_ty);3908 try self.store(new_ptr, value, ptr_ty, value_ty);
3902 },3909 },
3903 .tlv_reloc => {3910 .lea_tlv => {
3904 const addr_reg = try self.copyToTmpRegister(Type.usize, ptr);3911 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr);
3905 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);3912 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
3906 defer self.register_manager.unlockReg(addr_reg_lock);3913 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...@@ -3953,14 +3960,17 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32
39533960
3954 const dst_mcv: MCValue = result: {3961 const dst_mcv: MCValue = result: {
3955 switch (mcv) {3962 switch (mcv) {
3956 .stack_offset, .tlv_reloc => {3963 .stack_offset, .lea_tlv, .load_tlv => {
3957 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{3964 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{
3958 .immediate = field_offset,3965 .immediate = field_offset,
3959 });3966 });
3960 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);3967 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
3961 defer self.register_manager.unlockReg(offset_reg_lock);3968 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 });
3964 try self.genBinOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });3974 try self.genBinOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });
3965 break :result dst_mcv;3975 break :result dst_mcv;
3966 },3976 },
...@@ -4235,14 +4245,15 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue...@@ -4235,14 +4245,15 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue
4235 }));4245 }));
4236 },4246 },
4237 .ptr_stack_offset => unreachable,4247 .ptr_stack_offset => unreachable,
4238 .tlv_reloc => unreachable,4248 .lea_tlv => unreachable,
4239 .memory, .linker_load => {4249 .memory, .load_tlv, .linker_load => {
4240 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();4250 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
4241 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);4251 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
4242 defer self.register_manager.unlockReg(addr_reg_lock);4252 defer self.register_manager.unlockReg(addr_reg_lock);
42434253
4244 switch (dst_mcv) {4254 switch (dst_mcv) {
4245 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),4255 .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 }),
4246 .linker_load => |load_struct| {4257 .linker_load => |load_struct| {
4247 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {4258 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
4248 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);4259 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
...@@ -4756,7 +4767,10 @@ fn genBinOp(...@@ -4756,7 +4767,10 @@ fn genBinOp(
4756 }4767 }
4757 }4768 }
4758 const dst_mcv = try self.allocRegOrMemAdvanced(lhs_ty, maybe_inst, true);4769 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 });
4760 break :dst dst_mcv;4774 break :dst dst_mcv;
4761 };4775 };
4762 const dst_mcv_lock: ?RegisterLock = switch (dst_mcv) {4776 const dst_mcv_lock: ?RegisterLock = switch (dst_mcv) {
...@@ -4897,7 +4911,7 @@ fn genBinOp(...@@ -4897,7 +4911,7 @@ fn genBinOp(
4897 .eflags,4911 .eflags,
4898 .register_overflow,4912 .register_overflow,
4899 .ptr_stack_offset,4913 .ptr_stack_offset,
4900 .tlv_reloc,4914 .lea_tlv,
4901 => unreachable,4915 => unreachable,
4902 .register => |src_reg| try self.asmCmovccRegisterRegister(4916 .register => |src_reg| try self.asmCmovccRegisterRegister(
4903 registerAlias(tmp_reg, cmov_abi_size),4917 registerAlias(tmp_reg, cmov_abi_size),
...@@ -4912,13 +4926,14 @@ fn genBinOp(...@@ -4912,13 +4926,14 @@ fn genBinOp(
4912 }),4926 }),
4913 cc,4927 cc,
4914 ),4928 ),
4915 .memory, .linker_load => {4929 .memory, .load_tlv, .linker_load => {
4916 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();4930 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
4917 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);4931 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
4918 defer self.register_manager.unlockReg(addr_reg_lock);4932 defer self.register_manager.unlockReg(addr_reg_lock);
49194933
4920 switch (mat_src_mcv) {4934 switch (mat_src_mcv) {
4921 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),4935 .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 }),
4922 .linker_load => |load_struct| {4937 .linker_load => |load_struct| {
4923 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {4938 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
4924 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);4939 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...@@ -4982,13 +4997,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
4982 .undef => unreachable,4997 .undef => unreachable,
4983 .dead, .unreach => unreachable,4998 .dead, .unreach => unreachable,
4984 .register_overflow => unreachable,4999 .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 },
4992 .register => |src_reg| switch (ty.zigTypeTag()) {5000 .register => |src_reg| switch (ty.zigTypeTag()) {
4993 .Float => {5001 .Float => {
4994 if (intrinsicsAllowed(self.target.*, ty)) {5002 if (intrinsicsAllowed(self.target.*, ty)) {
...@@ -5037,7 +5045,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s...@@ -5037,7 +5045,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5037 )),5045 )),
5038 else => unreachable,5046 else => unreachable,
5039 },5047 },
5040 .memory, .linker_load, .eflags => {5048 .ptr_stack_offset, .memory, .lea_tlv, .load_tlv, .linker_load, .eflags => {
5041 assert(abi_size <= 8);5049 assert(abi_size <= 8);
5042 const dst_reg_lock = self.register_manager.lockReg(dst_reg);5050 const dst_reg_lock = self.register_manager.lockReg(dst_reg);
5043 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);5051 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...@@ -5052,19 +5060,20 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5052 ),5060 ),
5053 }5061 }
5054 },5062 },
5055 .memory, .linker_load, .stack_offset => {5063 .memory, .load_tlv, .linker_load, .stack_offset => {
5056 const dst: ?struct {5064 const dst: ?struct {
5057 addr_reg: Register,5065 addr_reg: Register,
5058 addr_lock: RegisterLock,5066 addr_lock: RegisterLock,
5059 } = switch (dst_mcv) {5067 } = switch (dst_mcv) {
5060 else => unreachable,5068 else => unreachable,
5061 .memory, .linker_load => dst: {5069 .memory, .load_tlv, .linker_load => dst: {
5062 const dst_addr_reg = (try self.register_manager.allocReg(null, gp)).to64();5070 const dst_addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
5063 const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);5071 const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);
5064 errdefer self.register_manager.unlockReg(dst_addr_lock);5072 errdefer self.register_manager.unlockReg(dst_addr_lock);
50655073
5066 switch (dst_mcv) {5074 switch (dst_mcv) {
5067 .memory => |addr| try self.genSetReg(Type.usize, dst_addr_reg, .{ .immediate = addr }),5075 .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 }),
5068 .linker_load => |load_struct| {5077 .linker_load => |load_struct| {
5069 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {5078 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
5070 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);5079 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...@@ -5099,7 +5108,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5099 addr_lock: RegisterLock,5108 addr_lock: RegisterLock,
5100 } = switch (src_mcv) {5109 } = switch (src_mcv) {
5101 else => null,5110 else => null,
5102 .memory, .linker_load => src: {5111 .memory, .load_tlv, .linker_load => src: {
5103 const src_limb_reg = try self.register_manager.allocReg(null, gp);5112 const src_limb_reg = try self.register_manager.allocReg(null, gp);
5104 const src_limb_lock = self.register_manager.lockRegAssumeUnused(src_limb_reg);5113 const src_limb_lock = self.register_manager.lockRegAssumeUnused(src_limb_reg);
5105 errdefer self.register_manager.unlockReg(src_limb_lock);5114 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...@@ -5110,6 +5119,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
51105119
5111 switch (src_mcv) {5120 switch (src_mcv) {
5112 .memory => |addr| try self.genSetReg(Type.usize, src_addr_reg, .{ .immediate = addr }),5121 .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 }),
5113 .linker_load => |load_struct| {5123 .linker_load => |load_struct| {
5114 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {5124 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
5115 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);5125 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...@@ -5233,7 +5243,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5233 else => unreachable,5243 else => unreachable,
5234 }5244 }
5235 },5245 },
5236 .memory, .linker_load, .tlv_reloc => {5246 .memory, .linker_load, .lea_tlv, .load_tlv => {
5237 try self.asmRegisterMemory(5247 try self.asmRegisterMemory(
5238 .mov,5248 .mov,
5239 registerAlias(src.?.limb_reg, limb_abi_size),5249 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...@@ -5272,7 +5282,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5272 }5282 }
5273 },5283 },
5274 .ptr_stack_offset => unreachable,5284 .ptr_stack_offset => unreachable,
5275 .tlv_reloc => unreachable,5285 .lea_tlv => unreachable,
5276 }5286 }
5277}5287}
52785288
...@@ -5286,7 +5296,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -5286,7 +5296,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
5286 .dead, .unreach, .immediate => unreachable,5296 .dead, .unreach, .immediate => unreachable,
5287 .eflags => unreachable,5297 .eflags => unreachable,
5288 .ptr_stack_offset => unreachable,5298 .ptr_stack_offset => unreachable,
5289 .tlv_reloc => unreachable,5299 .lea_tlv => unreachable,
5290 .register_overflow => unreachable,5300 .register_overflow => unreachable,
5291 .register => |dst_reg| {5301 .register => |dst_reg| {
5292 const dst_alias = registerAlias(dst_reg, abi_size);5302 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...@@ -5298,7 +5308,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
5298 .undef => try self.genSetReg(dst_ty, dst_reg, .undef),5308 .undef => try self.genSetReg(dst_ty, dst_reg, .undef),
5299 .dead, .unreach => unreachable,5309 .dead, .unreach => unreachable,
5300 .ptr_stack_offset => unreachable,5310 .ptr_stack_offset => unreachable,
5301 .tlv_reloc => unreachable,5311 .lea_tlv => unreachable,
5302 .register_overflow => unreachable,5312 .register_overflow => unreachable,
5303 .register => |src_reg| try self.asmRegisterRegister(5313 .register => |src_reg| try self.asmRegisterRegister(
5304 .imul,5314 .imul,
...@@ -5325,7 +5335,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -5325,7 +5335,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
5325 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .rbp, .disp = -off }),5335 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .rbp, .disp = -off }),
5326 );5336 );
5327 },5337 },
5328 .memory => {5338 .memory, .load_tlv => {
5329 return self.fail("TODO implement x86 multiply source memory", .{});5339 return self.fail("TODO implement x86 multiply source memory", .{});
5330 },5340 },
5331 .linker_load => {5341 .linker_load => {
...@@ -5342,7 +5352,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -5342,7 +5352,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
5342 .undef => return self.genSetStack(dst_ty, off, .undef, .{}),5352 .undef => return self.genSetStack(dst_ty, off, .undef, .{}),
5343 .dead, .unreach => unreachable,5353 .dead, .unreach => unreachable,
5344 .ptr_stack_offset => unreachable,5354 .ptr_stack_offset => unreachable,
5345 .tlv_reloc => unreachable,5355 .lea_tlv => unreachable,
5346 .register_overflow => unreachable,5356 .register_overflow => unreachable,
5347 .register => |src_reg| {5357 .register => |src_reg| {
5348 // copy dst to a register5358 // copy dst to a register
...@@ -5365,7 +5375,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -5365,7 +5375,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
53655375
5366 return self.genSetStack(dst_ty, off, .{ .register = dst_reg }, .{});5376 return self.genSetStack(dst_ty, off, .{ .register = dst_reg }, .{});
5367 },5377 },
5368 .memory, .stack_offset => {5378 .memory, .load_tlv, .stack_offset => {
5369 return self.fail("TODO implement x86 multiply source memory", .{});5379 return self.fail("TODO implement x86 multiply source memory", .{});
5370 },5380 },
5371 .linker_load => {5381 .linker_load => {
...@@ -5376,7 +5386,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -5376,7 +5386,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
5376 },5386 },
5377 }5387 }
5378 },5388 },
5379 .memory => {5389 .memory, .load_tlv => {
5380 return self.fail("TODO implement x86 multiply destination memory", .{});5390 return self.fail("TODO implement x86 multiply destination memory", .{});
5381 },5391 },
5382 .linker_load => {5392 .linker_load => {
...@@ -5565,7 +5575,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -5565,7 +5575,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
5565 .linker_load => unreachable,5575 .linker_load => unreachable,
5566 .eflags => unreachable,5576 .eflags => unreachable,
5567 .register_overflow => unreachable,5577 .register_overflow => unreachable,
5568 .tlv_reloc => unreachable,5578 .lea_tlv => unreachable,
5579 .load_tlv => unreachable,
5569 }5580 }
5570 }5581 }
55715582
...@@ -5604,7 +5615,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -5604,7 +5615,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
5604 .linker_load => unreachable,5615 .linker_load => unreachable,
5605 .eflags => unreachable,5616 .eflags => unreachable,
5606 .register_overflow => unreachable,5617 .register_overflow => unreachable,
5607 .tlv_reloc => unreachable,5618 .lea_tlv => unreachable,
5619 .load_tlv => unreachable,
5608 }5620 }
5609 }5621 }
56105622
...@@ -6126,7 +6138,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -6126,7 +6138,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
6126 .register_overflow,6138 .register_overflow,
6127 .ptr_stack_offset,6139 .ptr_stack_offset,
6128 .eflags,6140 .eflags,
6129 .tlv_reloc,6141 .lea_tlv,
6130 => unreachable,6142 => unreachable,
61316143
6132 .register => |opt_reg| {6144 .register => |opt_reg| {
...@@ -6147,13 +6159,14 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -6147,13 +6159,14 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
6147 return .{ .eflags = .nc };6159 return .{ .eflags = .nc };
6148 },6160 },
61496161
6150 .memory, .linker_load => {6162 .memory, .load_tlv, .linker_load => {
6151 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();6163 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
6152 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);6164 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
6153 defer self.register_manager.unlockReg(addr_reg_lock);6165 defer self.register_manager.unlockReg(addr_reg_lock);
61546166
6155 switch (opt_mcv) {6167 switch (opt_mcv) {
6156 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),6168 .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 }),
6157 .linker_load => |load_struct| {6170 .linker_load => |load_struct| {
6158 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {6171 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
6159 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);6172 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...@@ -7099,7 +7112,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
7099 else => return self.fail("TODO implement inputs on stack for {} with abi size > 8", .{mcv}),7112 else => return self.fail("TODO implement inputs on stack for {} with abi size > 8", .{mcv}),
7100 }7113 }
7101 },7114 },
7102 .memory, .linker_load => {7115 .memory, .load_tlv, .linker_load => {
7103 if (abi_size <= 8) {7116 if (abi_size <= 8) {
7104 const reg = try self.copyToTmpRegister(ty, mcv);7117 const reg = try self.copyToTmpRegister(ty, mcv);
7105 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });7118 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...@@ -7111,6 +7124,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
71117124
7112 switch (mcv) {7125 switch (mcv) {
7113 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),7126 .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 }),
7114 .linker_load => |load_struct| {7128 .linker_load => |load_struct| {
7115 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {7129 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
7116 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);7130 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...@@ -7170,7 +7184,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
7170 },7184 },
7171 }7185 }
7172 },7186 },
7173 .ptr_stack_offset, .tlv_reloc => {7187 .ptr_stack_offset, .lea_tlv => {
7174 const reg = try self.copyToTmpRegister(ty, mcv);7188 const reg = try self.copyToTmpRegister(ty, mcv);
7175 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });7189 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
7176 },7190 },
...@@ -7328,7 +7342,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl...@@ -7328,7 +7342,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
7328 },7342 },
7329 }7343 }
7330 },7344 },
7331 .memory, .linker_load => if (abi_size <= 8) {7345 .memory, .load_tlv, .linker_load => if (abi_size <= 8) {
7332 const reg = try self.copyToTmpRegister(ty, mcv);7346 const reg = try self.copyToTmpRegister(ty, mcv);
7333 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts);7347 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts);
7334 } else {7348 } else {
...@@ -7338,6 +7352,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl...@@ -7338,6 +7352,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
73387352
7339 switch (mcv) {7353 switch (mcv) {
7340 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),7354 .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 }),
7341 .linker_load => |load_struct| {7356 .linker_load => |load_struct| {
7342 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {7357 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
7343 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);7358 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...@@ -7375,7 +7390,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
7375 .{ .immediate = abi_size },7390 .{ .immediate = abi_size },
7376 .{},7391 .{},
7377 ),7392 ),
7378 .ptr_stack_offset, .tlv_reloc => {7393 .ptr_stack_offset, .lea_tlv => {
7379 const tmp_reg = try self.copyToTmpRegister(ty, mcv);7394 const tmp_reg = try self.copyToTmpRegister(ty, mcv);
7380 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);7395 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7381 defer self.register_manager.unlockReg(tmp_lock);7396 defer self.register_manager.unlockReg(tmp_lock);
...@@ -7484,7 +7499,10 @@ fn genInlineMemcpy(...@@ -7484,7 +7499,10 @@ fn genInlineMemcpy(
7484 .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),7499 .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),
7485 }7500 }
7486 },7501 },
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 }),
7488 .stack_offset, .ptr_stack_offset => |off| {7506 .stack_offset, .ptr_stack_offset => |off| {
7489 try self.asmRegisterMemory(switch (dst_ptr) {7507 try self.asmRegisterMemory(switch (dst_ptr) {
7490 .stack_offset => .mov,7508 .stack_offset => .mov,
...@@ -7527,7 +7545,10 @@ fn genInlineMemcpy(...@@ -7527,7 +7545,10 @@ fn genInlineMemcpy(
7527 .got, .direct => try self.asmMovLinker(.rsi, atom_index, load_struct),7545 .got, .direct => try self.asmMovLinker(.rsi, atom_index, load_struct),
7528 }7546 }
7529 },7547 },
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 }),
7531 .stack_offset, .ptr_stack_offset => |off| {7552 .stack_offset, .ptr_stack_offset => |off| {
7532 try self.asmRegisterMemory(switch (src_ptr) {7553 try self.asmRegisterMemory(switch (src_ptr) {
7533 .stack_offset => .mov,7554 .stack_offset => .mov,
...@@ -7593,7 +7614,10 @@ fn genInlineMemset(...@@ -7593,7 +7614,10 @@ fn genInlineMemset(
7593 .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),7614 .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),
7594 }7615 }
7595 },7616 },
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 }),
7597 .stack_offset, .ptr_stack_offset => |off| {7621 .stack_offset, .ptr_stack_offset => |off| {
7598 try self.asmRegisterMemory(switch (dst_ptr) {7622 try self.asmRegisterMemory(switch (dst_ptr) {
7599 .stack_offset => .mov,7623 .stack_offset => .mov,
...@@ -7769,7 +7793,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -7769,7 +7793,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
7769 }7793 }
7770 },7794 },
7771 },7795 },
7772 .tlv_reloc => |sym_index| {7796 .lea_tlv => |sym_index| {
7773 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: {
7774 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);7798 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
7775 break :blk macho_file.getAtom(atom).getSymbolIndex().?;7799 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
...@@ -7793,6 +7817,33 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -7793,6 +7817,33 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
7793 try self.genSetReg(Type.usize, reg, .{ .register = .rax });7817 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)});7818 } else return self.fail("TODO emit ptr to TLV sequence on {s}", .{@tagName(self.bin_file.tag)});
7795 },7819 },
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 },
7796 .linker_load => |load_struct| {7847 .linker_load => |load_struct| {
7797 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {7848 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
7798 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);7849 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
...@@ -8586,7 +8637,11 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -8586,7 +8637,11 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
8586 const elem_byte_off = @intCast(i32, elem_off / elem_abi_bits * elem_abi_size);8637 const elem_byte_off = @intCast(i32, elem_off / elem_abi_bits * elem_abi_size);
8587 const elem_bit_off = elem_off % elem_abi_bits;8638 const elem_bit_off = elem_off % elem_abi_bits;
8588 const elem_mcv = try self.resolveInst(elem);8639 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) {
8590 .register => |reg| self.register_manager.lockReg(reg),8645 .register => |reg| self.register_manager.lockReg(reg),
8591 .immediate => |imm| lock: {8646 .immediate => |imm| lock: {
8592 if (imm == 0) continue;8647 if (imm == 0) continue;
...@@ -8596,7 +8651,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -8596,7 +8651,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
8596 };8651 };
8597 defer if (elem_lock) |lock| self.register_manager.unlockReg(lock);8652 defer if (elem_lock) |lock| self.register_manager.unlockReg(lock);
8598 const elem_reg = registerAlias(8653 const elem_reg = registerAlias(
8599 try self.copyToTmpRegister(elem_ty, elem_mcv),8654 try self.copyToTmpRegister(elem_ty, mat_elem_mcv),
8600 elem_abi_size,8655 elem_abi_size,
8601 );8656 );
8602 const elem_extra_bits = self.regExtraBits(elem_ty);8657 const elem_extra_bits = self.regExtraBits(elem_ty);
...@@ -8616,7 +8671,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -8616,7 +8671,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
8616 .{ .register = elem_reg },8671 .{ .register = elem_reg },
8617 );8672 );
8618 if (elem_bit_off > elem_extra_bits) {8673 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);
8620 if (elem_extra_bits > 0) {8675 if (elem_extra_bits > 0) {
8621 try self.truncateRegister(elem_ty, registerAlias(reg, elem_abi_size));8676 try self.truncateRegister(elem_ty, registerAlias(reg, elem_abi_size));
8622 }8677 }
...@@ -8641,7 +8696,11 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -8641,7 +8696,11 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
8641 const elem_ty = result_ty.structFieldType(elem_i);8696 const elem_ty = result_ty.structFieldType(elem_i);
8642 const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, self.target.*));8697 const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, self.target.*));
8643 const elem_mcv = try self.resolveInst(elem);8698 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, .{});
8645 }8704 }
8646 break :res .{ .stack_offset = stack_offset };8705 break :res .{ .stack_offset = stack_offset };
8647 },8706 },
...@@ -8652,8 +8711,12 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -8652,8 +8711,12 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
86528711
8653 for (elements, 0..) |elem, elem_i| {8712 for (elements, 0..) |elem, elem_i| {
8654 const elem_mcv = try self.resolveInst(elem);8713 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 };
8655 const elem_off = @intCast(i32, elem_size * elem_i);8718 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, .{});
8657 }8720 }
8658 break :res MCValue{ .stack_offset = stack_offset };8721 break :res MCValue{ .stack_offset = stack_offset };
8659 },8722 },
...@@ -8779,7 +8842,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -8779,7 +8842,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
8779 .linker_load => |ll| .{ .linker_load = ll },8842 .linker_load => |ll| .{ .linker_load = ll },
8780 .immediate => |imm| .{ .immediate = imm },8843 .immediate => |imm| .{ .immediate = imm },
8781 .memory => |addr| .{ .memory = addr },8844 .memory => |addr| .{ .memory = addr },
8782 .tlv_reloc => |sym_index| .{ .tlv_reloc = sym_index },8845 .load_tlv => |sym_index| .{ .load_tlv = sym_index },
8783 },8846 },
8784 .fail => |msg| {8847 .fail => |msg| {
8785 self.err_msg = msg;8848 self.err_msg = msg;
src/codegen.zig+4-4
...@@ -932,10 +932,10 @@ pub const GenResult = union(enum) {...@@ -932,10 +932,10 @@ pub const GenResult = union(enum) {
932 /// such as ARM, the immediate will never exceed 32-bits.932 /// such as ARM, the immediate will never exceed 32-bits.
933 immediate: u64,933 immediate: u64,
934 linker_load: LinkerLoad,934 linker_load: LinkerLoad,
935 /// Pointer to a threadlocal variable.935 /// Threadlocal variable with address deferred until the linker allocates
936 /// The address resolution will be deferred until the linker allocates everything in virtual memory.936 /// everything in virtual memory.
937 /// Payload is a symbol index.937 /// Payload is a symbol index.
938 tlv_reloc: u32,938 load_tlv: u32,
939 /// Direct by-address reference to memory location.939 /// Direct by-address reference to memory location.
940 memory: u64,940 memory: u64,
941 };941 };
...@@ -1005,7 +1005,7 @@ fn genDeclRef(...@@ -1005,7 +1005,7 @@ fn genDeclRef(
1005 const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);1005 const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);
1006 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;1006 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
1007 if (is_threadlocal) {1007 if (is_threadlocal) {
1008 return GenResult.mcv(.{ .tlv_reloc = sym_index });1008 return GenResult.mcv(.{ .load_tlv = sym_index });
1009 }1009 }
1010 return GenResult.mcv(.{ .linker_load = .{1010 return GenResult.mcv(.{ .linker_load = .{
1011 .type = .got,1011 .type = .got,