| ... | ... | @@ -120,6 +120,10 @@ pub fn lowerMir(emit: *Emit) InnerError!void { |
| 120 | 120 | |
| 121 | 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 | 127 | .mov_moffs => try emit.mirMovMoffs(inst), |
| 124 | 128 | |
| 125 | 129 | .movsx => try emit.mirMovsx(inst), |
| ... | ... | @@ -213,6 +217,16 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE |
| 213 | 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 | 230 | .m_sib => { |
| 217 | 231 | const msib = emit.mir.extraData(Mir.MemorySib, data.payload).data; |
| 218 | 232 | operands[0] = .{ .mem = Mir.MemorySib.decode(msib) }; |
| ... | ... | @@ -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 { |
| 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 | | // } |
| 419 | fn 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 | } |
| 446 | 457 | |
| 447 | 458 | fn mirPushPopRegisterList(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void { |
| 448 | 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 | 485 | } |
| 475 | 486 | } |
| 476 | 487 | |
| 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 | | // } |
| 488 | fn 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 | } |
| 665 | 545 | |
| 666 | 546 | fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| 667 | 547 | const payload = emit.mir.instructions.items(.data)[inst].payload; |