authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-11 22:17:04+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-13 11:47:51+02:00
logee6b4fad4714d596255f034c0b000438ee6ca943
tree71539c5df0db2d9370a1b028f615feb4c72746df
parent382de7bf1de8314e97eb67426b693b966f2c4e1b

x86_64: remove loadMemPtrIntoRegister in genSetReg

Add two emit helpers for linker reloc based `lea` and `mov` instructions: `asmMovLinker` and `asmLeaLinker`.

4 files changed, 90 insertions(+), 20 deletions(-)

src/arch/x86_64/CodeGen.zig+77-19
...@@ -731,6 +731,40 @@ fn asmMemoryRegisterImmediate(...@@ -731,6 +731,40 @@ fn asmMemoryRegisterImmediate(
731 });731 });
732}732}
733733
734fn asmMovLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codegen.LinkerLoad) !void {
735 const ops: Mir.Inst.Ops = switch (linker_load.type) {
736 .got => .got_reloc,
737 .direct => .direct_reloc,
738 .import => .import_reloc,
739 };
740 _ = try self.addInst(.{
741 .tag = .mov_linker,
742 .ops = ops,
743 .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{
744 .reg = @enumToInt(reg),
745 .atom_index = atom_index,
746 .sym_index = linker_load.sym_index,
747 }) },
748 });
749}
750
751fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codegen.LinkerLoad) !void {
752 const ops: Mir.Inst.Ops = switch (linker_load.type) {
753 .got => .got_reloc,
754 .direct => .direct_reloc,
755 .import => .import_reloc,
756 };
757 _ = try self.addInst(.{
758 .tag = .lea_linker,
759 .ops = ops,
760 .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{
761 .reg = @enumToInt(reg),
762 .atom_index = atom_index,
763 .sym_index = linker_load.sym_index,
764 }) },
765 });
766}
767
734fn gen(self: *Self) InnerError!void {768fn gen(self: *Self) InnerError!void {
735 const cc = self.fn_type.fnCallingConvention();769 const cc = self.fn_type.fnCallingConvention();
736 if (cc != .Naked) {770 if (cc != .Naked) {
...@@ -7454,10 +7488,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -7454,10 +7488,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
74547488
7455 try self.asmRegisterRegister(.mov, registerAlias(reg, abi_size), registerAlias(src_reg, abi_size));7489 try self.asmRegisterRegister(.mov, registerAlias(reg, abi_size), registerAlias(src_reg, abi_size));
7456 },7490 },
7457 .memory, .linker_load => switch (ty.zigTypeTag()) {7491 .memory => |addr| switch (ty.zigTypeTag()) {
7458 .Float => {7492 .Float => {
7459 const base_reg = try self.register_manager.allocReg(null, gp);7493 const base_reg = (try self.register_manager.allocReg(null, gp)).to64();
7460 try self.loadMemPtrIntoRegister(base_reg, Type.usize, mcv);7494 try self.genSetReg(Type.usize, base_reg, .{ .immediate = addr });
74617495
7462 if (intrinsicsAllowed(self.target.*, ty)) {7496 if (intrinsicsAllowed(self.target.*, ty)) {
7463 return self.asmRegisterMemory(7497 return self.asmRegisterMemory(
...@@ -7469,29 +7503,20 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -7469,29 +7503,20 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
7469 }),7503 }),
7470 },7504 },
7471 reg.to128(),7505 reg.to128(),
7472 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base_reg.to64() }),7506 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base_reg }),
7473 );7507 );
7474 }7508 }
74757509
7476 return self.fail("TODO genSetReg from memory for float with no intrinsics", .{});7510 return self.fail("TODO genSetReg from memory for float with no intrinsics", .{});
7477 },7511 },
7478 else => switch (mcv) {7512 else => {
7479 else => unreachable,7513 if (addr <= math.maxInt(i32)) {
7480 .linker_load => {
7481 try self.loadMemPtrIntoRegister(reg, Type.usize, mcv);
7482 try self.asmRegisterMemory(
7483 .mov,
7484 registerAlias(reg, abi_size),
7485 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }),
7486 );
7487 },
7488 .memory => |x| if (x <= math.maxInt(i32)) {
7489 try self.asmRegisterMemory(7514 try self.asmRegisterMemory(
7490 .mov,7515 .mov,
7491 registerAlias(reg, abi_size),7516 registerAlias(reg, abi_size),
7492 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{7517 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{
7493 .base = .ds,7518 .base = .ds,
7494 .disp = @intCast(i32, x),7519 .disp = @intCast(i32, addr),
7495 }),7520 }),
7496 );7521 );
7497 } else {7522 } else {
...@@ -7501,20 +7526,53 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -7501,20 +7526,53 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
7501 _ = try self.addInst(.{7526 _ = try self.addInst(.{
7502 .tag = .mov_moffs,7527 .tag = .mov_moffs,
7503 .ops = .rax_moffs,7528 .ops = .rax_moffs,
7504 .data = .{ .payload = try self.addExtra(Mir.MemoryMoffs.encode(.ds, x)) },7529 .data = .{ .payload = try self.addExtra(Mir.MemoryMoffs.encode(.ds, addr)) },
7505 });7530 });
7506 } else {7531 } else {
7507 // Rather than duplicate the logic used for the move, we just use a self-call with a new MCValue.7532 // Rather than duplicate the logic used for the move, we just use a self-call with a new MCValue.
7508 try self.genSetReg(ty, reg, MCValue{ .immediate = x });7533 try self.genSetReg(Type.usize, reg, MCValue{ .immediate = addr });
7509 try self.asmRegisterMemory(7534 try self.asmRegisterMemory(
7510 .mov,7535 .mov,
7511 registerAlias(reg, abi_size),7536 registerAlias(reg, abi_size),
7512 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }),7537 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }),
7513 );7538 );
7514 }7539 }
7515 },7540 }
7516 },7541 },
7517 },7542 },
7543 .linker_load => |load_struct| {
7544 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
7545 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
7546 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
7547 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {
7548 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
7549 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
7550 } else unreachable;
7551
7552 switch (ty.zigTypeTag()) {
7553 .Float => {
7554 const base_reg = (try self.register_manager.allocReg(null, gp)).to64();
7555 try self.asmLeaLinker(base_reg, atom_index, load_struct);
7556
7557 if (intrinsicsAllowed(self.target.*, ty)) {
7558 return self.asmRegisterMemory(
7559 switch (ty.tag()) {
7560 .f32 => .movss,
7561 .f64 => .movsd,
7562 else => return self.fail("TODO genSetReg from memory for {}", .{
7563 ty.fmt(self.bin_file.options.module.?),
7564 }),
7565 },
7566 reg.to128(),
7567 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base_reg.to64() }),
7568 );
7569 }
7570
7571 return self.fail("TODO genSetReg from memory for float with no intrinsics", .{});
7572 },
7573 else => try self.asmMovLinker(registerAlias(reg, abi_size), atom_index, load_struct),
7574 }
7575 },
7518 .stack_offset => |off| {7576 .stack_offset => |off| {
7519 switch (ty.zigTypeTag()) {7577 switch (ty.zigTypeTag()) {
7520 .Int => switch (ty.intInfo(self.target.*).signedness) {7578 .Int => switch (ty.intInfo(self.target.*).signedness) {
src/arch/x86_64/Emit.zig+1-1
...@@ -65,7 +65,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -65,7 +65,7 @@ pub fn emitMir(emit: *Emit) Error!void {
65 });65 });
66 } else return emit.fail("TODO implement {} for {}", .{ inst.tag, emit.bin_file.tag }),66 } else return emit.fail("TODO implement {} for {}", .{ inst.tag, emit.bin_file.tag }),
6767
68 .lea_linker => if (emit.bin_file.cast(link.File.MachO)) |macho_file| {68 .mov_linker, .lea_linker => if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
69 const metadata =69 const metadata =
70 emit.lower.mir.extraData(Mir.LeaRegisterReloc, inst.data.payload).data;70 emit.lower.mir.extraData(Mir.LeaRegisterReloc, inst.data.payload).data;
71 const reloc_type = switch (inst.ops) {71 const reloc_type = switch (inst.ops) {
src/arch/x86_64/Lower.zig+10
...@@ -127,6 +127,7 @@ pub fn lowerMir(lower: *Lower, inst: Mir.Inst) Error![]const Instruction {...@@ -127,6 +127,7 @@ pub fn lowerMir(lower: *Lower, inst: Mir.Inst) Error![]const Instruction {
127 .call_extern => try lower.emit(.none, .call, &.{.{ .imm = Immediate.s(0) }}),127 .call_extern => try lower.emit(.none, .call, &.{.{ .imm = Immediate.s(0) }}),
128128
129 .lea_linker => try lower.mirLeaLinker(inst),129 .lea_linker => try lower.mirLeaLinker(inst),
130 .mov_linker => try lower.mirMovLinker(inst),
130131
131 .mov_moffs => try lower.mirMovMoffs(inst),132 .mov_moffs => try lower.mirMovMoffs(inst),
132133
...@@ -444,6 +445,15 @@ fn mirLeaLinker(lower: *Lower, inst: Mir.Inst) Error!void {...@@ -444,6 +445,15 @@ fn mirLeaLinker(lower: *Lower, inst: Mir.Inst) Error!void {
444 });445 });
445}446}
446447
448fn mirMovLinker(lower: *Lower, inst: Mir.Inst) Error!void {
449 const metadata = lower.mir.extraData(Mir.LeaRegisterReloc, inst.data.payload).data;
450 const reg = @intToEnum(Register, metadata.reg);
451 try lower.emit(.none, .mov, &.{
452 .{ .reg = reg },
453 .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },
454 });
455}
456
447const abi = @import("abi.zig");457const abi = @import("abi.zig");
448const assert = std.debug.assert;458const assert = std.debug.assert;
449const bits = @import("bits.zig");459const bits = @import("bits.zig");
src/arch/x86_64/Mir.zig+2
...@@ -233,6 +233,8 @@ pub const Inst = struct {...@@ -233,6 +233,8 @@ pub const Inst = struct {
233233
234 /// Load effective address of a symbol not yet allocated in VM.234 /// Load effective address of a symbol not yet allocated in VM.
235 lea_linker,235 lea_linker,
236 /// Move address of a symbol not yet allocated in VM.
237 mov_linker,
236238
237 /// End of prologue239 /// End of prologue
238 dbg_prologue_end,240 dbg_prologue_end,