[llvm] r271118 - Fix production of R_X86_64_GOTPCRELX/R_X86_64_REX_GOTPCRELX.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Sat May 28 08:51:40 PDT 2016


Author: rafael
Date: Sat May 28 10:51:38 2016
New Revision: 271118

URL: http://llvm.org/viewvc/llvm-project?rev=271118&view=rev
Log:
Fix production of R_X86_64_GOTPCRELX/R_X86_64_REX_GOTPCRELX.

We were producing R_X86_64_GOTPCRELX for invalid instructions and
sometimes producing R_X86_64_GOTPCRELX instead of
R_X86_64_REX_GOTPCRELX.

Added:
    llvm/trunk/test/MC/ELF/got-relaxed-no-relax.s
    llvm/trunk/test/MC/ELF/got-relaxed-rex.s
Modified:
    llvm/trunk/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
    llvm/trunk/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
    llvm/trunk/lib/Target/X86/MCTargetDesc/X86FixupKinds.h
    llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
    llvm/trunk/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
    llvm/trunk/test/MC/ELF/got-relaxed.s

Modified: llvm/trunk/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp?rev=271118&r1=271117&r2=271118&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp (original)
+++ llvm/trunk/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp Sat May 28 10:51:38 2016
@@ -42,6 +42,8 @@ static unsigned getFixupKindLog2Size(uns
     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},

Modified: llvm/trunk/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp?rev=271118&r1=271117&r2=271118&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp (original)
+++ llvm/trunk/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp Sat May 28 10:51:38 2016
@@ -68,6 +68,8 @@ static X86_64RelType getType64(unsigned
   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
     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;
     }

Modified: llvm/trunk/lib/Target/X86/MCTargetDesc/X86FixupKinds.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86FixupKinds.h?rev=271118&r1=271117&r2=271118&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/MCTargetDesc/X86FixupKinds.h (original)
+++ llvm/trunk/lib/Target/X86/MCTargetDesc/X86FixupKinds.h Sat May 28 10:51:38 2016
@@ -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.

Modified: llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp?rev=271118&r1=271117&r2=271118&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp Sat May 28 10:51:38 2016
@@ -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, S
   // 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, S
   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(
     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::EmitSegmentOverri
   }
 }
 
-/// 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(
   // 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(
     EmitByte(0x3A, CurByte, OS);
     break;
   }
+  return Ret;
 }
 
 void X86MCCodeEmitter::
@@ -1156,8 +1179,9 @@ encodeInstruction(const MCInst &MI, raw_
   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_
     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_
 
     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_
     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;
   }

