From 64d083c81add9243be14ac3e0833e02754c42c1e Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Thu, 24 Mar 2016 17:18:14 +0000 Subject: [PATCH] [MC][mips] Add MipsMCInstrAnalysis class and register it as MC instruction analyzer The `MipsMCInstrAnalysis` class overrides the `evaluateBranch` method and calculates target addresses for branch and calls instructions. That allows llvm-objdump to print functions' names in branch instructions in the disassemble mode. Differential Revision: http://reviews.llvm.org/D18209 llvm-svn: 264309 --- .../Mips/MCTargetDesc/MipsMCTargetDesc.cpp | 36 +++++++++++++++++++ test/MC/Mips/instr-analysis.s | 36 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 test/MC/Mips/instr-analysis.s diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp index 949ee1474f9..f1b81814b7c 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp @@ -20,6 +20,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/MC/MCCodeGenInfo.h" #include "llvm/MC/MCELFStreamer.h" +#include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -129,6 +130,38 @@ createMipsObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { return new MipsTargetELFStreamer(S, STI); } +namespace { + +class MipsMCInstrAnalysis : public MCInstrAnalysis { +public: + MipsMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} + + bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + uint64_t &Target) const override { + unsigned NumOps = Inst.getNumOperands(); + if (NumOps == 0) + return false; + switch (Info->get(Inst.getOpcode()).OpInfo[NumOps - 1].OperandType) { + case MCOI::OPERAND_UNKNOWN: + case MCOI::OPERAND_IMMEDIATE: + // jal, bal ... + Target = Inst.getOperand(NumOps - 1).getImm(); + return true; + case MCOI::OPERAND_PCREL: + // b, j, beq ... + Target = Addr + Inst.getOperand(NumOps - 1).getImm(); + return true; + default: + return false; + } + } +}; +} + +static MCInstrAnalysis *createMipsMCInstrAnalysis(const MCInstrInfo *Info) { + return new MipsMCInstrAnalysis(Info); +} + extern "C" void LLVMInitializeMipsTargetMC() { for (Target *T : {&TheMipsTarget, &TheMipselTarget, &TheMips64Target, &TheMips64elTarget}) { @@ -156,6 +189,9 @@ extern "C" void LLVMInitializeMipsTargetMC() { // Register the MC subtarget info. TargetRegistry::RegisterMCSubtargetInfo(*T, createMipsMCSubtargetInfo); + // Register the MC instruction analyzer. + TargetRegistry::RegisterMCInstrAnalysis(*T, createMipsMCInstrAnalysis); + // Register the MCInstPrinter. TargetRegistry::RegisterMCInstPrinter(*T, createMipsMCInstPrinter); diff --git a/test/MC/Mips/instr-analysis.s b/test/MC/Mips/instr-analysis.s new file mode 100644 index 00000000000..58abfd0f472 --- /dev/null +++ b/test/MC/Mips/instr-analysis.s @@ -0,0 +1,36 @@ +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o - \ +# RUN: | llvm-objdump -d - | FileCheck %s + +# CHECK: foo: +# CHECK-NEXT: 0: 0c 00 00 02 jal 8 +# CHECK-NEXT: 4: 00 00 00 00 nop +# +# CHECK: loc1: +# CHECK-NEXT: 8: 0c 00 00 06 jal 24 +# CHECK-NEXT: c: 00 00 00 00 nop +# +# CHECK: loc2: +# CHECK-NEXT: 10: 10 00 ff fd b -8 +# CHECK-NEXT: 14: 00 00 00 00 nop +# +# CHECK: loc3: +# CHECK-NEXT: 18: 10 43 ff fd beq $2, $3, -8 +# CHECK-NEXT: 1c: 00 00 00 00 nop +# CHECK-NEXT: 20: 04 11 ff f9 bal -24 +# CHECK-NEXT: 24: 00 00 00 00 nop +# CHECK-NEXT: 28: 08 00 00 04 j 16 + + .text + .globl foo + .ent foo +foo: + jal loc1 +loc1: + jal loc3 +loc2: + b loc1 +loc3: + beq $2, $3, loc2 + bal loc1 + j loc2 + .end foo