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
491491 });
492492}
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
494525fn asmMemory(self: *Self, tag: Mir.Inst.Tag, m: Memory) !void {
495526 const ops: Mir.Inst.Ops = switch (m) {
496527 .sib => .m_sib,
......@@ -2767,27 +2798,20 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
27672798 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
27682799 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
27692800 } else unreachable;
2770 const flags: u2 = switch (load_struct.type) {
2771 .got => 0b00,
2772 .direct => 0b01,
2773 .import => 0b10,
2801 const ops: Mir.Inst.Ops = switch (load_struct.type) {
2802 .got => .got_reloc,
2803 .direct => .direct_reloc,
2804 .import => .import_reloc,
27742805 };
2775 _ = abi_size;
2776 _ = atom_index;
2777 _ = flags;
2778 // _ = try self.addInst(.{
2779 // .tag = .lea_pic,
2780 // .ops = Mir.Inst.Ops.encode(.{
2781 // .reg1 = registerAlias(reg, abi_size),
2782 // .flags = flags,
2783 // }),
2784 // .data = .{
2785 // .relocation = .{
2786 // .atom_index = atom_index,
2787 // .sym_index = load_struct.sym_index,
2788 // },
2789 // },
2790 // });
2806 _ = try self.addInst(.{
2807 .tag = .lea_linker,
2808 .ops = ops,
2809 .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{
2810 .reg = @enumToInt(registerAlias(reg, abi_size)),
2811 .atom_index = atom_index,
2812 .sym_index = load_struct.sym_index,
2813 }) },
2814 });
27912815 },
27922816 .memory => |addr| {
27932817 // 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
36903714 registerAlias(src_reg, abi_size),
36913715 ),
36923716 .immediate => |imm| {
3693 // TODO take into account the type's ABI size when selecting the register alias
3694 // register, immediate
36953717 if (math.minInt(i32) <= imm and imm <= math.maxInt(i32)) {
3696 // _ = try self.addInst(.{
3697 // .tag = .imul_complex,
3698 // .ops = Mir.Inst.Ops.encode(.{
3699 // .reg1 = dst_reg.to32(),
3700 // .reg2 = dst_reg.to32(),
3701 // .flags = 0b10,
3702 // }),
3703 // .data = .{ .imm = @intCast(u32, imm) },
3704 // });
3718 // TODO take into account the type's ABI size when selecting the register alias
3719 // register, immediate
3720 try self.asmRegisterRegisterImmediate(
3721 .imul,
3722 dst_reg.to32(),
3723 dst_reg.to32(),
3724 Immediate.u(@intCast(u32, imm)),
3725 );
37053726 } else {
37063727 // TODO verify we don't spill and assign to the same register as dst_mcv
37073728 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
40344055 const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
40354056 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
40364057 const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;
4037 _ = sym_index;
4038 _ = atom_index;
4039 // _ = try self.addInst(.{
4040 // .tag = .call_extern,
4041 // .ops = undefined,
4042 // .data = .{ .relocation = .{
4043 // .atom_index = atom_index,
4044 // .sym_index = sym_index,
4045 // } },
4046 // });
4058 _ = try self.addInst(.{
4059 .tag = .call_extern,
4060 .ops = undefined,
4061 .data = .{ .relocation = .{
4062 .atom_index = atom_index,
4063 .sym_index = sym_index,
4064 } },
4065 });
40474066 } else {
40484067 return self.fail("TODO implement calling extern functions", .{});
40494068 }
......@@ -5528,7 +5547,6 @@ fn genInlineMemcpy(
55285547 const index_reg = regs[2].to64();
55295548 const count_reg = regs[3].to64();
55305549 const tmp_reg = regs[4].to8();
5531 _ = tmp_reg;
55325550
55335551 switch (dst_ptr) {
55345552 .memory, .linker_load => {
......@@ -5575,7 +5593,6 @@ fn genInlineMemcpy(
55755593 }
55765594
55775595 try self.genSetReg(Type.usize, count_reg, len);
5578
55795596 try self.asmRegisterImmediate(.mov, index_reg, Immediate.u(0));
55805597
55815598 const loop_start = try self.addInst(.{
......@@ -5595,26 +5612,22 @@ fn genInlineMemcpy(
55955612 } },
55965613 });
55975614
5598 // mov tmp, [addr + index_reg]
5599 // _ = try self.addInst(.{
5600 // .tag = .mov_scale_src,
5601 // .ops = Mir.Inst.Ops.encode(.{
5602 // .reg1 = tmp_reg.to8(),
5603 // .reg2 = src_addr_reg,
5604 // }),
5605 // .data = .{ .payload = try self.addExtra(Mir.IndexRegisterDisp.encode(index_reg, 0)) },
5606 // });
5607
5608 // mov [stack_offset + index_reg], tmp
5609 // _ = try self.addInst(.{
5610 // .tag = .mov_scale_dst,
5611 // .ops = Mir.Inst.Ops.encode(.{
5612 // .reg1 = dst_addr_reg,
5613 // .reg2 = tmp_reg.to8(),
5614 // }),
5615 // .data = .{ .payload = try self.addExtra(Mir.IndexRegisterDisp.encode(index_reg, 0)) },
5616 // });
5617
5615 try self.asmRegisterMemory(.mov, tmp_reg.to8(), Memory.sib(.byte, .{
5616 .base = src_addr_reg,
5617 .scale_index = .{
5618 .scale = 1,
5619 .index = index_reg,
5620 },
5621 .disp = 0,
5622 }));
5623 try self.asmMemoryRegister(.mov, Memory.sib(.byte, .{
5624 .base = dst_addr_reg,
5625 .scale_index = .{
5626 .scale = 1,
5627 .index = index_reg,
5628 },
5629 .disp = 0,
5630 }), tmp_reg.to8());
56185631 try self.asmRegisterImmediate(.add, index_reg, Immediate.u(1));
56195632 try self.asmRegisterImmediate(.sub, count_reg, Immediate.u(1));
56205633
......@@ -5655,15 +5668,10 @@ fn genInlineMemset(
56555668 try self.loadMemPtrIntoRegister(addr_reg, Type.usize, dst_ptr);
56565669 },
56575670 .ptr_stack_offset, .stack_offset => |off| {
5658 _ = off;
5659 // _ = try self.addInst(.{
5660 // .tag = .lea,
5661 // .ops = Mir.Inst.Ops.encode(.{
5662 // .reg1 = addr_reg.to64(),
5663 // .reg2 = opts.dest_stack_base orelse .rbp,
5664 // }),
5665 // .data = .{ .disp = -off },
5666 // });
5671 try self.asmRegisterMemory(.lea, addr_reg.to64(), Memory.sib(.qword, .{
5672 .base = opts.dest_stack_base orelse .rbp,
5673 .disp = -off,
5674 }));
56675675 },
56685676 .register => |reg| {
56695677 try self.asmRegisterRegister(
......@@ -5703,18 +5711,14 @@ fn genInlineMemset(
57035711 if (x > math.maxInt(i32)) {
57045712 return self.fail("TODO inline memset for value immediate larger than 32bits", .{});
57055713 }
5706 // mov byte ptr [rbp + index_reg + stack_offset], imm
5707 // _ = try self.addInst(.{
5708 // .tag = .mov_mem_index_imm,
5709 // .ops = Mir.Inst.Ops.encode(.{
5710 // .reg1 = addr_reg,
5711 // }),
5712 // .data = .{ .payload = try self.addExtra(Mir.IndexRegisterDispImm.encode(
5713 // index_reg,
5714 // 0,
5715 // @intCast(u32, x),
5716 // )) },
5717 // });
5714 try self.asmMemoryImmediate(.mov, Memory.sib(.byte, .{
5715 .base = addr_reg,
5716 .scale_index = .{
5717 .scale = 1,
5718 .index = index_reg,
5719 },
5720 .disp = 0,
5721 }), Immediate.u(@intCast(u8, x)));
57185722 },
57195723 else => return self.fail("TODO inline memset for value of type {}", .{value}),
57205724 }
src/arch/x86_64/Emit.zig+109-229
......@@ -120,6 +120,10 @@ pub fn lowerMir(emit: *Emit) InnerError!void {
120120
121121 .jmp_reloc => try emit.mirJmpReloc(inst),
122122
123 .call_extern => try emit.mirCallExtern(inst),
124
125 .lea_linker => try emit.mirLeaLinker(inst),
126
123127 .mov_moffs => try emit.mirMovMoffs(inst),
124128
125129 .movsx => try emit.mirMovsx(inst),
......@@ -213,6 +217,16 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE
213217 .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) },
214218 };
215219 },
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 },
216230 .m_sib => {
217231 const msib = emit.mir.extraData(Mir.MemorySib, data.payload).data;
218232 operands[0] = .{ .mem = Mir.MemorySib.decode(msib) };
......@@ -402,47 +416,44 @@ fn mirJmpReloc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
402416 }
403417}
404418
405// fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
406// const tag = emit.mir.instructions.items(.tag)[inst];
407// assert(tag == .call_extern);
408// const relocation = emit.mir.instructions.items(.data)[inst].relocation;
409
410// const offset = blk: {
411// // callq
412// try emit.encode(.call, .{
413// .op1 = .{ .imm = Immediate.s(0) },
414// });
415// break :blk @intCast(u32, emit.code.items.len) - 4;
416// };
417
418// if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
419// // Add relocation to the decl.
420// const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
421// const target = macho_file.getGlobalByIndex(relocation.sym_index);
422// try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
423// .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
424// .target = target,
425// .offset = offset,
426// .addend = 0,
427// .pcrel = true,
428// .length = 2,
429// });
430// } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
431// // Add relocation to the decl.
432// const atom_index = coff_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
433// const target = coff_file.getGlobalByIndex(relocation.sym_index);
434// try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
435// .type = .direct,
436// .target = target,
437// .offset = offset,
438// .addend = 0,
439// .pcrel = true,
440// .length = 2,
441// });
442// } else {
443// return emit.fail("TODO implement call_extern for linking backends different than MachO and COFF", .{});
444// }
445// }
419fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
420 const relocation = emit.mir.instructions.items(.data)[inst].relocation;
421
422 const offset = blk: {
423 try emit.encode(.call, .{
424 .op1 = .{ .imm = Immediate.s(0) },
425 });
426 break :blk @intCast(u32, emit.code.items.len) - 4;
427 };
428
429 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
430 // Add relocation to the decl.
431 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
432 const target = macho_file.getGlobalByIndex(relocation.sym_index);
433 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
434 .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
435 .target = target,
436 .offset = offset,
437 .addend = 0,
438 .pcrel = true,
439 .length = 2,
440 });
441 } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
442 // Add relocation to the decl.
443 const atom_index = coff_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
444 const target = coff_file.getGlobalByIndex(relocation.sym_index);
445 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
446 .type = .direct,
447 .target = target,
448 .offset = offset,
449 .addend = 0,
450 .pcrel = true,
451 .length = 2,
452 });
453 } else {
454 return emit.fail("TODO implement call_extern for linking backends different than MachO and COFF", .{});
455 }
456}
446457
447458fn mirPushPopRegisterList(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void {
448459 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)
474485 }
475486}
476487
477// fn mirJmpCall(emit: *Emit, mnemonic: Instruction.Mnemonic, inst: Mir.Inst.Index) InnerError!void {
478// const ops = emit.mir.instructions.items(.ops)[inst].decode();
479// switch (ops.flags) {
480// 0b00 => {
481// const target = emit.mir.instructions.items(.data)[inst].inst;
482// const source = emit.code.items.len;
483// try emit.encode(mnemonic, .{
484// .op1 = .{ .imm = Immediate.s(0) },
485// });
486// try emit.relocs.append(emit.bin_file.allocator, .{
487// .source = source,
488// .target = target,
489// .offset = emit.code.items.len - 4,
490// .length = 5,
491// });
492// },
493// 0b01 => {
494// if (ops.reg1 == .none) {
495// const disp = emit.mir.instructions.items(.data)[inst].disp;
496// return emit.encode(mnemonic, .{
497// .op1 = .{ .mem = Memory.sib(.qword, .{ .disp = disp }) },
498// });
499// }
500// return emit.encode(mnemonic, .{
501// .op1 = .{ .reg = ops.reg1 },
502// });
503// },
504// 0b10 => {
505// const disp = emit.mir.instructions.items(.data)[inst].disp;
506// return emit.encode(mnemonic, .{
507// .op1 = .{ .mem = Memory.sib(.qword, .{
508// .base = ops.reg1,
509// .disp = disp,
510// }) },
511// });
512// },
513// 0b11 => return emit.fail("TODO unused variant jmp/call 0b11", .{}),
514// }
515// }
516
517// fn mirLea(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
518// const tag = emit.mir.instructions.items(.tag)[inst];
519// assert(tag == .lea);
520// const ops = emit.mir.instructions.items(.ops)[inst].decode();
521// switch (ops.flags) {
522// 0b00 => {
523// const disp = emit.mir.instructions.items(.data)[inst].disp;
524// const src_reg: ?Register = if (ops.reg2 != .none) ops.reg2 else null;
525// return emit.encode(.lea, .{
526// .op1 = .{ .reg = ops.reg1 },
527// .op2 = .{ .mem = Memory.sib(Memory.PtrSize.fromBitSize(ops.reg1.bitSize()), .{
528// .base = src_reg,
529// .disp = disp,
530// }) },
531// });
532// },
533// 0b01 => {
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// }
488fn mirLeaLinker(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
489 const ops = emit.mir.instructions.items(.ops)[inst];
490 const payload = emit.mir.instructions.items(.data)[inst].payload;
491 const metadata = emit.mir.extraData(Mir.LeaRegisterReloc, payload).data;
492 const reg = @intToEnum(Register, metadata.reg);
493
494 try emit.encode(.lea, .{
495 .op1 = .{ .reg = reg },
496 .op2 = .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },
497 });
498
499 const end_offset = emit.code.items.len;
500
501 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
502 const reloc_type = switch (ops) {
503 .got_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_GOT),
504 .direct_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),
505 else => unreachable,
506 };
507 const atom_index = macho_file.getAtomIndexForSymbol(.{
508 .sym_index = metadata.atom_index,
509 .file = null,
510 }).?;
511 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
512 .type = reloc_type,
513 .target = .{ .sym_index = metadata.sym_index, .file = null },
514 .offset = @intCast(u32, end_offset - 4),
515 .addend = 0,
516 .pcrel = true,
517 .length = 2,
518 });
519 } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
520 const atom_index = coff_file.getAtomIndexForSymbol(.{
521 .sym_index = metadata.atom_index,
522 .file = null,
523 }).?;
524 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
525 .type = switch (ops) {
526 .got_reloc => .got,
527 .direct_reloc => .direct,
528 .import_reloc => .import,
529 else => unreachable,
530 },
531 .target = switch (ops) {
532 .got_reloc, .direct_reloc => .{ .sym_index = metadata.sym_index, .file = null },
533 .import_reloc => coff_file.getGlobalByIndex(metadata.sym_index),
534 else => unreachable,
535 },
536 .offset = @intCast(u32, end_offset - 4),
537 .addend = 0,
538 .pcrel = true,
539 .length = 2,
540 });
541 } else {
542 return emit.fail("TODO implement lea reg, [rip + reloc] for linking backends different than MachO", .{});
543 }
544}
665545
666546fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
667547 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 {
142142 /// Jump with relocation to another local MIR instruction
143143 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
145152 /// End of prologue
146153 dbg_prologue_end,
147154 /// Start of epilogue
......@@ -169,6 +176,12 @@ pub const Inst = struct {
169176 /// Register, register, register operands.
170177 /// Uses `rrr` payload.
171178 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,
172185 /// Register with condition code (CC).
173186 /// Uses `r_c` payload.
174187 r_c,
......@@ -199,12 +212,6 @@ pub const Inst = struct {
199212 /// Register, memory (RIP) operands.
200213 /// Uses `rx` payload.
201214 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,
208215 /// Single memory (SIB) operand.
209216 /// Uses `payload` with extra data of type `MemorySib`.
210217 m_sib,
......@@ -250,6 +257,15 @@ pub const Inst = struct {
250257 rm_cc,
251258 /// Uses `reloc` payload.
252259 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,
253269 };
254270
255271 pub const Data = union {
......@@ -279,6 +295,16 @@ pub const Inst = struct {
279295 r2: Register,
280296 r3: Register,
281297 },
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 },
282308 /// Register with condition code (CC).
283309 r_c: struct {
284310 r1: Register,
......@@ -339,13 +365,7 @@ pub const Inst = struct {
339365
340366pub const LeaRegisterReloc = struct {
341367 /// Destination register.
342 reg: Register,
343 /// Type of the load.
344 load_type: enum(u2) {
345 got,
346 direct,
347 import,
348 },
368 reg: u32,
349369 /// Index of the containing atom.
350370 atom_index: u32,
351371 /// Index into the linker's symbol table.