diff options
Diffstat (limited to 'llvm/lib')
5 files changed, 70 insertions, 31 deletions
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index baa6f0c432e..34fe3cdc5ba 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -42,6 +42,8 @@ static unsigned getFixupKindLog2Size(unsigned Kind) { return 1; case FK_PCRel_4: case X86::reloc_riprel_4byte: + case X86::reloc_riprel_4byte_relax: + case X86::reloc_riprel_4byte_relax_rex: case X86::reloc_riprel_4byte_movq_load: case X86::reloc_signed_4byte: case X86::reloc_global_offset_table: @@ -88,6 +90,8 @@ public: const static MCFixupKindInfo Infos[X86::NumTargetFixupKinds] = { {"reloc_riprel_4byte", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, {"reloc_riprel_4byte_movq_load", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, + {"reloc_riprel_4byte_relax", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, + {"reloc_riprel_4byte_relax_rex", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, {"reloc_signed_4byte", 0, 32, 0}, {"reloc_global_offset_table", 0, 32, 0}, {"reloc_global_offset_table8", 0, 64, 0}, diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp index 6fa479e4d7e..e5084f90f98 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp @@ -68,6 +68,8 @@ static X86_64RelType getType64(unsigned Kind, case FK_Data_4: case FK_PCRel_4: case X86::reloc_riprel_4byte: + case X86::reloc_riprel_4byte_relax: + case X86::reloc_riprel_4byte_relax_rex: case X86::reloc_riprel_4byte_movq_load: return RT64_32; case FK_PCRel_2: @@ -182,8 +184,9 @@ static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc, switch (Kind) { default: return ELF::R_X86_64_GOTPCREL; - case X86::reloc_riprel_4byte: + case X86::reloc_riprel_4byte_relax: return ELF::R_X86_64_GOTPCRELX; + case X86::reloc_riprel_4byte_relax_rex: case X86::reloc_riprel_4byte_movq_load: return ELF::R_X86_64_REX_GOTPCRELX; } diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86FixupKinds.h b/llvm/lib/Target/X86/MCTargetDesc/X86FixupKinds.h index 4899900dcef..417e04a5d94 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86FixupKinds.h +++ b/llvm/lib/Target/X86/MCTargetDesc/X86FixupKinds.h @@ -17,6 +17,10 @@ namespace X86 { enum Fixups { reloc_riprel_4byte = FirstTargetFixupKind, // 32-bit rip-relative reloc_riprel_4byte_movq_load, // 32-bit rip-relative in movq + reloc_riprel_4byte_relax, // 32-bit rip-relative in relaxable + // instruction + reloc_riprel_4byte_relax_rex, // 32-bit rip-relative in relaxable + // instruction with rex prefix reloc_signed_4byte, // 32-bit signed. Unlike FK_Data_4 // this will be sign extended at // runtime. diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index d06d1a6caf8..682213908bc 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -122,11 +122,9 @@ public: EmitByte(ModRMByte(SS, Index, Base), CurByte, OS); } - - void EmitMemModRMByte(const MCInst &MI, unsigned Op, - unsigned RegOpcodeField, - uint64_t TSFlags, unsigned &CurByte, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups, + void emitMemModRMByte(const MCInst &MI, unsigned Op, unsigned RegOpcodeField, + uint64_t TSFlags, bool Rex, unsigned &CurByte, + raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; void encodeInstruction(const MCInst &MI, raw_ostream &OS, @@ -140,10 +138,9 @@ public: void EmitSegmentOverridePrefix(unsigned &CurByte, unsigned SegOperand, const MCInst &MI, raw_ostream &OS) const; - void EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, + bool emitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, const MCInstrDesc &Desc, - const MCSubtargetInfo &STI, - raw_ostream &OS) const; + const MCSubtargetInfo &STI, raw_ostream &OS) const; uint8_t DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, int MemOperand, const MCInstrDesc &Desc) const; @@ -330,7 +327,9 @@ EmitImmediate(const MCOperand &DispOp, SMLoc Loc, unsigned Size, // the start of the field, not the end of the field. if (FixupKind == FK_PCRel_4 || FixupKind == MCFixupKind(X86::reloc_riprel_4byte) || - FixupKind == MCFixupKind(X86::reloc_riprel_4byte_movq_load)) + FixupKind == MCFixupKind(X86::reloc_riprel_4byte_movq_load) || + FixupKind == MCFixupKind(X86::reloc_riprel_4byte_relax) || + FixupKind == MCFixupKind(X86::reloc_riprel_4byte_relax_rex)) ImmOffset -= 4; if (FixupKind == FK_PCRel_2) ImmOffset -= 2; @@ -346,12 +345,12 @@ EmitImmediate(const MCOperand &DispOp, SMLoc Loc, unsigned Size, EmitConstant(0, Size, CurByte, OS); } -void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op, +void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, unsigned RegOpcodeField, - uint64_t TSFlags, unsigned &CurByte, - raw_ostream &OS, + uint64_t TSFlags, bool Rex, + unsigned &CurByte, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const{ + const MCSubtargetInfo &STI) const { const MCOperand &Disp = MI.getOperand(Op+X86::AddrDisp); const MCOperand &Base = MI.getOperand(Op+X86::AddrBaseReg); const MCOperand &Scale = MI.getOperand(Op+X86::AddrScaleAmt); @@ -366,13 +365,32 @@ void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op, assert(IndexReg.getReg() == 0 && "Invalid rip-relative address"); EmitByte(ModRMByte(0, RegOpcodeField, 5), CurByte, OS); - unsigned FixupKind = X86::reloc_riprel_4byte; - + unsigned Opcode = MI.getOpcode(); // movq loads are handled with a special relocation form which allows the // linker to eliminate some loads for GOT references which end up in the // same linkage unit. - if (MI.getOpcode() == X86::MOV64rm) - FixupKind = X86::reloc_riprel_4byte_movq_load; + unsigned FixupKind = [=]() { + switch (Opcode) { + default: + return X86::reloc_riprel_4byte; + case X86::MOV64rm: + assert(Rex); + return X86::reloc_riprel_4byte_movq_load; + case X86::CALL64m: + case X86::JMP64m: + case X86::TEST64rm: + case X86::ADC64rm: + case X86::ADD64rm: + case X86::AND64rm: + case X86::CMP64rm: + case X86::OR64rm: + case X86::SBB64rm: + case X86::SUB64rm: + case X86::XOR64rm: + return Rex ? X86::reloc_riprel_4byte_relax_rex + : X86::reloc_riprel_4byte_relax; + } + }(); // rip-relative addressing is actually relative to the *next* instruction. // Since an immediate can follow the mod/rm byte for an instruction, this @@ -1027,16 +1045,18 @@ void X86MCCodeEmitter::EmitSegmentOverridePrefix(unsigned &CurByte, } } -/// EmitOpcodePrefix - Emit all instruction prefixes prior to the opcode. +/// Emit all instruction prefixes prior to the opcode. /// /// MemOperand is the operand # of the start of a memory operand if present. If /// Not present, it is -1. -void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, +/// +/// Returns true if a REX prefix was used. +bool X86MCCodeEmitter::emitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, const MCInstrDesc &Desc, const MCSubtargetInfo &STI, raw_ostream &OS) const { - + bool Ret = false; // Emit the operand size opcode prefix as needed. if ((TSFlags & X86II::OpSizeMask) == (is16BitMode(STI) ? X86II::OpSize32 : X86II::OpSize16)) @@ -1061,8 +1081,10 @@ void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // Handle REX prefix. // FIXME: Can this come before F2 etc to simplify emission? if (is64BitMode(STI)) { - if (uint8_t REX = DetermineREXPrefix(MI, TSFlags, MemOperand, Desc)) + if (uint8_t REX = DetermineREXPrefix(MI, TSFlags, MemOperand, Desc)) { EmitByte(0x40 | REX, CurByte, OS); + Ret = true; + } } // 0x0F escape code must be emitted just before the opcode. @@ -1082,6 +1104,7 @@ void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, EmitByte(0x3A, CurByte, OS); break; } + return Ret; } void X86MCCodeEmitter:: @@ -1156,8 +1179,9 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, if (need_address_override) EmitByte(0x67, CurByte, OS); + bool Rex = false; if (Encoding == 0) - EmitOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, STI, OS); + Rex = emitOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, STI, OS); else EmitVEXOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, OS); @@ -1270,9 +1294,8 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV) ++SrcRegNum; - EmitMemModRMByte(MI, CurOp, - GetX86RegNum(MI.getOperand(SrcRegNum)), - TSFlags, CurByte, OS, Fixups, STI); + emitMemModRMByte(MI, CurOp, GetX86RegNum(MI.getOperand(SrcRegNum)), TSFlags, + Rex, CurByte, OS, Fixups, STI); CurOp = SrcRegNum + 1; break; } @@ -1315,8 +1338,8 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, EmitByte(BaseOpcode, CurByte, OS); - EmitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)), - TSFlags, CurByte, OS, Fixups, STI); + emitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)), + TSFlags, Rex, CurByte, OS, Fixups, STI); CurOp = FirstMemOp + X86::AddrNumOperands; if (HasVEX_4VOp3) ++CurOp; @@ -1351,8 +1374,9 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, if (HasEVEX_K) // Skip writemask ++CurOp; EmitByte(BaseOpcode, CurByte, OS); - EmitMemModRMByte(MI, CurOp, (Form == X86II::MRMXm) ? 0 : Form-X86II::MRM0m, - TSFlags, CurByte, OS, Fixups, STI); + emitMemModRMByte(MI, CurOp, + (Form == X86II::MRMXm) ? 0 : Form - X86II::MRM0m, TSFlags, + Rex, CurByte, OS, Fixups, STI); CurOp += X86::AddrNumOperands; break; } diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp index 191ebeac726..c098edec589 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp @@ -73,7 +73,9 @@ public: static bool isFixupKindRIPRel(unsigned Kind) { return Kind == X86::reloc_riprel_4byte || - Kind == X86::reloc_riprel_4byte_movq_load; + Kind == X86::reloc_riprel_4byte_movq_load || + Kind == X86::reloc_riprel_4byte_relax || + Kind == X86::reloc_riprel_4byte_relax_rex; } static unsigned getFixupKindLog2Size(unsigned Kind) { @@ -87,6 +89,8 @@ static unsigned getFixupKindLog2Size(unsigned Kind) { case FK_PCRel_4: // FIXME: Remove these!!! case X86::reloc_riprel_4byte: + case X86::reloc_riprel_4byte_relax: + case X86::reloc_riprel_4byte_relax_rex: case X86::reloc_riprel_4byte_movq_load: case X86::reloc_signed_4byte: case FK_Data_4: return 2; |