Commit d0e7212539
Changed files (3)
src
arch
src/arch/x86_64/CodeGen.zig
@@ -491,6 +491,37 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Imme
});
}
+fn asmRegisterRegisterImmediate(
+ self: *Self,
+ tag: Mir.Inst.Tag,
+ reg1: Register,
+ reg2: Register,
+ imm: Immediate,
+) !void {
+ const ops: Mir.Inst.Ops = switch (imm) {
+ .signed => .rri_s,
+ .unsigned => .rri_u,
+ };
+ const data: Mir.Inst.Data = switch (ops) {
+ .rri_s => .{ .rri_s = .{
+ .r1 = reg1,
+ .r2 = reg2,
+ .imm = imm.signed,
+ } },
+ .rri_u => .{ .rri_u = .{
+ .r1 = reg1,
+ .r2 = reg2,
+ .imm = @intCast(u32, imm.unsigned),
+ } },
+ else => unreachable,
+ };
+ _ = try self.addInst(.{
+ .tag = tag,
+ .ops = ops,
+ .data = data,
+ });
+}
+
fn asmMemory(self: *Self, tag: Mir.Inst.Tag, m: Memory) !void {
const ops: Mir.Inst.Ops = switch (m) {
.sib => .m_sib,
@@ -2767,27 +2798,20 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
break :blk coff_file.getAtom(atom).getSymbolIndex().?;
} else unreachable;
- const flags: u2 = switch (load_struct.type) {
- .got => 0b00,
- .direct => 0b01,
- .import => 0b10,
+ const ops: Mir.Inst.Ops = switch (load_struct.type) {
+ .got => .got_reloc,
+ .direct => .direct_reloc,
+ .import => .import_reloc,
};
- _ = abi_size;
- _ = atom_index;
- _ = flags;
- // _ = try self.addInst(.{
- // .tag = .lea_pic,
- // .ops = Mir.Inst.Ops.encode(.{
- // .reg1 = registerAlias(reg, abi_size),
- // .flags = flags,
- // }),
- // .data = .{
- // .relocation = .{
- // .atom_index = atom_index,
- // .sym_index = load_struct.sym_index,
- // },
- // },
- // });
+ _ = try self.addInst(.{
+ .tag = .lea_linker,
+ .ops = ops,
+ .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{
+ .reg = @enumToInt(registerAlias(reg, abi_size)),
+ .atom_index = atom_index,
+ .sym_index = load_struct.sym_index,
+ }) },
+ });
},
.memory => |addr| {
// TODO: in case the address fits in an imm32 we can use [ds:imm32]
@@ -3690,18 +3714,15 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
registerAlias(src_reg, abi_size),
),
.immediate => |imm| {
- // TODO take into account the type's ABI size when selecting the register alias
- // register, immediate
if (math.minInt(i32) <= imm and imm <= math.maxInt(i32)) {
- // _ = try self.addInst(.{
- // .tag = .imul_complex,
- // .ops = Mir.Inst.Ops.encode(.{
- // .reg1 = dst_reg.to32(),
- // .reg2 = dst_reg.to32(),
- // .flags = 0b10,
- // }),
- // .data = .{ .imm = @intCast(u32, imm) },
- // });
+ // TODO take into account the type's ABI size when selecting the register alias
+ // register, immediate
+ try self.asmRegisterRegisterImmediate(
+ .imul,
+ dst_reg.to32(),
+ dst_reg.to32(),
+ Immediate.u(@intCast(u32, imm)),
+ );
} else {
// TODO verify we don't spill and assign to the same register as dst_mcv
const src_reg = try self.copyToTmpRegister(dst_ty, src_mcv);
@@ -4034,16 +4055,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;
- _ = sym_index;
- _ = atom_index;
- // _ = try self.addInst(.{
- // .tag = .call_extern,
- // .ops = undefined,
- // .data = .{ .relocation = .{
- // .atom_index = atom_index,
- // .sym_index = sym_index,
- // } },
- // });
+ _ = try self.addInst(.{
+ .tag = .call_extern,
+ .ops = undefined,
+ .data = .{ .relocation = .{
+ .atom_index = atom_index,
+ .sym_index = sym_index,
+ } },
+ });
} else {
return self.fail("TODO implement calling extern functions", .{});
}
@@ -5528,7 +5547,6 @@ fn genInlineMemcpy(
const index_reg = regs[2].to64();
const count_reg = regs[3].to64();
const tmp_reg = regs[4].to8();
- _ = tmp_reg;
switch (dst_ptr) {
.memory, .linker_load => {
@@ -5575,7 +5593,6 @@ fn genInlineMemcpy(
}
try self.genSetReg(Type.usize, count_reg, len);
-
try self.asmRegisterImmediate(.mov, index_reg, Immediate.u(0));
const loop_start = try self.addInst(.{
@@ -5595,26 +5612,22 @@ fn genInlineMemcpy(
} },
});
- // mov tmp, [addr + index_reg]
- // _ = try self.addInst(.{
- // .tag = .mov_scale_src,
- // .ops = Mir.Inst.Ops.encode(.{
- // .reg1 = tmp_reg.to8(),
- // .reg2 = src_addr_reg,
- // }),
- // .data = .{ .payload = try self.addExtra(Mir.IndexRegisterDisp.encode(index_reg, 0)) },
- // });
-
- // mov [stack_offset + index_reg], tmp
- // _ = try self.addInst(.{
- // .tag = .mov_scale_dst,
- // .ops = Mir.Inst.Ops.encode(.{
- // .reg1 = dst_addr_reg,
- // .reg2 = tmp_reg.to8(),
- // }),
- // .data = .{ .payload = try self.addExtra(Mir.IndexRegisterDisp.encode(index_reg, 0)) },
- // });
-
+ try self.asmRegisterMemory(.mov, tmp_reg.to8(), Memory.sib(.byte, .{
+ .base = src_addr_reg,
+ .scale_index = .{
+ .scale = 1,
+ .index = index_reg,
+ },
+ .disp = 0,
+ }));
+ try self.asmMemoryRegister(.mov, Memory.sib(.byte, .{
+ .base = dst_addr_reg,
+ .scale_index = .{
+ .scale = 1,
+ .index = index_reg,
+ },
+ .disp = 0,
+ }), tmp_reg.to8());
try self.asmRegisterImmediate(.add, index_reg, Immediate.u(1));
try self.asmRegisterImmediate(.sub, count_reg, Immediate.u(1));
@@ -5655,15 +5668,10 @@ fn genInlineMemset(
try self.loadMemPtrIntoRegister(addr_reg, Type.usize, dst_ptr);
},
.ptr_stack_offset, .stack_offset => |off| {
- _ = off;
- // _ = try self.addInst(.{
- // .tag = .lea,
- // .ops = Mir.Inst.Ops.encode(.{
- // .reg1 = addr_reg.to64(),
- // .reg2 = opts.dest_stack_base orelse .rbp,
- // }),
- // .data = .{ .disp = -off },
- // });
+ try self.asmRegisterMemory(.lea, addr_reg.to64(), Memory.sib(.qword, .{
+ .base = opts.dest_stack_base orelse .rbp,
+ .disp = -off,
+ }));
},
.register => |reg| {
try self.asmRegisterRegister(
@@ -5703,18 +5711,14 @@ fn genInlineMemset(
if (x > math.maxInt(i32)) {
return self.fail("TODO inline memset for value immediate larger than 32bits", .{});
}
- // mov byte ptr [rbp + index_reg + stack_offset], imm
- // _ = try self.addInst(.{
- // .tag = .mov_mem_index_imm,
- // .ops = Mir.Inst.Ops.encode(.{
- // .reg1 = addr_reg,
- // }),
- // .data = .{ .payload = try self.addExtra(Mir.IndexRegisterDispImm.encode(
- // index_reg,
- // 0,
- // @intCast(u32, x),
- // )) },
- // });
+ try self.asmMemoryImmediate(.mov, Memory.sib(.byte, .{
+ .base = addr_reg,
+ .scale_index = .{
+ .scale = 1,
+ .index = index_reg,
+ },
+ .disp = 0,
+ }), Immediate.u(@intCast(u8, x)));
},
else => return self.fail("TODO inline memset for value of type {}", .{value}),
}
src/arch/x86_64/Emit.zig
@@ -120,6 +120,10 @@ pub fn lowerMir(emit: *Emit) InnerError!void {
.jmp_reloc => try emit.mirJmpReloc(inst),
+ .call_extern => try emit.mirCallExtern(inst),
+
+ .lea_linker => try emit.mirLeaLinker(inst),
+
.mov_moffs => try emit.mirMovMoffs(inst),
.movsx => try emit.mirMovsx(inst),
@@ -213,6 +217,16 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE
.{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) },
};
},
+ .rri_s => operands[0..3].* = .{
+ .{ .reg = data.rri_s.r1 },
+ .{ .reg = data.rri_s.r2 },
+ .{ .imm = Immediate.s(data.rri_s.imm) },
+ },
+ .rri_u => operands[0..3].* = .{
+ .{ .reg = data.rri_u.r1 },
+ .{ .reg = data.rri_u.r2 },
+ .{ .imm = Immediate.u(data.rri_u.imm) },
+ },
.m_sib => {
const msib = emit.mir.extraData(Mir.MemorySib, data.payload).data;
operands[0] = .{ .mem = Mir.MemorySib.decode(msib) };
@@ -402,47 +416,44 @@ fn mirJmpReloc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
}
}
-// fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
-// const tag = emit.mir.instructions.items(.tag)[inst];
-// assert(tag == .call_extern);
-// const relocation = emit.mir.instructions.items(.data)[inst].relocation;
-
-// const offset = blk: {
-// // callq
-// try emit.encode(.call, .{
-// .op1 = .{ .imm = Immediate.s(0) },
-// });
-// break :blk @intCast(u32, emit.code.items.len) - 4;
-// };
-
-// if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
-// // Add relocation to the decl.
-// const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
-// const target = macho_file.getGlobalByIndex(relocation.sym_index);
-// try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
-// .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
-// .target = target,
-// .offset = offset,
-// .addend = 0,
-// .pcrel = true,
-// .length = 2,
-// });
-// } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
-// // Add relocation to the decl.
-// const atom_index = coff_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
-// const target = coff_file.getGlobalByIndex(relocation.sym_index);
-// try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
-// .type = .direct,
-// .target = target,
-// .offset = offset,
-// .addend = 0,
-// .pcrel = true,
-// .length = 2,
-// });
-// } else {
-// return emit.fail("TODO implement call_extern for linking backends different than MachO and COFF", .{});
-// }
-// }
+fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
+ const relocation = emit.mir.instructions.items(.data)[inst].relocation;
+
+ const offset = blk: {
+ try emit.encode(.call, .{
+ .op1 = .{ .imm = Immediate.s(0) },
+ });
+ break :blk @intCast(u32, emit.code.items.len) - 4;
+ };
+
+ if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
+ // Add relocation to the decl.
+ const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
+ const target = macho_file.getGlobalByIndex(relocation.sym_index);
+ try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
+ .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
+ .target = target,
+ .offset = offset,
+ .addend = 0,
+ .pcrel = true,
+ .length = 2,
+ });
+ } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
+ // Add relocation to the decl.
+ const atom_index = coff_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
+ const target = coff_file.getGlobalByIndex(relocation.sym_index);
+ try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
+ .type = .direct,
+ .target = target,
+ .offset = offset,
+ .addend = 0,
+ .pcrel = true,
+ .length = 2,
+ });
+ } else {
+ return emit.fail("TODO implement call_extern for linking backends different than MachO and COFF", .{});
+ }
+}
fn mirPushPopRegisterList(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void {
const payload = emit.mir.instructions.items(.data)[inst].payload;
@@ -474,194 +485,63 @@ fn mirPushPopRegisterList(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index)
}
}
-// fn mirJmpCall(emit: *Emit, mnemonic: Instruction.Mnemonic, inst: Mir.Inst.Index) InnerError!void {
-// const ops = emit.mir.instructions.items(.ops)[inst].decode();
-// switch (ops.flags) {
-// 0b00 => {
-// const target = emit.mir.instructions.items(.data)[inst].inst;
-// const source = emit.code.items.len;
-// try emit.encode(mnemonic, .{
-// .op1 = .{ .imm = Immediate.s(0) },
-// });
-// try emit.relocs.append(emit.bin_file.allocator, .{
-// .source = source,
-// .target = target,
-// .offset = emit.code.items.len - 4,
-// .length = 5,
-// });
-// },
-// 0b01 => {
-// if (ops.reg1 == .none) {
-// const disp = emit.mir.instructions.items(.data)[inst].disp;
-// return emit.encode(mnemonic, .{
-// .op1 = .{ .mem = Memory.sib(.qword, .{ .disp = disp }) },
-// });
-// }
-// return emit.encode(mnemonic, .{
-// .op1 = .{ .reg = ops.reg1 },
-// });
-// },
-// 0b10 => {
-// const disp = emit.mir.instructions.items(.data)[inst].disp;
-// return emit.encode(mnemonic, .{
-// .op1 = .{ .mem = Memory.sib(.qword, .{
-// .base = ops.reg1,
-// .disp = disp,
-// }) },
-// });
-// },
-// 0b11 => return emit.fail("TODO unused variant jmp/call 0b11", .{}),
-// }
-// }
-
-// fn mirLea(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
-// const tag = emit.mir.instructions.items(.tag)[inst];
-// assert(tag == .lea);
-// const ops = emit.mir.instructions.items(.ops)[inst].decode();
-// switch (ops.flags) {
-// 0b00 => {
-// const disp = emit.mir.instructions.items(.data)[inst].disp;
-// const src_reg: ?Register = if (ops.reg2 != .none) ops.reg2 else null;
-// return emit.encode(.lea, .{
-// .op1 = .{ .reg = ops.reg1 },
-// .op2 = .{ .mem = Memory.sib(Memory.PtrSize.fromBitSize(ops.reg1.bitSize()), .{
-// .base = src_reg,
-// .disp = disp,
-// }) },
-// });
-// },
-// 0b01 => {
-// const start_offset = emit.code.items.len;
-// try emit.encode(.lea, .{
-// .op1 = .{ .reg = ops.reg1 },
-// .op2 = .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(ops.reg1.bitSize()), 0) },
-// });
-// const end_offset = emit.code.items.len;
-// // Backpatch the displacement
-// const payload = emit.mir.instructions.items(.data)[inst].payload;
-// const imm = emit.mir.extraData(Mir.Imm64, payload).data.decode();
-// const disp = @intCast(i32, @intCast(i64, imm) - @intCast(i64, end_offset - start_offset));
-// mem.writeIntLittle(i32, emit.code.items[end_offset - 4 ..][0..4], disp);
-// },
-// 0b10 => {
-// const payload = emit.mir.instructions.items(.data)[inst].payload;
-// const index_reg_disp = emit.mir.extraData(Mir.IndexRegisterDisp, payload).data.decode();
-// const src_reg: ?Register = if (ops.reg2 != .none) ops.reg2 else null;
-// const scale_index = Memory.ScaleIndex{
-// .scale = 1,
-// .index = index_reg_disp.index,
-// };
-// return emit.encode(.lea, .{
-// .op1 = .{ .reg = ops.reg1 },
-// .op2 = .{ .mem = Memory.sib(Memory.PtrSize.fromBitSize(ops.reg1.bitSize()), .{
-// .base = src_reg,
-// .scale_index = scale_index,
-// .disp = index_reg_disp.disp,
-// }) },
-// });
-// },
-// 0b11 => return emit.fail("TODO unused LEA variant 0b11", .{}),
-// }
-// }
-
-// fn mirLeaPic(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
-// const tag = emit.mir.instructions.items(.tag)[inst];
-// assert(tag == .lea_pic);
-// const ops = emit.mir.instructions.items(.ops)[inst].decode();
-// const relocation = emit.mir.instructions.items(.data)[inst].relocation;
-
-// switch (ops.flags) {
-// 0b00, 0b01, 0b10 => {},
-// else => return emit.fail("TODO unused LEA PIC variant 0b11", .{}),
-// }
-
-// try emit.encode(.lea, .{
-// .op1 = .{ .reg = ops.reg1 },
-// .op2 = .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(ops.reg1.bitSize()), 0) },
-// });
-
-// const end_offset = emit.code.items.len;
-
-// if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
-// const reloc_type = switch (ops.flags) {
-// 0b00 => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_GOT),
-// 0b01 => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),
-// else => unreachable,
-// };
-// const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
-// try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
-// .type = reloc_type,
-// .target = .{ .sym_index = relocation.sym_index, .file = null },
-// .offset = @intCast(u32, end_offset - 4),
-// .addend = 0,
-// .pcrel = true,
-// .length = 2,
-// });
-// } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
-// const atom_index = coff_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
-// try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
-// .type = switch (ops.flags) {
-// 0b00 => .got,
-// 0b01 => .direct,
-// 0b10 => .import,
-// else => unreachable,
-// },
-// .target = switch (ops.flags) {
-// 0b00, 0b01 => .{ .sym_index = relocation.sym_index, .file = null },
-// 0b10 => coff_file.getGlobalByIndex(relocation.sym_index),
-// else => unreachable,
-// },
-// .offset = @intCast(u32, end_offset - 4),
-// .addend = 0,
-// .pcrel = true,
-// .length = 2,
-// });
-// } else {
-// return emit.fail("TODO implement lea reg, [rip + reloc] for linking backends different than MachO", .{});
-// }
-// }
-
-// fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
-// const tag = emit.mir.instructions.items(.tag)[inst];
-// assert(tag == .call_extern);
-// const relocation = emit.mir.instructions.items(.data)[inst].relocation;
-
-// const offset = blk: {
-// // callq
-// try emit.encode(.call, .{
-// .op1 = .{ .imm = Immediate.s(0) },
-// });
-// break :blk @intCast(u32, emit.code.items.len) - 4;
-// };
-
-// if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
-// // Add relocation to the decl.
-// const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
-// const target = macho_file.getGlobalByIndex(relocation.sym_index);
-// try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
-// .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
-// .target = target,
-// .offset = offset,
-// .addend = 0,
-// .pcrel = true,
-// .length = 2,
-// });
-// } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
-// // Add relocation to the decl.
-// const atom_index = coff_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
-// const target = coff_file.getGlobalByIndex(relocation.sym_index);
-// try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
-// .type = .direct,
-// .target = target,
-// .offset = offset,
-// .addend = 0,
-// .pcrel = true,
-// .length = 2,
-// });
-// } else {
-// return emit.fail("TODO implement call_extern for linking backends different than MachO and COFF", .{});
-// }
-// }
+fn mirLeaLinker(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
+ const ops = emit.mir.instructions.items(.ops)[inst];
+ const payload = emit.mir.instructions.items(.data)[inst].payload;
+ const metadata = emit.mir.extraData(Mir.LeaRegisterReloc, payload).data;
+ const reg = @intToEnum(Register, metadata.reg);
+
+ try emit.encode(.lea, .{
+ .op1 = .{ .reg = reg },
+ .op2 = .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },
+ });
+
+ const end_offset = emit.code.items.len;
+
+ if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
+ const reloc_type = switch (ops) {
+ .got_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_GOT),
+ .direct_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),
+ else => unreachable,
+ };
+ const atom_index = macho_file.getAtomIndexForSymbol(.{
+ .sym_index = metadata.atom_index,
+ .file = null,
+ }).?;
+ try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
+ .type = reloc_type,
+ .target = .{ .sym_index = metadata.sym_index, .file = null },
+ .offset = @intCast(u32, end_offset - 4),
+ .addend = 0,
+ .pcrel = true,
+ .length = 2,
+ });
+ } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
+ const atom_index = coff_file.getAtomIndexForSymbol(.{
+ .sym_index = metadata.atom_index,
+ .file = null,
+ }).?;
+ try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
+ .type = switch (ops) {
+ .got_reloc => .got,
+ .direct_reloc => .direct,
+ .import_reloc => .import,
+ else => unreachable,
+ },
+ .target = switch (ops) {
+ .got_reloc, .direct_reloc => .{ .sym_index = metadata.sym_index, .file = null },
+ .import_reloc => coff_file.getGlobalByIndex(metadata.sym_index),
+ else => unreachable,
+ },
+ .offset = @intCast(u32, end_offset - 4),
+ .addend = 0,
+ .pcrel = true,
+ .length = 2,
+ });
+ } else {
+ return emit.fail("TODO implement lea reg, [rip + reloc] for linking backends different than MachO", .{});
+ }
+}
fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
const payload = emit.mir.instructions.items(.data)[inst].payload;
src/arch/x86_64/Mir.zig
@@ -142,6 +142,13 @@ pub const Inst = struct {
/// Jump with relocation to another local MIR instruction
jmp_reloc,
+ /// Call to an extern symbol via linker relocation.
+ /// Uses `relocation` payload.
+ call_extern,
+
+ /// Load effective address of a symbol not yet allocated in VM.
+ lea_linker,
+
/// End of prologue
dbg_prologue_end,
/// Start of epilogue
@@ -169,6 +176,12 @@ pub const Inst = struct {
/// Register, register, register operands.
/// Uses `rrr` payload.
rrr,
+ /// Register, register, immediate (sign-extended) operands.
+ /// Uses `rri_s` payload.
+ rri_s,
+ /// Register, register, immediate (unsigned) operands.
+ /// Uses `rri_u` payload.
+ rri_u,
/// Register with condition code (CC).
/// Uses `r_c` payload.
r_c,
@@ -199,12 +212,6 @@ pub const Inst = struct {
/// Register, memory (RIP) operands.
/// Uses `rx` payload.
rm_rip,
- /// Register, memory, immediate (unsigned) operands
- /// Uses `rx` payload.
- rmi_u,
- /// Register, memory, immediate (sign-extended) operands
- /// Uses `rx` payload.
- rmi_s,
/// Single memory (SIB) operand.
/// Uses `payload` with extra data of type `MemorySib`.
m_sib,
@@ -250,6 +257,15 @@ pub const Inst = struct {
rm_cc,
/// Uses `reloc` payload.
reloc,
+ /// Linker relocation - GOT indirection.
+ /// Uses `payload` payload with extra data of type `LeaRegisterReloc`.
+ got_reloc,
+ /// Linker relocation - direct reference.
+ /// Uses `payload` payload with extra data of type `LeaRegisterReloc`.
+ direct_reloc,
+ /// Linker relocation - imports table indirection (binding).
+ /// Uses `payload` payload with extra data of type `LeaRegisterReloc`.
+ import_reloc,
};
pub const Data = union {
@@ -279,6 +295,16 @@ pub const Inst = struct {
r2: Register,
r3: Register,
},
+ rri_s: struct {
+ r1: Register,
+ r2: Register,
+ imm: i32,
+ },
+ rri_u: struct {
+ r1: Register,
+ r2: Register,
+ imm: u32,
+ },
/// Register with condition code (CC).
r_c: struct {
r1: Register,
@@ -339,13 +365,7 @@ pub const Inst = struct {
pub const LeaRegisterReloc = struct {
/// Destination register.
- reg: Register,
- /// Type of the load.
- load_type: enum(u2) {
- got,
- direct,
- import,
- },
+ reg: u32,
/// Index of the containing atom.
atom_index: u32,
/// Index into the linker's symbol table.