| ... | ... | @@ -132,10 +132,12 @@ pub const MCValue = union(enum) { |
| 132 | 132 | memory: u64, |
| 133 | 133 | /// The value is in memory but requires a linker relocation fixup. |
| 134 | 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. |
| 135 | /// The value is a threadlocal variable. |
| 137 | 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 | 141 | /// The value is one of the stack variables. |
| 140 | 142 | /// If the type is a pointer, it means the pointer address is in the stack at this offset. |
| 141 | 143 | stack_offset: i32, |
| ... | ... | @@ -150,7 +152,8 @@ pub const MCValue = union(enum) { |
| 150 | 152 | .stack_offset, |
| 151 | 153 | .ptr_stack_offset, |
| 152 | 154 | .linker_load, |
| 153 | | .tlv_reloc, |
| 155 | .load_tlv, |
| 156 | .lea_tlv, |
| 154 | 157 | => true, |
| 155 | 158 | else => false, |
| 156 | 159 | }; |
| ... | ... | @@ -2923,7 +2926,8 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2923 | 2926 | })); |
| 2924 | 2927 | }, |
| 2925 | 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 | 2931 | .linker_load => |load_struct| { |
| 2928 | 2932 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 2929 | 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 | 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 | 3659 | const reg = try self.copyToTmpRegister(ptr_ty, ptr); |
| 3655 | 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 | 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 | 3815 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); |
| 3811 | 3816 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 3812 | 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 | 3824 | |
| 3820 | 3825 | switch (value) { |
| 3821 | 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 | 3828 | .linker_load => |load_struct| { |
| 3823 | 3829 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 3824 | 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 | 3861 | .{ .immediate = abi_size }, |
| 3856 | 3862 | .{}, |
| 3857 | 3863 | ), |
| 3858 | | .ptr_stack_offset, .tlv_reloc => { |
| 3864 | .ptr_stack_offset, .lea_tlv => { |
| 3859 | 3865 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); |
| 3860 | 3866 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 3861 | 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 | 3870 | }, |
| 3865 | 3871 | } |
| 3866 | 3872 | }, |
| 3867 | | .memory, .linker_load => { |
| 3873 | .memory, .load_tlv, .linker_load => { |
| 3868 | 3874 | const value_lock: ?RegisterLock = switch (value) { |
| 3869 | 3875 | .register => |reg| self.register_manager.lockReg(reg), |
| 3870 | 3876 | else => null, |
| ... | ... | @@ -3881,6 +3887,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3881 | 3887 | // Load the pointer, which is stored in memory |
| 3882 | 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 | 3891 | .linker_load => |load_struct| { |
| 3885 | 3892 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 3886 | 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 | 3907 | const new_ptr = MCValue{ .register = addr_reg }; |
| 3901 | 3908 | try self.store(new_ptr, value, ptr_ty, value_ty); |
| 3902 | 3909 | }, |
| 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); |
| 3905 | 3912 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 3906 | 3913 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 3907 | 3914 | |
| ... | ... | @@ -3953,14 +3960,17 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32 |
| 3953 | 3960 | |
| 3954 | 3961 | const dst_mcv: MCValue = result: { |
| 3955 | 3962 | switch (mcv) { |
| 3956 | | .stack_offset, .tlv_reloc => { |
| 3963 | .stack_offset, .lea_tlv, .load_tlv => { |
| 3957 | 3964 | const offset_reg = try self.copyToTmpRegister(ptr_ty, .{ |
| 3958 | 3965 | .immediate = field_offset, |
| 3959 | 3966 | }); |
| 3960 | 3967 | const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg); |
| 3961 | 3968 | defer self.register_manager.unlockReg(offset_reg_lock); |
| 3962 | 3969 | |
| 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 | 3974 | try self.genBinOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg }); |
| 3965 | 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 | 4245 | })); |
| 4236 | 4246 | }, |
| 4237 | 4247 | .ptr_stack_offset => unreachable, |
| 4238 | | .tlv_reloc => unreachable, |
| 4239 | | .memory, .linker_load => { |
| 4248 | .lea_tlv => unreachable, |
| 4249 | .memory, .load_tlv, .linker_load => { |
| 4240 | 4250 | const addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 4241 | 4251 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 4242 | 4252 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 4243 | 4253 | |
| 4244 | 4254 | switch (dst_mcv) { |
| 4245 | 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 | 4257 | .linker_load => |load_struct| { |
| 4247 | 4258 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 4248 | 4259 | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| ... | ... | @@ -4756,7 +4767,10 @@ fn genBinOp( |
| 4756 | 4767 | } |
| 4757 | 4768 | } |
| 4758 | 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 | 4774 | break :dst dst_mcv; |
| 4761 | 4775 | }; |
| 4762 | 4776 | const dst_mcv_lock: ?RegisterLock = switch (dst_mcv) { |
| ... | ... | @@ -4897,7 +4911,7 @@ fn genBinOp( |
| 4897 | 4911 | .eflags, |
| 4898 | 4912 | .register_overflow, |
| 4899 | 4913 | .ptr_stack_offset, |
| 4900 | | .tlv_reloc, |
| 4914 | .lea_tlv, |
| 4901 | 4915 | => unreachable, |
| 4902 | 4916 | .register => |src_reg| try self.asmCmovccRegisterRegister( |
| 4903 | 4917 | registerAlias(tmp_reg, cmov_abi_size), |
| ... | ... | @@ -4912,13 +4926,14 @@ fn genBinOp( |
| 4912 | 4926 | }), |
| 4913 | 4927 | cc, |
| 4914 | 4928 | ), |
| 4915 | | .memory, .linker_load => { |
| 4929 | .memory, .load_tlv, .linker_load => { |
| 4916 | 4930 | const addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 4917 | 4931 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 4918 | 4932 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 4919 | 4933 | |
| 4920 | 4934 | switch (mat_src_mcv) { |
| 4921 | 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 | 4937 | .linker_load => |load_struct| { |
| 4923 | 4938 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 4924 | 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 | 4997 | .undef => unreachable, |
| 4983 | 4998 | .dead, .unreach => unreachable, |
| 4984 | 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 | 5000 | .register => |src_reg| switch (ty.zigTypeTag()) { |
| 4993 | 5001 | .Float => { |
| 4994 | 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 | 5045 | )), |
| 5038 | 5046 | else => unreachable, |
| 5039 | 5047 | }, |
| 5040 | | .memory, .linker_load, .eflags => { |
| 5048 | .ptr_stack_offset, .memory, .lea_tlv, .load_tlv, .linker_load, .eflags => { |
| 5041 | 5049 | assert(abi_size <= 8); |
| 5042 | 5050 | const dst_reg_lock = self.register_manager.lockReg(dst_reg); |
| 5043 | 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 | 5060 | ), |
| 5053 | 5061 | } |
| 5054 | 5062 | }, |
| 5055 | | .memory, .linker_load, .stack_offset => { |
| 5063 | .memory, .load_tlv, .linker_load, .stack_offset => { |
| 5056 | 5064 | const dst: ?struct { |
| 5057 | 5065 | addr_reg: Register, |
| 5058 | 5066 | addr_lock: RegisterLock, |
| 5059 | 5067 | } = switch (dst_mcv) { |
| 5060 | 5068 | else => unreachable, |
| 5061 | | .memory, .linker_load => dst: { |
| 5069 | .memory, .load_tlv, .linker_load => dst: { |
| 5062 | 5070 | const dst_addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 5063 | 5071 | const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg); |
| 5064 | 5072 | errdefer self.register_manager.unlockReg(dst_addr_lock); |
| 5065 | 5073 | |
| 5066 | 5074 | switch (dst_mcv) { |
| 5067 | 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 | 5077 | .linker_load => |load_struct| { |
| 5069 | 5078 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 5070 | 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 | 5108 | addr_lock: RegisterLock, |
| 5100 | 5109 | } = switch (src_mcv) { |
| 5101 | 5110 | else => null, |
| 5102 | | .memory, .linker_load => src: { |
| 5111 | .memory, .load_tlv, .linker_load => src: { |
| 5103 | 5112 | const src_limb_reg = try self.register_manager.allocReg(null, gp); |
| 5104 | 5113 | const src_limb_lock = self.register_manager.lockRegAssumeUnused(src_limb_reg); |
| 5105 | 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 | 5119 | |
| 5111 | 5120 | switch (src_mcv) { |
| 5112 | 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 | 5123 | .linker_load => |load_struct| { |
| 5114 | 5124 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 5115 | 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 | 5243 | else => unreachable, |
| 5234 | 5244 | } |
| 5235 | 5245 | }, |
| 5236 | | .memory, .linker_load, .tlv_reloc => { |
| 5246 | .memory, .linker_load, .lea_tlv, .load_tlv => { |
| 5237 | 5247 | try self.asmRegisterMemory( |
| 5238 | 5248 | .mov, |
| 5239 | 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 | 5282 | } |
| 5273 | 5283 | }, |
| 5274 | 5284 | .ptr_stack_offset => unreachable, |
| 5275 | | .tlv_reloc => unreachable, |
| 5285 | .lea_tlv => unreachable, |
| 5276 | 5286 | } |
| 5277 | 5287 | } |
| 5278 | 5288 | |
| ... | ... | @@ -5286,7 +5296,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 5286 | 5296 | .dead, .unreach, .immediate => unreachable, |
| 5287 | 5297 | .eflags => unreachable, |
| 5288 | 5298 | .ptr_stack_offset => unreachable, |
| 5289 | | .tlv_reloc => unreachable, |
| 5299 | .lea_tlv => unreachable, |
| 5290 | 5300 | .register_overflow => unreachable, |
| 5291 | 5301 | .register => |dst_reg| { |
| 5292 | 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 | 5308 | .undef => try self.genSetReg(dst_ty, dst_reg, .undef), |
| 5299 | 5309 | .dead, .unreach => unreachable, |
| 5300 | 5310 | .ptr_stack_offset => unreachable, |
| 5301 | | .tlv_reloc => unreachable, |
| 5311 | .lea_tlv => unreachable, |
| 5302 | 5312 | .register_overflow => unreachable, |
| 5303 | 5313 | .register => |src_reg| try self.asmRegisterRegister( |
| 5304 | 5314 | .imul, |
| ... | ... | @@ -5325,7 +5335,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 5325 | 5335 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .rbp, .disp = -off }), |
| 5326 | 5336 | ); |
| 5327 | 5337 | }, |
| 5328 | | .memory => { |
| 5338 | .memory, .load_tlv => { |
| 5329 | 5339 | return self.fail("TODO implement x86 multiply source memory", .{}); |
| 5330 | 5340 | }, |
| 5331 | 5341 | .linker_load => { |
| ... | ... | @@ -5342,7 +5352,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 5342 | 5352 | .undef => return self.genSetStack(dst_ty, off, .undef, .{}), |
| 5343 | 5353 | .dead, .unreach => unreachable, |
| 5344 | 5354 | .ptr_stack_offset => unreachable, |
| 5345 | | .tlv_reloc => unreachable, |
| 5355 | .lea_tlv => unreachable, |
| 5346 | 5356 | .register_overflow => unreachable, |
| 5347 | 5357 | .register => |src_reg| { |
| 5348 | 5358 | // copy dst to a register |
| ... | ... | @@ -5365,7 +5375,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 5365 | 5375 | |
| 5366 | 5376 | return self.genSetStack(dst_ty, off, .{ .register = dst_reg }, .{}); |
| 5367 | 5377 | }, |
| 5368 | | .memory, .stack_offset => { |
| 5378 | .memory, .load_tlv, .stack_offset => { |
| 5369 | 5379 | return self.fail("TODO implement x86 multiply source memory", .{}); |
| 5370 | 5380 | }, |
| 5371 | 5381 | .linker_load => { |
| ... | ... | @@ -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 | 5390 | return self.fail("TODO implement x86 multiply destination memory", .{}); |
| 5381 | 5391 | }, |
| 5382 | 5392 | .linker_load => { |
| ... | ... | @@ -5565,7 +5575,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 5565 | 5575 | .linker_load => unreachable, |
| 5566 | 5576 | .eflags => unreachable, |
| 5567 | 5577 | .register_overflow => unreachable, |
| 5568 | | .tlv_reloc => unreachable, |
| 5578 | .lea_tlv => unreachable, |
| 5579 | .load_tlv => unreachable, |
| 5569 | 5580 | } |
| 5570 | 5581 | } |
| 5571 | 5582 | |
| ... | ... | @@ -5604,7 +5615,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 5604 | 5615 | .linker_load => unreachable, |
| 5605 | 5616 | .eflags => unreachable, |
| 5606 | 5617 | .register_overflow => unreachable, |
| 5607 | | .tlv_reloc => unreachable, |
| 5618 | .lea_tlv => unreachable, |
| 5619 | .load_tlv => unreachable, |
| 5608 | 5620 | } |
| 5609 | 5621 | } |
| 5610 | 5622 | |
| ... | ... | @@ -6126,7 +6138,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 6126 | 6138 | .register_overflow, |
| 6127 | 6139 | .ptr_stack_offset, |
| 6128 | 6140 | .eflags, |
| 6129 | | .tlv_reloc, |
| 6141 | .lea_tlv, |
| 6130 | 6142 | => unreachable, |
| 6131 | 6143 | |
| 6132 | 6144 | .register => |opt_reg| { |
| ... | ... | @@ -6147,13 +6159,14 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 6147 | 6159 | return .{ .eflags = .nc }; |
| 6148 | 6160 | }, |
| 6149 | 6161 | |
| 6150 | | .memory, .linker_load => { |
| 6162 | .memory, .load_tlv, .linker_load => { |
| 6151 | 6163 | const addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 6152 | 6164 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 6153 | 6165 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 6154 | 6166 | |
| 6155 | 6167 | switch (opt_mcv) { |
| 6156 | 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 | 6170 | .linker_load => |load_struct| { |
| 6158 | 6171 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 6159 | 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 | 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 | 7116 | if (abi_size <= 8) { |
| 7104 | 7117 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 7105 | 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 | 7124 | |
| 7112 | 7125 | switch (mcv) { |
| 7113 | 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 | 7128 | .linker_load => |load_struct| { |
| 7115 | 7129 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 7116 | 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 | 7184 | }, |
| 7171 | 7185 | } |
| 7172 | 7186 | }, |
| 7173 | | .ptr_stack_offset, .tlv_reloc => { |
| 7187 | .ptr_stack_offset, .lea_tlv => { |
| 7174 | 7188 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 7175 | 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 | 7342 | }, |
| 7329 | 7343 | } |
| 7330 | 7344 | }, |
| 7331 | | .memory, .linker_load => if (abi_size <= 8) { |
| 7345 | .memory, .load_tlv, .linker_load => if (abi_size <= 8) { |
| 7332 | 7346 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 7333 | 7347 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts); |
| 7334 | 7348 | } else { |
| ... | ... | @@ -7338,6 +7352,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 7338 | 7352 | |
| 7339 | 7353 | switch (mcv) { |
| 7340 | 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 | 7356 | .linker_load => |load_struct| { |
| 7342 | 7357 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 7343 | 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 | 7390 | .{ .immediate = abi_size }, |
| 7376 | 7391 | .{}, |
| 7377 | 7392 | ), |
| 7378 | | .ptr_stack_offset, .tlv_reloc => { |
| 7393 | .ptr_stack_offset, .lea_tlv => { |
| 7379 | 7394 | const tmp_reg = try self.copyToTmpRegister(ty, mcv); |
| 7380 | 7395 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7381 | 7396 | defer self.register_manager.unlockReg(tmp_lock); |
| ... | ... | @@ -7484,7 +7499,10 @@ fn genInlineMemcpy( |
| 7484 | 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 | 7506 | .stack_offset, .ptr_stack_offset => |off| { |
| 7489 | 7507 | try self.asmRegisterMemory(switch (dst_ptr) { |
| 7490 | 7508 | .stack_offset => .mov, |
| ... | ... | @@ -7527,7 +7545,10 @@ fn genInlineMemcpy( |
| 7527 | 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 | 7552 | .stack_offset, .ptr_stack_offset => |off| { |
| 7532 | 7553 | try self.asmRegisterMemory(switch (src_ptr) { |
| 7533 | 7554 | .stack_offset => .mov, |
| ... | ... | @@ -7593,7 +7614,10 @@ fn genInlineMemset( |
| 7593 | 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 | 7621 | .stack_offset, .ptr_stack_offset => |off| { |
| 7598 | 7622 | try self.asmRegisterMemory(switch (dst_ptr) { |
| 7599 | 7623 | .stack_offset => .mov, |
| ... | ... | @@ -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 | 7797 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 7774 | 7798 | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 7775 | 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 | 7817 | try self.genSetReg(Type.usize, reg, .{ .register = .rax }); |
| 7794 | 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 | 7847 | .linker_load => |load_struct| { |
| 7797 | 7848 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 7798 | 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 | 8637 | const elem_byte_off = @intCast(i32, elem_off / elem_abi_bits * elem_abi_size); |
| 8587 | 8638 | const elem_bit_off = elem_off % elem_abi_bits; |
| 8588 | 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 | 8645 | .register => |reg| self.register_manager.lockReg(reg), |
| 8591 | 8646 | .immediate => |imm| lock: { |
| 8592 | 8647 | if (imm == 0) continue; |
| ... | ... | @@ -8596,7 +8651,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 8596 | 8651 | }; |
| 8597 | 8652 | defer if (elem_lock) |lock| self.register_manager.unlockReg(lock); |
| 8598 | 8653 | const elem_reg = registerAlias( |
| 8599 | | try self.copyToTmpRegister(elem_ty, elem_mcv), |
| 8654 | try self.copyToTmpRegister(elem_ty, mat_elem_mcv), |
| 8600 | 8655 | elem_abi_size, |
| 8601 | 8656 | ); |
| 8602 | 8657 | const elem_extra_bits = self.regExtraBits(elem_ty); |
| ... | ... | @@ -8616,7 +8671,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 8616 | 8671 | .{ .register = elem_reg }, |
| 8617 | 8672 | ); |
| 8618 | 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 | 8675 | if (elem_extra_bits > 0) { |
| 8621 | 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 | 8696 | const elem_ty = result_ty.structFieldType(elem_i); |
| 8642 | 8697 | const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, self.target.*)); |
| 8643 | 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 | 8705 | break :res .{ .stack_offset = stack_offset }; |
| 8647 | 8706 | }, |
| ... | ... | @@ -8652,8 +8711,12 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 8652 | 8711 | |
| 8653 | 8712 | for (elements, 0..) |elem, elem_i| { |
| 8654 | 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 | 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 | 8721 | break :res MCValue{ .stack_offset = stack_offset }; |
| 8659 | 8722 | }, |
| ... | ... | @@ -8779,7 +8842,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { |
| 8779 | 8842 | .linker_load => |ll| .{ .linker_load = ll }, |
| 8780 | 8843 | .immediate => |imm| .{ .immediate = imm }, |
| 8781 | 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 | 8847 | .fail => |msg| { |
| 8785 | 8848 | self.err_msg = msg; |