diff options
author | Sam Parker <sam.parker@arm.com> | 2017-03-15 10:21:23 +0000 |
---|---|---|
committer | Sam Parker <sam.parker@arm.com> | 2017-03-15 10:21:23 +0000 |
commit | 274472f7c507da918243606440597e939e1cd5a8 (patch) | |
tree | 055d26f3fd9c93f0b965eaf248decc0e08757736 /llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp | |
parent | 3fa5fd1dd278004d4f9b9427814a916e8cafadc9 (diff) | |
download | bcm5719-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.cpp | 88 |
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); |