authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-09-10 00:18:39+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-09-10 00:18:39+02:00
logfc5a6e0e327c1b671aa782d24059e27e5aa55c84
treedb51f363314a023bec3c9c5eefc05839971a5c4a
parentd8f210354577eda1b438d692b28bb3a582913b5a

x86_64: combine got_load, direct_load and imports_load into linker_load MCV


3 files changed, 70 insertions(+), 144 deletions(-)

src/arch/x86_64/CodeGen.zig+67-141
......@@ -128,15 +128,11 @@ pub const MCValue = union(enum) {
128128 /// The value is in memory at a hard-coded address.
129129 /// If the type is a pointer, it means the pointer address is at this memory location.
130130 memory: u64,
131 /// The value is in memory referenced indirectly via a GOT entry index.
132 /// If the type is a pointer, it means the pointer is referenced indirectly via GOT.
133 /// When lowered, linker will emit a relocation of type X86_64_RELOC_GOT.
134 got_load: u32,
135 imports_load: u32,
136 /// The value is in memory referenced directly via symbol index.
137 /// If the type is a pointer, it means the pointer is referenced directly via symbol index.
138 /// When lowered, linker will emit a relocation of type X86_64_RELOC_SIGNED.
139 direct_load: u32,
131 /// The value is in memory but requires a linker relocation fixup:
132 /// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
133 /// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
134 /// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
135 linker_load: struct { @"type": enum { got, direct, import }, sym_index: u32 },
140136 /// The value is one of the stack variables.
141137 /// If the type is a pointer, it means the pointer address is in the stack at this offset.
142138 stack_offset: i32,
......@@ -150,9 +146,7 @@ pub const MCValue = union(enum) {
150146 .memory,
151147 .stack_offset,
152148 .ptr_stack_offset,
153 .direct_load,
154 .got_load,
155 .imports_load,
149 .linker_load,
156150 => true,
157151 else => false,
158152 };
......@@ -165,26 +159,6 @@ pub const MCValue = union(enum) {
165159 };
166160 }
167161
168 fn isMutable(mcv: MCValue) bool {
169 return switch (mcv) {
170 .none => unreachable,
171 .unreach => unreachable,
172 .dead => unreachable,
173
174 .immediate,
175 .memory,
176 .eflags,
177 .ptr_stack_offset,
178 .undef,
179 .register_overflow,
180 => false,
181
182 .register,
183 .stack_offset,
184 => true,
185 };
186 }
187
188162 fn isRegister(mcv: MCValue) bool {
189163 return switch (mcv) {
190164 .register => true,
......@@ -2307,11 +2281,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
23072281 .data = .{ .imm = @bitCast(u32, -off) },
23082282 });
23092283 },
2310 .memory,
2311 .got_load,
2312 .direct_load,
2313 .imports_load,
2314 => {
2284 .memory, .linker_load => {
23152285 try self.loadMemPtrIntoRegister(addr_reg, Type.usize, array);
23162286 },
23172287 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
......@@ -2652,11 +2622,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
26522622 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),
26532623 }
26542624 },
2655 .memory,
2656 .got_load,
2657 .direct_load,
2658 .imports_load,
2659 => {
2625 .memory, .linker_load => {
26602626 const reg = try self.copyToTmpRegister(ptr_ty, ptr);
26612627 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
26622628 },
......@@ -2691,10 +2657,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
26912657
26922658fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue) InnerError!void {
26932659 switch (ptr) {
2694 .got_load,
2695 .direct_load,
2696 .imports_load,
2697 => |sym_index| {
2660 .linker_load => |load_struct| {
26982661 const abi_size = @intCast(u32, ptr_ty.abiSize(self.target.*));
26992662 const mod = self.bin_file.options.module.?;
27002663 const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl);
......@@ -2702,11 +2665,10 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
27022665 fn_owner_decl.link.macho.sym_index
27032666 else
27042667 fn_owner_decl.link.coff.sym_index;
2705 const flags: u2 = switch (ptr) {
2706 .got_load => 0b00,
2707 .direct_load => 0b01,
2708 .imports_load => 0b10,
2709 else => unreachable,
2668 const flags: u2 = switch (load_struct.@"type") {
2669 .got => 0b00,
2670 .direct => 0b01,
2671 .import => 0b10,
27102672 };
27112673 _ = try self.addInst(.{
27122674 .tag = .lea_pic,
......@@ -2717,7 +2679,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
27172679 .data = .{
27182680 .relocation = .{
27192681 .atom_index = atom_index,
2720 .sym_index = sym_index,
2682 .sym_index = load_struct.sym_index,
27212683 },
27222684 },
27232685 });
......@@ -2801,9 +2763,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
28012763 .register => |src_reg| {
28022764 try self.genInlineMemcpyRegisterRegister(value_ty, reg, src_reg, 0);
28032765 },
2804 .got_load,
2805 .direct_load,
2806 .imports_load,
2766 .linker_load,
28072767 .memory,
28082768 .stack_offset,
28092769 => {
......@@ -2822,11 +2782,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
28222782 },
28232783 }
28242784 },
2825 .got_load,
2826 .direct_load,
2827 .imports_load,
2828 .memory,
2829 => {
2785 .linker_load, .memory => {
28302786 const value_lock: ?RegisterLock = switch (value) {
28312787 .register => |reg| self.register_manager.lockReg(reg),
28322788 else => null,
......@@ -2894,11 +2850,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
28942850 .register => {
28952851 return self.store(new_ptr, value, ptr_ty, value_ty);
28962852 },
2897 .got_load,
2898 .direct_load,
2899 .imports_load,
2900 .memory,
2901 => {
2853 .linker_load, .memory => {
29022854 if (abi_size <= 8) {
29032855 const tmp_reg = try self.register_manager.allocReg(null, gp);
29042856 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
......@@ -3606,9 +3558,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
36063558 });
36073559 },
36083560 .memory,
3609 .got_load,
3610 .direct_load,
3611 .imports_load,
3561 .linker_load,
36123562 .eflags,
36133563 => {
36143564 assert(abi_size <= 8);
......@@ -3694,10 +3644,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
36943644 => {
36953645 return self.fail("TODO implement x86 ADD/SUB/CMP source memory", .{});
36963646 },
3697 .got_load,
3698 .direct_load,
3699 .imports_load,
3700 => {
3647 .linker_load => {
37013648 return self.fail("TODO implement x86 ADD/SUB/CMP source symbol at index in linker", .{});
37023649 },
37033650 .eflags => {
......@@ -3708,10 +3655,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
37083655 .memory => {
37093656 return self.fail("TODO implement x86 ADD/SUB/CMP destination memory", .{});
37103657 },
3711 .got_load,
3712 .direct_load,
3713 .imports_load,
3714 => {
3658 .linker_load => {
37153659 return self.fail("TODO implement x86 ADD/SUB/CMP destination symbol at index", .{});
37163660 },
37173661 }
......@@ -3779,10 +3723,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
37793723 .memory => {
37803724 return self.fail("TODO implement x86 multiply source memory", .{});
37813725 },
3782 .got_load,
3783 .direct_load,
3784 .imports_load,
3785 => {
3726 .linker_load => {
37863727 return self.fail("TODO implement x86 multiply source symbol at index in linker", .{});
37873728 },
37883729 .eflags => {
......@@ -3826,10 +3767,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
38263767 .memory, .stack_offset => {
38273768 return self.fail("TODO implement x86 multiply source memory", .{});
38283769 },
3829 .got_load,
3830 .direct_load,
3831 .imports_load,
3832 => {
3770 .linker_load => {
38333771 return self.fail("TODO implement x86 multiply source symbol at index in linker", .{});
38343772 },
38353773 .eflags => {
......@@ -3840,10 +3778,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
38403778 .memory => {
38413779 return self.fail("TODO implement x86 multiply destination memory", .{});
38423780 },
3843 .got_load,
3844 .direct_load,
3845 .imports_load,
3846 => {
3781 .linker_load => {
38473782 return self.fail("TODO implement x86 multiply destination symbol at index in linker", .{});
38483783 },
38493784 }
......@@ -4006,9 +3941,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
40063941 .unreach => unreachable,
40073942 .dead => unreachable,
40083943 .memory => unreachable,
4009 .got_load => unreachable,
4010 .direct_load => unreachable,
4011 .imports_load => unreachable,
3944 .linker_load => unreachable,
40123945 .eflags => unreachable,
40133946 .register_overflow => unreachable,
40143947 }
......@@ -4066,7 +3999,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
40663999 const func = func_payload.data;
40674000 const fn_owner_decl = mod.declPtr(func.owner_decl);
40684001 try self.genSetReg(Type.initTag(.usize), .rax, .{
4069 .got_load = fn_owner_decl.link.coff.sym_index,
4002 .linker_load = .{
4003 .@"type" = .got,
4004 .sym_index = fn_owner_decl.link.coff.sym_index,
4005 },
40704006 });
40714007 _ = try self.addInst(.{
40724008 .tag = .call,
......@@ -4087,7 +4023,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
40874023 }
40884024 const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
40894025 try self.genSetReg(Type.initTag(.usize), .rax, .{
4090 .imports_load = sym_index,
4026 .linker_load = .{
4027 .@"type" = .import,
4028 .sym_index = sym_index,
4029 },
40914030 });
40924031 _ = try self.addInst(.{
40934032 .tag = .call,
......@@ -4119,7 +4058,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
41194058 const func = func_payload.data;
41204059 const fn_owner_decl = mod.declPtr(func.owner_decl);
41214060 const sym_index = fn_owner_decl.link.macho.sym_index;
4122 try self.genSetReg(Type.initTag(.usize), .rax, .{ .got_load = sym_index });
4061 try self.genSetReg(Type.initTag(.usize), .rax, .{
4062 .linker_load = .{
4063 .@"type" = .got,
4064 .sym_index = sym_index,
4065 },
4066 });
41234067 // callq *%rax
41244068 _ = try self.addInst(.{
41254069 .tag = .call,
......@@ -4505,11 +4449,7 @@ fn genVarDbgInfo(
45054449 leb128.writeILEB128(dbg_info.writer(), -off) catch unreachable;
45064450 dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
45074451 },
4508 .memory,
4509 .got_load,
4510 .direct_load,
4511 .imports_load,
4512 => {
4452 .memory, .linker_load => {
45134453 const ptr_width = @intCast(u8, @divExact(self.target.cpu.arch.ptrBitWidth(), 8));
45144454 const is_ptr = switch (tag) {
45154455 .dbg_var_ptr => true,
......@@ -4540,10 +4480,11 @@ fn genVarDbgInfo(
45404480 try dbg_info.append(DW.OP.deref);
45414481 }
45424482 switch (mcv) {
4543 .got_load,
4544 .direct_load,
4545 .imports_load,
4546 => |index| try dw.addExprlocReloc(index, offset, is_ptr),
4483 .linker_load => |load_struct| try dw.addExprlocReloc(
4484 load_struct.sym_index,
4485 offset,
4486 is_ptr,
4487 ),
45474488 else => {},
45484489 }
45494490 },
......@@ -5587,11 +5528,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
55875528 else => return self.fail("TODO implement inputs on stack for {} with abi size > 8", .{mcv}),
55885529 }
55895530 },
5590 .memory,
5591 .direct_load,
5592 .got_load,
5593 .imports_load,
5594 => {
5531 .memory, .linker_load => {
55955532 if (abi_size <= 8) {
55965533 const reg = try self.copyToTmpRegister(ty, mcv);
55975534 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
......@@ -5835,11 +5772,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
58355772 },
58365773 }
58375774 },
5838 .memory,
5839 .got_load,
5840 .direct_load,
5841 .imports_load,
5842 => {
5775 .memory, .linker_load => {
58435776 if (abi_size <= 8) {
58445777 const reg = try self.copyToTmpRegister(ty, mcv);
58455778 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts);
......@@ -5959,11 +5892,7 @@ fn genInlineMemcpy(
59595892 const tmp_reg = regs[4].to8();
59605893
59615894 switch (dst_ptr) {
5962 .memory,
5963 .got_load,
5964 .direct_load,
5965 .imports_load,
5966 => {
5895 .memory, .linker_load => {
59675896 try self.loadMemPtrIntoRegister(dst_addr_reg, Type.usize, dst_ptr);
59685897 },
59695898 .ptr_stack_offset, .stack_offset => |off| {
......@@ -5992,11 +5921,7 @@ fn genInlineMemcpy(
59925921 }
59935922
59945923 switch (src_ptr) {
5995 .memory,
5996 .got_load,
5997 .direct_load,
5998 .imports_load,
5999 => {
5924 .memory, .linker_load => {
60005925 try self.loadMemPtrIntoRegister(src_addr_reg, Type.usize, src_ptr);
60015926 },
60025927 .ptr_stack_offset, .stack_offset => |off| {
......@@ -6120,11 +6045,7 @@ fn genInlineMemset(
61206045 const index_reg = regs[1].to64();
61216046
61226047 switch (dst_ptr) {
6123 .memory,
6124 .got_load,
6125 .direct_load,
6126 .imports_load,
6127 => {
6048 .memory, .linker_load => {
61286049 try self.loadMemPtrIntoRegister(addr_reg, Type.usize, dst_ptr);
61296050 },
61306051 .ptr_stack_offset, .stack_offset => |off| {
......@@ -6356,10 +6277,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
63566277 .data = undefined,
63576278 });
63586279 },
6359 .direct_load,
6360 .got_load,
6361 .imports_load,
6362 => {
6280 .linker_load => {
63636281 switch (ty.zigTypeTag()) {
63646282 .Float => {
63656283 const base_reg = try self.register_manager.allocReg(null, gp);
......@@ -6753,11 +6671,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
67536671 // TODO Is this the only condition for pointer dereference for memcpy?
67546672 const src: MCValue = blk: {
67556673 switch (src_ptr) {
6756 .got_load,
6757 .direct_load,
6758 .imports_load,
6759 .memory,
6760 => {
6674 .linker_load, .memory => {
67616675 const reg = try self.register_manager.allocReg(null, gp);
67626676 try self.loadMemPtrIntoRegister(reg, src_ty, src_ptr);
67636677 _ = try self.addInst(.{
......@@ -6997,10 +6911,16 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
69976911 return MCValue{ .memory = got_addr };
69986912 } else if (self.bin_file.cast(link.File.MachO)) |_| {
69996913 assert(decl.link.macho.sym_index != 0);
7000 return MCValue{ .got_load = decl.link.macho.sym_index };
6914 return MCValue{ .linker_load = .{
6915 .@"type" = .got,
6916 .sym_index = decl.link.macho.sym_index,
6917 } };
70016918 } else if (self.bin_file.cast(link.File.Coff)) |_| {
70026919 assert(decl.link.coff.sym_index != 0);
7003 return MCValue{ .got_load = decl.link.coff.sym_index };
6920 return MCValue{ .linker_load = .{
6921 .@"type" = .got,
6922 .sym_index = decl.link.coff.sym_index,
6923 } };
70046924 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
70056925 try p9.seeDecl(decl_index);
70066926 const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;
......@@ -7019,9 +6939,15 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
70196939 const vaddr = elf_file.local_symbols.items[local_sym_index].st_value;
70206940 return MCValue{ .memory = vaddr };
70216941 } else if (self.bin_file.cast(link.File.MachO)) |_| {
7022 return MCValue{ .direct_load = local_sym_index };
6942 return MCValue{ .linker_load = .{
6943 .@"type" = .direct,
6944 .sym_index = local_sym_index,
6945 } };
70236946 } else if (self.bin_file.cast(link.File.Coff)) |_| {
7024 return MCValue{ .direct_load = local_sym_index };
6947 return MCValue{ .linker_load = .{
6948 .@"type" = .direct,
6949 .sym_index = local_sym_index,
6950 } };
70256951 } else if (self.bin_file.cast(link.File.Plan9)) |_| {
70266952 return self.fail("TODO lower unnamed const in Plan9", .{});
70276953 } else {
src/arch/x86_64/Emit.zig+1-1
......@@ -1021,7 +1021,7 @@ fn mirLeaPic(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
10211021 .@"type" = switch (ops.flags) {
10221022 0b00 => .got,
10231023 0b01 => .direct,
1024 0b10 => .imports,
1024 0b10 => .import,
10251025 else => unreachable,
10261026 },
10271027 .target = switch (ops.flags) {
src/link/Coff.zig+2-2
......@@ -127,7 +127,7 @@ pub const Reloc = struct {
127127 @"type": enum {
128128 got,
129129 direct,
130 imports,
130 import,
131131 },
132132 target: SymbolWithLoc,
133133 offset: u32,
......@@ -141,7 +141,7 @@ pub const Reloc = struct {
141141 switch (self.@"type") {
142142 .got => return coff_file.getGotAtomForSymbol(self.target),
143143 .direct => return coff_file.getAtomForSymbol(self.target),
144 .imports => return coff_file.getImportAtomForSymbol(self.target),
144 .import => return coff_file.getImportAtomForSymbol(self.target),
145145 }
146146 }
147147};