| ... | ... | @@ -132,6 +132,10 @@ 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. |
| 137 | /// Payload is a symbol index. |
| 138 | tlv_reloc: u32, |
| 135 | 139 | /// The value is one of the stack variables. |
| 136 | 140 | /// If the type is a pointer, it means the pointer address is in the stack at this offset. |
| 137 | 141 | stack_offset: i32, |
| ... | ... | @@ -146,6 +150,7 @@ pub const MCValue = union(enum) { |
| 146 | 150 | .stack_offset, |
| 147 | 151 | .ptr_stack_offset, |
| 148 | 152 | .linker_load, |
| 153 | .tlv_reloc, |
| 149 | 154 | => true, |
| 150 | 155 | else => false, |
| 151 | 156 | }; |
| ... | ... | @@ -736,7 +741,6 @@ fn asmMovLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege |
| 736 | 741 | .got => .got_reloc, |
| 737 | 742 | .direct => .direct_reloc, |
| 738 | 743 | .import => .import_reloc, |
| 739 | | .tlv => .tlv_reloc, |
| 740 | 744 | }; |
| 741 | 745 | _ = try self.addInst(.{ |
| 742 | 746 | .tag = .mov_linker, |
| ... | ... | @@ -754,7 +758,6 @@ fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege |
| 754 | 758 | .got => .got_reloc, |
| 755 | 759 | .direct => .direct_reloc, |
| 756 | 760 | .import => .import_reloc, |
| 757 | | .tlv => .tlv_reloc, |
| 758 | 761 | }; |
| 759 | 762 | _ = try self.addInst(.{ |
| 760 | 763 | .tag = .lea_linker, |
| ... | ... | @@ -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 | 773 | fn gen(self: *Self) InnerError!void { |
| 780 | 774 | const cc = self.fn_type.fnCallingConvention(); |
| 781 | 775 | if (cc != .Naked) { |
| ... | ... | @@ -2929,6 +2923,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2929 | 2923 | })); |
| 2930 | 2924 | }, |
| 2931 | 2925 | .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }), |
| 2926 | .tlv_reloc => try self.genSetReg(array_ty, addr_reg, array), |
| 2932 | 2927 | .linker_load => |load_struct| { |
| 2933 | 2928 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 2934 | 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 | 2937 | .import => unreachable, |
| 2943 | 2938 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 2944 | 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 | 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 | 3650 | else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}), |
| 3657 | 3651 | } |
| 3658 | 3652 | }, |
| 3659 | | .memory => { |
| 3653 | .memory, .tlv_reloc => { |
| 3660 | 3654 | const reg = try self.copyToTmpRegister(ptr_ty, ptr); |
| 3661 | 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 | 3670 | switch (load_struct.type) { |
| 3677 | 3671 | .import => unreachable, |
| 3678 | 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 | 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 | 3831 | .import => unreachable, |
| 3839 | 3832 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 3840 | 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 | 3836 | else => unreachable, |
| ... | ... | @@ -3863,7 +3855,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3863 | 3855 | .{ .immediate = abi_size }, |
| 3864 | 3856 | .{}, |
| 3865 | 3857 | ), |
| 3866 | | .ptr_stack_offset => { |
| 3858 | .ptr_stack_offset, .tlv_reloc => { |
| 3867 | 3859 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); |
| 3868 | 3860 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 3869 | 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 | 3892 | switch (load_struct.type) { |
| 3901 | 3893 | .import => unreachable, |
| 3902 | 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 | 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 | 3908 | const new_ptr = MCValue{ .register = addr_reg }; |
| 3910 | 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 | 3953 | |
| 3955 | 3954 | const dst_mcv: MCValue = result: { |
| 3956 | 3955 | switch (mcv) { |
| 3957 | | .stack_offset => { |
| 3956 | .stack_offset, .tlv_reloc => { |
| 3958 | 3957 | const offset_reg = try self.copyToTmpRegister(ptr_ty, .{ |
| 3959 | 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 | 4235 | })); |
| 4237 | 4236 | }, |
| 4238 | 4237 | .ptr_stack_offset => unreachable, |
| 4238 | .tlv_reloc => unreachable, |
| 4239 | 4239 | .memory, .linker_load => { |
| 4240 | 4240 | const addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 4241 | 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 | 4256 | .import => unreachable, |
| 4257 | 4257 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 4258 | 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 | 4261 | else => unreachable, |
| ... | ... | @@ -4898,6 +4897,7 @@ fn genBinOp( |
| 4898 | 4897 | .eflags, |
| 4899 | 4898 | .register_overflow, |
| 4900 | 4899 | .ptr_stack_offset, |
| 4900 | .tlv_reloc, |
| 4901 | 4901 | => unreachable, |
| 4902 | 4902 | .register => |src_reg| try self.asmCmovccRegisterRegister( |
| 4903 | 4903 | registerAlias(tmp_reg, cmov_abi_size), |
| ... | ... | @@ -4932,7 +4932,6 @@ fn genBinOp( |
| 4932 | 4932 | .import => unreachable, |
| 4933 | 4933 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 4934 | 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 | 4937 | else => unreachable, |
| ... | ... | @@ -4983,7 +4982,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 4983 | 4982 | .undef => unreachable, |
| 4984 | 4983 | .dead, .unreach => unreachable, |
| 4985 | 4984 | .register_overflow => unreachable, |
| 4986 | | .ptr_stack_offset => { |
| 4985 | .ptr_stack_offset, .tlv_reloc => { |
| 4987 | 4986 | const dst_reg_lock = self.register_manager.lockReg(dst_reg); |
| 4988 | 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 | 5078 | .import => unreachable, |
| 5080 | 5079 | .got => try self.asmMovLinker(dst_addr_reg, atom_index, load_struct), |
| 5081 | 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 | 5083 | else => unreachable, |
| ... | ... | @@ -5125,7 +5123,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 5125 | 5123 | .import => unreachable, |
| 5126 | 5124 | .got => try self.asmMovLinker(src_addr_reg, atom_index, load_struct), |
| 5127 | 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 | 5128 | else => unreachable, |
| ... | ... | @@ -5236,7 +5233,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 5236 | 5233 | else => unreachable, |
| 5237 | 5234 | } |
| 5238 | 5235 | }, |
| 5239 | | .memory, .linker_load => { |
| 5236 | .memory, .linker_load, .tlv_reloc => { |
| 5240 | 5237 | try self.asmRegisterMemory( |
| 5241 | 5238 | .mov, |
| 5242 | 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 | 5272 | } |
| 5276 | 5273 | }, |
| 5277 | 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 | 5286 | .dead, .unreach, .immediate => unreachable, |
| 5289 | 5287 | .eflags => unreachable, |
| 5290 | 5288 | .ptr_stack_offset => unreachable, |
| 5289 | .tlv_reloc => unreachable, |
| 5291 | 5290 | .register_overflow => unreachable, |
| 5292 | 5291 | .register => |dst_reg| { |
| 5293 | 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 | 5298 | .undef => try self.genSetReg(dst_ty, dst_reg, .undef), |
| 5300 | 5299 | .dead, .unreach => unreachable, |
| 5301 | 5300 | .ptr_stack_offset => unreachable, |
| 5301 | .tlv_reloc => unreachable, |
| 5302 | 5302 | .register_overflow => unreachable, |
| 5303 | 5303 | .register => |src_reg| try self.asmRegisterRegister( |
| 5304 | 5304 | .imul, |
| ... | ... | @@ -5342,6 +5342,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 5342 | 5342 | .undef => return self.genSetStack(dst_ty, off, .undef, .{}), |
| 5343 | 5343 | .dead, .unreach => unreachable, |
| 5344 | 5344 | .ptr_stack_offset => unreachable, |
| 5345 | .tlv_reloc => unreachable, |
| 5345 | 5346 | .register_overflow => unreachable, |
| 5346 | 5347 | .register => |src_reg| { |
| 5347 | 5348 | // copy dst to a register |
| ... | ... | @@ -5564,6 +5565,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 5564 | 5565 | .linker_load => unreachable, |
| 5565 | 5566 | .eflags => unreachable, |
| 5566 | 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 | 5604 | .linker_load => unreachable, |
| 5603 | 5605 | .eflags => unreachable, |
| 5604 | 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 | 6126 | .register_overflow, |
| 6124 | 6127 | .ptr_stack_offset, |
| 6125 | 6128 | .eflags, |
| 6129 | .tlv_reloc, |
| 6126 | 6130 | => unreachable, |
| 6127 | 6131 | |
| 6128 | 6132 | .register => |opt_reg| { |
| ... | ... | @@ -6163,7 +6167,6 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 6163 | 6167 | .import => unreachable, |
| 6164 | 6168 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 6165 | 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 | 6172 | else => unreachable, |
| ... | ... | @@ -7121,7 +7124,6 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 7121 | 7124 | .import => unreachable, |
| 7122 | 7125 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 7123 | 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 | 7129 | else => unreachable, |
| ... | ... | @@ -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 | 7174 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 7173 | 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 | 7351 | .import => unreachable, |
| 7350 | 7352 | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 7351 | 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 | 7356 | else => unreachable, |
| ... | ... | @@ -7374,7 +7375,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 7374 | 7375 | .{ .immediate = abi_size }, |
| 7375 | 7376 | .{}, |
| 7376 | 7377 | ), |
| 7377 | | .ptr_stack_offset => { |
| 7378 | .ptr_stack_offset, .tlv_reloc => { |
| 7378 | 7379 | const tmp_reg = try self.copyToTmpRegister(ty, mcv); |
| 7379 | 7380 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7380 | 7381 | defer self.register_manager.unlockReg(tmp_lock); |
| ... | ... | @@ -7481,13 +7482,9 @@ fn genInlineMemcpy( |
| 7481 | 7482 | switch (load_struct.type) { |
| 7482 | 7483 | .import => unreachable, |
| 7483 | 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 | 7488 | .stack_offset, .ptr_stack_offset => |off| { |
| 7492 | 7489 | try self.asmRegisterMemory(switch (dst_ptr) { |
| 7493 | 7490 | .stack_offset => .mov, |
| ... | ... | @@ -7528,13 +7525,9 @@ fn genInlineMemcpy( |
| 7528 | 7525 | switch (load_struct.type) { |
| 7529 | 7526 | .import => unreachable, |
| 7530 | 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 | 7531 | .stack_offset, .ptr_stack_offset => |off| { |
| 7539 | 7532 | try self.asmRegisterMemory(switch (src_ptr) { |
| 7540 | 7533 | .stack_offset => .mov, |
| ... | ... | @@ -7598,13 +7591,9 @@ fn genInlineMemset( |
| 7598 | 7591 | switch (load_struct.type) { |
| 7599 | 7592 | .import => unreachable, |
| 7600 | 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 | 7597 | .stack_offset, .ptr_stack_offset => |off| { |
| 7609 | 7598 | try self.asmRegisterMemory(switch (dst_ptr) { |
| 7610 | 7599 | .stack_offset => .mov, |
| ... | ... | @@ -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 | 7796 | .linker_load => |load_struct| { |
| 7784 | 7797 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 7785 | 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 | 7805 | switch (ty.zigTypeTag()) { |
| 7793 | 7806 | .Float => { |
| 7794 | 7807 | const base_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 7795 | | switch (load_struct.type) { |
| 7796 | | .tlv => try self.genTlvPtr(base_reg, atom_index, load_struct), |
| 7797 | | else => try self.asmLeaLinker(base_reg, atom_index, load_struct), |
| 7798 | | } |
| 7808 | try self.asmLeaLinker(base_reg, atom_index, load_struct); |
| 7799 | 7809 | |
| 7800 | 7810 | if (intrinsicsAllowed(self.target.*, ty)) { |
| 7801 | 7811 | return self.asmRegisterMemory( |
| ... | ... | @@ -7813,17 +7823,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 7813 | 7823 | |
| 7814 | 7824 | return self.fail("TODO genSetReg from memory for float with no intrinsics", .{}); |
| 7815 | 7825 | }, |
| 7816 | | else => switch (load_struct.type) { |
| 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 | | }, |
| 7826 | else => try self.asmMovLinker(registerAlias(reg, abi_size), atom_index, load_struct), |
| 7827 | 7827 | } |
| 7828 | 7828 | }, |
| 7829 | 7829 | .stack_offset => |off| { |
| ... | ... | @@ -8779,6 +8779,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { |
| 8779 | 8779 | .linker_load => |ll| .{ .linker_load = ll }, |
| 8780 | 8780 | .immediate => |imm| .{ .immediate = imm }, |
| 8781 | 8781 | .memory => |addr| .{ .memory = addr }, |
| 8782 | .tlv_reloc => |sym_index| .{ .tlv_reloc = sym_index }, |
| 8782 | 8783 | }, |
| 8783 | 8784 | .fail => |msg| { |
| 8784 | 8785 | self.err_msg = msg; |