diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-04-11 22:17:04 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-04-13 11:47:51 +0200 |
| commit | ee6b4fad4714d596255f034c0b000438ee6ca943 (patch) | |
| tree | 71539c5df0db2d9370a1b028f615feb4c72746df /src/arch | |
| parent | 382de7bf1de8314e97eb67426b693b966f2c4e1b (diff) | |
| download | zig-ee6b4fad4714d596255f034c0b000438ee6ca943.tar.gz zig-ee6b4fad4714d596255f034c0b000438ee6ca943.zip | |
x86_64: remove loadMemPtrIntoRegister in genSetReg
Add two emit helpers for linker reloc based `lea` and `mov`
instructions: `asmMovLinker` and `asmLeaLinker`.
Diffstat (limited to 'src/arch')
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 96 | ||||
| -rw-r--r-- | src/arch/x86_64/Emit.zig | 2 | ||||
| -rw-r--r-- | src/arch/x86_64/Lower.zig | 10 | ||||
| -rw-r--r-- | src/arch/x86_64/Mir.zig | 2 |
4 files changed, 90 insertions, 20 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 7344af9673..374029c64c 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -731,6 +731,40 @@ fn asmMemoryRegisterImmediate( }); } +fn asmMovLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codegen.LinkerLoad) !void { + const ops: Mir.Inst.Ops = switch (linker_load.type) { + .got => .got_reloc, + .direct => .direct_reloc, + .import => .import_reloc, + }; + _ = try self.addInst(.{ + .tag = .mov_linker, + .ops = ops, + .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{ + .reg = @enumToInt(reg), + .atom_index = atom_index, + .sym_index = linker_load.sym_index, + }) }, + }); +} + +fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codegen.LinkerLoad) !void { + const ops: Mir.Inst.Ops = switch (linker_load.type) { + .got => .got_reloc, + .direct => .direct_reloc, + .import => .import_reloc, + }; + _ = try self.addInst(.{ + .tag = .lea_linker, + .ops = ops, + .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{ + .reg = @enumToInt(reg), + .atom_index = atom_index, + .sym_index = linker_load.sym_index, + }) }, + }); +} + fn gen(self: *Self) InnerError!void { const cc = self.fn_type.fnCallingConvention(); if (cc != .Naked) { @@ -7454,10 +7488,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void try self.asmRegisterRegister(.mov, registerAlias(reg, abi_size), registerAlias(src_reg, abi_size)); }, - .memory, .linker_load => switch (ty.zigTypeTag()) { + .memory => |addr| switch (ty.zigTypeTag()) { .Float => { - const base_reg = try self.register_manager.allocReg(null, gp); - try self.loadMemPtrIntoRegister(base_reg, Type.usize, mcv); + const base_reg = (try self.register_manager.allocReg(null, gp)).to64(); + try self.genSetReg(Type.usize, base_reg, .{ .immediate = addr }); if (intrinsicsAllowed(self.target.*, ty)) { return self.asmRegisterMemory( @@ -7469,29 +7503,20 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void }), }, reg.to128(), - Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base_reg.to64() }), + Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base_reg }), ); } return self.fail("TODO genSetReg from memory for float with no intrinsics", .{}); }, - else => switch (mcv) { - else => unreachable, - .linker_load => { - try self.loadMemPtrIntoRegister(reg, Type.usize, mcv); - try self.asmRegisterMemory( - .mov, - registerAlias(reg, abi_size), - Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }), - ); - }, - .memory => |x| if (x <= math.maxInt(i32)) { + else => { + if (addr <= math.maxInt(i32)) { try self.asmRegisterMemory( .mov, registerAlias(reg, abi_size), Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .ds, - .disp = @intCast(i32, x), + .disp = @intCast(i32, addr), }), ); } else { @@ -7501,20 +7526,53 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void _ = try self.addInst(.{ .tag = .mov_moffs, .ops = .rax_moffs, - .data = .{ .payload = try self.addExtra(Mir.MemoryMoffs.encode(.ds, x)) }, + .data = .{ .payload = try self.addExtra(Mir.MemoryMoffs.encode(.ds, addr)) }, }); } else { // Rather than duplicate the logic used for the move, we just use a self-call with a new MCValue. - try self.genSetReg(ty, reg, MCValue{ .immediate = x }); + try self.genSetReg(Type.usize, reg, MCValue{ .immediate = addr }); try self.asmRegisterMemory( .mov, registerAlias(reg, abi_size), Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }), ); } - }, + } }, }, + .linker_load => |load_struct| { + const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { + const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); + break :blk macho_file.getAtom(atom).getSymbolIndex().?; + } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { + const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); + break :blk coff_file.getAtom(atom).getSymbolIndex().?; + } else unreachable; + + switch (ty.zigTypeTag()) { + .Float => { + const base_reg = (try self.register_manager.allocReg(null, gp)).to64(); + try self.asmLeaLinker(base_reg, atom_index, load_struct); + + if (intrinsicsAllowed(self.target.*, ty)) { + return self.asmRegisterMemory( + switch (ty.tag()) { + .f32 => .movss, + .f64 => .movsd, + else => return self.fail("TODO genSetReg from memory for {}", .{ + ty.fmt(self.bin_file.options.module.?), + }), + }, + reg.to128(), + Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base_reg.to64() }), + ); + } + + return self.fail("TODO genSetReg from memory for float with no intrinsics", .{}); + }, + else => try self.asmMovLinker(registerAlias(reg, abi_size), atom_index, load_struct), + } + }, .stack_offset => |off| { switch (ty.zigTypeTag()) { .Int => switch (ty.intInfo(self.target.*).signedness) { diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig index 052139a4e5..30d63b6adf 100644 --- a/src/arch/x86_64/Emit.zig +++ b/src/arch/x86_64/Emit.zig @@ -65,7 +65,7 @@ pub fn emitMir(emit: *Emit) Error!void { }); } else return emit.fail("TODO implement {} for {}", .{ inst.tag, emit.bin_file.tag }), - .lea_linker => if (emit.bin_file.cast(link.File.MachO)) |macho_file| { + .mov_linker, .lea_linker => if (emit.bin_file.cast(link.File.MachO)) |macho_file| { const metadata = emit.lower.mir.extraData(Mir.LeaRegisterReloc, inst.data.payload).data; const reloc_type = switch (inst.ops) { diff --git a/src/arch/x86_64/Lower.zig b/src/arch/x86_64/Lower.zig index f4d9db57e8..e88484c9da 100644 --- a/src/arch/x86_64/Lower.zig +++ b/src/arch/x86_64/Lower.zig @@ -127,6 +127,7 @@ pub fn lowerMir(lower: *Lower, inst: Mir.Inst) Error![]const Instruction { .call_extern => try lower.emit(.none, .call, &.{.{ .imm = Immediate.s(0) }}), .lea_linker => try lower.mirLeaLinker(inst), + .mov_linker => try lower.mirMovLinker(inst), .mov_moffs => try lower.mirMovMoffs(inst), @@ -444,6 +445,15 @@ fn mirLeaLinker(lower: *Lower, inst: Mir.Inst) Error!void { }); } +fn mirMovLinker(lower: *Lower, inst: Mir.Inst) Error!void { + const metadata = lower.mir.extraData(Mir.LeaRegisterReloc, inst.data.payload).data; + const reg = @intToEnum(Register, metadata.reg); + try lower.emit(.none, .mov, &.{ + .{ .reg = reg }, + .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) }, + }); +} + const abi = @import("abi.zig"); const assert = std.debug.assert; const bits = @import("bits.zig"); diff --git a/src/arch/x86_64/Mir.zig b/src/arch/x86_64/Mir.zig index 0ceee6bac1..835e9bfdcb 100644 --- a/src/arch/x86_64/Mir.zig +++ b/src/arch/x86_64/Mir.zig @@ -233,6 +233,8 @@ pub const Inst = struct { /// Load effective address of a symbol not yet allocated in VM. lea_linker, + /// Move address of a symbol not yet allocated in VM. + mov_linker, /// End of prologue dbg_prologue_end, |
