mirror of
https://github.com/ziglang/zig.git
synced 2026-02-05 14:07:04 +00:00
x86_64: remove loadMemPtrIntoRegister in genSetReg
Add two emit helpers for linker reloc based `lea` and `mov` instructions: `asmMovLinker` and `asmLeaLinker`.
This commit is contained in:
parent
382de7bf1d
commit
ee6b4fad47
@ -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) {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user