[llvm-commits] [llvm] r141129 - in /llvm/trunk: include/llvm-c/Disassembler.h include/llvm/MC/MCDisassembler.h lib/MC/MCDisassembler/Disassembler.cpp lib/MC/MCInstPrinter.cpp lib/Target/ARM/ARMInstrInfo.td lib/Target/ARM/ARMInstrThumb2.td lib/Target/ARM/Disassembler/ARMDisassembler.cpp lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp

Kevin Enderby enderby at apple.com
Tue Oct 4 15:44:49 PDT 2011


Author: enderby
Date: Tue Oct  4 17:44:48 2011
New Revision: 141129

URL: http://llvm.org/viewvc/llvm-project?rev=141129&view=rev
Log:
Adding back support for printing operands symbolically to ARM's new disassembler
using llvm's public 'C' disassembler API now including annotations.

Hooked this up to Darwin's otool(1) so it can again print things like branch
targets for example this:
 blx _puts
instead of this:
 blx #-36
and includes support for annotations for branches to symbol stubs like:
 bl	0x40 @ symbol stub for: _puts
and annotations for pc relative loads like this:
 ldr	r3, #8 @ literal pool for: Hello, world!
Also again can print the expression encoded in the Mach-O relocation entries for
things like this:
 movt r0, :upper16:((_foo-_bar)+1234)

Modified:
    llvm/trunk/include/llvm-c/Disassembler.h
    llvm/trunk/include/llvm/MC/MCDisassembler.h
    llvm/trunk/lib/MC/MCDisassembler/Disassembler.cpp
    llvm/trunk/lib/MC/MCInstPrinter.cpp
    llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
    llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
    llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
    llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp

Modified: llvm/trunk/include/llvm-c/Disassembler.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/Disassembler.h?rev=141129&r1=141128&r2=141129&view=diff
==============================================================================
--- llvm/trunk/include/llvm-c/Disassembler.h (original)
+++ llvm/trunk/include/llvm-c/Disassembler.h Tue Oct  4 17:44:48 2011
@@ -66,7 +66,7 @@
  */
 struct LLVMOpInfoSymbol1 {
   uint64_t Present;  /* 1 if this symbol is present */
-  char *Name;        /* symbol name if not NULL */
+  const char *Name;  /* symbol name if not NULL */
   uint64_t Value;    /* symbol value if name is NULL */
 };
 
@@ -93,11 +93,35 @@
  * disassembler for things like adding a comment for a PC plus a constant
  * offset load instruction to use a symbol name instead of a load address value.
  * It is passed the block information is saved when the disassembler context is
- * created and a value of a symbol to look up.  If no symbol is found NULL is
- * returned.
+ * created and the ReferenceValue to look up as a symbol.  If no symbol is found
+ * for the ReferenceValue NULL is returned.  The ReferenceType of the
+ * instruction is passed indirectly as is the PC of the instruction in
+ * ReferencePC.  If the output reference can be determined its type is returned
+ * indirectly in ReferenceType along with ReferenceName if any, or that is set
+ * to NULL.
  */
 typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo,
-                                                uint64_t SymbolValue);
+                                                uint64_t ReferenceValue,
+						uint64_t *ReferenceType,
+						uint64_t ReferencePC,
+						const char **ReferenceName);
+/**
+ * The reference types on input and output.
+ */
+/* No input reference type or no output reference type. */
+#define LLVMDisassembler_ReferenceType_InOut_None 0
+
+/* The input reference is from a branch instruction. */
+#define LLVMDisassembler_ReferenceType_In_Branch 1
+/* The input reference is from a PC relative load instruction. */
+#define LLVMDisassembler_ReferenceType_In_PCrel_Load 2
+
+/* The output reference is to as symbol stub. */
+#define LLVMDisassembler_ReferenceType_Out_SymbolStub 1
+/* The output reference is to a symbol address in a literal pool. */
+#define LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr 2
+/* The output reference is to a cstring address in a literal pool. */
+#define LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr 3
 
 #ifdef __cplusplus
 extern "C" {

Modified: llvm/trunk/include/llvm/MC/MCDisassembler.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCDisassembler.h?rev=141129&r1=141128&r2=141129&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCDisassembler.h (original)
+++ llvm/trunk/include/llvm/MC/MCDisassembler.h Tue Oct  4 17:44:48 2011
@@ -55,7 +55,9 @@
   };
 
   /// Constructor     - Performs initial setup for the disassembler.
