| ... | @@ -132,6 +132,10 @@ pub const MCValue = union(enum) { | ... | @@ -132,6 +132,10 @@ pub const MCValue = union(enum) { |
| 132 | memory: u64, | 132 | memory: u64, |
| 133 | /// The value is in memory but requires a linker relocation fixup. | 133 | /// The value is in memory but requires a linker relocation fixup. |
| 134 | linker_load: codegen.LinkerLoad, | 134 | linker_load: codegen.LinkerLoad, |
| | 135 | /// Pointer to a threadlocal variable. |
| | 136 | /// The address resolution will be deferred until the linker allocates everything in virtual memory. |
| | 137 | /// Payload is a symbol index. |
| | 138 | tlv_reloc: u32, |
| 135 | /// The value is one of the stack variables. | 139 | /// The value is one of the stack variables. |
| 136 | /// If the type is a pointer, it means the pointer address is in the stack at this offset. | 140 | /// If the type is a pointer, it means the pointer address is in the stack at this offset. |
| 137 | stack_offset: i32, | 141 | stack_offset: i32, |
| ... | @@ -146,6 +150,7 @@ pub const MCValue = union(enum) { | ... | @@ -146,6 +150,7 @@ pub const MCValue = union(enum) { |
| 146 | .stack_offset, | 150 | .stack_offset, |
| 147 | .ptr_stack_offset, | 151 | .ptr_stack_offset, |
| 148 | .linker_load, | 152 | .linker_load, |
| | 153 | .tlv_reloc, |
| 149 | => true, | 154 | => true, |
| 150 | else => false, | 155 | else => false, |
| 151 | }; | 156 | }; |
| ... | @@ -736,7 +741,6 @@ fn asmMovLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege | ... | @@ -736,7 +741,6 @@ fn asmMovLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege |
| 736 | .got => .got_reloc, | 741 | .got => .got_reloc, |
| 737 | .direct => .direct_reloc, | 742 | .direct => .direct_reloc, |
| 738 | .import => .import_reloc, | 743 | .import => .import_reloc, |
| 739 | .tlv => .tlv_reloc, | | |
| 740 | }; | 744 | }; |
| 741 | _ = try self.addInst(.{ | 745 | _ = try self.addInst(.{ |
| 742 | .tag = .mov_linker, | 746 | .tag = .mov_linker, |
| ... | @@ -754,7 +758,6 @@ fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege | ... | @@ -754,7 +758,6 @@ fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege |
| 754 | .got => .got_reloc, | 758 | .got => .got_reloc, |
| 755 | .direct => .direct_reloc, | 759 | .direct => .direct_reloc, |
| 756 | .import => .import_reloc, | 760 | .import => .import_reloc, |
| 757 | .tlv => .tlv_reloc, | | |
| 758 | }; | 761 | }; |
| 759 | _ = try self.addInst(.{ | 762 | _ = try self.addInst(.{ |
| 760 | .tag = .lea_linker, | 763 | .tag = .lea_linker, |
| ... | @@ -767,15 +770,6 @@ fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege | ... | @@ -767,15 +770,6 @@ fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege |
| 767 | }); | 770 | }); |
| 768 | } | 771 | } |
| 769 | | 772 | |
| 770 | fn genTlvPtr(self: *Self, reg: Register, atom_index: u32, linker_load: codegen.LinkerLoad) !void { | | |
| 771 | assert(linker_load.type == .tlv); | | |
| 772 | if (self.bin_file.cast(link.File.MachO)) |_| { | | |
| 773 | try self.asmMovLinker(.rdi, atom_index, linker_load); | | |
| 774 | try self.asmMemory(.call, Memory.sib(.qword, .{ .base = .rdi })); | | |
| 775 | try self.genSetReg(Type.usize, reg, .{ .register = .rax }); | | |
| 776 | } else return self.fail("TODO emit ptr-to-TLV sequence on {s}", .{@tagName(self.bin_file.tag)}); | | |
| 777 | } | | |
| 778 | | | |
| 779 | fn gen(self: *Self) InnerError!void { | 773 | fn gen(self: *Self) InnerError!void { |
| 780 | const cc = self.fn_type.fnCallingConvention(); | 774 | const cc = self.fn_type.fnCallingConvention(); |
| 781 | if (cc != .Naked) { | 775 | if (cc != .Naked) { |
| ... | @@ -2929,6 +2923,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2929,6 +2923,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2929 | })); | 2923 | })); |
| 2930 | }, | 2924 | }, |
| 2931 | .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }), | 2925 | .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }), |
| | 2926 | .tlv_reloc => try self.genSetReg(array_ty, addr_reg, array), |
| 2932 | .linker_load => |load_struct| { | 2927 | .linker_load => |load_struct| { |
| 2933 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { | 2928 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 2934 | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); | 2929 | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| ... | @@ -2942,7 +2937,6 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2942,7 +2937,6 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2942 | .import => unreachable, | 2937 | .import => unreachable, |
| 2943 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), | 2938 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 2944 | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), | 2939 | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), |
| 2945 | .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct), | | |
| 2946 | } | 2940 | } |
| 2947 | }, | 2941 | }, |
| 2948 | else => return self.fail("TODO implement array_elem_val when array is {}", .{array}), | 2942 | else => return self.fail("TODO implement array_elem_val when array is {}", .{array}), |
| ... | @@ -3656,7 +3650,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -3656,7 +3650,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 3656 | else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}), | 3650 | else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}), |
| 3657 | } | 3651 | } |
| 3658 | }, | 3652 | }, |
| 3659 | .memory => { | 3653 | .memory, .tlv_reloc => { |
| 3660 | const reg = try self.copyToTmpRegister(ptr_ty, ptr); | 3654 | const reg = try self.copyToTmpRegister(ptr_ty, ptr); |
| 3661 | try self.load(dst_mcv, .{ .register = reg }, ptr_ty); | 3655 | try self.load(dst_mcv, .{ .register = reg }, ptr_ty); |
| 3662 | }, | 3656 | }, |
| ... | @@ -3676,7 +3670,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -3676,7 +3670,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 3676 | switch (load_struct.type) { | 3670 | switch (load_struct.type) { |
| 3677 | .import => unreachable, | 3671 | .import => unreachable, |
| 3678 | .got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct), | 3672 | .got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 3679 | .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct), | | |
| 3680 | } | 3673 | } |
| 3681 | | 3674 | |
| 3682 | try self.load(dst_mcv, .{ .register = addr_reg }, ptr_ty); | 3675 | try self.load(dst_mcv, .{ .register = addr_reg }, ptr_ty); |
| ... | @@ -3838,7 +3831,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -3838,7 +3831,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3838 | .import => unreachable, | 3831 | .import => unreachable, |
| 3839 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), | 3832 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 3840 | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), | 3833 | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), |
| 3841 | .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct), | | |
| 3842 | } | 3834 | } |
| 3843 | }, | 3835 | }, |
| 3844 | else => unreachable, | 3836 | else => unreachable, |
| ... | @@ -3863,7 +3855,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -3863,7 +3855,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3863 | .{ .immediate = abi_size }, | 3855 | .{ .immediate = abi_size }, |
| 3864 | .{}, | 3856 | .{}, |
| 3865 | ), | 3857 | ), |
| 3866 | .ptr_stack_offset => { | 3858 | .ptr_stack_offset, .tlv_reloc => { |
| 3867 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); | 3859 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); |
| 3868 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 3860 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 3869 | defer self.register_manager.unlockReg(tmp_lock); | 3861 | defer self.register_manager.unlockReg(tmp_lock); |
| ... | @@ -3900,12 +3892,19 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -3900,12 +3892,19 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3900 | switch (load_struct.type) { | 3892 | switch (load_struct.type) { |
| 3901 | .import => unreachable, | 3893 | .import => unreachable, |
| 3902 | .got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct), | 3894 | .got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 3903 | .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct), | | |
| 3904 | } | 3895 | } |
| 3905 | }, | 3896 | }, |
| 3906 | else => unreachable, | 3897 | else => unreachable, |
| 3907 | } | 3898 | } |
| 3908 | | 3899 | |
| | 3900 | const new_ptr = MCValue{ .register = addr_reg }; |
| | 3901 | try self.store(new_ptr, value, ptr_ty, value_ty); |
| | 3902 | }, |
| | 3903 | .tlv_reloc => { |
| | 3904 | const addr_reg = try self.copyToTmpRegister(Type.usize, ptr); |
| | 3905 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| | 3906 | defer self.register_manager.unlockReg(addr_reg_lock); |
| | 3907 | |
| 3909 | const new_ptr = MCValue{ .register = addr_reg }; | 3908 | const new_ptr = MCValue{ .register = addr_reg }; |
| 3910 | try self.store(new_ptr, value, ptr_ty, value_ty); | 3909 | try self.store(new_ptr, value, ptr_ty, value_ty); |
| 3911 | }, | 3910 | }, |
| ... | @@ -3954,7 +3953,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32 | ... | @@ -3954,7 +3953,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32 |
| 3954 | | 3953 | |
| 3955 | const dst_mcv: MCValue = result: { | 3954 | const dst_mcv: MCValue = result: { |
| 3956 | switch (mcv) { | 3955 | switch (mcv) { |
| 3957 | .stack_offset => { | 3956 | .stack_offset, .tlv_reloc => { |
| 3958 | const offset_reg = try self.copyToTmpRegister(ptr_ty, .{ | 3957 | const offset_reg = try self.copyToTmpRegister(ptr_ty, .{ |
| 3959 | .immediate = field_offset, | 3958 | .immediate = field_offset, |
| 3960 | }); | 3959 | }); |
| ... | @@ -4236,6 +4235,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue | ... | @@ -4236,6 +4235,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue |
| 4236 | })); | 4235 | })); |
| 4237 | }, | 4236 | }, |
| 4238 | .ptr_stack_offset => unreachable, | 4237 | .ptr_stack_offset => unreachable, |
| | 4238 | .tlv_reloc => unreachable, |
| 4239 | .memory, .linker_load => { | 4239 | .memory, .linker_load => { |
| 4240 | const addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); | 4240 | const addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 4241 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); | 4241 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| ... | @@ -4256,7 +4256,6 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue | ... | @@ -4256,7 +4256,6 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue |
| 4256 | .import => unreachable, | 4256 | .import => unreachable, |
| 4257 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), | 4257 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 4258 | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), | 4258 | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), |
| 4259 | .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct), | | |
| 4260 | } | 4259 | } |
| 4261 | }, | 4260 | }, |
| 4262 | else => unreachable, | 4261 | else => unreachable, |
| ... | @@ -4898,6 +4897,7 @@ fn genBinOp( | ... | @@ -4898,6 +4897,7 @@ fn genBinOp( |
| 4898 | .eflags, | 4897 | .eflags, |
| 4899 | .register_overflow, | 4898 | .register_overflow, |
| 4900 | .ptr_stack_offset, | 4899 | .ptr_stack_offset, |
| | 4900 | .tlv_reloc, |
| 4901 | => unreachable, | 4901 | => unreachable, |
| 4902 | .register => |src_reg| try self.asmCmovccRegisterRegister( | 4902 | .register => |src_reg| try self.asmCmovccRegisterRegister( |
| 4903 | registerAlias(tmp_reg, cmov_abi_size), | 4903 | registerAlias(tmp_reg, cmov_abi_size), |
| ... | @@ -4932,7 +4932,6 @@ fn genBinOp( | ... | @@ -4932,7 +4932,6 @@ fn genBinOp( |
| 4932 | .import => unreachable, | 4932 | .import => unreachable, |
| 4933 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), | 4933 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 4934 | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), | 4934 | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), |
| 4935 | .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct), | | |
| 4936 | } | 4935 | } |
| 4937 | }, | 4936 | }, |
| 4938 | else => unreachable, | 4937 | else => unreachable, |
| ... | @@ -4983,7 +4982,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s | ... | @@ -4983,7 +4982,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 4983 | .undef => unreachable, | 4982 | .undef => unreachable, |
| 4984 | .dead, .unreach => unreachable, | 4983 | .dead, .unreach => unreachable, |
| 4985 | .register_overflow => unreachable, | 4984 | .register_overflow => unreachable, |
| 4986 | .ptr_stack_offset => { | 4985 | .ptr_stack_offset, .tlv_reloc => { |
| 4987 | const dst_reg_lock = self.register_manager.lockReg(dst_reg); | 4986 | const dst_reg_lock = self.register_manager.lockReg(dst_reg); |
| 4988 | defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock); | 4987 | defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock); |
| 4989 | | 4988 | |
| ... | @@ -5079,7 +5078,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s | ... | @@ -5079,7 +5078,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 5079 | .import => unreachable, | 5078 | .import => unreachable, |
| 5080 | .got => try self.asmMovLinker(dst_addr_reg, atom_index, load_struct), | 5079 | .got => try self.asmMovLinker(dst_addr_reg, atom_index, load_struct), |
| 5081 | .direct => try self.asmLeaLinker(dst_addr_reg, atom_index, load_struct), | 5080 | .direct => try self.asmLeaLinker(dst_addr_reg, atom_index, load_struct), |
| 5082 | .tlv => try self.genTlvPtr(dst_addr_reg, atom_index, load_struct), | | |
| 5083 | } | 5081 | } |
| 5084 | }, | 5082 | }, |
| 5085 | else => unreachable, | 5083 | else => unreachable, |
| ... | @@ -5125,7 +5123,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s | ... | @@ -5125,7 +5123,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 5125 | .import => unreachable, | 5123 | .import => unreachable, |
| 5126 | .got => try self.asmMovLinker(src_addr_reg, atom_index, load_struct), | 5124 | .got => try self.asmMovLinker(src_addr_reg, atom_index, load_struct), |
| 5127 | .direct => try self.asmLeaLinker(src_addr_reg, atom_index, load_struct), | 5125 | .direct => try self.asmLeaLinker(src_addr_reg, atom_index, load_struct), |
| 5128 | .tlv => try self.genTlvPtr(src_addr_reg, atom_index, load_struct), | | |
| 5129 | } | 5126 | } |
| 5130 | }, | 5127 | }, |
| 5131 | else => unreachable, | 5128 | else => unreachable, |
| ... | @@ -5236,7 +5233,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s | ... | @@ -5236,7 +5233,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 5236 | else => unreachable, | 5233 | else => unreachable, |
| 5237 | } | 5234 | } |
| 5238 | }, | 5235 | }, |
| 5239 | .memory, .linker_load => { | 5236 | .memory, .linker_load, .tlv_reloc => { |
| 5240 | try self.asmRegisterMemory( | 5237 | try self.asmRegisterMemory( |
| 5241 | .mov, | 5238 | .mov, |
| 5242 | registerAlias(src.?.limb_reg, limb_abi_size), | 5239 | registerAlias(src.?.limb_reg, limb_abi_size), |
| ... | @@ -5275,6 +5272,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s | ... | @@ -5275,6 +5272,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 5275 | } | 5272 | } |
| 5276 | }, | 5273 | }, |
| 5277 | .ptr_stack_offset => unreachable, | 5274 | .ptr_stack_offset => unreachable, |
| | 5275 | .tlv_reloc => unreachable, |
| 5278 | } | 5276 | } |
| 5279 | } | 5277 | } |
| 5280 | | 5278 | |
| ... | @@ -5288,6 +5286,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M | ... | @@ -5288,6 +5286,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 5288 | .dead, .unreach, .immediate => unreachable, | 5286 | .dead, .unreach, .immediate => unreachable, |
| 5289 | .eflags => unreachable, | 5287 | .eflags => unreachable, |
| 5290 | .ptr_stack_offset => unreachable, | 5288 | .ptr_stack_offset => unreachable, |
| | 5289 | .tlv_reloc => unreachable, |
| 5291 | .register_overflow => unreachable, | 5290 | .register_overflow => unreachable, |
| 5292 | .register => |dst_reg| { | 5291 | .register => |dst_reg| { |
| 5293 | const dst_alias = registerAlias(dst_reg, abi_size); | 5292 | const dst_alias = registerAlias(dst_reg, abi_size); |
| ... | @@ -5299,6 +5298,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M | ... | @@ -5299,6 +5298,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 5299 | .undef => try self.genSetReg(dst_ty, dst_reg, .undef), | 5298 | .undef => try self.genSetReg(dst_ty, dst_reg, .undef), |
| 5300 | .dead, .unreach => unreachable, | 5299 | .dead, .unreach => unreachable, |
| 5301 | .ptr_stack_offset => unreachable, | 5300 | .ptr_stack_offset => unreachable, |
| | 5301 | .tlv_reloc => unreachable, |
| 5302 | .register_overflow => unreachable, | 5302 | .register_overflow => unreachable, |
| 5303 | .register => |src_reg| try self.asmRegisterRegister( | 5303 | .register => |src_reg| try self.asmRegisterRegister( |
| 5304 | .imul, | 5304 | .imul, |
| ... | @@ -5342,6 +5342,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M | ... | @@ -5342,6 +5342,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 5342 | .undef => return self.genSetStack(dst_ty, off, .undef, .{}), | 5342 | .undef => return self.genSetStack(dst_ty, off, .undef, .{}), |
| 5343 | .dead, .unreach => unreachable, | 5343 | .dead, .unreach => unreachable, |
| 5344 | .ptr_stack_offset => unreachable, | 5344 | .ptr_stack_offset => unreachable, |
| | 5345 | .tlv_reloc => unreachable, |
| 5345 | .register_overflow => unreachable, | 5346 | .register_overflow => unreachable, |
| 5346 | .register => |src_reg| { | 5347 | .register => |src_reg| { |
| 5347 | // copy dst to a register | 5348 | // copy dst to a register |
| ... | @@ -5564,6 +5565,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -5564,6 +5565,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 5564 | .linker_load => unreachable, | 5565 | .linker_load => unreachable, |
| 5565 | .eflags => unreachable, | 5566 | .eflags => unreachable, |
| 5566 | .register_overflow => unreachable, | 5567 | .register_overflow => unreachable, |
| | 5568 | .tlv_reloc => unreachable, |
| 5567 | } | 5569 | } |
| 5568 | } | 5570 | } |
| 5569 | | 5571 | |
| ... | @@ -5602,6 +5604,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -5602,6 +5604,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 5602 | .linker_load => unreachable, | 5604 | .linker_load => unreachable, |
| 5603 | .eflags => unreachable, | 5605 | .eflags => unreachable, |
| 5604 | .register_overflow => unreachable, | 5606 | .register_overflow => unreachable, |
| | 5607 | .tlv_reloc => unreachable, |
| 5605 | } | 5608 | } |
| 5606 | } | 5609 | } |
| 5607 | | 5610 | |
| ... | @@ -6123,6 +6126,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC | ... | @@ -6123,6 +6126,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 6123 | .register_overflow, | 6126 | .register_overflow, |
| 6124 | .ptr_stack_offset, | 6127 | .ptr_stack_offset, |
| 6125 | .eflags, | 6128 | .eflags, |
| | 6129 | .tlv_reloc, |
| 6126 | => unreachable, | 6130 | => unreachable, |
| 6127 | | 6131 | |
| 6128 | .register => |opt_reg| { | 6132 | .register => |opt_reg| { |
| ... | @@ -6163,7 +6167,6 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC | ... | @@ -6163,7 +6167,6 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 6163 | .import => unreachable, | 6167 | .import => unreachable, |
| 6164 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), | 6168 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 6165 | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), | 6169 | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), |
| 6166 | .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct), | | |
| 6167 | } | 6170 | } |
| 6168 | }, | 6171 | }, |
| 6169 | else => unreachable, | 6172 | else => unreachable, |
| ... | @@ -7121,7 +7124,6 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE | ... | @@ -7121,7 +7124,6 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 7121 | .import => unreachable, | 7124 | .import => unreachable, |
| 7122 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), | 7125 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 7123 | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), | 7126 | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), |
| 7124 | .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct), | | |
| 7125 | } | 7127 | } |
| 7126 | }, | 7128 | }, |
| 7127 | else => unreachable, | 7129 | else => unreachable, |
| ... | @@ -7168,7 +7170,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE | ... | @@ -7168,7 +7170,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 7168 | }, | 7170 | }, |
| 7169 | } | 7171 | } |
| 7170 | }, | 7172 | }, |
| 7171 | .ptr_stack_offset => { | 7173 | .ptr_stack_offset, .tlv_reloc => { |
| 7172 | const reg = try self.copyToTmpRegister(ty, mcv); | 7174 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 7173 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); | 7175 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| 7174 | }, | 7176 | }, |
| ... | @@ -7349,7 +7351,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl | ... | @@ -7349,7 +7351,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 7349 | .import => unreachable, | 7351 | .import => unreachable, |
| 7350 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), | 7352 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 7351 | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), | 7353 | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), |
| 7352 | .tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct), | | |
| 7353 | } | 7354 | } |
| 7354 | }, | 7355 | }, |
| 7355 | else => unreachable, | 7356 | else => unreachable, |
| ... | @@ -7374,7 +7375,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl | ... | @@ -7374,7 +7375,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 7374 | .{ .immediate = abi_size }, | 7375 | .{ .immediate = abi_size }, |
| 7375 | .{}, | 7376 | .{}, |
| 7376 | ), | 7377 | ), |
| 7377 | .ptr_stack_offset => { | 7378 | .ptr_stack_offset, .tlv_reloc => { |
| 7378 | const tmp_reg = try self.copyToTmpRegister(ty, mcv); | 7379 | const tmp_reg = try self.copyToTmpRegister(ty, mcv); |
| 7379 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 7380 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7380 | defer self.register_manager.unlockReg(tmp_lock); | 7381 | defer self.register_manager.unlockReg(tmp_lock); |
| ... | @@ -7481,13 +7482,9 @@ fn genInlineMemcpy( | ... | @@ -7481,13 +7482,9 @@ fn genInlineMemcpy( |
| 7481 | switch (load_struct.type) { | 7482 | switch (load_struct.type) { |
| 7482 | .import => unreachable, | 7483 | .import => unreachable, |
| 7483 | .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct), | 7484 | .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct), |
| 7484 | .tlv => { | | |
| 7485 | try self.genTlvPtr(.rdi, atom_index, load_struct); | | |
| 7486 | // Load the pointer, which is stored in memory | | |
| 7487 | try self.asmRegisterMemory(.mov, .rdi, Memory.sib(.qword, .{ .base = .rdi })); | | |
| 7488 | }, | | |
| 7489 | } | 7485 | } |
| 7490 | }, | 7486 | }, |
| | 7487 | .tlv_reloc => try self.genSetReg(Type.usize, .rdi, dst_ptr), |
| 7491 | .stack_offset, .ptr_stack_offset => |off| { | 7488 | .stack_offset, .ptr_stack_offset => |off| { |
| 7492 | try self.asmRegisterMemory(switch (dst_ptr) { | 7489 | try self.asmRegisterMemory(switch (dst_ptr) { |
| 7493 | .stack_offset => .mov, | 7490 | .stack_offset => .mov, |
| ... | @@ -7528,13 +7525,9 @@ fn genInlineMemcpy( | ... | @@ -7528,13 +7525,9 @@ fn genInlineMemcpy( |
| 7528 | switch (load_struct.type) { | 7525 | switch (load_struct.type) { |
| 7529 | .import => unreachable, | 7526 | .import => unreachable, |
| 7530 | .got, .direct => try self.asmMovLinker(.rsi, atom_index, load_struct), | 7527 | .got, .direct => try self.asmMovLinker(.rsi, atom_index, load_struct), |
| 7531 | .tlv => { | | |
| 7532 | try self.genTlvPtr(.rsi, atom_index, load_struct); | | |
| 7533 | // Load the pointer, which is stored in memory | | |
| 7534 | try self.asmRegisterMemory(.mov, .rsi, Memory.sib(.qword, .{ .base = .rsi })); | | |
| 7535 | }, | | |
| 7536 | } | 7528 | } |
| 7537 | }, | 7529 | }, |
| | 7530 | .tlv_reloc => try self.genSetReg(Type.usize, .rsi, src_ptr), |
| 7538 | .stack_offset, .ptr_stack_offset => |off| { | 7531 | .stack_offset, .ptr_stack_offset => |off| { |
| 7539 | try self.asmRegisterMemory(switch (src_ptr) { | 7532 | try self.asmRegisterMemory(switch (src_ptr) { |
| 7540 | .stack_offset => .mov, | 7533 | .stack_offset => .mov, |
| ... | @@ -7598,13 +7591,9 @@ fn genInlineMemset( | ... | @@ -7598,13 +7591,9 @@ fn genInlineMemset( |
| 7598 | switch (load_struct.type) { | 7591 | switch (load_struct.type) { |
| 7599 | .import => unreachable, | 7592 | .import => unreachable, |
| 7600 | .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct), | 7593 | .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct), |
| 7601 | .tlv => { | | |
| 7602 | try self.genTlvPtr(.rdi, atom_index, load_struct); | | |
| 7603 | // Load the pointer, which is stored in memory | | |
| 7604 | try self.asmRegisterMemory(.mov, .rdi, Memory.sib(.qword, .{ .base = .rdi })); | | |
| 7605 | }, | | |
| 7606 | } | 7594 | } |
| 7607 | }, | 7595 | }, |
| | 7596 | .tlv_reloc => try self.genSetReg(Type.usize, .rdi, dst_ptr), |
| 7608 | .stack_offset, .ptr_stack_offset => |off| { | 7597 | .stack_offset, .ptr_stack_offset => |off| { |
| 7609 | try self.asmRegisterMemory(switch (dst_ptr) { | 7598 | try self.asmRegisterMemory(switch (dst_ptr) { |
| 7610 | .stack_offset => .mov, | 7599 | .stack_offset => .mov, |
| ... | @@ -7780,6 +7769,30 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -7780,6 +7769,30 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 7780 | } | 7769 | } |
| 7781 | }, | 7770 | }, |
| 7782 | }, | 7771 | }, |
| | 7772 | .tlv_reloc => |sym_index| { |
| | 7773 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| | 7774 | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| | 7775 | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| | 7776 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { |
| | 7777 | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| | 7778 | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| | 7779 | } else unreachable; |
| | 7780 | |
| | 7781 | if (self.bin_file.cast(link.File.MachO)) |_| { |
| | 7782 | _ = try self.addInst(.{ |
| | 7783 | .tag = .mov_linker, |
| | 7784 | .ops = .tlv_reloc, |
| | 7785 | .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{ |
| | 7786 | .reg = @enumToInt(Register.rdi), |
| | 7787 | .atom_index = atom_index, |
| | 7788 | .sym_index = sym_index, |
| | 7789 | }) }, |
| | 7790 | }); |
| | 7791 | // TODO: spill registers before calling |
| | 7792 | try self.asmMemory(.call, Memory.sib(.qword, .{ .base = .rdi })); |
| | 7793 | try self.genSetReg(Type.usize, reg, .{ .register = .rax }); |
| | 7794 | } else return self.fail("TODO emit ptr to TLV sequence on {s}", .{@tagName(self.bin_file.tag)}); |
| | 7795 | }, |
| 7783 | .linker_load => |load_struct| { | 7796 | .linker_load => |load_struct| { |
| 7784 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { | 7797 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 7785 | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); | 7798 | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| ... | @@ -7792,10 +7805,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -7792,10 +7805,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 7792 | switch (ty.zigTypeTag()) { | 7805 | switch (ty.zigTypeTag()) { |
| 7793 | .Float => { | 7806 | .Float => { |
| 7794 | const base_reg = (try self.register_manager.allocReg(null, gp)).to64(); | 7807 | const base_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 7795 | switch (load_struct.type) { | 7808 | try self.asmLeaLinker(base_reg, atom_index, load_struct); |
| 7796 | .tlv => try self.genTlvPtr(base_reg, atom_index, load_struct), | | |
| 7797 | else => try self.asmLeaLinker(base_reg, atom_index, load_struct), | | |
| 7798 | } | | |
| 7799 | | 7809 | |
| 7800 | if (intrinsicsAllowed(self.target.*, ty)) { | 7810 | if (intrinsicsAllowed(self.target.*, ty)) { |
| 7801 | return self.asmRegisterMemory( | 7811 | return self.asmRegisterMemory( |
| ... | @@ -7813,17 +7823,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -7813,17 +7823,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 7813 | | 7823 | |
| 7814 | return self.fail("TODO genSetReg from memory for float with no intrinsics", .{}); | 7824 | return self.fail("TODO genSetReg from memory for float with no intrinsics", .{}); |
| 7815 | }, | 7825 | }, |
| 7816 | else => switch (load_struct.type) { | 7826 | else => try self.asmMovLinker(registerAlias(reg, abi_size), atom_index, load_struct), |
| 7817 | .tlv => { | | |
| 7818 | try self.genTlvPtr(reg.to64(), atom_index, load_struct); | | |
| 7819 | try self.asmRegisterMemory( | | |
| 7820 | .mov, | | |
| 7821 | registerAlias(reg, abi_size), | | |
| 7822 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }), | | |
| 7823 | ); | | |
| 7824 | }, | | |
| 7825 | else => try self.asmMovLinker(registerAlias(reg, abi_size), atom_index, load_struct), | | |
| 7826 | }, | | |
| 7827 | } | 7827 | } |
| 7828 | }, | 7828 | }, |
| 7829 | .stack_offset => |off| { | 7829 | .stack_offset => |off| { |
| ... | @@ -8779,6 +8779,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { | ... | @@ -8779,6 +8779,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { |
| 8779 | .linker_load => |ll| .{ .linker_load = ll }, | 8779 | .linker_load => |ll| .{ .linker_load = ll }, |
| 8780 | .immediate => |imm| .{ .immediate = imm }, | 8780 | .immediate => |imm| .{ .immediate = imm }, |
| 8781 | .memory => |addr| .{ .memory = addr }, | 8781 | .memory => |addr| .{ .memory = addr }, |
| | 8782 | .tlv_reloc => |sym_index| .{ .tlv_reloc = sym_index }, |
| 8782 | }, | 8783 | }, |
| 8783 | .fail => |msg| { | 8784 | .fail => |msg| { |
| 8784 | self.err_msg = msg; | 8785 | self.err_msg = msg; |