[llvm] r249164 - ARM: diagnose invalid local fixups on Thumb1

Tim Northover via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 2 11:07:19 PDT 2015


Author: tnorthover
Date: Fri Oct  2 13:07:18 2015
New Revision: 249164

URL: http://llvm.org/viewvc/llvm-project?rev=249164&view=rev
Log:
ARM: diagnose invalid local fixups on Thumb1

We previously stopped producing Thumb2 relaxations when they weren't supported,
but only diagnosed the case where an actual relocation was produced. We should
also tell people if local symbols aren't going to work rather than silently
overflowing.

Added:
    llvm/trunk/test/MC/ARM/thumb1-relax-adr-local.s
    llvm/trunk/test/MC/ARM/thumb1-relax-bcc-local.s
    llvm/trunk/test/MC/ARM/thumb1-relax-br-local.s
    llvm/trunk/test/MC/ARM/thumb1-relax-ldrlit-local-behind.s
    llvm/trunk/test/MC/ARM/thumb1-relax-ldrlit-local-misaligned.s
    llvm/trunk/test/MC/ARM/thumb1-relax-ldrlit-local-range.s
Modified:
    llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
    llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h
    llvm/trunk/test/MC/ARM/big-endian-thumb2-fixup.s

Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp?rev=249164&r1=249163&r2=249164&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp (original)
+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp Fri Oct  2 13:07:18 2015
@@ -181,9 +181,8 @@ bool ARMAsmBackend::mayNeedRelaxation(co
   return false;
 }
 