-  MCDisassembler(const MCSubtargetInfo &STI) : GetOpInfo(0), DisInfo(0), Ctx(0), STI(STI) {}
+  MCDisassembler(const MCSubtargetInfo &STI) : GetOpInfo(0), SymbolLookUp(0),
+                                               DisInfo(0), Ctx(0),
+                                               STI(STI), CommentStream(0) {}
   
   virtual ~MCDisassembler();
   
@@ -96,6 +98,8 @@
   //
   // The function to get the symbolic information for operands.
   LLVMOpInfoCallback GetOpInfo;
+  // The function to lookup a symbol name.
+  LLVMSymbolLookupCallback SymbolLookUp;
   // The pointer to the block of symbolic information for above call back.
   void *DisInfo;
   // The assembly context for creating symbols and MCExprs in place of
@@ -107,15 +111,24 @@
 
 public:
   void setupForSymbolicDisassembly(LLVMOpInfoCallback getOpInfo,
+                                   LLVMSymbolLookupCallback symbolLookUp,
                                    void *disInfo,
                                    MCContext *ctx) {
     GetOpInfo = getOpInfo;
+    SymbolLookUp = symbolLookUp;
     DisInfo = disInfo;
     Ctx = ctx;
   }
   LLVMOpInfoCallback getLLVMOpInfoCallback() const { return GetOpInfo; }
+  LLVMSymbolLookupCallback getLLVMSymbolLookupCallback() const {
+    return SymbolLookUp;
+  }
   void *getDisInfoBlock() const { return DisInfo; }
   MCContext *getMCContext() const { return Ctx; }
+
+  // Marked mutable because we cache it inside the disassembler, rather than
+  // having to pass it around as an argument through all the autogenerated code.
+  mutable raw_ostream *CommentStream;
 };
 
 } // namespace llvm

Modified: llvm/trunk/lib/MC/MCDisassembler/Disassembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCDisassembler/Disassembler.cpp?rev=141129&r1=141128&r2=141129&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCDisassembler/Disassembler.cpp (original)
+++ llvm/trunk/lib/MC/MCDisassembler/Disassembler.cpp Tue Oct  4 17:44:48 2011
@@ -68,7 +68,7 @@
   // Set up disassembler.
   MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI);
   assert(DisAsm && "Unable to create disassembler!");
-  DisAsm->setupForSymbolicDisassembly(GetOpInfo, DisInfo, Ctx);
+  DisAsm->setupForSymbolicDisassembly(GetOpInfo, SymbolLookUp, DisInfo, Ctx);
 
   // Set up the instruction printer.
   int AsmPrinterVariant = MAI->getAssemblerDialect();

Modified: llvm/trunk/lib/MC/MCInstPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCInstPrinter.cpp?rev=141129&r1=141128&r2=141129&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCInstPrinter.cpp (original)
+++ llvm/trunk/lib/MC/MCInstPrinter.cpp Tue Oct  4 17:44:48 2011
@@ -29,8 +29,8 @@
 void MCInstPrinter::printAnnotation(raw_ostream &OS, StringRef Annot) {
   if (!Annot.empty()) {
     if (CommentStream)
-      (*CommentStream) << Annot << "\n";
+      (*CommentStream) << Annot;
     else
-      OS << " " << MAI.getCommentString() << " " << Annot << "\n";
+      OS << " " << MAI.getCommentString() << " " << Annot;
   }
 }

Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=141129&r1=141128&r2=141129&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Tue Oct  4 17:44:48 2011
@@ -2915,6 +2915,7 @@
   let Inst{19-16} = imm{15-12};
   let Inst{20} = 0;
   let Inst{25} = 1;
