authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-15 11:10:20+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-15 11:10:24+02:00
logb82130709d121222f793c082dbbe6c29e7f2ec41
treeaefd8d64c71850c27106823feabd50feb35b908a
parent179117c114ca44d977f794961762e110c1955911

x86_64: cleanup different memory load types

Split `MCValue.linker_load` into `.load_got`, `.load_direct`, and `.lea_direct`.

6 files changed, 288 insertions(+), 426 deletions(-)

src/arch/aarch64/CodeGen.zig+2-1
...@@ -6168,9 +6168,10 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -6168,9 +6168,10 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6168 .mcv => |mcv| switch (mcv) {6168 .mcv => |mcv| switch (mcv) {
6169 .none => .none,6169 .none => .none,
6170 .undef => .undef,6170 .undef => .undef,
6171 .linker_load => |ll| .{ .linker_load = ll },
6172 .immediate => |imm| .{ .immediate = imm },6171 .immediate => |imm| .{ .immediate = imm },
6173 .memory => |addr| .{ .memory = addr },6172 .memory => |addr| .{ .memory = addr },
6173 .load_got => |sym_index| .{ .linker_load = .{ .type = .got, .sym_index = sym_index } },
6174 .load_direct => |sym_index| .{ .linker_load = .{ .type = .direct, .sym_index = sym_index } },
6174 .load_tlv => unreachable, // TODO6175 .load_tlv => unreachable, // TODO
6175 },6176 },
6176 .fail => |msg| {6177 .fail => |msg| {
src/arch/arm/CodeGen.zig+1-1
...@@ -6114,7 +6114,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -6114,7 +6114,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6114 .mcv => |mcv| switch (mcv) {6114 .mcv => |mcv| switch (mcv) {
6115 .none => .none,6115 .none => .none,
6116 .undef => .undef,6116 .undef => .undef,
6117 .load_tlv, .linker_load => unreachable, // TODO6117 .load_got, .load_direct, .load_tlv => unreachable, // TODO
6118 .immediate => |imm| .{ .immediate = @truncate(u32, imm) },6118 .immediate => |imm| .{ .immediate = @truncate(u32, imm) },
6119 .memory => |addr| .{ .memory = addr },6119 .memory => |addr| .{ .memory = addr },
6120 },6120 },
src/arch/riscv64/CodeGen.zig+1-1
...@@ -2572,7 +2572,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -2572,7 +2572,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
2572 .mcv => |mcv| switch (mcv) {2572 .mcv => |mcv| switch (mcv) {
2573 .none => .none,2573 .none => .none,
2574 .undef => .undef,2574 .undef => .undef,
2575 .load_tlv, .linker_load => unreachable, // TODO2575 .load_got, .load_direct, .load_tlv => unreachable, // TODO
2576 .immediate => |imm| .{ .immediate = imm },2576 .immediate => |imm| .{ .immediate = imm },
2577 .memory => |addr| .{ .memory = addr },2577 .memory => |addr| .{ .memory = addr },
2578 },2578 },
src/arch/sparc64/CodeGen.zig+1-1
...@@ -3931,7 +3931,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -3931,7 +3931,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
3931 .mcv => |mcv| switch (mcv) {3931 .mcv => |mcv| switch (mcv) {
3932 .none => .none,3932 .none => .none,
3933 .undef => .undef,3933 .undef => .undef,
3934 .load_tlv, .linker_load => unreachable, // TODO3934 .load_got, .load_direct, .load_tlv => unreachable, // TODO
3935 .immediate => |imm| .{ .immediate = imm },3935 .immediate => |imm| .{ .immediate = imm },
3936 .memory => |addr| .{ .memory = addr },3936 .memory => |addr| .{ .memory = addr },
3937 },3937 },
src/arch/x86_64/CodeGen.zig+272-405
...@@ -130,8 +130,15 @@ pub const MCValue = union(enum) {...@@ -130,8 +130,15 @@ pub const MCValue = union(enum) {
130 /// The value is in memory at a hard-coded address.130 /// The value is in memory at a hard-coded address.
131 /// If the type is a pointer, it means the pointer address is at this memory location.131 /// If the type is a pointer, it means the pointer address is at this memory location.
132 memory: u64,132 memory: u64,
133 /// The value is in memory but requires a linker relocation fixup.133 /// The value is in memory.
134 linker_load: codegen.LinkerLoad,134 /// Payload is a symbol index.
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,
135 /// The value is a threadlocal variable.142 /// The value is a threadlocal variable.
136 /// Payload is a symbol index.143 /// Payload is a symbol index.
137 load_tlv: u32,144 load_tlv: u32,
...@@ -151,7 +158,9 @@ pub const MCValue = union(enum) {...@@ -151,7 +158,9 @@ pub const MCValue = union(enum) {
151 .memory,158 .memory,
152 .stack_offset,159 .stack_offset,
153 .ptr_stack_offset,160 .ptr_stack_offset,
154 .linker_load,161 .load_direct,
162 .lea_direct,
163 .load_got,
155 .load_tlv,164 .load_tlv,
156 .lea_tlv,165 .lea_tlv,
157 => true,166 => true,
...@@ -739,40 +748,6 @@ fn asmMemoryRegisterImmediate(...@@ -739,40 +748,6 @@ fn asmMemoryRegisterImmediate(
739 });748 });
740}749}
741750
742fn asmMovLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codegen.LinkerLoad) !void {
743 const ops: Mir.Inst.Ops = switch (linker_load.type) {
744 .got => .got_reloc,
745 .direct => .direct_reloc,
746 .import => .import_reloc,
747 };
748 _ = try self.addInst(.{
749 .tag = .mov_linker,
750 .ops = ops,
751 .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{
752 .reg = @enumToInt(reg),
753 .atom_index = atom_index,
754 .sym_index = linker_load.sym_index,
755 }) },
756 });
757}
758
759fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codegen.LinkerLoad) !void {
760 const ops: Mir.Inst.Ops = switch (linker_load.type) {
761 .got => .got_reloc,
762 .direct => .direct_reloc,
763 .import => .import_reloc,
764 };
765 _ = try self.addInst(.{
766 .tag = .lea_linker,
767 .ops = ops,
768 .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{
769 .reg = @enumToInt(reg),
770 .atom_index = atom_index,
771 .sym_index = linker_load.sym_index,
772 }) },
773 });
774}
775
776fn gen(self: *Self) InnerError!void {751fn gen(self: *Self) InnerError!void {
777 const cc = self.fn_type.fnCallingConvention();752 const cc = self.fn_type.fnCallingConvention();
778 if (cc != .Naked) {753 if (cc != .Naked) {
...@@ -2925,24 +2900,14 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2925,24 +2900,14 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
2925 .disp = -off,2900 .disp = -off,
2926 }));2901 }));
2927 },2902 },
2928 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),2903 .load_got => try self.genSetReg(array_ty, addr_reg, array),
2929 .lea_tlv => unreachable,2904 .memory, .load_direct, .load_tlv => try self.genSetReg(Type.usize, addr_reg, switch (array) {
2930 .load_tlv => |sym_index| try self.genSetReg(array_ty, addr_reg, .{ .lea_tlv = sym_index }),2905 .memory => |addr| .{ .immediate = addr },
2931 .linker_load => |load_struct| {2906 .load_direct => |sym_index| .{ .lea_direct = sym_index },
2932 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {2907 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
2933 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);2908 else => unreachable,
2934 break :blk macho_file.getAtom(atom).getSymbolIndex().?;2909 }),
2935 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {2910 .lea_direct, .lea_tlv => unreachable,
2936 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
2937 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
2938 } else unreachable;
2939
2940 switch (load_struct.type) {
2941 .import => unreachable,
2942 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
2943 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
2944 }
2945 },
2946 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),2911 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
2947 }2912 }
29482913
...@@ -3654,31 +3619,15 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -3654,31 +3619,15 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
3654 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),3619 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),
3655 }3620 }
3656 },3621 },
3657 .load_tlv => |sym_index| try self.load(dst_mcv, .{ .lea_tlv = sym_index }, ptr_ty),3622 .load_direct, .load_tlv => |sym_index| try self.load(dst_mcv, switch (ptr) {
3658 .memory, .lea_tlv => {3623 .load_direct => .{ .lea_direct = sym_index },
3624 .load_tlv => .{ .lea_tlv = sym_index },
3625 else => unreachable,
3626 }, ptr_ty),
3627 .memory, .load_got, .lea_direct, .lea_tlv => {
3659 const reg = try self.copyToTmpRegister(ptr_ty, ptr);3628 const reg = try self.copyToTmpRegister(ptr_ty, ptr);
3660 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);3629 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
3661 },3630 },
3662 .linker_load => |load_struct| {
3663 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
3664 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
3665 defer self.register_manager.unlockReg(addr_reg_lock);
3666
3667 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
3668 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
3669 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
3670 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {
3671 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
3672 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
3673 } else unreachable;
3674
3675 switch (load_struct.type) {
3676 .import => unreachable,
3677 .got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct),
3678 }
3679
3680 try self.load(dst_mcv, .{ .register = addr_reg }, ptr_ty);
3681 },
3682 }3631 }
3683}3632}
36843633
...@@ -3811,7 +3760,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -3811,7 +3760,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3811 -@intCast(i32, overflow_bit_offset),3760 -@intCast(i32, overflow_bit_offset),
3812 );3761 );
3813 },3762 },
3814 .memory, .load_tlv, .linker_load => if (abi_size <= 8) {3763 .memory, .load_tlv, .load_direct => if (abi_size <= 8) {
3815 const tmp_reg = try self.copyToTmpRegister(value_ty, value);3764 const tmp_reg = try self.copyToTmpRegister(value_ty, value);
3816 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);3765 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
3817 defer self.register_manager.unlockReg(tmp_lock);3766 defer self.register_manager.unlockReg(tmp_lock);
...@@ -3822,26 +3771,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -3822,26 +3771,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3822 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);3771 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
3823 defer self.register_manager.unlockReg(addr_lock);3772 defer self.register_manager.unlockReg(addr_lock);
38243773
3825 switch (value) {3774 try self.genSetReg(Type.usize, addr_reg, switch (value) {
3826 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),3775 .memory => |addr| .{ .immediate = addr },
3827 .load_tlv => |sym_index| try self.genSetReg(Type.usize, addr_reg, .{ .lea_tlv = sym_index }),3776 .load_direct => |sym_index| .{ .lea_direct = sym_index },
3828 .linker_load => |load_struct| {3777 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
3829 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
3830 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
3831 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
3832 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {
3833 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
3834 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
3835 } else unreachable;
3836 switch (load_struct.type) {
3837 .import => unreachable,
3838 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
3839 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
3840 }
3841 },
3842 else => unreachable,3778 else => unreachable,
3843 }3779 });
3844
3845 try self.genInlineMemcpy(3780 try self.genInlineMemcpy(
3846 ptr,3781 ptr,
3847 .{ .register = addr_reg },3782 .{ .register = addr_reg },
...@@ -3861,7 +3796,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -3861,7 +3796,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3861 .{ .immediate = abi_size },3796 .{ .immediate = abi_size },
3862 .{},3797 .{},
3863 ),3798 ),
3864 .ptr_stack_offset, .lea_tlv => {3799 .ptr_stack_offset, .load_got, .lea_direct, .lea_tlv => {
3865 const tmp_reg = try self.copyToTmpRegister(value_ty, value);3800 const tmp_reg = try self.copyToTmpRegister(value_ty, value);
3866 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);3801 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
3867 defer self.register_manager.unlockReg(tmp_lock);3802 defer self.register_manager.unlockReg(tmp_lock);
...@@ -3870,7 +3805,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -3870,7 +3805,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3870 },3805 },
3871 }3806 }
3872 },3807 },
3873 .memory, .load_tlv, .linker_load => {3808 .memory, .load_direct, .load_tlv => {
3874 const value_lock: ?RegisterLock = switch (value) {3809 const value_lock: ?RegisterLock = switch (value) {
3875 .register => |reg| self.register_manager.lockReg(reg),3810 .register => |reg| self.register_manager.lockReg(reg),
3876 else => null,3811 else => null,
...@@ -3887,27 +3822,15 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -3887,27 +3822,15 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3887 // Load the pointer, which is stored in memory3822 // Load the pointer, which is stored in memory
3888 try self.asmRegisterMemory(.mov, addr_reg, Memory.sib(.qword, .{ .base = addr_reg }));3823 try self.asmRegisterMemory(.mov, addr_reg, Memory.sib(.qword, .{ .base = addr_reg }));
3889 },3824 },
3825 .load_direct => |sym_index| try self.genSetReg(ptr_ty, addr_reg, .{ .lea_direct = sym_index }),
3890 .load_tlv => |sym_index| try self.genSetReg(ptr_ty, addr_reg, .{ .lea_tlv = sym_index }),3826 .load_tlv => |sym_index| try self.genSetReg(ptr_ty, addr_reg, .{ .lea_tlv = sym_index }),
3891 .linker_load => |load_struct| {
3892 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
3893 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
3894 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
3895 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {
3896 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
3897 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
3898 } else unreachable;
3899 switch (load_struct.type) {
3900 .import => unreachable,
3901 .got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct),
3902 }
3903 },
3904 else => unreachable,3827 else => unreachable,
3905 }3828 }
39063829
3907 const new_ptr = MCValue{ .register = addr_reg };3830 const new_ptr = MCValue{ .register = addr_reg };
3908 try self.store(new_ptr, value, ptr_ty, value_ty);3831 try self.store(new_ptr, value, ptr_ty, value_ty);
3909 },3832 },
3910 .lea_tlv => {3833 .load_got, .lea_direct, .lea_tlv => {
3911 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr);3834 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr);
3912 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);3835 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
3913 defer self.register_manager.unlockReg(addr_reg_lock);3836 defer self.register_manager.unlockReg(addr_reg_lock);
...@@ -4245,32 +4168,18 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue...@@ -4245,32 +4168,18 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue
4245 }));4168 }));
4246 },4169 },
4247 .ptr_stack_offset => unreachable,4170 .ptr_stack_offset => unreachable,
4248 .lea_tlv => unreachable,4171 .load_got, .lea_direct, .lea_tlv => unreachable,
4249 .memory, .load_tlv, .linker_load => {4172 .memory, .load_direct, .load_tlv => {
4250 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();4173 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
4251 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);4174 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
4252 defer self.register_manager.unlockReg(addr_reg_lock);4175 defer self.register_manager.unlockReg(addr_reg_lock);
42534176
4254 switch (dst_mcv) {4177 try self.genSetReg(Type.usize, addr_reg, switch (dst_mcv) {
4255 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),4178 .memory => |addr| .{ .immediate = addr },
4256 .load_tlv => |sym_index| try self.genSetReg(Type.usize, addr_reg, .{ .lea_tlv = sym_index }),4179 .load_direct => |sym_index| .{ .lea_direct = sym_index },
4257 .linker_load => |load_struct| {4180 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
4258 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
4259 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
4260 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
4261 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {
4262 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
4263 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
4264 } else unreachable;
4265
4266 switch (load_struct.type) {
4267 .import => unreachable,
4268 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
4269 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
4270 }
4271 },
4272 else => unreachable,4181 else => unreachable,
4273 }4182 });
4274 try self.asmMemory(4183 try self.asmMemory(
4275 mir_tag,4184 mir_tag,
4276 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = addr_reg }),4185 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = addr_reg }),
...@@ -4768,6 +4677,7 @@ fn genBinOp(...@@ -4768,6 +4677,7 @@ fn genBinOp(
4768 }4677 }
4769 const dst_mcv = try self.allocRegOrMemAdvanced(lhs_ty, maybe_inst, true);4678 const dst_mcv = try self.allocRegOrMemAdvanced(lhs_ty, maybe_inst, true);
4770 try self.setRegOrMem(lhs_ty, dst_mcv, switch (lhs) {4679 try self.setRegOrMem(lhs_ty, dst_mcv, switch (lhs) {
4680 .load_direct => |sym_index| .{ .lea_direct = sym_index },
4771 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },4681 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
4772 else => lhs,4682 else => lhs,
4773 });4683 });
...@@ -4911,6 +4821,8 @@ fn genBinOp(...@@ -4911,6 +4821,8 @@ fn genBinOp(
4911 .eflags,4821 .eflags,
4912 .register_overflow,4822 .register_overflow,
4913 .ptr_stack_offset,4823 .ptr_stack_offset,
4824 .load_got,
4825 .lea_direct,
4914 .lea_tlv,4826 .lea_tlv,
4915 => unreachable,4827 => unreachable,
4916 .register => |src_reg| try self.asmCmovccRegisterRegister(4828 .register => |src_reg| try self.asmCmovccRegisterRegister(
...@@ -4926,32 +4838,17 @@ fn genBinOp(...@@ -4926,32 +4838,17 @@ fn genBinOp(
4926 }),4838 }),
4927 cc,4839 cc,
4928 ),4840 ),
4929 .memory, .load_tlv, .linker_load => {4841 .memory, .load_direct, .load_tlv => {
4930 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();4842 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
4931 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);4843 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
4932 defer self.register_manager.unlockReg(addr_reg_lock);4844 defer self.register_manager.unlockReg(addr_reg_lock);
49334845
4934 switch (mat_src_mcv) {4846 try self.genSetReg(Type.usize, addr_reg, switch (mat_src_mcv) {
4935 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),4847 .memory => |addr| .{ .immediate = addr },
4936 .load_tlv => |sym_index| try self.genSetReg(Type.usize, addr_reg, .{ .lea_tlv = sym_index }),4848 .load_direct => |sym_index| .{ .lea_direct = sym_index },
4937 .linker_load => |load_struct| {4849 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
4938 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
4939 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
4940 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
4941 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {
4942 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
4943 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
4944 } else unreachable;
4945
4946 switch (load_struct.type) {
4947 .import => unreachable,
4948 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
4949 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
4950 }
4951 },
4952 else => unreachable,4850 else => unreachable,
4953 }4851 });
4954
4955 try self.asmCmovccRegisterMemory(4852 try self.asmCmovccRegisterMemory(
4956 registerAlias(tmp_reg, cmov_abi_size),4853 registerAlias(tmp_reg, cmov_abi_size),
4957 Memory.sib(Memory.PtrSize.fromSize(cmov_abi_size), .{ .base = addr_reg }),4854 Memory.sib(Memory.PtrSize.fromSize(cmov_abi_size), .{ .base = addr_reg }),
...@@ -5045,7 +4942,15 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s...@@ -5045,7 +4942,15 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5045 )),4942 )),
5046 else => unreachable,4943 else => unreachable,
5047 },4944 },
5048 .ptr_stack_offset, .memory, .lea_tlv, .load_tlv, .linker_load, .eflags => {4945 .ptr_stack_offset,
4946 .memory,
4947 .load_got,
4948 .lea_direct,
4949 .load_direct,
4950 .lea_tlv,
4951 .load_tlv,
4952 .eflags,
4953 => {
5049 assert(abi_size <= 8);4954 assert(abi_size <= 8);
5050 const dst_reg_lock = self.register_manager.lockReg(dst_reg);4955 const dst_reg_lock = self.register_manager.lockReg(dst_reg);
5051 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);4956 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
...@@ -5060,37 +4965,23 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s...@@ -5060,37 +4965,23 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5060 ),4965 ),
5061 }4966 }
5062 },4967 },
5063 .memory, .load_tlv, .linker_load, .stack_offset => {4968 .memory, .load_got, .load_direct, .load_tlv, .stack_offset => {
5064 const dst: ?struct {4969 const dst: ?struct {
5065 addr_reg: Register,4970 addr_reg: Register,
5066 addr_lock: RegisterLock,4971 addr_lock: RegisterLock,
5067 } = switch (dst_mcv) {4972 } = switch (dst_mcv) {
5068 else => unreachable,4973 else => unreachable,
5069 .memory, .load_tlv, .linker_load => dst: {4974 .memory, .load_got, .load_direct, .load_tlv => dst: {
5070 const dst_addr_reg = (try self.register_manager.allocReg(null, gp)).to64();4975 const dst_addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
5071 const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);4976 const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);
5072 errdefer self.register_manager.unlockReg(dst_addr_lock);4977 errdefer self.register_manager.unlockReg(dst_addr_lock);
50734978
5074 switch (dst_mcv) {4979 try self.genSetReg(Type.usize, dst_addr_reg, switch (dst_mcv) {
5075 .memory => |addr| try self.genSetReg(Type.usize, dst_addr_reg, .{ .immediate = addr }),4980 .memory => |addr| .{ .immediate = addr },
5076 .load_tlv => |sym_index| try self.genSetReg(Type.usize, dst_addr_reg, .{ .lea_tlv = sym_index }),4981 .load_direct => |sym_index| .{ .lea_direct = sym_index },
5077 .linker_load => |load_struct| {4982 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
5078 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {4983 else => dst_mcv,
5079 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);4984 });
5080 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
5081 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {
5082 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
5083 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
5084 } else unreachable;
5085
5086 switch (load_struct.type) {
5087 .import => unreachable,
5088 .got => try self.asmMovLinker(dst_addr_reg, atom_index, load_struct),
5089 .direct => try self.asmLeaLinker(dst_addr_reg, atom_index, load_struct),
5090 }
5091 },
5092 else => unreachable,
5093 }
50944985
5095 break :dst .{4986 break :dst .{
5096 .addr_reg = dst_addr_reg,4987 .addr_reg = dst_addr_reg,
...@@ -5108,7 +4999,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s...@@ -5108,7 +4999,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5108 addr_lock: RegisterLock,4999 addr_lock: RegisterLock,
5109 } = switch (src_mcv) {5000 } = switch (src_mcv) {
5110 else => null,5001 else => null,
5111 .memory, .load_tlv, .linker_load => src: {5002 .memory, .load_got, .load_direct, .load_tlv => src: {
5112 const src_limb_reg = try self.register_manager.allocReg(null, gp);5003 const src_limb_reg = try self.register_manager.allocReg(null, gp);
5113 const src_limb_lock = self.register_manager.lockRegAssumeUnused(src_limb_reg);5004 const src_limb_lock = self.register_manager.lockRegAssumeUnused(src_limb_reg);
5114 errdefer self.register_manager.unlockReg(src_limb_lock);5005 errdefer self.register_manager.unlockReg(src_limb_lock);
...@@ -5117,26 +5008,12 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s...@@ -5117,26 +5008,12 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5117 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);5008 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);
5118 errdefer self.register_manager.unlockReg(src_addr_lock);5009 errdefer self.register_manager.unlockReg(src_addr_lock);
51195010
5120 switch (src_mcv) {5011 try self.genSetReg(Type.usize, src_addr_reg, switch (src_mcv) {
5121 .memory => |addr| try self.genSetReg(Type.usize, src_addr_reg, .{ .immediate = addr }),5012 .memory => |addr| .{ .immediate = addr },
5122 .load_tlv => |sym_index| try self.genSetReg(Type.usize, src_addr_reg, .{ .lea_tlv = sym_index }),5013 .load_direct => |sym_index| .{ .lea_direct = sym_index },
5123 .linker_load => |load_struct| {5014 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
5124 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {5015 else => src_mcv,
5125 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);5016 });
5126 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
5127 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {
5128 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
5129 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
5130 } else unreachable;
5131
5132 switch (load_struct.type) {
5133 .import => unreachable,
5134 .got => try self.asmMovLinker(src_addr_reg, atom_index, load_struct),
5135 .direct => try self.asmLeaLinker(src_addr_reg, atom_index, load_struct),
5136 }
5137 },
5138 else => unreachable,
5139 }
51405017
5141 break :src .{5018 break :src .{
5142 .addr_reg = src_addr_reg,5019 .addr_reg = src_addr_reg,
...@@ -5179,7 +5056,11 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s...@@ -5179,7 +5056,11 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5179 .base = .rbp,5056 .base = .rbp,
5180 .disp = off - dst_off,5057 .disp = off - dst_off,
5181 },5058 },
5182 .memory, .linker_load => .{ .base = dst.?.addr_reg, .disp = off },5059 .memory,
5060 .load_got,
5061 .load_direct,
5062 .load_tlv,
5063 => .{ .base = dst.?.addr_reg, .disp = off },
5183 },5064 },
5184 );5065 );
5185 switch (src_mcv) {5066 switch (src_mcv) {
...@@ -5243,7 +5124,11 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s...@@ -5243,7 +5124,11 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5243 else => unreachable,5124 else => unreachable,
5244 }5125 }
5245 },5126 },
5246 .memory, .linker_load, .lea_tlv, .load_tlv => {5127 .memory,
5128 .load_got,
5129 .load_direct,
5130 .load_tlv,
5131 => {
5247 try self.asmRegisterMemory(5132 try self.asmRegisterMemory(
5248 .mov,5133 .mov,
5249 registerAlias(src.?.limb_reg, limb_abi_size),5134 registerAlias(src.?.limb_reg, limb_abi_size),
...@@ -5258,11 +5143,19 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s...@@ -5258,11 +5143,19 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5258 registerAlias(src.?.limb_reg, limb_abi_size),5143 registerAlias(src.?.limb_reg, limb_abi_size),
5259 );5144 );
5260 },5145 },
5261 .stack_offset, .ptr_stack_offset, .eflags => {5146 .stack_offset,
5147 .ptr_stack_offset,
5148 .eflags,
5149 .lea_direct,
5150 .lea_tlv,
5151 => {
5262 const src_limb_reg = try self.copyToTmpRegister(limb_ty, switch (src_mcv) {5152 const src_limb_reg = try self.copyToTmpRegister(limb_ty, switch (src_mcv) {
5263 .stack_offset => |src_off| .{ .stack_offset = src_off - off },5153 .stack_offset => |src_off| .{ .stack_offset = src_off - off },
5264 .ptr_stack_offset,5154 .ptr_stack_offset,
5265 .eflags,5155 .eflags,
5156 .load_got,
5157 .lea_direct,
5158 .lea_tlv,
5266 => off: {5159 => off: {
5267 assert(off == 0);5160 assert(off == 0);
5268 break :off src_mcv;5161 break :off src_mcv;
...@@ -5283,6 +5176,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s...@@ -5283,6 +5176,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5283 },5176 },
5284 .ptr_stack_offset => unreachable,5177 .ptr_stack_offset => unreachable,
5285 .lea_tlv => unreachable,5178 .lea_tlv => unreachable,
5179 .lea_direct => unreachable,
5286 }5180 }
5287}5181}
52885182
...@@ -5296,6 +5190,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -5296,6 +5190,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
5296 .dead, .unreach, .immediate => unreachable,5190 .dead, .unreach, .immediate => unreachable,
5297 .eflags => unreachable,5191 .eflags => unreachable,
5298 .ptr_stack_offset => unreachable,5192 .ptr_stack_offset => unreachable,
5193 .lea_direct => unreachable,
5299 .lea_tlv => unreachable,5194 .lea_tlv => unreachable,
5300 .register_overflow => unreachable,5195 .register_overflow => unreachable,
5301 .register => |dst_reg| {5196 .register => |dst_reg| {
...@@ -5308,6 +5203,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -5308,6 +5203,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
5308 .undef => try self.genSetReg(dst_ty, dst_reg, .undef),5203 .undef => try self.genSetReg(dst_ty, dst_reg, .undef),
5309 .dead, .unreach => unreachable,5204 .dead, .unreach => unreachable,
5310 .ptr_stack_offset => unreachable,5205 .ptr_stack_offset => unreachable,
5206 .lea_direct => unreachable,
5311 .lea_tlv => unreachable,5207 .lea_tlv => unreachable,
5312 .register_overflow => unreachable,5208 .register_overflow => unreachable,
5313 .register => |src_reg| try self.asmRegisterRegister(5209 .register => |src_reg| try self.asmRegisterRegister(
...@@ -5335,12 +5231,13 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -5335,12 +5231,13 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
5335 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .rbp, .disp = -off }),5231 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .rbp, .disp = -off }),
5336 );5232 );
5337 },5233 },
5338 .memory, .load_tlv => {5234 .memory,
5235 .load_got,
5236 .load_direct,
5237 .load_tlv,
5238 => {
5339 return self.fail("TODO implement x86 multiply source memory", .{});5239 return self.fail("TODO implement x86 multiply source memory", .{});
5340 },5240 },
5341 .linker_load => {
5342 return self.fail("TODO implement x86 multiply source symbol at index in linker", .{});
5343 },
5344 .eflags => {5241 .eflags => {
5345 return self.fail("TODO implement x86 multiply source eflags", .{});5242 return self.fail("TODO implement x86 multiply source eflags", .{});
5346 },5243 },
...@@ -5352,6 +5249,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -5352,6 +5249,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
5352 .undef => return self.genSetStack(dst_ty, off, .undef, .{}),5249 .undef => return self.genSetStack(dst_ty, off, .undef, .{}),
5353 .dead, .unreach => unreachable,5250 .dead, .unreach => unreachable,
5354 .ptr_stack_offset => unreachable,5251 .ptr_stack_offset => unreachable,
5252 .lea_direct => unreachable,
5355 .lea_tlv => unreachable,5253 .lea_tlv => unreachable,
5356 .register_overflow => unreachable,5254 .register_overflow => unreachable,
5357 .register => |src_reg| {5255 .register => |src_reg| {
...@@ -5375,23 +5273,26 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -5375,23 +5273,26 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
53755273
5376 return self.genSetStack(dst_ty, off, .{ .register = dst_reg }, .{});5274 return self.genSetStack(dst_ty, off, .{ .register = dst_reg }, .{});
5377 },5275 },
5378 .memory, .load_tlv, .stack_offset => {5276 .memory,
5277 .load_got,
5278 .load_direct,
5279 .load_tlv,
5280 .stack_offset,
5281 => {
5379 return self.fail("TODO implement x86 multiply source memory", .{});5282 return self.fail("TODO implement x86 multiply source memory", .{});
5380 },5283 },
5381 .linker_load => {
5382 return self.fail("TODO implement x86 multiply source symbol at index in linker", .{});
5383 },
5384 .eflags => {5284 .eflags => {
5385 return self.fail("TODO implement x86 multiply source eflags", .{});5285 return self.fail("TODO implement x86 multiply source eflags", .{});
5386 },5286 },
5387 }5287 }
5388 },5288 },
5389 .memory, .load_tlv => {5289 .memory,
5290 .load_got,
5291 .load_direct,
5292 .load_tlv,
5293 => {
5390 return self.fail("TODO implement x86 multiply destination memory", .{});5294 return self.fail("TODO implement x86 multiply destination memory", .{});
5391 },5295 },
5392 .linker_load => {
5393 return self.fail("TODO implement x86 multiply destination symbol at index in linker", .{});
5394 },
5395 }5296 }
5396}5297}
53975298
...@@ -5471,7 +5372,8 @@ fn genVarDbgInfo(...@@ -5471,7 +5372,8 @@ fn genVarDbgInfo(
5471 .offset = -off,5372 .offset = -off,
5472 } },5373 } },
5473 .memory => |address| .{ .memory = address },5374 .memory => |address| .{ .memory = address },
5474 .linker_load => |linker_load| .{ .linker_load = linker_load },5375 .load_got => |sym_index| .{ .linker_load = .{ .type = .got, .sym_index = sym_index } },
5376 .load_direct => |sym_index| .{ .linker_load = .{ .type = .direct, .sym_index = sym_index } },
5475 .immediate => |x| .{ .immediate = x },5377 .immediate => |x| .{ .immediate = x },
5476 .undef => .undef,5378 .undef => .undef,
5477 .none => .none,5379 .none => .none,
...@@ -5572,9 +5474,11 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -5572,9 +5474,11 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
5572 .unreach => unreachable,5474 .unreach => unreachable,
5573 .dead => unreachable,5475 .dead => unreachable,
5574 .memory => unreachable,5476 .memory => unreachable,
5575 .linker_load => unreachable,
5576 .eflags => unreachable,5477 .eflags => unreachable,
5577 .register_overflow => unreachable,5478 .register_overflow => unreachable,
5479 .load_got => unreachable,
5480 .lea_direct => unreachable,
5481 .load_direct => unreachable,
5578 .lea_tlv => unreachable,5482 .lea_tlv => unreachable,
5579 .load_tlv => unreachable,5483 .load_tlv => unreachable,
5580 }5484 }
...@@ -5612,9 +5516,11 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -5612,9 +5516,11 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
5612 .unreach => unreachable,5516 .unreach => unreachable,
5613 .dead => unreachable,5517 .dead => unreachable,
5614 .memory => unreachable,5518 .memory => unreachable,
5615 .linker_load => unreachable,
5616 .eflags => unreachable,5519 .eflags => unreachable,
5617 .register_overflow => unreachable,5520 .register_overflow => unreachable,
5521 .load_got => unreachable,
5522 .lea_direct => unreachable,
5523 .load_direct => unreachable,
5618 .lea_tlv => unreachable,5524 .lea_tlv => unreachable,
5619 .load_tlv => unreachable,5525 .load_tlv => unreachable,
5620 }5526 }
...@@ -5639,21 +5545,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -5639,21 +5545,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
5639 .base = .ds,5545 .base = .ds,
5640 .disp = @intCast(i32, got_addr),5546 .disp = @intCast(i32, got_addr),
5641 }));5547 }));
5642 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {5548 } else if (self.bin_file.cast(link.File.Coff)) |_| {
5643 const atom_index = try coff_file.getOrCreateAtomForDecl(func.owner_decl);5549 const sym_index = try self.getSymbolIndexForDecl(func.owner_decl);
5644 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;5550 try self.genSetReg(Type.usize, .rax, .{ .load_got = sym_index });
5645 try self.genSetReg(Type.usize, .rax, .{ .linker_load = .{
5646 .type = .got,
5647 .sym_index = sym_index,
5648 } });
5649 try self.asmRegister(.call, .rax);5551 try self.asmRegister(.call, .rax);
5650 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {5552 } else if (self.bin_file.cast(link.File.MachO)) |_| {
5651 const atom_index = try macho_file.getOrCreateAtomForDecl(func.owner_decl);5553 const sym_index = try self.getSymbolIndexForDecl(func.owner_decl);
5652 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;5554 try self.genSetReg(Type.usize, .rax, .{ .load_got = sym_index });
5653 try self.genSetReg(Type.usize, .rax, .{ .linker_load = .{
5654 .type = .got,
5655 .sym_index = sym_index,
5656 } });
5657 try self.asmRegister(.call, .rax);5555 try self.asmRegister(.call, .rax);
5658 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {5556 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
5659 const decl_block_index = try p9.seeDecl(func.owner_decl);5557 const decl_block_index = try p9.seeDecl(func.owner_decl);
...@@ -5673,18 +5571,21 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -5673,18 +5571,21 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
5673 const decl_name = mem.sliceTo(mod.declPtr(extern_fn.owner_decl).name, 0);5571 const decl_name = mem.sliceTo(mod.declPtr(extern_fn.owner_decl).name, 0);
5674 const lib_name = mem.sliceTo(extern_fn.lib_name, 0);5572 const lib_name = mem.sliceTo(extern_fn.lib_name, 0);
5675 if (self.bin_file.cast(link.File.Coff)) |coff_file| {5573 if (self.bin_file.cast(link.File.Coff)) |coff_file| {
5574 const atom_index = try self.getSymbolIndexForDecl(self.mod_fn.owner_decl);
5676 const sym_index = try coff_file.getGlobalSymbol(decl_name, lib_name);5575 const sym_index = try coff_file.getGlobalSymbol(decl_name, lib_name);
5677 try self.genSetReg(Type.usize, .rax, .{5576 _ = try self.addInst(.{
5678 .linker_load = .{5577 .tag = .mov_linker,
5679 .type = .import,5578 .ops = .import_reloc,
5579 .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{
5580 .reg = @enumToInt(Register.rax),
5581 .atom_index = atom_index,
5680 .sym_index = sym_index,5582 .sym_index = sym_index,
5681 },5583 }) },
5682 });5584 });
5683 try self.asmRegister(.call, .rax);5585 try self.asmRegister(.call, .rax);
5684 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {5586 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
5685 const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);5587 const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);
5686 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);5588 const atom_index = try self.getSymbolIndexForDecl(self.mod_fn.owner_decl);
5687 const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;
5688 _ = try self.addInst(.{5589 _ = try self.addInst(.{
5689 .tag = .call_extern,5590 .tag = .call_extern,
5690 .ops = undefined,5591 .ops = undefined,
...@@ -5883,20 +5784,14 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {...@@ -5883,20 +5784,14 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {
5883 4, // dword alignment5784 4, // dword alignment
5884 );5785 );
5885 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;5786 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
5886 try self.genSetReg(Type.usize, addr_reg, .{ .linker_load = .{5787 try self.genSetReg(Type.usize, addr_reg, .{ .load_got = sym_index });
5887 .type = .got,
5888 .sym_index = sym_index,
5889 } });
5890 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {5788 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
5891 const atom_index = try macho_file.getOrCreateAtomForLazySymbol(5789 const atom_index = try macho_file.getOrCreateAtomForLazySymbol(
5892 .{ .kind = .const_data, .ty = Type.anyerror },5790 .{ .kind = .const_data, .ty = Type.anyerror },
5893 4, // dword alignment5791 4, // dword alignment
5894 );5792 );
5895 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;5793 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
5896 try self.genSetReg(Type.usize, addr_reg, .{ .linker_load = .{5794 try self.genSetReg(Type.usize, addr_reg, .{ .load_got = sym_index });
5897 .type = .got,
5898 .sym_index = sym_index,
5899 } });
5900 } else {5795 } else {
5901 return self.fail("TODO implement airErrorName for x86_64 {s}", .{@tagName(self.bin_file.tag)});5796 return self.fail("TODO implement airErrorName for x86_64 {s}", .{@tagName(self.bin_file.tag)});
5902 }5797 }
...@@ -6138,6 +6033,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -6138,6 +6033,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
6138 .register_overflow,6033 .register_overflow,
6139 .ptr_stack_offset,6034 .ptr_stack_offset,
6140 .eflags,6035 .eflags,
6036 .lea_direct,
6141 .lea_tlv,6037 .lea_tlv,
6142 => unreachable,6038 => unreachable,
61436039
...@@ -6159,31 +6055,21 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -6159,31 +6055,21 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
6159 return .{ .eflags = .nc };6055 return .{ .eflags = .nc };
6160 },6056 },
61616057
6162 .memory, .load_tlv, .linker_load => {6058 .memory,
6059 .load_got,
6060 .load_direct,
6061 .load_tlv,
6062 => {
6163 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();6063 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
6164 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);6064 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
6165 defer self.register_manager.unlockReg(addr_reg_lock);6065 defer self.register_manager.unlockReg(addr_reg_lock);
61666066
6167 switch (opt_mcv) {6067 try self.genSetReg(Type.usize, addr_reg, switch (opt_mcv) {
6168 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),6068 .memory => |addr| .{ .immediate = addr },
6169 .load_tlv => |sym_index| try self.genSetReg(Type.usize, addr_reg, .{ .lea_tlv = sym_index }),6069 .load_direct => |sym_index| .{ .lea_direct = sym_index },
6170 .linker_load => |load_struct| {6070 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
6171 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {6071 else => opt_mcv,
6172 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);6072 });
6173 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
6174 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {
6175 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
6176 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
6177 } else unreachable;
6178
6179 switch (load_struct.type) {
6180 .import => unreachable,
6181 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
6182 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
6183 }
6184 },
6185 else => unreachable,
6186 }
61876073
6188 const some_abi_size = @intCast(u32, some_info.ty.abiSize(self.target.*));6074 const some_abi_size = @intCast(u32, some_info.ty.abiSize(self.target.*));
6189 try self.asmMemoryImmediate(.cmp, Memory.sib(6075 try self.asmMemoryImmediate(.cmp, Memory.sib(
...@@ -7112,7 +6998,10 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE...@@ -7112,7 +6998,10 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
7112 else => return self.fail("TODO implement inputs on stack for {} with abi size > 8", .{mcv}),6998 else => return self.fail("TODO implement inputs on stack for {} with abi size > 8", .{mcv}),
7113 }6999 }
7114 },7000 },
7115 .memory, .load_tlv, .linker_load => {7001 .memory,
7002 .load_direct,
7003 .load_tlv,
7004 => {
7116 if (abi_size <= 8) {7005 if (abi_size <= 8) {
7117 const reg = try self.copyToTmpRegister(ty, mcv);7006 const reg = try self.copyToTmpRegister(ty, mcv);
7118 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });7007 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
...@@ -7122,27 +7011,12 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE...@@ -7122,27 +7011,12 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
7122 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);7011 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
7123 defer self.register_manager.unlockReg(addr_lock);7012 defer self.register_manager.unlockReg(addr_lock);
71247013
7125 switch (mcv) {7014 try self.genSetReg(Type.usize, addr_reg, switch (mcv) {
7126 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),7015 .memory => |addr| .{ .immediate = addr },
7127 .load_tlv => |sym_index| try self.genSetReg(Type.usize, addr_reg, .{ .lea_tlv = sym_index }),7016 .load_direct => |sym_index| .{ .lea_direct = sym_index },
7128 .linker_load => |load_struct| {7017 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
7129 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
7130 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
7131 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
7132 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {
7133 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
7134 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
7135 } else unreachable;
7136
7137 switch (load_struct.type) {
7138 .import => unreachable,
7139 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
7140 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
7141 }
7142 },
7143 else => unreachable,7018 else => unreachable,
7144 }7019 });
7145
7146 try self.genInlineMemcpy(7020 try self.genInlineMemcpy(
7147 .{ .ptr_stack_offset = stack_offset },7021 .{ .ptr_stack_offset = stack_offset },
7148 .{ .register = addr_reg },7022 .{ .register = addr_reg },
...@@ -7184,7 +7058,11 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE...@@ -7184,7 +7058,11 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
7184 },7058 },
7185 }7059 }
7186 },7060 },
7187 .ptr_stack_offset, .lea_tlv => {7061 .ptr_stack_offset,
7062 .load_got,
7063 .lea_direct,
7064 .lea_tlv,
7065 => {
7188 const reg = try self.copyToTmpRegister(ty, mcv);7066 const reg = try self.copyToTmpRegister(ty, mcv);
7189 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });7067 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
7190 },7068 },
...@@ -7342,7 +7220,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl...@@ -7342,7 +7220,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
7342 },7220 },
7343 }7221 }
7344 },7222 },
7345 .memory, .load_tlv, .linker_load => if (abi_size <= 8) {7223 .memory,
7224 .load_direct,
7225 .load_tlv,
7226 => if (abi_size <= 8) {
7346 const reg = try self.copyToTmpRegister(ty, mcv);7227 const reg = try self.copyToTmpRegister(ty, mcv);
7347 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts);7228 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts);
7348 } else {7229 } else {
...@@ -7350,27 +7231,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl...@@ -7350,27 +7231,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
7350 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);7231 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
7351 defer self.register_manager.unlockReg(addr_lock);7232 defer self.register_manager.unlockReg(addr_lock);
73527233
7353 switch (mcv) {7234 try self.genSetReg(Type.usize, addr_reg, switch (mcv) {
7354 .memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),7235 .memory => |addr| .{ .immediate = addr },
7355 .load_tlv => |sym_index| try self.genSetReg(Type.usize, addr_reg, .{ .lea_tlv = sym_index }),7236 .load_direct => |sym_index| .{ .lea_direct = sym_index },
7356 .linker_load => |load_struct| {7237 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
7357 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
7358 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
7359 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
7360 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {
7361 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
7362 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
7363 } else unreachable;
7364
7365 switch (load_struct.type) {
7366 .import => unreachable,
7367 .got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
7368 .direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
7369 }
7370 },
7371 else => unreachable,7238 else => unreachable,
7372 }7239 });
7373
7374 try self.genInlineMemcpy(7240 try self.genInlineMemcpy(
7375 .{ .ptr_stack_offset = stack_offset },7241 .{ .ptr_stack_offset = stack_offset },
7376 .{ .register = addr_reg },7242 .{ .register = addr_reg },
...@@ -7390,7 +7256,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl...@@ -7390,7 +7256,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
7390 .{ .immediate = abi_size },7256 .{ .immediate = abi_size },
7391 .{},7257 .{},
7392 ),7258 ),
7393 .ptr_stack_offset, .lea_tlv => {7259 .ptr_stack_offset,
7260 .load_got,
7261 .lea_direct,
7262 .lea_tlv,
7263 => {
7394 const tmp_reg = try self.copyToTmpRegister(ty, mcv);7264 const tmp_reg = try self.copyToTmpRegister(ty, mcv);
7395 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);7265 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7396 defer self.register_manager.unlockReg(tmp_lock);7266 defer self.register_manager.unlockReg(tmp_lock);
...@@ -7485,21 +7355,13 @@ fn genInlineMemcpy(...@@ -7485,21 +7355,13 @@ fn genInlineMemcpy(
7485 // Load the pointer, which is stored in memory7355 // Load the pointer, which is stored in memory
7486 try self.asmRegisterMemory(.mov, .rdi, Memory.sib(.qword, .{ .base = .rdi }));7356 try self.asmRegisterMemory(.mov, .rdi, Memory.sib(.qword, .{ .base = .rdi }));
7487 },7357 },
7488 .linker_load => |load_struct| {7358 .load_got,
7489 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {7359 .lea_direct,
7490 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);7360 .load_direct,
7491 break :blk macho_file.getAtom(atom).getSymbolIndex().?;7361 .lea_tlv,
7492 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {7362 .load_tlv,
7493 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);7363 => try self.genSetReg(Type.usize, .rdi, switch (dst_ptr) {
7494 break :blk coff_file.getAtom(atom).getSymbolIndex().?;7364 .load_direct => |sym_index| .{ .lea_direct = sym_index },
7495 } else unreachable;
7496
7497 switch (load_struct.type) {
7498 .import => unreachable,
7499 .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),
7500 }
7501 },
7502 .lea_tlv, .load_tlv => try self.genSetReg(Type.usize, .rdi, switch (dst_ptr) {
7503 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },7365 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
7504 else => dst_ptr,7366 else => dst_ptr,
7505 }),7367 }),
...@@ -7531,21 +7393,13 @@ fn genInlineMemcpy(...@@ -7531,21 +7393,13 @@ fn genInlineMemcpy(
7531 // Load the pointer, which is stored in memory7393 // Load the pointer, which is stored in memory
7532 try self.asmRegisterMemory(.mov, .rsi, Memory.sib(.qword, .{ .base = .rsi }));7394 try self.asmRegisterMemory(.mov, .rsi, Memory.sib(.qword, .{ .base = .rsi }));
7533 },7395 },
7534 .linker_load => |load_struct| {7396 .load_got,
7535 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {7397 .lea_direct,
7536 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);7398 .load_direct,
7537 break :blk macho_file.getAtom(atom).getSymbolIndex().?;7399 .lea_tlv,
7538 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {7400 .load_tlv,
7539 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);7401 => try self.genSetReg(Type.usize, .rsi, switch (src_ptr) {
7540 break :blk coff_file.getAtom(atom).getSymbolIndex().?;7402 .load_direct => |sym_index| .{ .lea_direct = sym_index },
7541 } else unreachable;
7542
7543 switch (load_struct.type) {
7544 .import => unreachable,
7545 .got, .direct => try self.asmMovLinker(.rsi, atom_index, load_struct),
7546 }
7547 },
7548 .lea_tlv, .load_tlv => try self.genSetReg(Type.usize, .rsi, switch (src_ptr) {
7549 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },7403 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
7550 else => src_ptr,7404 else => src_ptr,
7551 }),7405 }),
...@@ -7600,21 +7454,13 @@ fn genInlineMemset(...@@ -7600,21 +7454,13 @@ fn genInlineMemset(
7600 // Load the pointer, which is stored in memory7454 // Load the pointer, which is stored in memory
7601 try self.asmRegisterMemory(.mov, .rdi, Memory.sib(.qword, .{ .base = .rdi }));7455 try self.asmRegisterMemory(.mov, .rdi, Memory.sib(.qword, .{ .base = .rdi }));
7602 },7456 },
7603 .linker_load => |load_struct| {7457 .load_got,
7604 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {7458 .lea_direct,
7605 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);7459 .load_direct,
7606 break :blk macho_file.getAtom(atom).getSymbolIndex().?;7460 .lea_tlv,
7607 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {7461 .load_tlv,
7608 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);7462 => try self.genSetReg(Type.usize, .rdi, switch (dst_ptr) {
7609 break :blk coff_file.getAtom(atom).getSymbolIndex().?;7463 .load_direct => |sym_index| .{ .lea_direct = sym_index },
7610 } else unreachable;
7611
7612 switch (load_struct.type) {
7613 .import => unreachable,
7614 .got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),
7615 }
7616 },
7617 .lea_tlv, .load_tlv => try self.genSetReg(Type.usize, .rdi, switch (dst_ptr) {
7618 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },7464 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
7619 else => dst_ptr,7465 else => dst_ptr,
7620 }),7466 }),
...@@ -7793,15 +7639,64 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -7793,15 +7639,64 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
7793 }7639 }
7794 },7640 },
7795 },7641 },
7796 .lea_tlv => |sym_index| {7642 .load_got, .lea_direct => |sym_index| {
7797 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {7643 const atom_index = try self.getSymbolIndexForDecl(self.mod_fn.owner_decl);
7798 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);7644 _ = try self.addInst(.{
7799 break :blk macho_file.getAtom(atom).getSymbolIndex().?;7645 .tag = switch (mcv) {
7800 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {7646 .load_got => .mov_linker,
7801 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);7647 .lea_direct => .lea_linker,
7802 break :blk coff_file.getAtom(atom).getSymbolIndex().?;7648 else => unreachable,
7803 } else unreachable;7649 },
7650 .ops = switch (mcv) {
7651 .load_got => .got_reloc,
7652 .lea_direct => .direct_reloc,
7653 else => unreachable,
7654 },
7655 .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{
7656 .reg = @enumToInt(reg),
7657 .atom_index = atom_index,
7658 .sym_index = sym_index,
7659 }) },
7660 });
7661 },
7662 .load_direct => |sym_index| {
7663 switch (ty.zigTypeTag()) {
7664 .Float => {
7665 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
7666 try self.genSetReg(Type.usize, addr_reg, .{ .lea_direct = sym_index });
7667
7668 if (intrinsicsAllowed(self.target.*, ty)) {
7669 return self.asmRegisterMemory(
7670 switch (ty.tag()) {
7671 .f32 => .movss,
7672 .f64 => .movsd,
7673 else => return self.fail("TODO genSetReg from memory for {}", .{
7674 ty.fmt(self.bin_file.options.module.?),
7675 }),
7676 },
7677 reg.to128(),
7678 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = addr_reg }),
7679 );
7680 }
78047681
7682 return self.fail("TODO genSetReg from memory for float with no intrinsics", .{});
7683 },
7684 else => {
7685 const atom_index = try self.getSymbolIndexForDecl(self.mod_fn.owner_decl);
7686 _ = try self.addInst(.{
7687 .tag = .mov_linker,
7688 .ops = .direct_reloc,
7689 .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{
7690 .reg = @enumToInt(registerAlias(reg, abi_size)),
7691 .atom_index = atom_index,
7692 .sym_index = sym_index,
7693 }) },
7694 });
7695 },
7696 }
7697 },
7698 .lea_tlv => |sym_index| {
7699 const atom_index = try self.getSymbolIndexForDecl(self.mod_fn.owner_decl);
7805 if (self.bin_file.cast(link.File.MachO)) |_| {7700 if (self.bin_file.cast(link.File.MachO)) |_| {
7806 _ = try self.addInst(.{7701 _ = try self.addInst(.{
7807 .tag = .mov_linker,7702 .tag = .mov_linker,
...@@ -7844,39 +7739,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -7844,39 +7739,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
7844 ),7739 ),
7845 }7740 }
7846 },7741 },
7847 .linker_load => |load_struct| {
7848 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
7849 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
7850 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
7851 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {
7852 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
7853 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
7854 } else unreachable;
7855
7856 switch (ty.zigTypeTag()) {
7857 .Float => {
7858 const base_reg = (try self.register_manager.allocReg(null, gp)).to64();
7859 try self.asmLeaLinker(base_reg, atom_index, load_struct);
7860
7861 if (intrinsicsAllowed(self.target.*, ty)) {
7862 return self.asmRegisterMemory(
7863 switch (ty.tag()) {
7864 .f32 => .movss,
7865 .f64 => .movsd,
7866 else => return self.fail("TODO genSetReg from memory for {}", .{
7867 ty.fmt(self.bin_file.options.module.?),
7868 }),
7869 },
7870 reg.to128(),
7871 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base_reg.to64() }),
7872 );
7873 }
7874
7875 return self.fail("TODO genSetReg from memory for float with no intrinsics", .{});
7876 },
7877 else => try self.asmMovLinker(registerAlias(reg, abi_size), atom_index, load_struct),
7878 }
7879 },
7880 .stack_offset => |off| {7742 .stack_offset => |off| {
7881 switch (ty.zigTypeTag()) {7743 switch (ty.zigTypeTag()) {
7882 .Int => switch (ty.intInfo(self.target.*).signedness) {7744 .Int => switch (ty.intInfo(self.target.*).signedness) {
...@@ -8515,20 +8377,14 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {...@@ -8515,20 +8377,14 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
8515 4, // dword alignment8377 4, // dword alignment
8516 );8378 );
8517 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;8379 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
8518 try self.genSetReg(Type.usize, addr_reg, .{ .linker_load = .{8380 try self.genSetReg(Type.usize, addr_reg, .{ .load_got = sym_index });
8519 .type = .got,
8520 .sym_index = sym_index,
8521 } });
8522 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {8381 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
8523 const atom_index = try macho_file.getOrCreateAtomForLazySymbol(8382 const atom_index = try macho_file.getOrCreateAtomForLazySymbol(
8524 .{ .kind = .const_data, .ty = Type.anyerror },8383 .{ .kind = .const_data, .ty = Type.anyerror },
8525 4, // dword alignment8384 4, // dword alignment
8526 );8385 );
8527 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;8386 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
8528 try self.genSetReg(Type.usize, addr_reg, .{ .linker_load = .{8387 try self.genSetReg(Type.usize, addr_reg, .{ .load_got = sym_index });
8529 .type = .got,
8530 .sym_index = sym_index,
8531 } });
8532 } else {8388 } else {
8533 return self.fail("TODO implement airErrorName for x86_64 {s}", .{@tagName(self.bin_file.tag)});8389 return self.fail("TODO implement airErrorName for x86_64 {s}", .{@tagName(self.bin_file.tag)});
8534 }8390 }
...@@ -8839,9 +8695,10 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -8839,9 +8695,10 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
8839 .mcv => |mcv| switch (mcv) {8695 .mcv => |mcv| switch (mcv) {
8840 .none => .none,8696 .none => .none,
8841 .undef => .undef,8697 .undef => .undef,
8842 .linker_load => |ll| .{ .linker_load = ll },
8843 .immediate => |imm| .{ .immediate = imm },8698 .immediate => |imm| .{ .immediate = imm },
8844 .memory => |addr| .{ .memory = addr },8699 .memory => |addr| .{ .memory = addr },
8700 .load_direct => |sym_index| .{ .load_direct = sym_index },
8701 .load_got => |sym_index| .{ .load_got = sym_index },
8845 .load_tlv => |sym_index| .{ .load_tlv = sym_index },8702 .load_tlv => |sym_index| .{ .load_tlv = sym_index },
8846 },8703 },
8847 .fail => |msg| {8704 .fail => |msg| {
...@@ -9140,3 +8997,13 @@ fn intrinsicsAllowed(target: Target, ty: Type) bool {...@@ -9140,3 +8997,13 @@ fn intrinsicsAllowed(target: Target, ty: Type) bool {
9140fn hasAvxSupport(target: Target) bool {8997fn hasAvxSupport(target: Target) bool {
9141 return Target.x86.featureSetHasAny(target.cpu.features, .{ .avx, .avx2 });8998 return Target.x86.featureSetHasAny(target.cpu.features, .{ .avx, .avx2 });
9142}8999}
9000
9001fn getSymbolIndexForDecl(self: *Self, decl_index: Module.Decl.Index) !u32 {
9002 if (self.bin_file.cast(link.File.MachO)) |macho_file| {
9003 const atom = try macho_file.getOrCreateAtomForDecl(decl_index);
9004 return macho_file.getAtom(atom).getSymbolIndex().?;
9005 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
9006 const atom = try coff_file.getOrCreateAtomForDecl(decl_index);
9007 return coff_file.getAtom(atom).getSymbolIndex().?;
9008 } else unreachable;
9009}
src/codegen.zig+11-17
...@@ -931,11 +931,17 @@ pub const GenResult = union(enum) {...@@ -931,11 +931,17 @@ pub const GenResult = union(enum) {
931 /// The bit-width of the immediate may be smaller than `u64`. For example, on 32-bit targets931 /// The bit-width of the immediate may be smaller than `u64`. For example, on 32-bit targets
932 /// such as ARM, the immediate will never exceed 32-bits.932 /// such as ARM, the immediate will never exceed 32-bits.
933 immediate: u64,933 immediate: u64,
934 linker_load: LinkerLoad,
935 /// Threadlocal variable with address deferred until the linker allocates934 /// Threadlocal variable with address deferred until the linker allocates
936 /// everything in virtual memory.935 /// everything in virtual memory.
937 /// Payload is a symbol index.936 /// Payload is a symbol index.
938 load_tlv: u32,937 load_tlv: u32,
938 /// Decl with address deferred until the linker allocates everything in virtual memory.
939 /// Payload is a symbol index.
940 load_direct: u32,
941 /// Decl referenced via GOT with address deferred until the linker allocates
942 /// everything in virtual memory.
943 /// Payload is a symbol index.
944 load_got: u32,
939 /// Direct by-address reference to memory location.945 /// Direct by-address reference to memory location.
940 memory: u64,946 memory: u64,
941 };947 };
...@@ -1007,17 +1013,11 @@ fn genDeclRef(...@@ -1007,17 +1013,11 @@ fn genDeclRef(
1007 if (is_threadlocal) {1013 if (is_threadlocal) {
1008 return GenResult.mcv(.{ .load_tlv = sym_index });1014 return GenResult.mcv(.{ .load_tlv = sym_index });
1009 }1015 }
1010 return GenResult.mcv(.{ .linker_load = .{1016 return GenResult.mcv(.{ .load_got = sym_index });
1011 .type = .got,
1012 .sym_index = sym_index,
1013 } });
1014 } else if (bin_file.cast(link.File.Coff)) |coff_file| {1017 } else if (bin_file.cast(link.File.Coff)) |coff_file| {
1015 const atom_index = try coff_file.getOrCreateAtomForDecl(decl_index);1018 const atom_index = try coff_file.getOrCreateAtomForDecl(decl_index);
1016 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;1019 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
1017 return GenResult.mcv(.{ .linker_load = .{1020 return GenResult.mcv(.{ .load_got = sym_index });
1018 .type = .got,
1019 .sym_index = sym_index,
1020 } });
1021 } else if (bin_file.cast(link.File.Plan9)) |p9| {1021 } else if (bin_file.cast(link.File.Plan9)) |p9| {
1022 const decl_block_index = try p9.seeDecl(decl_index);1022 const decl_block_index = try p9.seeDecl(decl_index);
1023 const decl_block = p9.getDeclBlock(decl_block_index);1023 const decl_block = p9.getDeclBlock(decl_block_index);
...@@ -1044,15 +1044,9 @@ fn genUnnamedConst(...@@ -1044,15 +1044,9 @@ fn genUnnamedConst(
1044 if (bin_file.cast(link.File.Elf)) |elf_file| {1044 if (bin_file.cast(link.File.Elf)) |elf_file| {
1045 return GenResult.mcv(.{ .memory = elf_file.getSymbol(local_sym_index).st_value });1045 return GenResult.mcv(.{ .memory = elf_file.getSymbol(local_sym_index).st_value });
1046 } else if (bin_file.cast(link.File.MachO)) |_| {1046 } else if (bin_file.cast(link.File.MachO)) |_| {
1047 return GenResult.mcv(.{ .linker_load = .{1047 return GenResult.mcv(.{ .load_direct = local_sym_index });
1048 .type = .direct,
1049 .sym_index = local_sym_index,
1050 } });
1051 } else if (bin_file.cast(link.File.Coff)) |_| {1048 } else if (bin_file.cast(link.File.Coff)) |_| {
1052 return GenResult.mcv(.{ .linker_load = .{1049 return GenResult.mcv(.{ .load_direct = local_sym_index });
1053 .type = .direct,
1054 .sym_index = local_sym_index,
1055 } });
1056 } else if (bin_file.cast(link.File.Plan9)) |p9| {1050 } else if (bin_file.cast(link.File.Plan9)) |p9| {
1057 const ptr_bits = target.cpu.arch.ptrBitWidth();1051 const ptr_bits = target.cpu.arch.ptrBitWidth();
1058 const ptr_bytes: u64 = @divExact(ptr_bits, 8);1052 const ptr_bytes: u64 = @divExact(ptr_bits, 8);