-bool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
-                                         const MCRelaxableFragment *DF,
-                                         const MCAsmLayout &Layout) const {
+const char *ARMAsmBackend::reasonForFixupRelaxation(const MCFixup &Fixup,
+                                                    uint64_t Value) const {
   switch ((unsigned)Fixup.getKind()) {
   case ARM::fixup_arm_thumb_br: {
     // Relaxing tB to t2B. tB has a signed 12-bit displacement with the
@@ -193,7 +192,9 @@ bool ARMAsmBackend::fixupNeedsRelaxation
     //
     // Relax if the value is too big for a (signed) i8.
     int64_t Offset = int64_t(Value) - 4;
-    return Offset > 2046 || Offset < -2048;
+    if (Offset > 2046 || Offset < -2048)
+      return "out of range pc-relative fixup value";
+    break;
   }
   case ARM::fixup_arm_thumb_bcc: {
     // Relaxing tBcc to t2Bcc. tBcc has a signed 9-bit displacement with the
@@ -203,23 +204,40 @@ bool ARMAsmBackend::fixupNeedsRelaxation
     //
     // Relax if the value is too big for a (signed) i8.
     int64_t Offset = int64_t(Value) - 4;
-    return Offset > 254 || Offset < -256;
+    if (Offset > 254 || Offset < -256)
+      return "out of range pc-relative fixup value";
+    break;
   }
   case ARM::fixup_thumb_adr_pcrel_10:
   case ARM::fixup_arm_thumb_cp: {
     // If the immediate is negative, greater than 1020, or not a multiple
     // of four, the wide version of the instruction must be used.
     int64_t Offset = int64_t(Value) - 4;
-    return Offset > 1020 || Offset < 0 || Offset & 3;
+    if (Offset & 3)
+      return "misaligned pc-relative fixup value";
+    else if (Offset > 1020 || Offset < 0)
+      return "out of range pc-relative fixup value";
+    break;
   }
-  case ARM::fixup_arm_thumb_cb:
+  case ARM::fixup_arm_thumb_cb: {
     // If we have a Thumb CBZ or CBNZ instruction and its target is the next
     // instruction it is is actually out of range for the instruction.
     // It will be changed to a NOP.
     int64_t Offset = (Value & ~1);
-    return Offset == 2;
+    if (Offset == 2)
+      return "will be converted to nop";
+    break;
   }
-  llvm_unreachable("Unexpected fixup kind in fixupNeedsRelaxation()!");
+  default:
+    llvm_unreachable("Unexpected fixup kind in reasonForFixupRelaxation()!");
+  }
+  return nullptr;
+}
+
+bool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
+                                         const MCRelaxableFragment *DF,
+                                         const MCAsmLayout &Layout) const {
+  return reasonForFixupRelaxation(Fixup, Value);
 }
 
 void ARMAsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const {
@@ -318,9 +336,10 @@ static uint32_t joinHalfWords(uint32_t F
   return Value;
 }
 
-static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
-                                 bool IsPCRel, MCContext *Ctx,
-                                 bool IsLittleEndian) {
+unsigned ARMAsmBackend::adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
+                                         bool IsPCRel, MCContext *Ctx,
+                                         bool IsLittleEndian,
+                                         bool IsResolved) const {
   unsigned Kind = Fixup.getKind();
   switch (Kind) {
   default:
@@ -384,8 +403,6 @@ static unsigned adjustFixupValue(const M
 
     return Value;
   }
-  case ARM::fixup_thumb_adr_pcrel_10:
-    return ((Value - 4) >> 2) & 0xff;
   case ARM::fixup_arm_adr_pcrel_12: {
     // ARM PC-relative values are offset by 8.
     Value -= 8;
@@ -518,21 +535,38 @@ static unsigned adjustFixupValue(const M
                            ((uint16_t)imm10LBits) << 1);
     return joinHalfWords(FirstHalf, SecondHalf, IsLittleEndian);
   }
+  case ARM::fixup_thumb_adr_pcrel_10:
   case ARM::fixup_arm_thumb_cp:
-    // Offset by 4, and don't encode the low two bits. Two bytes of that
-    // 'off by 4' is implicitly handled by the half-word ordering of the
-    // Thumb encoding, so we only need to adjust by 2 here.
-    return ((Value - 2) >> 2) & 0xff;
+    // On CPUs supporting Thumb2, this will be relaxed to an ldr.w, otherwise we
+    // could have an error on our hands.
+    if (Ctx && !STI->getFeatureBits()[ARM::FeatureThumb2] && IsResolved) {
+      const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
+      if (FixupDiagnostic)
+        Ctx->reportFatalError(Fixup.getLoc(), FixupDiagnostic);
+    }
+    // Offset by 4, and don't encode the low two bits.
+    return ((Value - 4) >> 2) & 0xff;
   case ARM::fixup_arm_thumb_cb: {
     // Offset by 4 and don't encode the lower bit, which is always 0.
+    // FIXME: diagnose if no Thumb2
     uint32_t Binary = (Value - 4) >> 1;
     return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3);
   }
   case ARM::fixup_arm_thumb_br:
     // Offset by 4 and don't encode the lower bit, which is always 0.
+    if (Ctx && !STI->getFeatureBits()[ARM::FeatureThumb2]) {
+      const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
+      if (FixupDiagnostic)
+        Ctx->reportFatalError(Fixup.getLoc(), FixupDiagnostic);
+    }
     return ((Value - 4) >> 1) & 0x7ff;
   case ARM::fixup_arm_thumb_bcc:
     // Offset by 4 and don't encode the lower bit, which is always 0.
+    if (Ctx && !STI->getFeatureBits()[ARM::FeatureThumb2]) {
+      const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
+      if (FixupDiagnostic)
+        Ctx->reportFatalError(Fixup.getLoc(), FixupDiagnostic);
+    }
     return ((Value - 4) >> 1) & 0xff;
   case ARM::fixup_arm_pcrel_10_unscaled: {
     Value = Value - 8; // ARM fixups offset by an additional word and don't
@@ -617,7 +651,7 @@ void ARMAsmBackend::processFixupValue(co
   // the instruction. This allows adjustFixupValue() to issue a diagnostic
   // if the value aren't invalid.
   (void)adjustFixupValue(Fixup, Value, false, &Asm.getContext(),
-                         IsLittleEndian);
+                         IsLittleEndian, IsResolved);
 }
 
 /// getFixupKindNumBytes - The number of bytes the fixup may change.
@@ -720,7 +754,8 @@ void ARMAsmBackend::applyFixup(const MCF
                                unsigned DataSize, uint64_t Value,
                                bool IsPCRel) const {
   unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
-  Value = adjustFixupValue(Fixup, Value, IsPCRel, nullptr, IsLittleEndian);
+  Value =
+      adjustFixupValue(Fixup, Value, IsPCRel, nullptr, IsLittleEndian, true);
   if (!Value)
     return; // Doesn't change encoding.
 

Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h?rev=249164&r1=249163&r2=249164&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h (original)
+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h Fri Oct  2 13:07:18 2015
@@ -45,6 +45,10 @@ public:
                          const MCValue &Target, uint64_t &Value,
                          bool &IsResolved) override;
 
+  unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, bool IsPCRel,
+                            MCContext *Ctx, bool IsLittleEndian,
+                            bool IsResolved) const;
+
   void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
                   uint64_t Value, bool IsPCRel) const override;
 
@@ -52,6 +56,9 @@ public:
 
   bool mayNeedRelaxation(const MCInst &Inst) const override;
 
+  const char *reasonForFixupRelaxation(const MCFixup &Fixup,
+                                       uint64_t Value) const;
+
   bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
                             const MCRelaxableFragment *DF,
                             const MCAsmLayout &Layout) const override;

Modified: llvm/trunk/test/MC/ARM/big-endian-thumb2-fixup.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/big-endian-thumb2-fixup.s?rev=249164&r1=249163&r2=249164&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/big-endian-thumb2-fixup.s (original)
+++ llvm/trunk/test/MC/ARM/big-endian-thumb2-fixup.s Fri Oct  2 13:07:18 2015
@@ -35,14 +35,14 @@ cond_label:
 
 @ARM::fixup_t2_ldst_precel_12
 .section s_ldst_precel_12,"ax",%progbits