+  let DecoderMethod = "DecodeArmMOVTWInstruction";
 }
 
 def : InstAlias<"mov${p} $Rd, $imm",
@@ -2940,6 +2941,7 @@
   let Inst{19-16} = imm{15-12};
   let Inst{20} = 0;
   let Inst{25} = 1;
+  let DecoderMethod = "DecodeArmMOVTWInstruction";
 }
 
 def MOVTi16_ga_pcrel : PseudoInst<(outs GPR:$Rd),

Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=141129&r1=141128&r2=141129&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Tue Oct  4 17:44:48 2011
@@ -1741,6 +1741,7 @@
   let Inst{26}    = imm{11};
   let Inst{14-12} = imm{10-8};
   let Inst{7-0}   = imm{7-0};
+  let DecoderMethod = "DecodeT2MOVTWInstruction";
 }
 
 def t2MOVi16_ga_pcrel : PseudoInst<(outs rGPR:$Rd),
@@ -1766,6 +1767,7 @@
   let Inst{26}    = imm{11};
   let Inst{14-12} = imm{10-8};
   let Inst{7-0}   = imm{7-0};
+  let DecoderMethod = "DecodeT2MOVTWInstruction";
 }
 
 def t2MOVTi16_ga_pcrel : PseudoInst<(outs rGPR:$Rd),

Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp?rev=141129&r1=141128&r2=141129&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (original)
+++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Tue Oct  4 17:44:48 2011
@@ -13,6 +13,7 @@
 #include "ARMRegisterInfo.h"
 #include "ARMSubtarget.h"
 #include "MCTargetDesc/ARMAddressingModes.h"
+#include "MCTargetDesc/ARMMCExpr.h"
 #include "MCTargetDesc/ARMBaseInfo.h"
 #include "llvm/MC/EDInstInfo.h"
 #include "llvm/MC/MCInst.h"
@@ -160,6 +161,10 @@
                                                   unsigned Insn,
                                                   uint64_t Adddress,
                                                   const void *Decoder);
