authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-09 23:56:55+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-11 20:05:49+01:00
logd0e72125396c391172758d28c21a9b901dcecc68
tree9c69c3ce6a51d6da54e9faee744e147ea3d7104f
parent022b308d6a0a3d3cf178ddc6e887f24369f69deb

x86_64: finish rolling out all MIR assembly helpers


3 files changed, 230 insertions(+), 326 deletions(-)

src/arch/x86_64/CodeGen.zig+88-84
...@@ -491,6 +491,37 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Imme...@@ -491,6 +491,37 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Imme
491 });491 });
492}492}
493493
494fn asmRegisterRegisterImmediate(
495 self: *Self,
496 tag: Mir.Inst.Tag,
497 reg1: Register,
498 reg2: Register,
499 imm: Immediate,
500) !void {
501 const ops: Mir.Inst.Ops = switch (imm) {
502 .signed => .rri_s,
503 .unsigned => .rri_u,
504 };
505 const data: Mir.Inst.Data = switch (ops) {
506 .rri_s => .{ .rri_s = .{
507 .r1 = reg1,
508 .r2 = reg2,
509 .imm = imm.signed,
510 } },
511 .rri_u => .{ .rri_u = .{
512 .r1 = reg1,
513 .r2 = reg2,
514 .imm = @intCast(u32, imm.unsigned),
515 } },
516 else => unreachable,
517 };
518 _ = try self.addInst(.{
519 .tag = tag,
520 .ops = ops,
521 .data = data,
522 });
523}
524
494fn asmMemory(self: *Self, tag: Mir.Inst.Tag, m: Memory) !void {525fn asmMemory(self: *Self, tag: Mir.Inst.Tag, m: Memory) !void {
495 const ops: Mir.Inst.Ops = switch (m) {526 const ops: Mir.Inst.Ops = switch (m) {
496 .sib => .m_sib,527 .sib => .m_sib,
...@@ -2767,27 +2798,20 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue...@@ -2767,27 +2798,20 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
2767 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);2798 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
2768 break :blk coff_file.getAtom(atom).getSymbolIndex().?;2799 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
2769 } else unreachable;2800 } else unreachable;
2770 const flags: u2 = switch (load_struct.type) {2801 const ops: Mir.Inst.Ops = switch (load_struct.type) {
2771 .got => 0b00,2802 .got => .got_reloc,
2772 .direct => 0b01,2803 .direct => .direct_reloc,
2773 .import => 0b10,2804 .import => .import_reloc,
2774 };2805 };
2775 _ = abi_size;2806 _ = try self.addInst(.{
2776 _ = atom_index;2807 .tag = .lea_linker,
2777 _ = flags;2808 .ops = ops,
2778 // _ = try self.addInst(.{2809 .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{
2779 // .tag = .lea_pic,2810 .reg = @enumToInt(registerAlias(reg, abi_size)),
2780 // .ops = Mir.Inst.Ops.encode(.{2811 .atom_index = atom_index,
2781 // .reg1 = registerAlias(reg, abi_size),2812 .sym_index = load_struct.sym_index,
2782 // .flags = flags,2813 }) },
2783 // }),2814 });
2784 // .data = .{
2785 // .relocation = .{
2786 // .atom_index = atom_index,
2787 // .sym_index = load_struct.sym_index,
2788 // },
2789 // },
2790 // });
2791 },2815 },
2792 .memory => |addr| {2816 .memory => |addr| {
2793 // TODO: in case the address fits in an imm32 we can use [ds:imm32]2817 // 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...@@ -3690,18 +3714,15 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
3690 registerAlias(src_reg, abi_size),3714 registerAlias(src_reg, abi_size),
3691 ),3715 ),
3692 .immediate => |imm| {3716 .immediate => |imm| {
3693 // TODO take into account the type's ABI size when selecting the register alias
3694 // register, immediate
3695 if (math.minInt(i32) <= imm and imm <= math.maxInt(i32)) {3717 if (math.minInt(i32) <= imm and imm <= math.maxInt(i32)) {
3696 // _ = try self.addInst(.{3718 // TODO take into account the type's ABI size when selecting the register alias
3697 // .tag = .imul_complex,3719 // register, immediate
3698 // .ops = Mir.Inst.Ops.encode(.{3720 try self.asmRegisterRegisterImmediate(
3699 // .reg1 = dst_reg.to32(),3721 .imul,
3700 // .reg2 = dst_reg.to32(),3722 dst_reg.to32(),
3701 // .flags = 0b10,3723 dst_reg.to32(),
3702 // }),3724 Immediate.u(@intCast(u32, imm)),
3703 // .data = .{ .imm = @intCast(u32, imm) },3725 );
3704 // });
3705 } else {3726 } else {
3706 // TODO verify we don't spill and assign to the same register as dst_mcv3727 // TODO verify we don't spill and assign to the same register as dst_mcv
3707 const src_reg = try self.copyToTmpRegister(dst_ty, src_mcv);3728 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...@@ -4034,16 +4055,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4034 const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));4055 const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
4035 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);4056 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
4036 const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;4057 const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;
4037 _ = sym_index;4058 _ = try self.addInst(.{
4038 _ = atom_index;4059 .tag = .call_extern,
4039 // _ = try self.addInst(.{4060 .ops = undefined,
4040 // .tag = .call_extern,4061 .data = .{ .relocation = .{
4041 // .ops = undefined,4062 .atom_index = atom_index,
4042 // .data = .{ .relocation = .{4063 .sym_index = sym_index,
4043 // .atom_index = atom_index,4064 } },
4044 // .sym_index = sym_index,4065 });
4045 // } },
4046 // });
4047 } else {4066 } else {
4048 return self.fail("TODO implement calling extern functions", .{});4067 return self.fail("TODO implement calling extern functions", .{});
4049 }4068 }
...@@ -5528,7 +5547,6 @@ fn genInlineMemcpy(...@@ -5528,7 +5547,6 @@ fn genInlineMemcpy(
5528 const index_reg = regs[2].to64();5547 const index_reg = regs[2].to64();
5529 const count_reg = regs[3].to64();5548 const count_reg = regs[3].to64();
5530 const tmp_reg = regs[4].to8();5549 const tmp_reg = regs[4].to8();
5531 _ = tmp_reg;
55325550
5533 switch (dst_ptr) {5551 switch (dst_ptr) {
5534 .memory, .linker_load => {5552 .memory, .linker_load => {
...@@ -5575,7 +5593,6 @@ fn genInlineMemcpy(...@@ -5575,7 +5593,6 @@ fn genInlineMemcpy(
5575 }5593 }
55765594
5577 try self.genSetReg(Type.usize, count_reg, len);5595 try self.genSetReg(Type.usize, count_reg, len);
5578
5579 try self.asmRegisterImmediate(.mov, index_reg, Immediate.u(0));5596 try self.asmRegisterImmediate(.mov, index_reg, Immediate.u(0));
55805597
5581 const loop_start = try self.addInst(.{5598 const loop_start = try self.addInst(.{
...@@ -5595,26 +5612,22 @@ fn genInlineMemcpy(...@@ -5595,26 +5612,22 @@ fn genInlineMemcpy(
5595 } },5612 } },
5596 });5613 });
55975614
5598 // mov tmp, [addr + index_reg]5615 try self.asmRegisterMemory(.mov, tmp_reg.to8(), Memory.sib(.byte, .{
5599 // _ = try self.addInst(.{5616 .base = src_addr_reg,
5600 // .tag = .mov_scale_src,5617 .scale_index = .{
5601 // .ops = Mir.Inst.Ops.encode(.{5618 .scale = 1,
5602 // .reg1 = tmp_reg.to8(),5619 .index = index_reg,
5603 // .reg2 = src_addr_reg,5620 },
5604 // }),5621 .disp = 0,
5605 // .data = .{ .payload = try self.addExtra(Mir.IndexRegisterDisp.encode(index_reg, 0)) },5622 }));
5606 // });5623 try self.asmMemoryRegister(.mov, Memory.sib(.byte, .{
56075624 .base = dst_addr_reg,
5608 // mov [stack_offset + index_reg], tmp5625 .scale_index = .{
5609 // _ = try self.addInst(.{5626 .scale = 1,
5610 // .tag = .mov_scale_dst,5627 .index = index_reg,
5611 // .ops = Mir.Inst.Ops.encode(.{5628 },
5612 // .reg1 = dst_addr_reg,5629 .disp = 0,
5613 // .reg2 = tmp_reg.to8(),5630 }), tmp_reg.to8());
5614 // }),
5615 // .data = .{ .payload = try self.addExtra(Mir.IndexRegisterDisp.encode(index_reg, 0)) },
5616 // });
5617
5618 try self.asmRegisterImmediate(.add, index_reg, Immediate.u(1));5631 try self.asmRegisterImmediate(.add, index_reg, Immediate.u(1));
5619 try self.asmRegisterImmediate(.sub, count_reg, Immediate.u(1));5632 try self.asmRegisterImmediate(.sub, count_reg, Immediate.u(1));
56205633
...@@ -5655,15 +5668,10 @@ fn genInlineMemset(...@@ -5655,15 +5668,10 @@ fn genInlineMemset(
5655 try self.loadMemPtrIntoRegister(addr_reg, Type.usize, dst_ptr);5668 try self.loadMemPtrIntoRegister(addr_reg, Type.usize, dst_ptr);
5656 },5669 },
5657 .ptr_stack_offset, .stack_offset => |off| {5670 .ptr_stack_offset, .stack_offset => |off| {
5658 _ = off;5671 try self.asmRegisterMemory(.lea, addr_reg.to64(), Memory.sib(.qword, .{
5659 // _ = try self.addInst(.{5672 .base = opts.dest_stack_base orelse .rbp,
5660 // .tag = .lea,5673 .disp = -off,
5661 // .ops = Mir.Inst.Ops.encode(.{5674 }));
5662 // .reg1 = addr_reg.to64(),
5663 // .reg2 = opts.dest_stack_base orelse .rbp,
5664 // }),
5665 // .data = .{ .disp = -off },
5666 // });
5667 },5675 },
5668 .register => |reg| {5676 .register => |reg| {
5669 try self.asmRegisterRegister(5677 try self.asmRegisterRegister(
...@@ -5703,18 +5711,14 @@ fn genInlineMemset(...@@ -5703,18 +5711,14 @@ fn genInlineMemset(
5703 if (x > math.maxInt(i32)) {5711 if (x > math.maxInt(i32)) {
5704 return self.fail("TODO inline memset for value immediate larger than 32bits", .{});5712 return self.fail("TODO inline memset for value immediate larger than 32bits", .{});
5705 }5713 }
5706 // mov byte ptr [rbp + index_reg + stack_offset], imm5714 try self.asmMemoryImmediate(.mov, Memory.sib(.byte, .{
5707 // _ = try self.addInst(.{5715 .base = addr_reg,
5708 // .tag = .mov_mem_index_imm,5716 .scale_index = .{
5709 // .ops = Mir.Inst.Ops.encode(.{5717 .scale = 1,
5710 // .reg1 = addr_reg,5718 .index = index_reg,
5711 // }),5719 },
5712 // .data = .{ .payload = try self.addExtra(Mir.IndexRegisterDispImm.encode(5720 .disp = 0,
5713 // index_reg,5721 }), Immediate.u(@intCast(u8, x)));
5714 // 0,
5715 // @intCast(u32, x),
5716 // )) },
5717 // });
5718 },5722 },
5719 else => return self.fail("TODO inline memset for value of type {}", .{value}),5723 else => return self.fail("TODO inline memset for value of type {}", .{value}),
5720 }5724 }
src/arch/x86_64/Emit.zig+109-229
...@@ -120,6 +120,10 @@ pub fn lowerMir(emit: *Emit) InnerError!void {...@@ -120,6 +120,10 @@ pub fn lowerMir(emit: *Emit) InnerError!void {
120120
121 .jmp_reloc => try emit.mirJmpReloc(inst),121 .jmp_reloc => try emit.mirJmpReloc(inst),
122122
123 .call_extern => try emit.mirCallExtern(inst),
124
125 .lea_linker => try emit.mirLeaLinker(inst),
126
123 .mov_moffs => try emit.mirMovMoffs(inst),127 .mov_moffs => try emit.mirMovMoffs(inst),
124128
125 .movsx => try emit.mirMovsx(inst),129 .movsx => try emit.mirMovsx(inst),
...@@ -213,6 +217,16 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE...@@ -213,6 +217,16 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE
213 .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) },217 .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) },
214 };218 };
215 },219 },
220 .rri_s => operands[0..3].* = .{
221 .{ .reg = data.rri_s.r1 },
222 .{ .reg = data.rri_s.r2 },
223 .{ .imm = Immediate.s(data.rri_s.imm) },
224 },
225 .rri_u => operands[0..3].* = .{
226 .{ .reg = data.rri_u.r1 },
227 .{ .reg = data.rri_u.r2 },
228 .{ .imm = Immediate.u(data.rri_u.imm) },
229 },
216 .m_sib => {230 .m_sib => {
217 const msib = emit.mir.extraData(Mir.MemorySib, data.payload).data;231 const msib = emit.mir.extraData(Mir.MemorySib, data.payload).data;
218 operands[0] = .{ .mem = Mir.MemorySib.decode(msib) };232 operands[0] = .{ .mem = Mir.MemorySib.decode(msib) };
...@@ -402,47 +416,44 @@ fn mirJmpReloc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {...@@ -402,47 +416,44 @@ fn mirJmpReloc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
402 }416 }
403}417}
404418
405// fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {419fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
406// const tag = emit.mir.instructions.items(.tag)[inst];420 const relocation = emit.mir.instructions.items(.data)[inst].relocation;
407// assert(tag == .call_extern);421
408// const relocation = emit.mir.instructions.items(.data)[inst].relocation;422 const offset = blk: {
409423 try emit.encode(.call, .{
410// const offset = blk: {424 .op1 = .{ .imm = Immediate.s(0) },
411// // callq425 });
412// try emit.encode(.call, .{426 break :blk @intCast(u32, emit.code.items.len) - 4;
413// .op1 = .{ .imm = Immediate.s(0) },427 };
414// });428
415// break :blk @intCast(u32, emit.code.items.len) - 4;429 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
416// };430 // Add relocation to the decl.
417431 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
418// if (emit.bin_file.cast(link.File.MachO)) |macho_file| {432 const target = macho_file.getGlobalByIndex(relocation.sym_index);
419// // Add relocation to the decl.433 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
420// const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;434 .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
421// const target = macho_file.getGlobalByIndex(relocation.sym_index);435 .target = target,
422// try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{436 .offset = offset,
423// .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),437 .addend = 0,
424// .target = target,438 .pcrel = true,
425// .offset = offset,439 .length = 2,
426// .addend = 0,440 });
427// .pcrel = true,441 } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
428// .length = 2,442 // Add relocation to the decl.
429// });443 const atom_index = coff_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
430// } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {444 const target = coff_file.getGlobalByIndex(relocation.sym_index);
431// // Add relocation to the decl.445 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
432// const atom_index = coff_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;446 .type = .direct,
433// const target = coff_file.getGlobalByIndex(relocation.sym_index);447 .target = target,
434// try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{448 .offset = offset,
435// .type = .direct,449 .addend = 0,
436// .target = target,450 .pcrel = true,
437// .offset = offset,451 .length = 2,
438// .addend = 0,452 });
439// .pcrel = true,453 } else {
440// .length = 2,454 return emit.fail("TODO implement call_extern for linking backends different than MachO and COFF", .{});
441// });455 }
442// } else {456}
443// return emit.fail("TODO implement call_extern for linking backends different than MachO and COFF", .{});
444// }
445// }
446457
447fn mirPushPopRegisterList(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void {458fn mirPushPopRegisterList(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void {
448 const payload = emit.mir.instructions.items(.data)[inst].payload;459 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)...@@ -474,194 +485,63 @@ fn mirPushPopRegisterList(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index)
474 }485 }
475}486}
476487
477// fn mirJmpCall(emit: *Emit, mnemonic: Instruction.Mnemonic, inst: Mir.Inst.Index) InnerError!void {488fn mirLeaLinker(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
478// const ops = emit.mir.instructions.items(.ops)[inst].decode();489 const ops = emit.mir.instructions.items(.ops)[inst];
479// switch (ops.flags) {490 const payload = emit.mir.instructions.items(.data)[inst].payload;
480// 0b00 => {491 const metadata = emit.mir.extraData(Mir.LeaRegisterReloc, payload).data;
481// const target = emit.mir.instructions.items(.data)[inst].inst;492 const reg = @intToEnum(Register, metadata.reg);
482// const source = emit.code.items.len;493
483// try emit.encode(mnemonic, .{494 try emit.encode(.lea, .{
484// .op1 = .{ .imm = Immediate.s(0) },495 .op1 = .{ .reg = reg },
485// });496 .op2 = .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },
486// try emit.relocs.append(emit.bin_file.allocator, .{497 });
487// .source = source,498
488// .target = target,499 const end_offset = emit.code.items.len;
489// .offset = emit.code.items.len - 4,500
490// .length = 5,501 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
491// });502 const reloc_type = switch (ops) {
492// },503 .got_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_GOT),
493// 0b01 => {504 .direct_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),
494// if (ops.reg1 == .none) {505 else => unreachable,
495// const disp = emit.mir.instructions.items(.data)[inst].disp;506 };
496// return emit.encode(mnemonic, .{507 const atom_index = macho_file.getAtomIndexForSymbol(.{
497// .op1 = .{ .mem = Memory.sib(.qword, .{ .disp = disp }) },508 .sym_index = metadata.atom_index,
498// });509 .file = null,
499// }510 }).?;
500// return emit.encode(mnemonic, .{511 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
501// .op1 = .{ .reg = ops.reg1 },512 .type = reloc_type,
502// });513 .target = .{ .sym_index = metadata.sym_index, .file = null },
503// },514 .offset = @intCast(u32, end_offset - 4),
504// 0b10 => {515 .addend = 0,
505// const disp = emit.mir.instructions.items(.data)[inst].disp;516 .pcrel = true,
506// return emit.encode(mnemonic, .{517 .length = 2,
507// .op1 = .{ .mem = Memory.sib(.qword, .{518 });
508// .base = ops.reg1,519 } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
509// .disp = disp,520 const atom_index = coff_file.getAtomIndexForSymbol(.{
510// }) },521 .sym_index = metadata.atom_index,
511// });522 .file = null,
512// },523 }).?;
513// 0b11 => return emit.fail("TODO unused variant jmp/call 0b11", .{}),524 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
514// }525 .type = switch (ops) {
515// }526 .got_reloc => .got,
516527 .direct_reloc => .direct,
517// fn mirLea(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {528 .import_reloc => .import,
518// const tag = emit.mir.instructions.items(.tag)[inst];529 else => unreachable,
519// assert(tag == .lea);530 },
520// const ops = emit.mir.instructions.items(.ops)[inst].decode();531 .target = switch (ops) {
521// switch (ops.flags) {532 .got_reloc, .direct_reloc => .{ .sym_index = metadata.sym_index, .file = null },
522// 0b00 => {533 .import_reloc => coff_file.getGlobalByIndex(metadata.sym_index),
523// const disp = emit.mir.instructions.items(.data)[inst].disp;534 else => unreachable,
524// const src_reg: ?Register = if (ops.reg2 != .none) ops.reg2 else null;535 },
525// return emit.encode(.lea, .{536 .offset = @intCast(u32, end_offset - 4),
526// .op1 = .{ .reg = ops.reg1 },537 .addend = 0,
527// .op2 = .{ .mem = Memory.sib(Memory.PtrSize.fromBitSize(ops.reg1.bitSize()), .{538 .pcrel = true,
528// .base = src_reg,539 .length = 2,
529// .disp = disp,540 });
530// }) },541 } else {
531// });542 return emit.fail("TODO implement lea reg, [rip + reloc] for linking backends different than MachO", .{});
532// },543 }
533// 0b01 => {544}
534// const start_offset = emit.code.items.len;
535// try emit.encode(.lea, .{
536// .op1 = .{ .reg = ops.reg1 },
537// .op2 = .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(ops.reg1.bitSize()), 0) },
538// });
539// const end_offset = emit.code.items.len;
540// // Backpatch the displacement
541// const payload = emit.mir.instructions.items(.data)[inst].payload;
542// const imm = emit.mir.extraData(Mir.Imm64, payload).data.decode();
543// const disp = @intCast(i32, @intCast(i64, imm) - @intCast(i64, end_offset - start_offset));
544// mem.writeIntLittle(i32, emit.code.items[end_offset - 4 ..][0..4], disp);
545// },
546// 0b10 => {
547// const payload = emit.mir.instructions.items(.data)[inst].payload;
548// const index_reg_disp = emit.mir.extraData(Mir.IndexRegisterDisp, payload).data.decode();
549// const src_reg: ?Register = if (ops.reg2 != .none) ops.reg2 else null;
550// const scale_index = Memory.ScaleIndex{
551// .scale = 1,
552// .index = index_reg_disp.index,
553// };
554// return emit.encode(.lea, .{
555// .op1 = .{ .reg = ops.reg1 },
556// .op2 = .{ .mem = Memory.sib(Memory.PtrSize.fromBitSize(ops.reg1.bitSize()), .{
557// .base = src_reg,
558// .scale_index = scale_index,
559// .disp = index_reg_disp.disp,
560// }) },
561// });
562// },
563// 0b11 => return emit.fail("TODO unused LEA variant 0b11", .{}),
564// }
565// }
566
567// fn mirLeaPic(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
568// const tag = emit.mir.instructions.items(.tag)[inst];
569// assert(tag == .lea_pic);
570// const ops = emit.mir.instructions.items(.ops)[inst].decode();
571// const relocation = emit.mir.instructions.items(.data)[inst].relocation;
572
573// switch (ops.flags) {
574// 0b00, 0b01, 0b10 => {},
575// else => return emit.fail("TODO unused LEA PIC variant 0b11", .{}),
576// }
577
578// try emit.encode(.lea, .{
579// .op1 = .{ .reg = ops.reg1 },
580// .op2 = .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(ops.reg1.bitSize()), 0) },
581// });
582
583// const end_offset = emit.code.items.len;
584
585// if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
586// const reloc_type = switch (ops.flags) {
587// 0b00 => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_GOT),
588// 0b01 => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),
589// else => unreachable,
590// };
591// const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
592// try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
593// .type = reloc_type,
594// .target = .{ .sym_index = relocation.sym_index, .file = null },
595// .offset = @intCast(u32, end_offset - 4),
596// .addend = 0,
597// .pcrel = true,
598// .length = 2,
599// });
600// } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
601// const atom_index = coff_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
602// try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
603// .type = switch (ops.flags) {
604// 0b00 => .got,
605// 0b01 => .direct,
606// 0b10 => .import,
607// else => unreachable,
608// },
609// .target = switch (ops.flags) {
610// 0b00, 0b01 => .{ .sym_index = relocation.sym_index, .file = null },
611// 0b10 => coff_file.getGlobalByIndex(relocation.sym_index),
612// else => unreachable,
613// },
614// .offset = @intCast(u32, end_offset - 4),
615// .addend = 0,
616// .pcrel = true,
617// .length = 2,
618// });
619// } else {
620// return emit.fail("TODO implement lea reg, [rip + reloc] for linking backends different than MachO", .{});
621// }
622// }
623
624// fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
625// const tag = emit.mir.instructions.items(.tag)[inst];
626// assert(tag == .call_extern);
627// const relocation = emit.mir.instructions.items(.data)[inst].relocation;
628
629// const offset = blk: {
630// // callq
631// try emit.encode(.call, .{
632// .op1 = .{ .imm = Immediate.s(0) },
633// });
634// break :blk @intCast(u32, emit.code.items.len) - 4;
635// };
636
637// if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
638// // Add relocation to the decl.
639// const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
640// const target = macho_file.getGlobalByIndex(relocation.sym_index);
641// try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
642// .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
643// .target = target,
644// .offset = offset,
645// .addend = 0,
646// .pcrel = true,
647// .length = 2,
648// });
649// } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
650// // Add relocation to the decl.
651// const atom_index = coff_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
652// const target = coff_file.getGlobalByIndex(relocation.sym_index);
653// try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
654// .type = .direct,
655// .target = target,
656// .offset = offset,
657// .addend = 0,
658// .pcrel = true,
659// .length = 2,
660// });
661// } else {
662// return emit.fail("TODO implement call_extern for linking backends different than MachO and COFF", .{});
663// }
664// }
665545
666fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {546fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
667 const payload = emit.mir.instructions.items(.data)[inst].payload;547 const payload = emit.mir.instructions.items(.data)[inst].payload;
src/arch/x86_64/Mir.zig+33-13
...@@ -142,6 +142,13 @@ pub const Inst = struct {...@@ -142,6 +142,13 @@ pub const Inst = struct {
142 /// Jump with relocation to another local MIR instruction142 /// Jump with relocation to another local MIR instruction
143 jmp_reloc,143 jmp_reloc,
144144
145 /// Call to an extern symbol via linker relocation.
146 /// Uses `relocation` payload.
147 call_extern,
148
149 /// Load effective address of a symbol not yet allocated in VM.
150 lea_linker,
151
145 /// End of prologue152 /// End of prologue
146 dbg_prologue_end,153 dbg_prologue_end,
147 /// Start of epilogue154 /// Start of epilogue
...@@ -169,6 +176,12 @@ pub const Inst = struct {...@@ -169,6 +176,12 @@ pub const Inst = struct {
169 /// Register, register, register operands.176 /// Register, register, register operands.
170 /// Uses `rrr` payload.177 /// Uses `rrr` payload.
171 rrr,178 rrr,
179 /// Register, register, immediate (sign-extended) operands.
180 /// Uses `rri_s` payload.
181 rri_s,
182 /// Register, register, immediate (unsigned) operands.
183 /// Uses `rri_u` payload.
184 rri_u,
172 /// Register with condition code (CC).185 /// Register with condition code (CC).
173 /// Uses `r_c` payload.186 /// Uses `r_c` payload.
174 r_c,187 r_c,
...@@ -199,12 +212,6 @@ pub const Inst = struct {...@@ -199,12 +212,6 @@ pub const Inst = struct {
199 /// Register, memory (RIP) operands.212 /// Register, memory (RIP) operands.
200 /// Uses `rx` payload.213 /// Uses `rx` payload.
201 rm_rip,214 rm_rip,
202 /// Register, memory, immediate (unsigned) operands
203 /// Uses `rx` payload.
204 rmi_u,
205 /// Register, memory, immediate (sign-extended) operands
206 /// Uses `rx` payload.
207 rmi_s,
208 /// Single memory (SIB) operand.215 /// Single memory (SIB) operand.
209 /// Uses `payload` with extra data of type `MemorySib`.216 /// Uses `payload` with extra data of type `MemorySib`.
210 m_sib,217 m_sib,
...@@ -250,6 +257,15 @@ pub const Inst = struct {...@@ -250,6 +257,15 @@ pub const Inst = struct {
250 rm_cc,257 rm_cc,
251 /// Uses `reloc` payload.258 /// Uses `reloc` payload.
252 reloc,259 reloc,
260 /// Linker relocation - GOT indirection.
261 /// Uses `payload` payload with extra data of type `LeaRegisterReloc`.
262 got_reloc,
263 /// Linker relocation - direct reference.
264 /// Uses `payload` payload with extra data of type `LeaRegisterReloc`.
265 direct_reloc,
266 /// Linker relocation - imports table indirection (binding).
267 /// Uses `payload` payload with extra data of type `LeaRegisterReloc`.
268 import_reloc,
253 };269 };
254270
255 pub const Data = union {271 pub const Data = union {
...@@ -279,6 +295,16 @@ pub const Inst = struct {...@@ -279,6 +295,16 @@ pub const Inst = struct {
279 r2: Register,295 r2: Register,
280 r3: Register,296 r3: Register,
281 },297 },
298 rri_s: struct {
299 r1: Register,
300 r2: Register,
301 imm: i32,
302 },
303 rri_u: struct {
304 r1: Register,
305 r2: Register,
306 imm: u32,
307 },
282 /// Register with condition code (CC).308 /// Register with condition code (CC).
283 r_c: struct {309 r_c: struct {
284 r1: Register,310 r1: Register,
...@@ -339,13 +365,7 @@ pub const Inst = struct {...@@ -339,13 +365,7 @@ pub const Inst = struct {
339365
340pub const LeaRegisterReloc = struct {366pub const LeaRegisterReloc = struct {
341 /// Destination register.367 /// Destination register.
342 reg: Register,368 reg: u32,
343 /// Type of the load.
344 load_type: enum(u2) {
345 got,
346 direct,
347 import,
348 },
349 /// Index of the containing atom.369 /// Index of the containing atom.
350 atom_index: u32,370 atom_index: u32,
351 /// Index into the linker's symbol table.371 /// Index into the linker's symbol table.