- 	ldr r0, ldst_precel_12_label
+ 	ldr.w r0, ldst_precel_12_label
 	nop
 	nop
 ldst_precel_12_label:
 
 @ARM::fixup_t2_adr_pcrel_12
 .section s_adr_pcrel_12,"ax",%progbits
- 	adr r0, adr_pcrel_12_label
+ 	adr.w r0, adr_pcrel_12_label
 	nop
 	nop
 adr_pcrel_12_label:

Added: llvm/trunk/test/MC/ARM/thumb1-relax-adr-local.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/thumb1-relax-adr-local.s?rev=249164&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/thumb1-relax-adr-local.s (added)
+++ llvm/trunk/test/MC/ARM/thumb1-relax-adr-local.s Fri Oct  2 13:07:18 2015
@@ -0,0 +1,9 @@
+@ RUN: not llvm-mc -triple thumbv6m-none-macho -filetype=obj -o /dev/null %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
+
+        .global func1
+        adr r0, Lmisaligned
+Lmisaligned:
+        .word 42
+
+@ CHECK-ERROR: misaligned pc-relative fixup value
+

Added: llvm/trunk/test/MC/ARM/thumb1-relax-bcc-local.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/thumb1-relax-bcc-local.s?rev=249164&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/thumb1-relax-bcc-local.s (added)
+++ llvm/trunk/test/MC/ARM/thumb1-relax-bcc-local.s Fri Oct  2 13:07:18 2015
@@ -0,0 +1,6 @@
+@ RUN: not llvm-mc -triple thumbv6m-none-macho -filetype=obj -o /dev/null %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
+
+        bne Lfar
+        .space 258
+Lfar:
+@ CHECK-ERROR: out of range pc-relative fixup value

Added: llvm/trunk/test/MC/ARM/thumb1-relax-br-local.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/thumb1-relax-br-local.s?rev=249164&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/thumb1-relax-br-local.s (added)
+++ llvm/trunk/test/MC/ARM/thumb1-relax-br-local.s Fri Oct  2 13:07:18 2015
@@ -0,0 +1,8 @@
+@ RUN: not llvm-mc -triple thumbv6m-none-macho -filetype=obj -o /dev/null %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
+
+        b Lfar
+        .space 2050
+
+Lfar:
+
+@ CHECK-ERROR: out of range pc-relative fixup value

Added: llvm/trunk/test/MC/ARM/thumb1-relax-ldrlit-local-behind.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/thumb1-relax-ldrlit-local-behind.s?rev=249164&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/thumb1-relax-ldrlit-local-behind.s (added)
+++ llvm/trunk/test/MC/ARM/thumb1-relax-ldrlit-local-behind.s Fri Oct  2 13:07:18 2015
@@ -0,0 +1,7 @@
+@ RUN: not llvm-mc -triple thumbv6m-none-macho -filetype=obj -o /dev/null %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
+
+Lhere:
+        ldr r0, Lhere
+
+@ CHECK-ERROR: out of range pc-relative fixup value
+

Added: llvm/trunk/test/MC/ARM/thumb1-relax-ldrlit-local-misaligned.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/thumb1-relax-ldrlit-local-misaligned.s?rev=249164&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/thumb1-relax-ldrlit-local-misaligned.s (added)
+++ llvm/trunk/test/MC/ARM/thumb1-relax-ldrlit-local-misaligned.s Fri Oct  2 13:07:18 2015
@@ -0,0 +1,10 @@
+@ RUN: not llvm-mc -triple thumbv6m-none-macho -filetype=obj -o /dev/null %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
+
+        .global func1
+_func1:
+        ldr r0, L_misaligned
+L_misaligned:
+        .word 42
+
+@ CHECK-ERROR: misaligned pc-relative fixup value
+

Added: llvm/trunk/test/MC/ARM/thumb1-relax-ldrlit-local-range.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/thumb1-relax-ldrlit-local-range.s?rev=249164&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/thumb1-relax-ldrlit-local-range.s (added)
+++ llvm/trunk/test/MC/ARM/thumb1-relax-ldrlit-local-range.s Fri Oct  2 13:07:18 2015
@@ -0,0 +1,13 @@
+@ RUN: not llvm-mc -triple thumbv6m-none-macho -filetype=obj -o /dev/null %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
+
+        .global func1
+_func1:
+        ldr r0, L_far
+        .space 1024
+
+        .p2align 2
+L_far:
+        .word 42
+
+@ CHECK-ERROR: out of range pc-relative fixup value
+




More information about the llvm-commits mailing list