+static DecodeStatus DecodeT2MOVTWInstruction(llvm::MCInst &Inst, unsigned Insn,
+                               uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeArmMOVTWInstruction(llvm::MCInst &Inst, unsigned Insn,
+                               uint64_t Address, const void *Decoder);
 static DecodeStatus DecodeSMLAInstruction(llvm::MCInst &Inst, unsigned Insn,
                                uint64_t Address, const void *Decoder);
 static DecodeStatus DecodeCPSInstruction(llvm::MCInst &Inst, unsigned Insn,
@@ -335,6 +340,8 @@
                                              uint64_t Address,
                                              raw_ostream &os,
                                              raw_ostream &cs) const {
+  CommentStream = &cs;
+
   uint8_t bytes[4];
 
   assert(!(STI.getFeatureBits() & ARM::ModeThumb) &&
@@ -411,6 +418,146 @@
 extern MCInstrDesc ARMInsts[];
 }
 
+/// tryAddingSymbolicOperand - trys to add a symbolic operand in place of the
+/// immediate Value in the MCInst.  The immediate Value has had any PC
+/// adjustment made by the caller.  If the instruction is a branch instruction
+/// then isBranch is true, else false.  If the getOpInfo() function was set as
+/// part of the setupForSymbolicDisassembly() call then that function is called
+/// to get any symbolic information at the Address for this instruction.  If
+/// that returns non-zero then the symbolic information it returns is used to
+/// create an MCExpr and that is added as an operand to the MCInst.  If
+/// getOpInfo() returns zero and isBranch is true then a symbol look up for
+/// Value is done and if a symbol is found an MCExpr is created with that, else
+/// an MCExpr with Value is created.  This function returns true if it adds an
+/// operand to the MCInst and false otherwise.
+static bool tryAddingSymbolicOperand(uint64_t Address, int32_t Value,
+                                     bool isBranch, uint64_t InstSize,
+                                     MCInst &MI, const void *Decoder) {
+  const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder);
+  LLVMOpInfoCallback getOpInfo = Dis->getLLVMOpInfoCallback();
+  if (!getOpInfo)
+    return false;
+
+  struct LLVMOpInfo1 SymbolicOp;
+  SymbolicOp.Value = Value;
+  void *DisInfo = Dis->getDisInfoBlock();
+  if (!getOpInfo(DisInfo, Address, 0 /* Offset */, InstSize, 1, &SymbolicOp)) {
+    if (isBranch) {
+      LLVMSymbolLookupCallback SymbolLookUp =
+                                            Dis->getLLVMSymbolLookupCallback();
+      if (SymbolLookUp) {
+        uint64_t ReferenceType;
+        ReferenceType = LLVMDisassembler_ReferenceType_In_Branch;
+        const char *ReferenceName;
+        const char *Name = SymbolLookUp(DisInfo, Value, &ReferenceType, Address,
+                                        &ReferenceName);
+        if (Name) {
+          SymbolicOp.AddSymbol.Name = Name;
+          SymbolicOp.AddSymbol.Present = true;
+          SymbolicOp.Value = 0;
+        }
+        else {
+          SymbolicOp.Value = Value;
+        }
+        if(ReferenceType == LLVMDisassembler_ReferenceType_Out_SymbolStub)
+          (*Dis->CommentStream) << "symbol stub for: " << ReferenceName;
+      }
+      else {
+        return false;
+      }
+    }
+    else {
+      return false;
+    }
+  }
+
+  MCContext *Ctx = Dis->getMCContext();
+  const MCExpr *Add = NULL;
+  if (SymbolicOp.AddSymbol.Present) {
+    if (SymbolicOp.AddSymbol.Name) {
+      StringRef Name(SymbolicOp.AddSymbol.Name);
+      MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name);
+      Add = MCSymbolRefExpr::Create(Sym, *Ctx);
+    } else {
+      Add = MCConstantExpr::Create(SymbolicOp.AddSymbol.Value, *Ctx);
+    }
+  }
+
+  const MCExpr *Sub = NULL;
+  if (SymbolicOp.SubtractSymbol.Present) {
+    if (SymbolicOp.SubtractSymbol.Name) {
+      StringRef Name(SymbolicOp.SubtractSymbol.Name);
+      MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name);
+      Sub = MCSymbolRefExpr::Create(Sym, *Ctx);
+    } else {
+      Sub = MCConstantExpr::Create(SymbolicOp.SubtractSymbol.Value, *Ctx);
+    }
+  }
+
+  const MCExpr *Off = NULL;
+  if (SymbolicOp.Value != 0)
+    Off = MCConstantExpr::Create(SymbolicOp.Value, *Ctx);
+
+  const MCExpr *Expr;
+  if (Sub) {
+    const MCExpr *LHS;
+    if (Add)
+      LHS = MCBinaryExpr::CreateSub(Add, Sub, *Ctx);
+    else
+      LHS = MCUnaryExpr::CreateMinus(Sub, *Ctx);
+    if (Off != 0)
+      Expr = MCBinaryExpr::CreateAdd(LHS, Off, *Ctx);
+    else
+      Expr = LHS;
+  } else if (Add) {
+    if (Off != 0)
+      Expr = MCBinaryExpr::CreateAdd(Add, Off, *Ctx);
+    else
+      Expr = Add;
+  } else {
+    if (Off != 0)
+      Expr = Off;
+    else
+      Expr = MCConstantExpr::Create(0, *Ctx);
+  }
+
+  if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_ARM_HI16)
+    MI.addOperand(MCOperand::CreateExpr(ARMMCExpr::CreateUpper16(Expr, *Ctx)));
+  else if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_ARM_LO16)
+    MI.addOperand(MCOperand::CreateExpr(ARMMCExpr::CreateLower16(Expr, *Ctx)));
+  else if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_None)
+    MI.addOperand(MCOperand::CreateExpr(Expr));
+  else 
+    assert("bad SymbolicOp.VariantKind");
+
+  return true;
+}
+
+/// tryAddingPcLoadReferenceComment - trys to add a comment as to what is being
+/// referenced by a load instruction with the base register that is the Pc.
+/// These can often be values in a literal pool near the Address of the
+/// instruction.  The Address of the instruction and its immediate Value are
+/// used as a possible literal pool entry.  The SymbolLookUp call back will
+/// return the name of a symbol referenced by the the literal pool's entry if
+/// the referenced address is that of a symbol.  Or it will return a pointer to
+/// a literal 'C' string if the referenced address of the literal pool's entry
+/// is an address into a section with 'C' string literals.
+static void tryAddingPcLoadReferenceComment(uint64_t Address, int Value,
+					    const void *Decoder) {
+  const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder);
+  LLVMSymbolLookupCallback SymbolLookUp = Dis->getLLVMSymbolLookupCallback();
+  if (SymbolLookUp) {
+    void *DisInfo = Dis->getDisInfoBlock();
+    uint64_t ReferenceType;
+    ReferenceType = LLVMDisassembler_ReferenceType_In_PCrel_Load;
+    const char *ReferenceName;
+    (void)SymbolLookUp(DisInfo, Value, &ReferenceType, Address, &ReferenceName);
+    if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr ||
+       ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr)
+      (*Dis->CommentStream) << "literal pool for: " << ReferenceName;
+  }
+}
+
 // Thumb1 instructions don't have explicit S bits.  Rather, they
 // implicitly set CPSR.  Since it's not represented in the encoding, the
 // auto-generated decoder won't inject the CPSR operand.  We need to fix