Modified: llvm/trunk/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp?rev=271118&r1=271117&r2=271118&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp (original)
+++ llvm/trunk/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp Sat May 28 10:51:38 2016
@@ -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(uns
   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;

Added: llvm/trunk/test/MC/ELF/got-relaxed-no-relax.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ELF/got-relaxed-no-relax.s?rev=271118&view=auto
==============================================================================
--- llvm/trunk/test/MC/ELF/got-relaxed-no-relax.s (added)
+++ llvm/trunk/test/MC/ELF/got-relaxed-no-relax.s Sat May 28 10:51:38 2016
@@ -0,0 +1,15 @@
+// RUN: llvm-mc -filetype=obj -relax-relocations -triple x86_64-pc-linux %s -o - | llvm-readobj -r | FileCheck %s
+
+// these should not produce relaxable relocations
+
+        movq foo at GOT, %rax
+        mulq foo at GOTPCREL(%rip)
+        .long foo at GOTPCREL
+
+// CHECK:      Relocations [
+// CHECK:        Section ({{.*}}) .rela.text {
+// CHECK-NEXT:     R_X86_64_GOT32 foo
+// CHECK-NEXT:     R_X86_64_GOTPCREL foo
+// CHECK-NEXT:     R_X86_64_GOTPCREL foo
+// CHECK-NEXT:   }
+// CHECK-NEXT: ]

Added: llvm/trunk/test/MC/ELF/got-relaxed-rex.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ELF/got-relaxed-rex.s?rev=271118&view=auto
==============================================================================
--- llvm/trunk/test/MC/ELF/got-relaxed-rex.s (added)
+++ llvm/trunk/test/MC/ELF/got-relaxed-rex.s Sat May 28 10:51:38 2016
@@ -0,0 +1,29 @@
+// RUN: llvm-mc -filetype=obj -relax-relocations -triple x86_64-pc-linux %s -o - | llvm-readobj -r | FileCheck %s
+
+// these should produce R_X86_64_REX_GOTPCRELX
+
+        movq mov at GOTPCREL(%rip), %rax
+        test %rax, test at GOTPCREL(%rip)
+        adc adc at GOTPCREL(%rip), %rax
+        add add at GOTPCREL(%rip), %rax
+        and and at GOTPCREL(%rip), %rax
+        cmp cmp at GOTPCREL(%rip), %rax
+        or  or at GOTPCREL(%rip), %rax
+        sbb sbb at GOTPCREL(%rip), %rax
+        sub sub at GOTPCREL(%rip), %rax
+        xor xor at GOTPCREL(%rip), %rax
+
+// CHECK:      Relocations [
+// CHECK-NEXT:   Section ({{.*}}) .rela.text {
+// CHECK-NEXT:     R_X86_64_REX_GOTPCRELX mov
+// CHECK-NEXT:     R_X86_64_REX_GOTPCRELX test
+// CHECK-NEXT:     R_X86_64_REX_GOTPCRELX adc
+// CHECK-NEXT:     R_X86_64_REX_GOTPCRELX add
+// CHECK-NEXT:     R_X86_64_REX_GOTPCRELX and
+// CHECK-NEXT:     R_X86_64_REX_GOTPCRELX cmp
+// CHECK-NEXT:     R_X86_64_REX_GOTPCRELX or
+// CHECK-NEXT:     R_X86_64_REX_GOTPCRELX sbb
+// CHECK-NEXT:     R_X86_64_REX_GOTPCRELX sub
+// CHECK-NEXT:     R_X86_64_REX_GOTPCRELX xor
+// CHECK-NEXT:   }
+// CHECK-NEXT: ]

Modified: llvm/trunk/test/MC/ELF/got-relaxed.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ELF/got-relaxed.s?rev=271118&r1=271117&r2=271118&view=diff
==============================================================================
--- llvm/trunk/test/MC/ELF/got-relaxed.s (original)
+++ llvm/trunk/test/MC/ELF/got-relaxed.s Sat May 28 10:51:38 2016
@@ -1,20 +1,13 @@
-// RUN: llvm-mc -filetype=obj -relax-relocations -triple x86_64-pc-linux-gnu %s -o - | llvm-readobj -r -t | FileCheck %s
+// RUN: llvm-mc -filetype=obj -relax-relocations -triple x86_64-pc-linux %s -o - | llvm-readobj -r | FileCheck %s
 
-// Test that this produces the correct relaxed relocations.
+// these should produce R_X86_64_GOTPCRELX
 
-        movl	foo at GOT, %eax
-        movl	foo at GOTPCREL(%rip), %eax
-        movq  foo at GOTPCREL(%rip), %rax
-        .long zed at GOTPCREL
+        call *call at GOTPCREL(%rip)
+        jmp *jmp at GOTPCREL(%rip)
 
 // CHECK:      Relocations [
-// CHECK:        Section ({{[^ ]+}}) .rela.text {
-// CHECK-NEXT:       0x{{[^ ]+}} R_X86_64_GOT32 foo 0x{{[^ ]+}}
-// CHECK-NEXT:       0x{{[^ ]+}} R_X86_64_GOTPCRELX foo 0x{{[^ ]+}}
-// CHECK-NEXT:       0x{{[^ ]+}} R_X86_64_REX_GOTPCRELX foo 0x{{[^ ]+}}
-// CHECK-NEXT:       0x{{[^ ]+}} R_X86_64_GOTPCREL zed 0x{{[^ ]+}}
+// CHECK-NEXT:   Section ({{.*}}) .rela.text {
+// CHECK-NEXT:     R_X86_64_GOTPCRELX call
+// CHECK-NEXT:     R_X86_64_GOTPCRELX jmp
 // CHECK-NEXT:   }
 // CHECK-NEXT: ]
-
-// CHECK:        Symbols [
-// CHECK-NOT:          _GLOBAL_OFFSET_TABLE_




More information about the llvm-commits mailing list