| author | |
| committer | |
| log | d0e72125396c391172758d28c21a9b901dcecc68 |
| tree | 9c69c3ce6a51d6da54e9faee744e147ea3d7104f |
| parent | 022b308d6a0a3d3cf178ddc6e887f24369f69deb |
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 | } |
| 493 | 493 | ||
| 494 | fn 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 | |||
| 494 | fn asmMemory(self: *Self, tag: Mir.Inst.Tag, m: Memory) !void { | 525 | fn 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_mcv | 3727 | // 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; | ||
| 5532 | 5550 | ||
| 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 | } |
| 5576 | 5594 | ||
| 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)); |
| 5580 | 5597 | ||
| 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 | }); |
| 5597 | 5614 | ||
| 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, .{ |
| 5607 | 5624 | .base = dst_addr_reg, | |
| 5608 | // mov [stack_offset + index_reg], tmp | 5625 | .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)); |
| 5620 | 5633 | ||
| ... | @@ -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], imm | 5714 | 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 { |
| 120 | 120 | ||
| 121 | .jmp_reloc => try emit.mirJmpReloc(inst), | 121 | .jmp_reloc => try emit.mirJmpReloc(inst), |
| 122 | 122 | ||
| 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), |
| 124 | 128 | ||
| 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 | } |
| 404 | 418 | ||
| 405 | // fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | 419 | fn 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: { |
| 409 | 423 | try emit.encode(.call, .{ | |
| 410 | // const offset = blk: { | 424 | .op1 = .{ .imm = Immediate.s(0) }, |
| 411 | // // callq | 425 | }); |
| 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. |
| 417 | 431 | 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 | // } | ||
| 446 | 457 | ||
| 447 | fn mirPushPopRegisterList(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void { | 458 | fn 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 | } |
| 476 | 487 | ||
| 477 | // fn mirJmpCall(emit: *Emit, mnemonic: Instruction.Mnemonic, inst: Mir.Inst.Index) InnerError!void { | 488 | fn 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, |
| 516 | 527 | .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 | // } | ||
| 665 | 545 | ||
| 666 | fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | 546 | fn 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 instruction | 142 | /// Jump with relocation to another local MIR instruction |
| 143 | jmp_reloc, | 143 | jmp_reloc, |
| 144 | 144 | ||
| 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 prologue | 152 | /// End of prologue |
| 146 | dbg_prologue_end, | 153 | dbg_prologue_end, |
| 147 | /// Start of epilogue | 154 | /// 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 | }; |
| 254 | 270 | ||
| 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 { |
| 339 | 365 | ||
| 340 | pub const LeaRegisterReloc = struct { | 366 | pub 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. |