@@ -542,6 +689,8 @@
                                                uint64_t Address,
                                                raw_ostream &os,
                                                raw_ostream &cs) const {
+  CommentStream = &cs;
+
   uint8_t bytes[4];
 
   assert((STI.getFeatureBits() & ARM::ModeThumb) &&
@@ -1624,6 +1773,55 @@
   return S;
 }
 
+static DecodeStatus DecodeT2MOVTWInstruction(llvm::MCInst &Inst, unsigned Insn,
+                                 uint64_t Address, const void *Decoder) {
+  DecodeStatus S = MCDisassembler::Success;
+
+  unsigned Rd = fieldFromInstruction32(Insn, 8, 4);
+  unsigned imm = 0;
+
+  imm |= (fieldFromInstruction32(Insn, 0, 8) << 0);
+  imm |= (fieldFromInstruction32(Insn, 12, 3) << 8);
+  imm |= (fieldFromInstruction32(Insn, 16, 4) << 12);
+  imm |= (fieldFromInstruction32(Insn, 26, 1) << 11);
+
+  if (Inst.getOpcode() == ARM::t2MOVTi16)
+    if (!Check(S, DecoderGPRRegisterClass(Inst, Rd, Address, Decoder)))
+      return MCDisassembler::Fail;
+  if (!Check(S, DecoderGPRRegisterClass(Inst, Rd, Address, Decoder)))
+    return MCDisassembler::Fail;
+
+  if (!tryAddingSymbolicOperand(Address, imm, false, 4, Inst, Decoder))
+    Inst.addOperand(MCOperand::CreateImm(imm));
+
+  return S;
+}
+
+static DecodeStatus DecodeArmMOVTWInstruction(llvm::MCInst &Inst, unsigned Insn,
+                                 uint64_t Address, const void *Decoder) {
+  DecodeStatus S = MCDisassembler::Success;
+
+  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+  unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+  unsigned imm = 0;
+
+  imm |= (fieldFromInstruction32(Insn, 0, 12) << 0);
+  imm |= (fieldFromInstruction32(Insn, 16, 4) << 12);
+
+  if (Inst.getOpcode() == ARM::MOVTi16)
+    if (!Check(S, DecoderGPRRegisterClass(Inst, Rd, Address, Decoder)))
+      return MCDisassembler::Fail;
+  if (!Check(S, DecoderGPRRegisterClass(Inst, Rd, Address, Decoder)))
+    return MCDisassembler::Fail;
+
+  if (!tryAddingSymbolicOperand(Address, imm, false, 4, Inst, Decoder))
+    Inst.addOperand(MCOperand::CreateImm(imm));
+
+  if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
+    return MCDisassembler::Fail;
+
+  return S;
+}
 
 static DecodeStatus DecodeSMLAInstruction(llvm::MCInst &Inst, unsigned Insn,
                                  uint64_t Address, const void *Decoder) {
@@ -1667,6 +1865,8 @@
   if (!add) imm *= -1;
   if (imm == 0 && !add) imm = INT32_MIN;
   Inst.addOperand(MCOperand::CreateImm(imm));
+  if (Rn == 15)
+    tryAddingPcLoadReferenceComment(Address, Address + imm + 8, Decoder);
 
   return S;
 }
@@ -1710,7 +1910,9 @@
     return S;
   }
 
