Index: llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp +++ llvm/trunk/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 @@ 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 @@ // 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); Index: llvm/trunk/test/MC/Mips/instr-analysis.s =================================================================== --- llvm/trunk/test/MC/Mips/instr-analysis.s +++ llvm/trunk/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