]> granicus.if.org Git - llvm/commitdiff
[ARM] Fix for branch label disassembly for Thumb
authorSam Parker <sam.parker@arm.com>
Wed, 15 Mar 2017 10:21:23 +0000 (10:21 +0000)
committerSam Parker <sam.parker@arm.com>
Wed, 15 Mar 2017 10:21:23 +0000 (10:21 +0000)
Different MCInstrAnalysis classes for arm and thumb mode, each with
their own evaluateBranch implementation. I added a test case and
fixed the coff-relocations test to use '<label>:' rather than
'<label>' in the CHECK-LABEL entries, since the ones without the
colon would match branch targets. Might be worth noticing that
llvm-objdump does not lookup the relocation and thus assigns it a
target depending on the encoded immediate which #0, so it thinks it
branches to the next instruction.

Committed on behalf of Andre Vieira (avieira).

Differential Revision: https://reviews.llvm.org/D30943

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

lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
test/MC/ARM/branch-disassemble.s [new file with mode: 0644]
test/MC/ARM/coff-relocations.s

index 9e4d202321e6c2f28168b706d37a8ce91072662f..263671d69fa8f1a9881dd9342678d0ae4d0f6e5c 100644 (file)
@@ -257,24 +257,43 @@ public:
                       uint64_t Size, uint64_t &Target) const override {
     // We only handle PCRel branches for now.
     if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType!=MCOI::OPERAND_PCREL)