-  Inst.addOperand(MCOperand::CreateImm(SignExtend32<26>(imm)));
+  if (!tryAddingSymbolicOperand(Address, Address + SignExtend32<26>(imm) + 8, true,
+                                4, Inst, Decoder))
+    Inst.addOperand(MCOperand::CreateImm(SignExtend32<26>(imm)));
   if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
     return MCDisassembler::Fail;
 
@@ -2595,7 +2797,10 @@
 
 static DecodeStatus DecodeThumbAddrModePC(llvm::MCInst &Inst, unsigned Val,
                                   uint64_t Address, const void *Decoder) {
-  Inst.addOperand(MCOperand::CreateImm(Val << 2));
+  unsigned imm = Val << 2;
+
+  Inst.addOperand(MCOperand::CreateImm(imm));
+  tryAddingPcLoadReferenceComment(Address, (Address & ~2u) + imm + 4, Decoder);
 
   return MCDisassembler::Success;
 }
@@ -2870,7 +3075,10 @@
 
 static DecodeStatus DecodeThumbBLXOffset(llvm::MCInst &Inst, unsigned Val,
                                  uint64_t Address, const void *Decoder) {
-  Inst.addOperand(MCOperand::CreateImm(SignExtend32<22>(Val << 1)));
+  if (!tryAddingSymbolicOperand(Address, 
+                                (Address & ~2u) + SignExtend32<22>(Val << 1) + 4,
+                                true, 4, Inst, Decoder))
+    Inst.addOperand(MCOperand::CreateImm(SignExtend32<22>(Val << 1)));
   return MCDisassembler::Success;
 }
 

Modified: llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp?rev=141129&r1=141128&r2=141129&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp (original)
+++ llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp Tue Oct  4 17:44:48 2011
@@ -207,7 +207,18 @@
     O << '#' << Op.getImm();
   } else {
     assert(Op.isExpr() && "unknown operand kind in printOperand");
-    O << *Op.getExpr();
+    // If a symbolic branch target was added as a constant expression then print
+    // that address in hex.
+    const MCConstantExpr *BranchTarget = dyn_cast<MCConstantExpr>(Op.getExpr());
+    int64_t Address;
+    if (BranchTarget && BranchTarget->EvaluateAsAbsolute(Address)) {
+      O << "0x";
+      O.write_hex(Address);
+    }
+    else {
+      // Otherwise, just print the expression.
+      O << *Op.getExpr();
+    }
   }
 }
 





More information about the llvm-commits mailing list