Thumb2 relaxation for LDR(literal).
authorJim Grosbach <grosbach@apple.com>
Wed, 18 Jan 2012 21:54:16 +0000 (21:54 +0000)
committerJim Grosbach <grosbach@apple.com>
Wed, 18 Jan 2012 21:54:16 +0000 (21:54 +0000)
If the fixup is out of range for the Thumb1 instruction, relax it
to the Thumb2 encoding instead.

rdar://10711829

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@148424 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
test/MC/MachO/ARM/relax-thumb-ldr-literal.s [new file with mode: 0644]

index d24265a817c75b915553850831595ce402d27d50..adedc208d0e622abbee01285479bce99e27e831d 100644 (file)
@@ -152,7 +152,8 @@ public:
 static unsigned getRelaxedOpcode(unsigned Op) {
   switch (Op) {
   default: return Op;
-  case ARM::tBcc: return ARM::t2Bcc;
+  case ARM::tBcc:       return ARM::t2Bcc;
+  case ARM::tLDRpciASM: return ARM::t2LDRpci;
   }
 }
 
@@ -166,14 +167,24 @@ bool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
                                          uint64_t Value,
                                          const MCInstFragment *DF,
                                          const MCAsmLayout &Layout) const {
-  // Relaxing tBcc to t2Bcc. tBcc has a signed 9-bit displacement with the
-  // low bit being an implied zero. There's an implied +4 offset for the
-  // branch, so we adjust the other way here to determine what's
-  // encodable.
-  //
-  // Relax if the value is too big for a (signed) i8.
-  int64_t Offset = int64_t(Value) - 4;
-  return Offset > 254 || Offset < -256;
+  switch (Fixup.getKind()) {
+  default: assert(0 && "Unexpected fixup kind in fixupNeedsRelaxation()!");
+  case ARM::fixup_arm_thumb_bcc: {
+    // Relaxing tBcc to t2Bcc. tBcc has a signed 9-bit displacement with the
+    // low bit being an implied zero. There's an implied +4 offset for the
+    // branch, so we adjust the other way here to determine what's
+    // encodable.
+    //
+    // Relax if the value is too big for a (signed) i8.
+    int64_t Offset = int64_t(Value) - 4;
+    return Offset > 254 || Offset < -256;
+  }
+  case ARM::fixup_arm_thumb_cp: {
+    int64_t Offset = int64_t(Value) - 4;
+    return Offset > 4095 || Offset < 0;
+  }
+  }
+  llvm_unreachable("Invalid switch/cash!?");
 }
 
 void ARMAsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const {
diff --git a/test/MC/MachO/ARM/relax-thumb-ldr-literal.s b/test/MC/MachO/ARM/relax-thumb-ldr-literal.s
new file mode 100644 (file)
index 0000000..8d26f6d
--- /dev/null
@@ -0,0 +1,13 @@
+@ RUN: llvm-mc -n -triple thumbv7-apple-darwin10 %s -filetype=obj -o %t.obj
+@ RUN: macho-dump --dump-section-data < %t.obj > %t.dump
+@ RUN: FileCheck < %t.dump %s
+
+       .syntax unified
+        .text
+       .thumb
+       .thumb_func _foo
+_foo:
+        ldr r2, (_foo - 4)
+
+@ CHECK: ('num_reloc', 0)
+@ CHECK: ('_section_data', '5ff80820')