| ... | ... | @@ -130,12 +130,21 @@ pub const MCValue = union(enum) { |
| 130 | 130 | /// The value is in memory at a hard-coded address. |
| 131 | 131 | /// If the type is a pointer, it means the pointer address is at this memory location. |
| 132 | 132 | memory: u64, |
| 133 | | /// The value is in memory but requires a linker relocation fixup. |
| 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. |
| 133 | /// The value is in memory. |
| 137 | 134 | /// Payload is a symbol index. |
| 138 | | tlv_reloc: u32, |
| 135 | load_direct: u32, |
| 136 | /// The value is a pointer to value in memory. |
| 137 | /// Payload is a symbol index. |
| 138 | lea_direct: u32, |
| 139 | /// The value is in memory referenced indirectly via GOT. |
| 140 | /// Payload is a symbol index. |
| 141 | load_got: u32, |
| 142 | /// The value is a threadlocal variable. |
| 143 | /// Payload is a symbol index. |
| 144 | load_tlv: u32, |
| 145 | /// The value is a pointer to threadlocal variable. |
| 146 | /// Payload is a symbol index. |
| 147 | lea_tlv: u32, |
| 139 | 148 | /// The value is one of the stack variables. |
| 140 | 149 | /// If the type is a pointer, it means the pointer address is in the stack at this offset. |
| 141 | 150 | stack_offset: i32, |
| ... | ... | @@ -149,8 +158,11 @@ pub const MCValue = union(enum) { |
| 149 | 158 | .memory, |
| 150 | 159 | .stack_offset, |
| 151 | 160 | .ptr_stack_offset, |
| 152 | | .linker_load, |
| 153 | | .tlv_reloc, |
| 161 | .load_direct, |
| 162 | .lea_direct, |
| 163 | .load_got, |
| 164 | .load_tlv, |
| 165 | .lea_tlv, |
| 154 | 166 | => true, |
| 155 | 167 | else => false, |
| 156 | 168 | }; |
| ... | ... | @@ -736,40 +748,6 @@ fn asmMemoryRegisterImmediate( |
| 736 | 748 | }); |
| 737 | 749 | } |
| 738 | 750 | |
| 739 | | fn asmMovLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codegen.LinkerLoad) !void { |
| 740 | | const ops: Mir.Inst.Ops = switch (linker_load.type) { |
| 741 | | .got => .got_reloc, |
| 742 | | .direct => .direct_reloc, |
| 743 | | .import => .import_reloc, |
| 744 | | }; |
| 745 | | _ = try self.addInst(.{ |
| 746 | | .tag = .mov_linker, |
| 747 | | .ops = ops, |
| 748 | | .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{ |
| 749 | | .reg = @enumToInt(reg), |
| 750 | | .atom_index = atom_index, |
| 751 | | .sym_index = linker_load.sym_index, |
| 752 | | }) }, |
| 753 | | }); |
| 754 | | } |
| 755 | | |
| 756 | | fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codegen.LinkerLoad) !void { |
| 757 | | const ops: Mir.Inst.Ops = switch (linker_load.type) { |
| 758 | | .got => .got_reloc, |
| 759 | | .direct => .direct_reloc, |
| 760 | | .import => .import_reloc, |
| 761 | | }; |
| 762 | | _ = try self.addInst(.{ |
| 763 | | .tag = .lea_linker, |
| 764 | | .ops = ops, |
| 765 | | .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{ |
| 766 | | .reg = @enumToInt(reg), |
| 767 | | .atom_index = atom_index, |
| 768 | | .sym_index = linker_load.sym_index, |
| 769 | | }) }, |
| 770 | | }); |
| 771 | | } |
| 772 | | |
| 773 | 751 | fn gen(self: *Self) InnerError!void { |
| 774 | 752 | const cc = self.fn_type.fnCallingConvention(); |
| 775 | 753 | if (cc != .Naked) { |
| ... | ... | @@ -2922,23 +2900,14 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2922 | 2900 | .disp = -off, |
| 2923 | 2901 | })); |
| 2924 | 2902 | }, |
| 2925 | | .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }), |
| 2926 | | .tlv_reloc => try self.genSetReg(array_ty, addr_reg, array), |
| 2927 | | .linker_load => |load_struct| { |
| 2928 | | 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); |
| 2930 | | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 2931 | | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { |
| 2932 | | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 2933 | | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 2934 | | } else unreachable; |
| 2935 | | |
| 2936 | | switch (load_struct.type) { |
| 2937 | | .import => unreachable, |
| 2938 | | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 2939 | | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), |
| 2940 | | } |
| 2941 | | }, |
| 2903 | .load_got => try self.genSetReg(array_ty, addr_reg, array), |
| 2904 | .memory, .load_direct, .load_tlv => try self.genSetReg(Type.usize, addr_reg, switch (array) { |
| 2905 | .memory => |addr| .{ .immediate = addr }, |
| 2906 | .load_direct => |sym_index| .{ .lea_direct = sym_index }, |
| 2907 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, |
| 2908 | else => unreachable, |
| 2909 | }), |
| 2910 | .lea_direct, .lea_tlv => unreachable, |
| 2942 | 2911 | else => return self.fail("TODO implement array_elem_val when array is {}", .{array}), |
| 2943 | 2912 | } |
| 2944 | 2913 | |
| ... | ... | @@ -3650,30 +3619,19 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 3650 | 3619 | else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}), |
| 3651 | 3620 | } |
| 3652 | 3621 | }, |
| 3653 | | .memory, .tlv_reloc => { |
| 3654 | | const reg = try self.copyToTmpRegister(ptr_ty, ptr); |
| 3655 | | try self.load(dst_mcv, .{ .register = reg }, ptr_ty); |
| 3656 | | }, |
| 3657 | | .linker_load => |load_struct| { |
| 3658 | | const addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 3622 | .load_direct => |sym_index| { |
| 3623 | const addr_reg = try self.copyToTmpRegister(Type.usize, .{ .lea_direct = sym_index }); |
| 3659 | 3624 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 3660 | 3625 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 3661 | | |
| 3662 | | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 3663 | | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 3664 | | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 3665 | | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { |
| 3666 | | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 3667 | | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 3668 | | } else unreachable; |
| 3669 | | |
| 3670 | | switch (load_struct.type) { |
| 3671 | | .import => unreachable, |
| 3672 | | .got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 3673 | | } |
| 3674 | | |
| 3626 | // Load the pointer, which is stored in memory |
| 3627 | try self.asmRegisterMemory(.mov, addr_reg, Memory.sib(.qword, .{ .base = addr_reg })); |
| 3675 | 3628 | try self.load(dst_mcv, .{ .register = addr_reg }, ptr_ty); |
| 3676 | 3629 | }, |
| 3630 | .load_tlv => |sym_index| try self.load(dst_mcv, .{ .lea_tlv = sym_index }, ptr_ty), |
| 3631 | .memory, .load_got, .lea_direct, .lea_tlv => { |
| 3632 | const reg = try self.copyToTmpRegister(ptr_ty, ptr); |
| 3633 | try self.load(dst_mcv, .{ .register = reg }, ptr_ty); |
| 3634 | }, |
| 3677 | 3635 | } |
| 3678 | 3636 | } |
| 3679 | 3637 | |
| ... | ... | @@ -3806,7 +3764,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3806 | 3764 | -@intCast(i32, overflow_bit_offset), |
| 3807 | 3765 | ); |
| 3808 | 3766 | }, |
| 3809 | | .memory, .linker_load => if (abi_size <= 8) { |
| 3767 | .memory, .load_tlv, .load_direct => if (abi_size <= 8) { |
| 3810 | 3768 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); |
| 3811 | 3769 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 3812 | 3770 | defer self.register_manager.unlockReg(tmp_lock); |
| ... | ... | @@ -3817,25 +3775,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3817 | 3775 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 3818 | 3776 | defer self.register_manager.unlockReg(addr_lock); |
| 3819 | 3777 | |
| 3820 | | switch (value) { |
| 3821 | | .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }), |
| 3822 | | .linker_load => |load_struct| { |
| 3823 | | 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); |
| 3825 | | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 3826 | | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { |
| 3827 | | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 3828 | | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 3829 | | } else unreachable; |
| 3830 | | switch (load_struct.type) { |
| 3831 | | .import => unreachable, |
| 3832 | | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 3833 | | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), |
| 3834 | | } |
| 3835 | | }, |
| 3778 | try self.genSetReg(Type.usize, addr_reg, switch (value) { |
| 3779 | .memory => |addr| .{ .immediate = addr }, |
| 3780 | .load_direct => |sym_index| .{ .lea_direct = sym_index }, |
| 3781 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, |
| 3836 | 3782 | else => unreachable, |
| 3837 | | } |
| 3838 | | |
| 3783 | }); |
| 3839 | 3784 | try self.genInlineMemcpy( |
| 3840 | 3785 | ptr, |
| 3841 | 3786 | .{ .register = addr_reg }, |
| ... | ... | @@ -3855,7 +3800,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3855 | 3800 | .{ .immediate = abi_size }, |
| 3856 | 3801 | .{}, |
| 3857 | 3802 | ), |
| 3858 | | .ptr_stack_offset, .tlv_reloc => { |
| 3803 | .ptr_stack_offset, .load_got, .lea_direct, .lea_tlv => { |
| 3859 | 3804 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); |
| 3860 | 3805 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 3861 | 3806 | defer self.register_manager.unlockReg(tmp_lock); |
| ... | ... | @@ -3864,7 +3809,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3864 | 3809 | }, |
| 3865 | 3810 | } |
| 3866 | 3811 | }, |
| 3867 | | .memory, .linker_load => { |
| 3812 | .memory, .load_direct, .load_tlv => { |
| 3868 | 3813 | const value_lock: ?RegisterLock = switch (value) { |
| 3869 | 3814 | .register => |reg| self.register_manager.lockReg(reg), |
| 3870 | 3815 | else => null, |
| ... | ... | @@ -3876,32 +3821,21 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3876 | 3821 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 3877 | 3822 | |
| 3878 | 3823 | switch (ptr) { |
| 3879 | | .memory => |addr| { |
| 3880 | | try self.genSetReg(ptr_ty, addr_reg, .{ .immediate = addr }); |
| 3881 | | // Load the pointer, which is stored in memory |
| 3882 | | try self.asmRegisterMemory(.mov, addr_reg, Memory.sib(.qword, .{ .base = addr_reg })); |
| 3883 | | }, |
| 3884 | | .linker_load => |load_struct| { |
| 3885 | | 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); |
| 3887 | | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 3888 | | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { |
| 3889 | | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 3890 | | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 3891 | | } else unreachable; |
| 3892 | | switch (load_struct.type) { |
| 3893 | | .import => unreachable, |
| 3894 | | .got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 3895 | | } |
| 3896 | | }, |
| 3824 | .memory => |addr| try self.genSetReg(ptr_ty, addr_reg, .{ .immediate = addr }), |
| 3825 | .load_direct => |sym_index| try self.genSetReg(ptr_ty, addr_reg, .{ .lea_direct = sym_index }), |
| 3826 | .load_tlv => |sym_index| try self.genSetReg(ptr_ty, addr_reg, .{ .lea_tlv = sym_index }), |
| 3897 | 3827 | else => unreachable, |
| 3898 | 3828 | } |
| 3829 | if (ptr != .load_tlv) { |
| 3830 | // Load the pointer, which is stored in memory |
| 3831 | try self.asmRegisterMemory(.mov, addr_reg, Memory.sib(.qword, .{ .base = addr_reg })); |
| 3832 | } |
| 3899 | 3833 | |
| 3900 | 3834 | const new_ptr = MCValue{ .register = addr_reg }; |
| 3901 | 3835 | try self.store(new_ptr, value, ptr_ty, value_ty); |
| 3902 | 3836 | }, |
| 3903 | | .tlv_reloc => { |
| 3904 | | const addr_reg = try self.copyToTmpRegister(Type.usize, ptr); |
| 3837 | .load_got, .lea_direct, .lea_tlv => { |
| 3838 | const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr); |
| 3905 | 3839 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 3906 | 3840 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 3907 | 3841 | |
| ... | ... | @@ -3953,14 +3887,17 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32 |
| 3953 | 3887 | |
| 3954 | 3888 | const dst_mcv: MCValue = result: { |
| 3955 | 3889 | switch (mcv) { |
| 3956 | | .stack_offset, .tlv_reloc => { |
| 3890 | .stack_offset, .lea_tlv, .load_tlv => { |
| 3957 | 3891 | const offset_reg = try self.copyToTmpRegister(ptr_ty, .{ |
| 3958 | 3892 | .immediate = field_offset, |
| 3959 | 3893 | }); |
| 3960 | 3894 | const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg); |
| 3961 | 3895 | defer self.register_manager.unlockReg(offset_reg_lock); |
| 3962 | 3896 | |
| 3963 | | const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, mcv); |
| 3897 | const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, switch (mcv) { |
| 3898 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, |
| 3899 | else => mcv, |
| 3900 | }); |
| 3964 | 3901 | try self.genBinOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg }); |
| 3965 | 3902 | break :result dst_mcv; |
| 3966 | 3903 | }, |
| ... | ... | @@ -4235,31 +4172,18 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue |
| 4235 | 4172 | })); |
| 4236 | 4173 | }, |
| 4237 | 4174 | .ptr_stack_offset => unreachable, |
| 4238 | | .tlv_reloc => unreachable, |
| 4239 | | .memory, .linker_load => { |
| 4175 | .load_got, .lea_direct, .lea_tlv => unreachable, |
| 4176 | .memory, .load_direct, .load_tlv => { |
| 4240 | 4177 | const addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 4241 | 4178 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 4242 | 4179 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 4243 | 4180 | |
| 4244 | | switch (dst_mcv) { |
| 4245 | | .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }), |
| 4246 | | .linker_load => |load_struct| { |
| 4247 | | 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); |
| 4249 | | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 4250 | | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { |
| 4251 | | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 4252 | | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 4253 | | } else unreachable; |
| 4254 | | |
| 4255 | | switch (load_struct.type) { |
| 4256 | | .import => unreachable, |
| 4257 | | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 4258 | | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), |
| 4259 | | } |
| 4260 | | }, |
| 4181 | try self.genSetReg(Type.usize, addr_reg, switch (dst_mcv) { |
| 4182 | .memory => |addr| .{ .immediate = addr }, |
| 4183 | .load_direct => |sym_index| .{ .lea_direct = sym_index }, |
| 4184 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, |
| 4261 | 4185 | else => unreachable, |
| 4262 | | } |
| 4186 | }); |
| 4263 | 4187 | try self.asmMemory( |
| 4264 | 4188 | mir_tag, |
| 4265 | 4189 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = addr_reg }), |
| ... | ... | @@ -4756,7 +4680,11 @@ fn genBinOp( |
| 4756 | 4680 | } |
| 4757 | 4681 | } |
| 4758 | 4682 | const dst_mcv = try self.allocRegOrMemAdvanced(lhs_ty, maybe_inst, true); |
| 4759 | | try self.setRegOrMem(lhs_ty, dst_mcv, lhs); |
| 4683 | try self.setRegOrMem(lhs_ty, dst_mcv, switch (lhs) { |
| 4684 | .load_direct => |sym_index| .{ .lea_direct = sym_index }, |
| 4685 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, |
| 4686 | else => lhs, |
| 4687 | }); |
| 4760 | 4688 | break :dst dst_mcv; |
| 4761 | 4689 | }; |
| 4762 | 4690 | const dst_mcv_lock: ?RegisterLock = switch (dst_mcv) { |
| ... | ... | @@ -4897,7 +4825,9 @@ fn genBinOp( |
| 4897 | 4825 | .eflags, |
| 4898 | 4826 | .register_overflow, |
| 4899 | 4827 | .ptr_stack_offset, |
| 4900 | | .tlv_reloc, |
| 4828 | .load_got, |
| 4829 | .lea_direct, |
| 4830 | .lea_tlv, |
| 4901 | 4831 | => unreachable, |
| 4902 | 4832 | .register => |src_reg| try self.asmCmovccRegisterRegister( |
| 4903 | 4833 | registerAlias(tmp_reg, cmov_abi_size), |
| ... | ... | @@ -4912,31 +4842,17 @@ fn genBinOp( |
| 4912 | 4842 | }), |
| 4913 | 4843 | cc, |
| 4914 | 4844 | ), |
| 4915 | | .memory, .linker_load => { |
| 4845 | .memory, .load_direct, .load_tlv => { |
| 4916 | 4846 | const addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 4917 | 4847 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 4918 | 4848 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 4919 | 4849 | |
| 4920 | | switch (mat_src_mcv) { |
| 4921 | | .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }), |
| 4922 | | .linker_load => |load_struct| { |
| 4923 | | 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); |
| 4925 | | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 4926 | | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { |
| 4927 | | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 4928 | | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 4929 | | } else unreachable; |
| 4930 | | |
| 4931 | | switch (load_struct.type) { |
| 4932 | | .import => unreachable, |
| 4933 | | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 4934 | | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), |
| 4935 | | } |
| 4936 | | }, |
| 4850 | try self.genSetReg(Type.usize, addr_reg, switch (mat_src_mcv) { |
| 4851 | .memory => |addr| .{ .immediate = addr }, |
| 4852 | .load_direct => |sym_index| .{ .lea_direct = sym_index }, |
| 4853 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, |
| 4937 | 4854 | else => unreachable, |
| 4938 | | } |
| 4939 | | |
| 4855 | }); |
| 4940 | 4856 | try self.asmCmovccRegisterMemory( |
| 4941 | 4857 | registerAlias(tmp_reg, cmov_abi_size), |
| 4942 | 4858 | Memory.sib(Memory.PtrSize.fromSize(cmov_abi_size), .{ .base = addr_reg }), |
| ... | ... | @@ -4982,13 +4898,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 4982 | 4898 | .undef => unreachable, |
| 4983 | 4899 | .dead, .unreach => unreachable, |
| 4984 | 4900 | .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 | 4901 | .register => |src_reg| switch (ty.zigTypeTag()) { |
| 4993 | 4902 | .Float => { |
| 4994 | 4903 | if (intrinsicsAllowed(self.target.*, ty)) { |
| ... | ... | @@ -5037,7 +4946,15 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 5037 | 4946 | )), |
| 5038 | 4947 | else => unreachable, |
| 5039 | 4948 | }, |
| 5040 | | .memory, .linker_load, .eflags => { |
| 4949 | .ptr_stack_offset, |
| 4950 | .memory, |
| 4951 | .load_got, |
| 4952 | .lea_direct, |
| 4953 | .load_direct, |
| 4954 | .lea_tlv, |
| 4955 | .load_tlv, |
| 4956 | .eflags, |
| 4957 | => { |
| 5041 | 4958 | assert(abi_size <= 8); |
| 5042 | 4959 | const dst_reg_lock = self.register_manager.lockReg(dst_reg); |
| 5043 | 4960 | defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock); |
| ... | ... | @@ -5052,36 +4969,23 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 5052 | 4969 | ), |
| 5053 | 4970 | } |
| 5054 | 4971 | }, |
| 5055 | | .memory, .linker_load, .stack_offset => { |
| 4972 | .memory, .load_got, .load_direct, .load_tlv, .stack_offset => { |
| 5056 | 4973 | const dst: ?struct { |
| 5057 | 4974 | addr_reg: Register, |
| 5058 | 4975 | addr_lock: RegisterLock, |
| 5059 | 4976 | } = switch (dst_mcv) { |
| 5060 | 4977 | else => unreachable, |
| 5061 | | .memory, .linker_load => dst: { |
| 4978 | .memory, .load_got, .load_direct, .load_tlv => dst: { |
| 5062 | 4979 | const dst_addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 5063 | 4980 | const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg); |
| 5064 | 4981 | errdefer self.register_manager.unlockReg(dst_addr_lock); |
| 5065 | 4982 | |
| 5066 | | switch (dst_mcv) { |
| 5067 | | .memory => |addr| try self.genSetReg(Type.usize, dst_addr_reg, .{ .immediate = addr }), |
| 5068 | | .linker_load => |load_struct| { |
| 5069 | | 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); |
| 5071 | | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 5072 | | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { |
| 5073 | | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 5074 | | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 5075 | | } else unreachable; |
| 5076 | | |
| 5077 | | switch (load_struct.type) { |
| 5078 | | .import => unreachable, |
| 5079 | | .got => try self.asmMovLinker(dst_addr_reg, atom_index, load_struct), |
| 5080 | | .direct => try self.asmLeaLinker(dst_addr_reg, atom_index, load_struct), |
| 5081 | | } |
| 5082 | | }, |
| 5083 | | else => unreachable, |
| 5084 | | } |
| 4983 | try self.genSetReg(Type.usize, dst_addr_reg, switch (dst_mcv) { |
| 4984 | .memory => |addr| .{ .immediate = addr }, |
| 4985 | .load_direct => |sym_index| .{ .lea_direct = sym_index }, |
| 4986 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, |
| 4987 | else => dst_mcv, |
| 4988 | }); |
| 5085 | 4989 | |
| 5086 | 4990 | break :dst .{ |
| 5087 | 4991 | .addr_reg = dst_addr_reg, |
| ... | ... | @@ -5099,7 +5003,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 5099 | 5003 | addr_lock: RegisterLock, |
| 5100 | 5004 | } = switch (src_mcv) { |
| 5101 | 5005 | else => null, |
| 5102 | | .memory, .linker_load => src: { |
| 5006 | .memory, .load_got, .load_direct, .load_tlv => src: { |
| 5103 | 5007 | const src_limb_reg = try self.register_manager.allocReg(null, gp); |
| 5104 | 5008 | const src_limb_lock = self.register_manager.lockRegAssumeUnused(src_limb_reg); |
| 5105 | 5009 | errdefer self.register_manager.unlockReg(src_limb_lock); |
| ... | ... | @@ -5108,25 +5012,12 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 5108 | 5012 | const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg); |
| 5109 | 5013 | errdefer self.register_manager.unlockReg(src_addr_lock); |
| 5110 | 5014 | |
| 5111 | | switch (src_mcv) { |
| 5112 | | .memory => |addr| try self.genSetReg(Type.usize, src_addr_reg, .{ .immediate = addr }), |
| 5113 | | .linker_load => |load_struct| { |
| 5114 | | 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); |
| 5116 | | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 5117 | | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { |
| 5118 | | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 5119 | | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 5120 | | } else unreachable; |
| 5121 | | |
| 5122 | | switch (load_struct.type) { |
| 5123 | | .import => unreachable, |
| 5124 | | .got => try self.asmMovLinker(src_addr_reg, atom_index, load_struct), |
| 5125 | | .direct => try self.asmLeaLinker(src_addr_reg, atom_index, load_struct), |
| 5126 | | } |
| 5127 | | }, |
| 5128 | | else => unreachable, |
| 5129 | | } |
| 5015 | try self.genSetReg(Type.usize, src_addr_reg, switch (src_mcv) { |
| 5016 | .memory => |addr| .{ .immediate = addr }, |
| 5017 | .load_direct => |sym_index| .{ .lea_direct = sym_index }, |
| 5018 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, |
| 5019 | else => src_mcv, |
| 5020 | }); |
| 5130 | 5021 | |
| 5131 | 5022 | break :src .{ |
| 5132 | 5023 | .addr_reg = src_addr_reg, |
| ... | ... | @@ -5169,7 +5060,11 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 5169 | 5060 | .base = .rbp, |
| 5170 | 5061 | .disp = off - dst_off, |
| 5171 | 5062 | }, |
| 5172 | | .memory, .linker_load => .{ .base = dst.?.addr_reg, .disp = off }, |
| 5063 | .memory, |
| 5064 | .load_got, |
| 5065 | .load_direct, |
| 5066 | .load_tlv, |
| 5067 | => .{ .base = dst.?.addr_reg, .disp = off }, |
| 5173 | 5068 | }, |
| 5174 | 5069 | ); |
| 5175 | 5070 | switch (src_mcv) { |
| ... | ... | @@ -5233,7 +5128,11 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 5233 | 5128 | else => unreachable, |
| 5234 | 5129 | } |
| 5235 | 5130 | }, |
| 5236 | | .memory, .linker_load, .tlv_reloc => { |
| 5131 | .memory, |
| 5132 | .load_got, |
| 5133 | .load_direct, |
| 5134 | .load_tlv, |
| 5135 | => { |
| 5237 | 5136 | try self.asmRegisterMemory( |
| 5238 | 5137 | .mov, |
| 5239 | 5138 | registerAlias(src.?.limb_reg, limb_abi_size), |
| ... | ... | @@ -5248,11 +5147,19 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 5248 | 5147 | registerAlias(src.?.limb_reg, limb_abi_size), |
| 5249 | 5148 | ); |
| 5250 | 5149 | }, |
| 5251 | | .stack_offset, .ptr_stack_offset, .eflags => { |
| 5150 | .stack_offset, |
| 5151 | .ptr_stack_offset, |
| 5152 | .eflags, |
| 5153 | .lea_direct, |
| 5154 | .lea_tlv, |
| 5155 | => { |
| 5252 | 5156 | const src_limb_reg = try self.copyToTmpRegister(limb_ty, switch (src_mcv) { |
| 5253 | 5157 | .stack_offset => |src_off| .{ .stack_offset = src_off - off }, |
| 5254 | 5158 | .ptr_stack_offset, |
| 5255 | 5159 | .eflags, |
| 5160 | .load_got, |
| 5161 | .lea_direct, |
| 5162 | .lea_tlv, |
| 5256 | 5163 | => off: { |
| 5257 | 5164 | assert(off == 0); |
| 5258 | 5165 | break :off src_mcv; |
| ... | ... | @@ -5272,7 +5179,8 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 5272 | 5179 | } |
| 5273 | 5180 | }, |
| 5274 | 5181 | .ptr_stack_offset => unreachable, |
| 5275 | | .tlv_reloc => unreachable, |
| 5182 | .lea_tlv => unreachable, |
| 5183 | .lea_direct => unreachable, |
| 5276 | 5184 | } |
| 5277 | 5185 | } |
| 5278 | 5186 | |
| ... | ... | @@ -5286,7 +5194,8 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 5286 | 5194 | .dead, .unreach, .immediate => unreachable, |
| 5287 | 5195 | .eflags => unreachable, |
| 5288 | 5196 | .ptr_stack_offset => unreachable, |
| 5289 | | .tlv_reloc => unreachable, |
| 5197 | .lea_direct => unreachable, |
| 5198 | .lea_tlv => unreachable, |
| 5290 | 5199 | .register_overflow => unreachable, |
| 5291 | 5200 | .register => |dst_reg| { |
| 5292 | 5201 | const dst_alias = registerAlias(dst_reg, abi_size); |
| ... | ... | @@ -5298,7 +5207,8 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 5298 | 5207 | .undef => try self.genSetReg(dst_ty, dst_reg, .undef), |
| 5299 | 5208 | .dead, .unreach => unreachable, |
| 5300 | 5209 | .ptr_stack_offset => unreachable, |
| 5301 | | .tlv_reloc => unreachable, |
| 5210 | .lea_direct => unreachable, |
| 5211 | .lea_tlv => unreachable, |
| 5302 | 5212 | .register_overflow => unreachable, |
| 5303 | 5213 | .register => |src_reg| try self.asmRegisterRegister( |
| 5304 | 5214 | .imul, |
| ... | ... | @@ -5325,12 +5235,13 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 5325 | 5235 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .rbp, .disp = -off }), |
| 5326 | 5236 | ); |
| 5327 | 5237 | }, |
| 5328 | | .memory => { |
| 5238 | .memory, |
| 5239 | .load_got, |
| 5240 | .load_direct, |
| 5241 | .load_tlv, |
| 5242 | => { |
| 5329 | 5243 | return self.fail("TODO implement x86 multiply source memory", .{}); |
| 5330 | 5244 | }, |
| 5331 | | .linker_load => { |
| 5332 | | return self.fail("TODO implement x86 multiply source symbol at index in linker", .{}); |
| 5333 | | }, |
| 5334 | 5245 | .eflags => { |
| 5335 | 5246 | return self.fail("TODO implement x86 multiply source eflags", .{}); |
| 5336 | 5247 | }, |
| ... | ... | @@ -5342,7 +5253,8 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 5342 | 5253 | .undef => return self.genSetStack(dst_ty, off, .undef, .{}), |
| 5343 | 5254 | .dead, .unreach => unreachable, |
| 5344 | 5255 | .ptr_stack_offset => unreachable, |
| 5345 | | .tlv_reloc => unreachable, |
| 5256 | .lea_direct => unreachable, |
| 5257 | .lea_tlv => unreachable, |
| 5346 | 5258 | .register_overflow => unreachable, |
| 5347 | 5259 | .register => |src_reg| { |
| 5348 | 5260 | // copy dst to a register |
| ... | ... | @@ -5365,23 +5277,26 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 5365 | 5277 | |
| 5366 | 5278 | return self.genSetStack(dst_ty, off, .{ .register = dst_reg }, .{}); |
| 5367 | 5279 | }, |
| 5368 | | .memory, .stack_offset => { |
| 5280 | .memory, |
| 5281 | .load_got, |
| 5282 | .load_direct, |
| 5283 | .load_tlv, |
| 5284 | .stack_offset, |
| 5285 | => { |
| 5369 | 5286 | return self.fail("TODO implement x86 multiply source memory", .{}); |
| 5370 | 5287 | }, |
| 5371 | | .linker_load => { |
| 5372 | | return self.fail("TODO implement x86 multiply source symbol at index in linker", .{}); |
| 5373 | | }, |
| 5374 | 5288 | .eflags => { |
| 5375 | 5289 | return self.fail("TODO implement x86 multiply source eflags", .{}); |
| 5376 | 5290 | }, |
| 5377 | 5291 | } |
| 5378 | 5292 | }, |
| 5379 | | .memory => { |
| 5293 | .memory, |
| 5294 | .load_got, |
| 5295 | .load_direct, |
| 5296 | .load_tlv, |
| 5297 | => { |
| 5380 | 5298 | return self.fail("TODO implement x86 multiply destination memory", .{}); |
| 5381 | 5299 | }, |
| 5382 | | .linker_load => { |
| 5383 | | return self.fail("TODO implement x86 multiply destination symbol at index in linker", .{}); |
| 5384 | | }, |
| 5385 | 5300 | } |
| 5386 | 5301 | } |
| 5387 | 5302 | |
| ... | ... | @@ -5461,7 +5376,8 @@ fn genVarDbgInfo( |
| 5461 | 5376 | .offset = -off, |
| 5462 | 5377 | } }, |
| 5463 | 5378 | .memory => |address| .{ .memory = address }, |
| 5464 | | .linker_load => |linker_load| .{ .linker_load = linker_load }, |
| 5379 | .load_got => |sym_index| .{ .linker_load = .{ .type = .got, .sym_index = sym_index } }, |
| 5380 | .load_direct => |sym_index| .{ .linker_load = .{ .type = .direct, .sym_index = sym_index } }, |
| 5465 | 5381 | .immediate => |x| .{ .immediate = x }, |
| 5466 | 5382 | .undef => .undef, |
| 5467 | 5383 | .none => .none, |
| ... | ... | @@ -5562,10 +5478,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 5562 | 5478 | .unreach => unreachable, |
| 5563 | 5479 | .dead => unreachable, |
| 5564 | 5480 | .memory => unreachable, |
| 5565 | | .linker_load => unreachable, |
| 5566 | 5481 | .eflags => unreachable, |
| 5567 | 5482 | .register_overflow => unreachable, |
| 5568 | | .tlv_reloc => unreachable, |
| 5483 | .load_got => unreachable, |
| 5484 | .lea_direct => unreachable, |
| 5485 | .load_direct => unreachable, |
| 5486 | .lea_tlv => unreachable, |
| 5487 | .load_tlv => unreachable, |
| 5569 | 5488 | } |
| 5570 | 5489 | } |
| 5571 | 5490 | |
| ... | ... | @@ -5601,10 +5520,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 5601 | 5520 | .unreach => unreachable, |
| 5602 | 5521 | .dead => unreachable, |
| 5603 | 5522 | .memory => unreachable, |
| 5604 | | .linker_load => unreachable, |
| 5605 | 5523 | .eflags => unreachable, |
| 5606 | 5524 | .register_overflow => unreachable, |
| 5607 | | .tlv_reloc => unreachable, |
| 5525 | .load_got => unreachable, |
| 5526 | .lea_direct => unreachable, |
| 5527 | .load_direct => unreachable, |
| 5528 | .lea_tlv => unreachable, |
| 5529 | .load_tlv => unreachable, |
| 5608 | 5530 | } |
| 5609 | 5531 | } |
| 5610 | 5532 | |
| ... | ... | @@ -5627,21 +5549,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 5627 | 5549 | .base = .ds, |
| 5628 | 5550 | .disp = @intCast(i32, got_addr), |
| 5629 | 5551 | })); |
| 5630 | | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { |
| 5631 | | const atom_index = try coff_file.getOrCreateAtomForDecl(func.owner_decl); |
| 5632 | | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; |
| 5633 | | try self.genSetReg(Type.usize, .rax, .{ .linker_load = .{ |
| 5634 | | .type = .got, |
| 5635 | | .sym_index = sym_index, |
| 5636 | | } }); |
| 5552 | } else if (self.bin_file.cast(link.File.Coff)) |_| { |
| 5553 | const sym_index = try self.getSymbolIndexForDecl(func.owner_decl); |
| 5554 | try self.genSetReg(Type.usize, .rax, .{ .load_got = sym_index }); |
| 5637 | 5555 | try self.asmRegister(.call, .rax); |
| 5638 | | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 5639 | | const atom_index = try macho_file.getOrCreateAtomForDecl(func.owner_decl); |
| 5640 | | const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; |
| 5641 | | try self.genSetReg(Type.usize, .rax, .{ .linker_load = .{ |
| 5642 | | .type = .got, |
| 5643 | | .sym_index = sym_index, |
| 5644 | | } }); |
| 5556 | } else if (self.bin_file.cast(link.File.MachO)) |_| { |
| 5557 | const sym_index = try self.getSymbolIndexForDecl(func.owner_decl); |
| 5558 | try self.genSetReg(Type.usize, .rax, .{ .load_got = sym_index }); |
| 5645 | 5559 | try self.asmRegister(.call, .rax); |
| 5646 | 5560 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| 5647 | 5561 | const decl_block_index = try p9.seeDecl(func.owner_decl); |
| ... | ... | @@ -5661,18 +5575,21 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 5661 | 5575 | const decl_name = mem.sliceTo(mod.declPtr(extern_fn.owner_decl).name, 0); |
| 5662 | 5576 | const lib_name = mem.sliceTo(extern_fn.lib_name, 0); |
| 5663 | 5577 | if (self.bin_file.cast(link.File.Coff)) |coff_file| { |
| 5578 | const atom_index = try self.getSymbolIndexForDecl(self.mod_fn.owner_decl); |
| 5664 | 5579 | const sym_index = try coff_file.getGlobalSymbol(decl_name, lib_name); |
| 5665 | | try self.genSetReg(Type.usize, .rax, .{ |
| 5666 | | .linker_load = .{ |
| 5667 | | .type = .import, |
| 5580 | _ = try self.addInst(.{ |
| 5581 | .tag = .mov_linker, |
| 5582 | .ops = .import_reloc, |
| 5583 | .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{ |
| 5584 | .reg = @enumToInt(Register.rax), |
| 5585 | .atom_index = atom_index, |
| 5668 | 5586 | .sym_index = sym_index, |
| 5669 | | }, |
| 5587 | }) }, |
| 5670 | 5588 | }); |
| 5671 | 5589 | try self.asmRegister(.call, .rax); |
| 5672 | 5590 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 5673 | 5591 | const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name); |
| 5674 | | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 5675 | | const atom_index = macho_file.getAtom(atom).getSymbolIndex().?; |
| 5592 | const atom_index = try self.getSymbolIndexForDecl(self.mod_fn.owner_decl); |
| 5676 | 5593 | _ = try self.addInst(.{ |
| 5677 | 5594 | .tag = .call_extern, |
| 5678 | 5595 | .ops = undefined, |
| ... | ... | @@ -5871,20 +5788,14 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { |
| 5871 | 5788 | 4, // dword alignment |
| 5872 | 5789 | ); |
| 5873 | 5790 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; |
| 5874 | | try self.genSetReg(Type.usize, addr_reg, .{ .linker_load = .{ |
| 5875 | | .type = .got, |
| 5876 | | .sym_index = sym_index, |
| 5877 | | } }); |
| 5791 | try self.genSetReg(Type.usize, addr_reg, .{ .load_got = sym_index }); |
| 5878 | 5792 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 5879 | 5793 | const atom_index = try macho_file.getOrCreateAtomForLazySymbol( |
| 5880 | 5794 | .{ .kind = .const_data, .ty = Type.anyerror }, |
| 5881 | 5795 | 4, // dword alignment |
| 5882 | 5796 | ); |
| 5883 | 5797 | const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; |
| 5884 | | try self.genSetReg(Type.usize, addr_reg, .{ .linker_load = .{ |
| 5885 | | .type = .got, |
| 5886 | | .sym_index = sym_index, |
| 5887 | | } }); |
| 5798 | try self.genSetReg(Type.usize, addr_reg, .{ .load_got = sym_index }); |
| 5888 | 5799 | } else { |
| 5889 | 5800 | return self.fail("TODO implement airErrorName for x86_64 {s}", .{@tagName(self.bin_file.tag)}); |
| 5890 | 5801 | } |
| ... | ... | @@ -6126,7 +6037,8 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 6126 | 6037 | .register_overflow, |
| 6127 | 6038 | .ptr_stack_offset, |
| 6128 | 6039 | .eflags, |
| 6129 | | .tlv_reloc, |
| 6040 | .lea_direct, |
| 6041 | .lea_tlv, |
| 6130 | 6042 | => unreachable, |
| 6131 | 6043 | |
| 6132 | 6044 | .register => |opt_reg| { |
| ... | ... | @@ -6147,30 +6059,21 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 6147 | 6059 | return .{ .eflags = .nc }; |
| 6148 | 6060 | }, |
| 6149 | 6061 | |
| 6150 | | .memory, .linker_load => { |
| 6062 | .memory, |
| 6063 | .load_got, |
| 6064 | .load_direct, |
| 6065 | .load_tlv, |
| 6066 | => { |
| 6151 | 6067 | const addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 6152 | 6068 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 6153 | 6069 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 6154 | 6070 | |
| 6155 | | switch (opt_mcv) { |
| 6156 | | .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }), |
| 6157 | | .linker_load => |load_struct| { |
| 6158 | | 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); |
| 6160 | | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 6161 | | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { |
| 6162 | | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 6163 | | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 6164 | | } else unreachable; |
| 6165 | | |
| 6166 | | switch (load_struct.type) { |
| 6167 | | .import => unreachable, |
| 6168 | | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 6169 | | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), |
| 6170 | | } |
| 6171 | | }, |
| 6172 | | else => unreachable, |
| 6173 | | } |
| 6071 | try self.genSetReg(Type.usize, addr_reg, switch (opt_mcv) { |
| 6072 | .memory => |addr| .{ .immediate = addr }, |
| 6073 | .load_direct => |sym_index| .{ .lea_direct = sym_index }, |
| 6074 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, |
| 6075 | else => opt_mcv, |
| 6076 | }); |
| 6174 | 6077 | |
| 6175 | 6078 | const some_abi_size = @intCast(u32, some_info.ty.abiSize(self.target.*)); |
| 6176 | 6079 | try self.asmMemoryImmediate(.cmp, Memory.sib( |
| ... | ... | @@ -7099,7 +7002,10 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 7099 | 7002 | else => return self.fail("TODO implement inputs on stack for {} with abi size > 8", .{mcv}), |
| 7100 | 7003 | } |
| 7101 | 7004 | }, |
| 7102 | | .memory, .linker_load => { |
| 7005 | .memory, |
| 7006 | .load_direct, |
| 7007 | .load_tlv, |
| 7008 | => { |
| 7103 | 7009 | if (abi_size <= 8) { |
| 7104 | 7010 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 7105 | 7011 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| ... | ... | @@ -7109,26 +7015,12 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 7109 | 7015 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 7110 | 7016 | defer self.register_manager.unlockReg(addr_lock); |
| 7111 | 7017 | |
| 7112 | | switch (mcv) { |
| 7113 | | .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }), |
| 7114 | | .linker_load => |load_struct| { |
| 7115 | | 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); |
| 7117 | | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 7118 | | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { |
| 7119 | | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 7120 | | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 7121 | | } else unreachable; |
| 7122 | | |
| 7123 | | switch (load_struct.type) { |
| 7124 | | .import => unreachable, |
| 7125 | | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 7126 | | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), |
| 7127 | | } |
| 7128 | | }, |
| 7018 | try self.genSetReg(Type.usize, addr_reg, switch (mcv) { |
| 7019 | .memory => |addr| .{ .immediate = addr }, |
| 7020 | .load_direct => |sym_index| .{ .lea_direct = sym_index }, |
| 7021 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, |
| 7129 | 7022 | else => unreachable, |
| 7130 | | } |
| 7131 | | |
| 7023 | }); |
| 7132 | 7024 | try self.genInlineMemcpy( |
| 7133 | 7025 | .{ .ptr_stack_offset = stack_offset }, |
| 7134 | 7026 | .{ .register = addr_reg }, |
| ... | ... | @@ -7170,7 +7062,11 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 7170 | 7062 | }, |
| 7171 | 7063 | } |
| 7172 | 7064 | }, |
| 7173 | | .ptr_stack_offset, .tlv_reloc => { |
| 7065 | .ptr_stack_offset, |
| 7066 | .load_got, |
| 7067 | .lea_direct, |
| 7068 | .lea_tlv, |
| 7069 | => { |
| 7174 | 7070 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 7175 | 7071 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| 7176 | 7072 | }, |
| ... | ... | @@ -7328,7 +7224,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 7328 | 7224 | }, |
| 7329 | 7225 | } |
| 7330 | 7226 | }, |
| 7331 | | .memory, .linker_load => if (abi_size <= 8) { |
| 7227 | .memory, |
| 7228 | .load_direct, |
| 7229 | .load_tlv, |
| 7230 | .lea_direct, |
| 7231 | .lea_tlv, |
| 7232 | => if (abi_size <= 8) { |
| 7332 | 7233 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 7333 | 7234 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts); |
| 7334 | 7235 | } else { |
| ... | ... | @@ -7336,26 +7237,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 7336 | 7237 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 7337 | 7238 | defer self.register_manager.unlockReg(addr_lock); |
| 7338 | 7239 | |
| 7339 | | switch (mcv) { |
| 7340 | | .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }), |
| 7341 | | .linker_load => |load_struct| { |
| 7342 | | 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); |
| 7344 | | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 7345 | | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { |
| 7346 | | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 7347 | | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 7348 | | } else unreachable; |
| 7349 | | |
| 7350 | | switch (load_struct.type) { |
| 7351 | | .import => unreachable, |
| 7352 | | .got => try self.asmMovLinker(addr_reg, atom_index, load_struct), |
| 7353 | | .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct), |
| 7354 | | } |
| 7355 | | }, |
| 7356 | | else => unreachable, |
| 7357 | | } |
| 7358 | | |
| 7240 | try self.genSetReg(Type.usize, addr_reg, switch (mcv) { |
| 7241 | .memory => |addr| .{ .immediate = addr }, |
| 7242 | .load_direct => |sym_index| .{ .lea_direct = sym_index }, |
| 7243 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, |
| 7244 | else => mcv, |
| 7245 | }); |
| 7359 | 7246 | try self.genInlineMemcpy( |
| 7360 | 7247 | .{ .ptr_stack_offset = stack_offset }, |
| 7361 | 7248 | .{ .register = addr_reg }, |
| ... | ... | @@ -7375,7 +7262,9 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 7375 | 7262 | .{ .immediate = abi_size }, |
| 7376 | 7263 | .{}, |
| 7377 | 7264 | ), |
| 7378 | | .ptr_stack_offset, .tlv_reloc => { |
| 7265 | .ptr_stack_offset, |
| 7266 | .load_got, |
| 7267 | => { |
| 7379 | 7268 | const tmp_reg = try self.copyToTmpRegister(ty, mcv); |
| 7380 | 7269 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7381 | 7270 | defer self.register_manager.unlockReg(tmp_lock); |
| ... | ... | @@ -7465,26 +7354,27 @@ fn genInlineMemcpy( |
| 7465 | 7354 | try self.spillRegisters(&.{ .rdi, .rsi, .rcx }); |
| 7466 | 7355 | |
| 7467 | 7356 | switch (dst_ptr) { |
| 7468 | | .memory => |addr| { |
| 7469 | | try self.genSetReg(Type.usize, .rdi, .{ .immediate = addr }); |
| 7357 | .lea_tlv, |
| 7358 | .load_tlv, |
| 7359 | => { |
| 7360 | try self.genSetReg(Type.usize, .rdi, switch (dst_ptr) { |
| 7361 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, |
| 7362 | else => dst_ptr, |
| 7363 | }); |
| 7364 | }, |
| 7365 | .memory, |
| 7366 | .load_got, |
| 7367 | .lea_direct, |
| 7368 | .load_direct, |
| 7369 | => { |
| 7370 | try self.genSetReg(Type.usize, .rdi, switch (dst_ptr) { |
| 7371 | .memory => |addr| .{ .immediate = addr }, |
| 7372 | .load_direct => |sym_index| .{ .lea_direct = sym_index }, |
| 7373 | else => dst_ptr, |
| 7374 | }); |
| 7470 | 7375 | // Load the pointer, which is stored in memory |
| 7471 | 7376 | try self.asmRegisterMemory(.mov, .rdi, Memory.sib(.qword, .{ .base = .rdi })); |
| 7472 | 7377 | }, |
| 7473 | | .linker_load => |load_struct| { |
| 7474 | | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 7475 | | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 7476 | | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 7477 | | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { |
| 7478 | | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 7479 | | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 7480 | | } else unreachable; |
| 7481 | | |
| 7482 | | switch (load_struct.type) { |
| 7483 | | .import => unreachable, |
| 7484 | | .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct), |
| 7485 | | } |
| 7486 | | }, |
| 7487 | | .tlv_reloc => try self.genSetReg(Type.usize, .rdi, dst_ptr), |
| 7488 | 7378 | .stack_offset, .ptr_stack_offset => |off| { |
| 7489 | 7379 | try self.asmRegisterMemory(switch (dst_ptr) { |
| 7490 | 7380 | .stack_offset => .mov, |
| ... | ... | @@ -7508,26 +7398,27 @@ fn genInlineMemcpy( |
| 7508 | 7398 | } |
| 7509 | 7399 | |
| 7510 | 7400 | switch (src_ptr) { |
| 7511 | | .memory => |addr| { |
| 7512 | | try self.genSetReg(Type.usize, .rsi, .{ .immediate = addr }); |
| 7401 | .lea_tlv, |
| 7402 | .load_tlv, |
| 7403 | => { |
| 7404 | try self.genSetReg(Type.usize, .rsi, switch (src_ptr) { |
| 7405 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, |
| 7406 | else => dst_ptr, |
| 7407 | }); |
| 7408 | }, |
| 7409 | .memory, |
| 7410 | .load_got, |
| 7411 | .lea_direct, |
| 7412 | .load_direct, |
| 7413 | => { |
| 7414 | try self.genSetReg(Type.usize, .rsi, switch (src_ptr) { |
| 7415 | .memory => |addr| .{ .immediate = addr }, |
| 7416 | .load_direct => |sym_index| .{ .lea_direct = sym_index }, |
| 7417 | else => src_ptr, |
| 7418 | }); |
| 7513 | 7419 | // Load the pointer, which is stored in memory |
| 7514 | 7420 | try self.asmRegisterMemory(.mov, .rsi, Memory.sib(.qword, .{ .base = .rsi })); |
| 7515 | 7421 | }, |
| 7516 | | .linker_load => |load_struct| { |
| 7517 | | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 7518 | | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 7519 | | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 7520 | | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { |
| 7521 | | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 7522 | | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 7523 | | } else unreachable; |
| 7524 | | |
| 7525 | | switch (load_struct.type) { |
| 7526 | | .import => unreachable, |
| 7527 | | .got, .direct => try self.asmMovLinker(.rsi, atom_index, load_struct), |
| 7528 | | } |
| 7529 | | }, |
| 7530 | | .tlv_reloc => try self.genSetReg(Type.usize, .rsi, src_ptr), |
| 7531 | 7422 | .stack_offset, .ptr_stack_offset => |off| { |
| 7532 | 7423 | try self.asmRegisterMemory(switch (src_ptr) { |
| 7533 | 7424 | .stack_offset => .mov, |
| ... | ... | @@ -7574,26 +7465,27 @@ fn genInlineMemset( |
| 7574 | 7465 | try self.spillRegisters(&.{ .rdi, .al, .rcx }); |
| 7575 | 7466 | |
| 7576 | 7467 | switch (dst_ptr) { |
| 7577 | | .memory => |addr| { |
| 7578 | | try self.genSetReg(Type.usize, .rdi, .{ .immediate = addr }); |
| 7468 | .lea_tlv, |
| 7469 | .load_tlv, |
| 7470 | => { |
| 7471 | try self.genSetReg(Type.usize, .rdi, switch (dst_ptr) { |
| 7472 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, |
| 7473 | else => dst_ptr, |
| 7474 | }); |
| 7475 | }, |
| 7476 | .load_got => try self.genSetReg(Type.usize, .rdi, dst_ptr), |
| 7477 | .memory, |
| 7478 | .lea_direct, |
| 7479 | .load_direct, |
| 7480 | => { |
| 7481 | try self.genSetReg(Type.usize, .rdi, switch (dst_ptr) { |
| 7482 | .memory => |addr| .{ .immediate = addr }, |
| 7483 | .load_direct => |sym_index| .{ .lea_direct = sym_index }, |
| 7484 | else => dst_ptr, |
| 7485 | }); |
| 7579 | 7486 | // Load the pointer, which is stored in memory |
| 7580 | 7487 | try self.asmRegisterMemory(.mov, .rdi, Memory.sib(.qword, .{ .base = .rdi })); |
| 7581 | 7488 | }, |
| 7582 | | .linker_load => |load_struct| { |
| 7583 | | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| 7584 | | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 7585 | | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 7586 | | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { |
| 7587 | | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 7588 | | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 7589 | | } else unreachable; |
| 7590 | | |
| 7591 | | switch (load_struct.type) { |
| 7592 | | .import => unreachable, |
| 7593 | | .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct), |
| 7594 | | } |
| 7595 | | }, |
| 7596 | | .tlv_reloc => try self.genSetReg(Type.usize, .rdi, dst_ptr), |
| 7597 | 7489 | .stack_offset, .ptr_stack_offset => |off| { |
| 7598 | 7490 | try self.asmRegisterMemory(switch (dst_ptr) { |
| 7599 | 7491 | .stack_offset => .mov, |
| ... | ... | @@ -7769,43 +7661,31 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 7769 | 7661 | } |
| 7770 | 7662 | }, |
| 7771 | 7663 | }, |
| 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)}); |
| 7664 | .load_got, .lea_direct => |sym_index| { |
| 7665 | const atom_index = try self.getSymbolIndexForDecl(self.mod_fn.owner_decl); |
| 7666 | _ = try self.addInst(.{ |
| 7667 | .tag = switch (mcv) { |
| 7668 | .load_got => .mov_linker, |
| 7669 | .lea_direct => .lea_linker, |
| 7670 | else => unreachable, |
| 7671 | }, |
| 7672 | .ops = switch (mcv) { |
| 7673 | .load_got => .got_reloc, |
| 7674 | .lea_direct => .direct_reloc, |
| 7675 | else => unreachable, |
| 7676 | }, |
| 7677 | .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{ |
| 7678 | .reg = @enumToInt(reg), |
| 7679 | .atom_index = atom_index, |
| 7680 | .sym_index = sym_index, |
| 7681 | }) }, |
| 7682 | }); |
| 7795 | 7683 | }, |
| 7796 | | .linker_load => |load_struct| { |
| 7797 | | 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); |
| 7799 | | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| 7800 | | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { |
| 7801 | | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 7802 | | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| 7803 | | } else unreachable; |
| 7804 | | |
| 7684 | .load_direct => |sym_index| { |
| 7805 | 7685 | switch (ty.zigTypeTag()) { |
| 7806 | 7686 | .Float => { |
| 7807 | | const base_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 7808 | | try self.asmLeaLinker(base_reg, atom_index, load_struct); |
| 7687 | const addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 7688 | try self.genSetReg(Type.usize, addr_reg, .{ .lea_direct = sym_index }); |
| 7809 | 7689 | |
| 7810 | 7690 | if (intrinsicsAllowed(self.target.*, ty)) { |
| 7811 | 7691 | return self.asmRegisterMemory( |
| ... | ... | @@ -7817,13 +7697,68 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 7817 | 7697 | }), |
| 7818 | 7698 | }, |
| 7819 | 7699 | reg.to128(), |
| 7820 | | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base_reg.to64() }), |
| 7700 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = addr_reg }), |
| 7821 | 7701 | ); |
| 7822 | 7702 | } |
| 7823 | 7703 | |
| 7824 | 7704 | return self.fail("TODO genSetReg from memory for float with no intrinsics", .{}); |
| 7825 | 7705 | }, |
| 7826 | | else => try self.asmMovLinker(registerAlias(reg, abi_size), atom_index, load_struct), |
| 7706 | else => { |
| 7707 | const atom_index = try self.getSymbolIndexForDecl(self.mod_fn.owner_decl); |
| 7708 | _ = try self.addInst(.{ |
| 7709 | .tag = .mov_linker, |
| 7710 | .ops = .direct_reloc, |
| 7711 | .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{ |
| 7712 | .reg = @enumToInt(registerAlias(reg, abi_size)), |
| 7713 | .atom_index = atom_index, |
| 7714 | .sym_index = sym_index, |
| 7715 | }) }, |
| 7716 | }); |
| 7717 | }, |
| 7718 | } |
| 7719 | }, |
| 7720 | .lea_tlv => |sym_index| { |
| 7721 | const atom_index = try self.getSymbolIndexForDecl(self.mod_fn.owner_decl); |
| 7722 | if (self.bin_file.cast(link.File.MachO)) |_| { |
| 7723 | _ = try self.addInst(.{ |
| 7724 | .tag = .mov_linker, |
| 7725 | .ops = .tlv_reloc, |
| 7726 | .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{ |
| 7727 | .reg = @enumToInt(Register.rdi), |
| 7728 | .atom_index = atom_index, |
| 7729 | .sym_index = sym_index, |
| 7730 | }) }, |
| 7731 | }); |
| 7732 | // TODO: spill registers before calling |
| 7733 | try self.asmMemory(.call, Memory.sib(.qword, .{ .base = .rdi })); |
| 7734 | try self.genSetReg(Type.usize, reg, .{ .register = .rax }); |
| 7735 | } else return self.fail("TODO emit ptr to TLV sequence on {s}", .{@tagName(self.bin_file.tag)}); |
| 7736 | }, |
| 7737 | .load_tlv => |sym_index| { |
| 7738 | const base_reg = switch (ty.zigTypeTag()) { |
| 7739 | .Float => (try self.register_manager.allocReg(null, gp)).to64(), |
| 7740 | else => reg.to64(), |
| 7741 | }; |
| 7742 | try self.genSetReg(Type.usize, base_reg, .{ .lea_tlv = sym_index }); |
| 7743 | switch (ty.zigTypeTag()) { |
| 7744 | .Float => if (intrinsicsAllowed(self.target.*, ty)) { |
| 7745 | return self.asmRegisterMemory( |
| 7746 | switch (ty.tag()) { |
| 7747 | .f32 => .movss, |
| 7748 | .f64 => .movsd, |
| 7749 | else => return self.fail("TODO genSetReg from memory for {}", .{ |
| 7750 | ty.fmt(self.bin_file.options.module.?), |
| 7751 | }), |
| 7752 | }, |
| 7753 | reg.to128(), |
| 7754 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base_reg }), |
| 7755 | ); |
| 7756 | } else return self.fail("TODO genSetReg from memory for float with no intrinsics", .{}), |
| 7757 | else => try self.asmRegisterMemory( |
| 7758 | .mov, |
| 7759 | registerAlias(reg, abi_size), |
| 7760 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base_reg }), |
| 7761 | ), |
| 7827 | 7762 | } |
| 7828 | 7763 | }, |
| 7829 | 7764 | .stack_offset => |off| { |
| ... | ... | @@ -8464,20 +8399,14 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { |
| 8464 | 8399 | 4, // dword alignment |
| 8465 | 8400 | ); |
| 8466 | 8401 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; |
| 8467 | | try self.genSetReg(Type.usize, addr_reg, .{ .linker_load = .{ |
| 8468 | | .type = .got, |
| 8469 | | .sym_index = sym_index, |
| 8470 | | } }); |
| 8402 | try self.genSetReg(Type.usize, addr_reg, .{ .load_got = sym_index }); |
| 8471 | 8403 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 8472 | 8404 | const atom_index = try macho_file.getOrCreateAtomForLazySymbol( |
| 8473 | 8405 | .{ .kind = .const_data, .ty = Type.anyerror }, |
| 8474 | 8406 | 4, // dword alignment |
| 8475 | 8407 | ); |
| 8476 | 8408 | const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; |
| 8477 | | try self.genSetReg(Type.usize, addr_reg, .{ .linker_load = .{ |
| 8478 | | .type = .got, |
| 8479 | | .sym_index = sym_index, |
| 8480 | | } }); |
| 8409 | try self.genSetReg(Type.usize, addr_reg, .{ .load_got = sym_index }); |
| 8481 | 8410 | } else { |
| 8482 | 8411 | return self.fail("TODO implement airErrorName for x86_64 {s}", .{@tagName(self.bin_file.tag)}); |
| 8483 | 8412 | } |
| ... | ... | @@ -8586,7 +8515,11 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 8586 | 8515 | const elem_byte_off = @intCast(i32, elem_off / elem_abi_bits * elem_abi_size); |
| 8587 | 8516 | const elem_bit_off = elem_off % elem_abi_bits; |
| 8588 | 8517 | const elem_mcv = try self.resolveInst(elem); |
| 8589 | | const elem_lock = switch (elem_mcv) { |
| 8518 | const mat_elem_mcv = switch (elem_mcv) { |
| 8519 | .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index }, |
| 8520 | else => elem_mcv, |
| 8521 | }; |
| 8522 | const elem_lock = switch (mat_elem_mcv) { |
| 8590 | 8523 | .register => |reg| self.register_manager.lockReg(reg), |
| 8591 | 8524 | .immediate => |imm| lock: { |
| 8592 | 8525 | if (imm == 0) continue; |
| ... | ... | @@ -8596,7 +8529,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 8596 | 8529 | }; |
| 8597 | 8530 | defer if (elem_lock) |lock| self.register_manager.unlockReg(lock); |
| 8598 | 8531 | const elem_reg = registerAlias( |
| 8599 | | try self.copyToTmpRegister(elem_ty, elem_mcv), |
| 8532 | try self.copyToTmpRegister(elem_ty, mat_elem_mcv), |
| 8600 | 8533 | elem_abi_size, |
| 8601 | 8534 | ); |
| 8602 | 8535 | const elem_extra_bits = self.regExtraBits(elem_ty); |
| ... | ... | @@ -8616,7 +8549,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 8616 | 8549 | .{ .register = elem_reg }, |
| 8617 | 8550 | ); |
| 8618 | 8551 | if (elem_bit_off > elem_extra_bits) { |
| 8619 | | const reg = try self.copyToTmpRegister(elem_ty, elem_mcv); |
| 8552 | const reg = try self.copyToTmpRegister(elem_ty, mat_elem_mcv); |
| 8620 | 8553 | if (elem_extra_bits > 0) { |
| 8621 | 8554 | try self.truncateRegister(elem_ty, registerAlias(reg, elem_abi_size)); |
| 8622 | 8555 | } |
| ... | ... | @@ -8641,7 +8574,11 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 8641 | 8574 | const elem_ty = result_ty.structFieldType(elem_i); |
| 8642 | 8575 | const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, self.target.*)); |
| 8643 | 8576 | const elem_mcv = try self.resolveInst(elem); |
| 8644 | | try self.genSetStack(elem_ty, stack_offset - elem_off, elem_mcv, .{}); |
| 8577 | const mat_elem_mcv = switch (elem_mcv) { |
| 8578 | .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index }, |
| 8579 | else => elem_mcv, |
| 8580 | }; |
| 8581 | try self.genSetStack(elem_ty, stack_offset - elem_off, mat_elem_mcv, .{}); |
| 8645 | 8582 | } |
| 8646 | 8583 | break :res .{ .stack_offset = stack_offset }; |
| 8647 | 8584 | }, |
| ... | ... | @@ -8652,8 +8589,12 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 8652 | 8589 | |
| 8653 | 8590 | for (elements, 0..) |elem, elem_i| { |
| 8654 | 8591 | const elem_mcv = try self.resolveInst(elem); |
| 8592 | const mat_elem_mcv = switch (elem_mcv) { |
| 8593 | .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index }, |
| 8594 | else => elem_mcv, |
| 8595 | }; |
| 8655 | 8596 | const elem_off = @intCast(i32, elem_size * elem_i); |
| 8656 | | try self.genSetStack(elem_ty, stack_offset - elem_off, elem_mcv, .{}); |
| 8597 | try self.genSetStack(elem_ty, stack_offset - elem_off, mat_elem_mcv, .{}); |
| 8657 | 8598 | } |
| 8658 | 8599 | break :res MCValue{ .stack_offset = stack_offset }; |
| 8659 | 8600 | }, |
| ... | ... | @@ -8776,10 +8717,11 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { |
| 8776 | 8717 | .mcv => |mcv| switch (mcv) { |
| 8777 | 8718 | .none => .none, |
| 8778 | 8719 | .undef => .undef, |
| 8779 | | .linker_load => |ll| .{ .linker_load = ll }, |
| 8780 | 8720 | .immediate => |imm| .{ .immediate = imm }, |
| 8781 | 8721 | .memory => |addr| .{ .memory = addr }, |
| 8782 | | .tlv_reloc => |sym_index| .{ .tlv_reloc = sym_index }, |
| 8722 | .load_direct => |sym_index| .{ .load_direct = sym_index }, |
| 8723 | .load_got => |sym_index| .{ .load_got = sym_index }, |
| 8724 | .load_tlv => |sym_index| .{ .load_tlv = sym_index }, |
| 8783 | 8725 | }, |
| 8784 | 8726 | .fail => |msg| { |
| 8785 | 8727 | self.err_msg = msg; |
| ... | ... | @@ -9077,3 +9019,13 @@ fn intrinsicsAllowed(target: Target, ty: Type) bool { |
| 9077 | 9019 | fn hasAvxSupport(target: Target) bool { |
| 9078 | 9020 | return Target.x86.featureSetHasAny(target.cpu.features, .{ .avx, .avx2 }); |
| 9079 | 9021 | } |
| 9022 | |
| 9023 | fn getSymbolIndexForDecl(self: *Self, decl_index: Module.Decl.Index) !u32 { |
| 9024 | if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 9025 | const atom = try macho_file.getOrCreateAtomForDecl(decl_index); |
| 9026 | return macho_file.getAtom(atom).getSymbolIndex().?; |
| 9027 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { |
| 9028 | const atom = try coff_file.getOrCreateAtomForDecl(decl_index); |
| 9029 | return coff_file.getAtom(atom).getSymbolIndex().?; |
| 9030 | } else unreachable; |
| 9031 | } |