aboutsummaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2023-04-11 22:17:04 +0200
committerJakub Konka <kubkon@jakubkonka.com>2023-04-13 11:47:51 +0200
commitee6b4fad4714d596255f034c0b000438ee6ca943 (patch)
tree71539c5df0db2d9370a1b028f615feb4c72746df /src/arch
parent382de7bf1de8314e97eb67426b693b966f2c4e1b (diff)
downloadzig-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.zig96
-rw-r--r--src/arch/x86_64/Emit.zig2
-rw-r--r--src/arch/x86_64/Lower.zig10
-rw-r--r--src/arch/x86_64/Mir.zig2
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,