summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
diff options
context:
space:
mode:
authorSam Parker <sam.parker@arm.com>2017-03-15 10:21:23 +0000
committerSam Parker <sam.parker@arm.com>2017-03-15 10:21:23 +0000
commit274472f7c507da918243606440597e939e1cd5a8 (patch)
tree055d26f3fd9c93f0b965eaf248decc0e08757736 /llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
parent3fa5fd1dd278004d4f9b9427814a916e8cafadc9 (diff)
downloadbcm5719-llvm-274472f7c507da918243606440597e939e1cd5a8.tar.gz
bcm5719-llvm-274472f7c507da918243606440597e939e1cd5a8.zip
[ARM] Fix for branch label disassembly for Thumb
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 llvm-svn: 297821
Diffstat (limited to 'llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp')
-rw-r--r--llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp88
1 files changed, 55 insertions, 33 deletions
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
index 9e4d202321e..263671d69fa 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
@@ -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;
+
+ int64_t Imm = Inst.getOperand(0).getImm();
+ Target = Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes.
+ return true;
+ }
+};
+
+class ThumbMCInstrAnalysis : public ARMMCInstrAnalysis {
+public:
+ ThumbMCInstrAnalysis(const MCInstrInfo *Info) : ARMMCInstrAnalysis(Info) {}
+
+ bool evaluateBranch(const MCInst &Inst, uint64_t Addr,
+ 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();
+ Target = Addr+Imm+4; // In Thumb mode the PC is always off by 4 bytes.
+ return true;
+ }
+};
+
+}
+
+static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) {
+ return new ARMMCInstrAnalysis(Info);
+}
+
+static MCInstrAnalysis *createThumbMCInstrAnalysis(const MCInstrInfo *Info) {
+ return new ThumbMCInstrAnalysis(Info);
+}
+
+// Force static initialization.
+extern "C" void LLVMInitializeARMTargetMC() {
+ for (Target *T : {&getTheARMLETarget(), &getTheARMBETarget(),
&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,
+ ARM_MC::createARMMCSubtargetInfo);
+
+ TargetRegistry::RegisterELFStreamer(*T, createELFStreamer);
+ TargetRegistry::RegisterCOFFStreamer(*T, createARMWinCOFFStreamer);
+ TargetRegistry::RegisterMachOStreamer(*T, createARMMachOStreamer);
// 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);
+ }
+
+ // Register the MC instruction analyzer.
+ for (Target *T : {&getTheARMLETarget(), &getTheARMBETarget()})
+ TargetRegistry::RegisterMCInstrAnalysis(*T, createARMMCInstrAnalysis);
+ for (Target *T : {&getTheThumbLETarget(), &getTheThumbBETarget()})
+ TargetRegistry::RegisterMCInstrAnalysis(*T, createThumbMCInstrAnalysis);
+
+ // Register the MC Code Emitter
+ for (Target *T : {&getTheARMLETarget(), &getTheThumbLETarget()})
+ TargetRegistry::RegisterMCCodeEmitter(*T, createARMLEMCCodeEmitter);
for (Target *T : {&getTheARMBETarget(), &getTheThumbBETarget()})
TargetRegistry::RegisterMCCodeEmitter(*T, createARMBEMCCodeEmitter);
OpenPOWER on IntegriCloud