-      return false;
-
-    int64_t Imm = Inst.getOperand(0).getImm();
-    // FIXME: This is not right for thumb.
-    Target = Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes.
-    return true;
-  }
-};
-
-}
-
-static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) {
-  return new ARMMCInstrAnalysis(Info);
-}
-
-// Force static initialization.
-extern "C" void LLVMInitializeARMTargetMC() {
-  for (Target *T : {&getTheARMLETarget(), &getTheARMBETarget(),
+      return false;\r
+\r
+    int64_t Imm = Inst.getOperand(0).getImm();\r
+    Target = Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes.\r
+    return true;\r
+  }\r
+};\r
+\r
+class ThumbMCInstrAnalysis : public ARMMCInstrAnalysis {\r
+public:\r
+  ThumbMCInstrAnalysis(const MCInstrInfo *Info) : ARMMCInstrAnalysis(Info) {}\r
+\r
+  bool evaluateBranch(const MCInst &Inst, uint64_t Addr,\r
+                      uint64_t Size, uint64_t &Target) const override {\r
+    // We only handle PCRel branches for now.\r
+    if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType!=MCOI::OPERAND_PCREL)\r
+      return false;\r
+\r
+    int64_t Imm = Inst.getOperand(0).getImm();\r
+    Target = Addr+Imm+4; // In Thumb mode the PC is always off by 4 bytes.\r
+    return true;\r
+  }\r
+};\r
+\r
+}\r
+\r
+static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) {\r
+  return new ARMMCInstrAnalysis(Info);\r
+}\r
+\r
+static MCInstrAnalysis *createThumbMCInstrAnalysis(const MCInstrInfo *Info) {\r
+  return new ThumbMCInstrAnalysis(Info);\r
+}\r
+\r
+// Force static initialization.\r
+extern "C" void LLVMInitializeARMTargetMC() {\r
+  for (Target *T : {&getTheARMLETarget(), &getTheARMBETarget(),\r
                     &getTheThumbLETarget(), &getTheThumbBETarget()}) {
     // Register the MC asm info.
     RegisterMCAsmInfoFn X(*T, createARMMCAsmInfo);
@@ -286,15 +305,12 @@ extern "C" void LLVMInitializeARMTargetMC() {
     TargetRegistry::RegisterMCRegInfo(*T, createARMMCRegisterInfo);
 
     // Register the MC subtarget info.
-    TargetRegistry::RegisterMCSubtargetInfo(*T,
-                                            ARM_MC::createARMMCSubtargetInfo);
-
-    // Register the MC instruction analyzer.
-    TargetRegistry::RegisterMCInstrAnalysis(*T, createARMMCInstrAnalysis);
-
-    TargetRegistry::RegisterELFStreamer(*T, createELFStreamer);
-    TargetRegistry::RegisterCOFFStreamer(*T, createARMWinCOFFStreamer);
-    TargetRegistry::RegisterMachOStreamer(*T, createARMMachOStreamer);
+    TargetRegistry::RegisterMCSubtargetInfo(*T,\r
+                                            ARM_MC::createARMMCSubtargetInfo);\r
+\r
+    TargetRegistry::RegisterELFStreamer(*T, createELFStreamer);\r
+    TargetRegistry::RegisterCOFFStreamer(*T, createARMWinCOFFStreamer);\r
+    TargetRegistry::RegisterMachOStreamer(*T, createARMMachOStreamer);\r
 
     // Register the obj target streamer.
     TargetRegistry::RegisterObjectTargetStreamer(*T,
@@ -310,12 +326,18 @@ extern "C" void LLVMInitializeARMTargetMC() {
     TargetRegistry::RegisterMCInstPrinter(*T, createARMMCInstPrinter);
 
     // Register the MC relocation info.
-    TargetRegistry::RegisterMCRelocationInfo(*T, createARMMCRelocationInfo);
-  }
-
-  // Register the MC Code Emitter
-  for (Target *T : {&getTheARMLETarget(), &getTheThumbLETarget()})
-    TargetRegistry::RegisterMCCodeEmitter(*T, createARMLEMCCodeEmitter);
+    TargetRegistry::RegisterMCRelocationInfo(*T, createARMMCRelocationInfo);\r
+  }\r
+\r
+  // Register the MC instruction analyzer.\r
+  for (Target *T : {&getTheARMLETarget(), &getTheARMBETarget()})\r
+    TargetRegistry::RegisterMCInstrAnalysis(*T, createARMMCInstrAnalysis);\r
+  for (Target *T : {&getTheThumbLETarget(), &getTheThumbBETarget()})\r
+    TargetRegistry::RegisterMCInstrAnalysis(*T, createThumbMCInstrAnalysis);\r
+\r
+  // Register the MC Code Emitter\r
+  for (Target *T : {&getTheARMLETarget(), &getTheThumbLETarget()})\r
+    TargetRegistry::RegisterMCCodeEmitter(*T, createARMLEMCCodeEmitter);\r
   for (Target *T : {&getTheARMBETarget(), &getTheThumbBETarget()})
     TargetRegistry::RegisterMCCodeEmitter(*T, createARMBEMCCodeEmitter);
 
diff --git a/test/MC/ARM/branch-disassemble.s b/test/MC/ARM/branch-disassemble.s
new file mode 100644 (file)
index 0000000..76cdea3
--- /dev/null
@@ -0,0 +1,15 @@
+@ RUN: llvm-mc -mcpu=cortex-a9 -triple armv7.arm-none-eabi -filetype obj -o - %s \\r
+@ RUN:   | llvm-objdump -mcpu=cortex-a9 -triple armv7.arm-none-eabi -d - \\r
+@ RUN:   | FileCheck %s -check-prefix CHECK-ARM\r
+\r
+@ RUN: llvm-mc -mcpu=cortex-m3 -triple thumbv7.arm-none-eabi -filetype obj -o - %s \\r
+@ RUN:   | llvm-objdump -mcpu=cortex-m3 -triple thumbv7.arm-none-eabi -d - \\r
+@ RUN:   | FileCheck %s -check-prefix CHECK-THUMB\r
+\r
+b.w .Lbranch\r
+@ CHECK-ARM: b #4 <$a.0+0xC>\r
+@ CHECK-THUMB: b.w #8 <$t.0+0xC>\r
+adds r0, r1, #42\r
+adds r1, r2, #42\r
+.Lbranch:\r
+movs r2, r3\r
index fa2d407bb8f3a4bfecd31b4596b56f1da6b3a56e..d0c56b048cbab6a3a5a24a31f59a3c271a62d52c 100644 (file)
        .global target
 
        .thumb_func
-branch24t:
-       b target
-
-@ CHECK-ENCODING-LABEL: branch24t
-@ CHECK-ENCODING-NEXT: b.w #0
-
-       .thumb_func
-branch20t:
-       bcc target
-
-@ CHECK-ENCODING-LABEL: branch20t
-@ CHECK-ENCODING-NEXT: blo.w #0
-
-       .thumb_func
-blx23t:
-       bl target
-
-@ CHECK-ENCODING-LABEL: blx23t
-@ CHECK-ENCODING-NEXT: bl #0
-
-       .thumb_func
+branch24t:\r
+       b target\r
+\r
+@ CHECK-ENCODING-LABEL: branch24t:\r
+@ CHECK-ENCODING-NEXT: b.w #0\r
+\r
+       .thumb_func\r
+branch20t:\r
+       bcc target\r
+\r
+@ CHECK-ENCODING-LABEL: branch20t:\r
+@ CHECK-ENCODING-NEXT: blo.w #0\r
+\r
+       .thumb_func\r
+blx23t:\r
+       bl target\r
+\r
+@ CHECK-ENCODING-LABEL: blx23t:\r
+@ CHECK-ENCODING-NEXT: bl #0\r
+\r
+       .thumb_func\r
 mov32t:
        movw r0, :lower16:target
-       movt r0, :upper16:target
-       blx r0
-
-@ CHECK-ENCODING-LABEL: mov32t
-@ CHECK-ENCODING-NEXT: movw r0, #0
-@ CHECK-ENCODING-NEXT: movt r0, #0
-@ CHECK-ENCODING-NEXT: blx r0
+       movt r0, :upper16:target\r
+       blx r0\r
+\r
+@ CHECK-ENCODING-LABEL: mov32t:\r
+@ CHECK-ENCODING-NEXT: movw r0, #0\r
+@ CHECK-ENCODING-NEXT: movt r0, #0\r
+@ CHECK-ENCODING-NEXT: blx r0\r
 
        .thumb_func
 addr32:
        ldr r0, .Laddr32
        bx r0
        trap
-.Laddr32:
-       .long target
-
-@ CHECK-ENCODING-LABEL: addr32
-@ CHECK-ENCODING-NEXT: ldr r0, [pc, #4]
-@ CHECK-ENCODING-NEXT: bx r0
-@ CHECK-ENCODING-NEXT: trap
+.Laddr32:\r
+       .long target\r
+\r
+@ CHECK-ENCODING-LABEL: addr32:\r
+@ CHECK-ENCODING-NEXT: ldr r0, [pc, #4]\r
+@ CHECK-ENCODING-NEXT: bx r0\r
+@ CHECK-ENCODING-NEXT: trap\r
 @ CHECK-ENCODING-NEXT: movs r0, r0
 @ CHECK-ENCODING-NEXT: movs r0, r0
 
@@ -62,13 +62,13 @@ addr32nb:
        ldr r0, .Laddr32nb
        bx r0
        trap
-.Laddr32nb:
-       .long target(imgrel)
-
-@ CHECK-ENCODING-LABEL: addr32nb
-@ CHECK-ENCODING-NEXT: ldr.w r0, [pc, #4]
-@ CHECK-ENCODING-NEXT: bx r0
-@ CHECK-ENCODING-NEXT: trap
+.Laddr32nb:\r
+       .long target(imgrel)\r
+\r
+@ CHECK-ENCODING-LABEL: addr32nb:\r
+@ CHECK-ENCODING-NEXT: ldr.w r0, [pc, #4]\r
+@ CHECK-ENCODING-NEXT: bx r0\r
+@ CHECK-ENCODING-NEXT: trap\r
 @ CHECK-ENCODING-NEXT: movs r0, r0
 @ CHECK-ENCODING-NEXT: movs r0, r0
 
@@ -77,13 +77,13 @@ secrel:
        ldr r0, .Lsecrel
        bx r0
        trap
-.Lsecrel:
-       .long target(secrel32)
-
-@ CHECK-ENCODING-LABEL: secrel
-@ CHECK-ENCODING-NEXT: ldr.w r0, [pc, #4]
-@ CHECK-ENCODING-NEXT: bx r0
-@ CHECK-ENCODING-NEXT: trap
+.Lsecrel:\r
+       .long target(secrel32)\r
+\r
+@ CHECK-ENCODING-LABEL: secrel:\r
+@ CHECK-ENCODING-NEXT: ldr.w r0, [pc, #4]\r
+@ CHECK-ENCODING-NEXT: bx r0\r
+@ CHECK-ENCODING-NEXT: trap\r
 @ CHECK-ENCODING-NEXT: movs r0, r0
 @ CHECK-ENCODING-NEXT: movs r0, r0