[llvm] 9525af7 - [DebugInfo] Support representation of multiple location operands in SDDbgValue

Stephen Tozer via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 8 10:55:34 PST 2021


Author: gbtozers
Date: 2021-03-08T18:45:17Z
New Revision: 9525af7b916a0f706c3646946a5c4cd7cf41cb55

URL: https://github.com/llvm/llvm-project/commit/9525af7b916a0f706c3646946a5c4cd7cf41cb55
DIFF: https://github.com/llvm/llvm-project/commit/9525af7b916a0f706c3646946a5c4cd7cf41cb55.diff

LOG: [DebugInfo] Support representation of multiple location operands in SDDbgValue

This patch modifies the class that represents debug values during ISel,
SDDbgValue, to support multiple location operands (to represent a dbg.value that
uses a DIArgList). Part of this class's functionality has been split off into a
new class, SDDbgOperand.

The new class SDDbgOperand represents a single value, corresponding to an SSA
value or MachineOperand in the IR and MIR respectively. Members of SDDbgValue
that were previously related to that specific value (as opposed to the
variable or DIExpression), such as the Kind enum, have been moved to
SDDbgOperand. SDDbgValue now contains an array of SDDbgOperand instead, allowing
it to hold more than one of these values.

All changes outside SDDbgValue are simply updates to use the new interface.

Differential Revision: https://reviews.llvm.org/D88585

Added: 
    

Modified: 
    llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
    llvm/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h
    llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
index a5978711b8717..c50f05079eee9 100644
--- a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
@@ -701,11 +701,12 @@ InstrEmitter::EmitDbgValue(SDDbgValue *SD,
     if (auto *InstrRef = EmitDbgInstrRef(SD, VRBaseMap))
       return InstrRef;
 
-  if (SD->getKind() == SDDbgValue::FRAMEIX) {
+  SDDbgOperand SDOperand = SD->getLocationOps()[0];
+  if (SDOperand.getKind() == SDDbgOperand::FRAMEIX) {
     // Stack address; this needs to be lowered in target-dependent fashion.
     // EmitTargetCodeForFrameDebugValue is responsible for allocation.
     auto FrameMI = BuildMI(*MF, DL, TII->get(TargetOpcode::DBG_VALUE))
-                       .addFrameIndex(SD->getFrameIx());
+                       .addFrameIndex(SDOperand.getFrameIx());
     if (SD->isIndirect())
       // Push [fi + 0] onto the DIExpression stack.
       FrameMI.addImm(0);
@@ -717,9 +718,9 @@ InstrEmitter::EmitDbgValue(SDDbgValue *SD,
   // Otherwise, we're going to create an instruction here.
   const MCInstrDesc &II = TII->get(TargetOpcode::DBG_VALUE);
   MachineInstrBuilder MIB = BuildMI(*MF, DL, II);
-  if (SD->getKind() == SDDbgValue::SDNODE) {
-    SDNode *Node = SD->getSDNode();
-    SDValue Op = SDValue(Node, SD->getResNo());
+  if (SDOperand.getKind() == SDDbgOperand::SDNODE) {
+    SDNode *Node = SDOperand.getSDNode();
+    SDValue Op = SDValue(Node, SDOperand.getResNo());
     // It's possible we replaced this SDNode with other(s) and therefore
     // didn't generate code for it.  It's better to catch these cases where
     // they happen and transfer the debug info, but trying to guarantee that
@@ -731,10 +732,10 @@ InstrEmitter::EmitDbgValue(SDDbgValue *SD,
     else
       AddOperand(MIB, Op, (*MIB).getNumOperands(), &II, VRBaseMap,
                  /*IsDebug=*/true, /*IsClone=*/false, /*IsCloned=*/false);
-  } else if (SD->getKind() == SDDbgValue::VREG) {
-    MIB.addReg(SD->getVReg(), RegState::Debug);
-  } else if (SD->getKind() == SDDbgValue::CONST) {
-    const Value *V = SD->getConst();
+  } else if (SDOperand.getKind() == SDDbgOperand::VREG) {
+    MIB.addReg(SDOperand.getVReg(), RegState::Debug);
+  } else if (SDOperand.getKind() == SDDbgOperand::CONST) {
+    const Value *V = SDOperand.getConst();
     if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
       if (CI->getBitWidth() > 64)
         MIB.addCImm(CI);
@@ -770,14 +771,18 @@ InstrEmitter::EmitDbgValue(SDDbgValue *SD,
 MachineInstr *
 InstrEmitter::EmitDbgInstrRef(SDDbgValue *SD,
                               DenseMap<SDValue, Register> &VRBaseMap) {
+  // No support for instruction references for variadic values yet.
+  if (SD->isVariadic())
+    return nullptr;
+  SDDbgOperand DbgOperand = SD->getLocationOps()[0];
   // Instruction referencing is still in a prototype state: for now we're only
   // going to support SDNodes within a block. Copies are not supported, they
   // don't actually define a value.
-  if (SD->getKind() != SDDbgValue::SDNODE)
+  if (DbgOperand.getKind() != SDDbgOperand::SDNODE)
     return nullptr;
 
-  SDNode *Node = SD->getSDNode();
-  SDValue Op = SDValue(Node, SD->getResNo());
+  SDNode *Node = DbgOperand.getSDNode();
+  SDValue Op = SDValue(Node, DbgOperand.getResNo());
   DenseMap<SDValue, Register>::iterator I = VRBaseMap.find(Op);
   if (I==VRBaseMap.end())
     return nullptr; // undef value: let EmitDbgValue produce a DBG_VALUE $noreg.

diff  --git a/llvm/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h b/llvm/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h
index 65b9d017fc5cd..d42481e9a1b55 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h
@@ -25,69 +25,140 @@ class SDNode;
 class Value;
 class raw_ostream;
 
-/// Holds the information from a dbg_value node through SDISel.
-/// We do not use SDValue here to avoid including its header.
-class SDDbgValue {
+/// Holds the information for a single machine location through SDISel; either
+/// an SDNode, a constant, a stack location, or a virtual register.
+class SDDbgOperand {
 public:
-  enum DbgValueKind {
-    SDNODE = 0,             ///< Value is the result of an expression.
-    CONST = 1,              ///< Value is a constant.
-    FRAMEIX = 2,            ///< Value is contents of a stack location.
-    VREG = 3                ///< Value is a virtual register.
+  enum Kind {
+    SDNODE = 0,  ///< Value is the result of an expression.
+    CONST = 1,   ///< Value is a constant.
+    FRAMEIX = 2, ///< Value is contents of a stack location.
+    VREG = 3     ///< Value is a virtual register.
   };
+  Kind getKind() const { return kind; }
+
+  /// Returns the SDNode* for a register ref
+  SDNode *getSDNode() const {
+    assert(kind == SDNODE);
+    return u.s.Node;
+  }
+
+  /// Returns the ResNo for a register ref
+  unsigned getResNo() const {
+    assert(kind == SDNODE);
+    return u.s.ResNo;
+  }
+
+  /// Returns the Value* for a constant
+  const Value *getConst() const {
+    assert(kind == CONST);
+    return u.Const;
+  }
+
+  /// Returns the FrameIx for a stack object
+  unsigned getFrameIx() const {
+    assert(kind == FRAMEIX);
+    return u.FrameIx;
+  }
+
+  /// Returns the Virtual Register for a VReg
+  unsigned getVReg() const {
+    assert(kind == VREG);
+    return u.VReg;
+  }
+
+  static SDDbgOperand fromNode(SDNode *Node, unsigned ResNo) {
+    return SDDbgOperand(Node, ResNo);
+  }
+  static SDDbgOperand fromFrameIdx(unsigned FrameIdx) {
+    return SDDbgOperand(FrameIdx, FRAMEIX);
+  }
+  static SDDbgOperand fromVReg(unsigned VReg) {
+    return SDDbgOperand(VReg, VREG);
+  }
+  static SDDbgOperand fromConst(const Value *Const) {
+    return SDDbgOperand(Const);
+  }
+
+  bool operator!=(const SDDbgOperand &Other) const { return !(*this == Other); }
+  bool operator==(const SDDbgOperand &Other) const {
+    if (kind != Other.kind)
+      return false;
+    switch (kind) {
+    case SDNODE:
+      return getSDNode() == Other.getSDNode() && getResNo() == Other.getResNo();
+    case CONST:
+      return getConst() == Other.getConst();
+    case VREG:
+      return getVReg() == Other.getVReg();
+    case FRAMEIX:
+      return getFrameIx() == Other.getFrameIx();
+    default:
+      llvm_unreachable("unknown kind");
+    }
+  }
+
 private:
+  Kind kind;
   union {
     struct {
-      SDNode *Node;         ///< Valid for expressions.
-      unsigned ResNo;       ///< Valid for expressions.
+      SDNode *Node;   ///< Valid for expressions.
+      unsigned ResNo; ///< Valid for expressions.
     } s;
-    const Value *Const;     ///< Valid for constants.
-    unsigned FrameIx;       ///< Valid for stack objects.
-    unsigned VReg;          ///< Valid for registers.
+    const Value *Const; ///< Valid for constants.
+    unsigned FrameIx;   ///< Valid for stack objects.
+    unsigned VReg;      ///< Valid for registers.
   } u;
-  DIVariable *Var;
-  DIExpression *Expr;
-  DebugLoc DL;
-  unsigned Order;
-  enum DbgValueKind kind;
-  bool IsIndirect;
-  bool Invalid = false;
-  bool Emitted = false;
 
-public:
   /// Constructor for non-constants.
-  SDDbgValue(DIVariable *Var, DIExpression *Expr, SDNode *N, unsigned R,
-             bool indir, DebugLoc dl, unsigned O)
-      : Var(Var), Expr(Expr), DL(std::move(dl)), Order(O), IsIndirect(indir) {
-    kind = SDNODE;
+  SDDbgOperand(SDNode *N, unsigned R) : kind(SDNODE) {
     u.s.Node = N;
     u.s.ResNo = R;
   }
-
   /// Constructor for constants.
-  SDDbgValue(DIVariable *Var, DIExpression *Expr, const Value *C, DebugLoc dl,
-             unsigned O)
-      : Var(Var), Expr(Expr), DL(std::move(dl)), Order(O), IsIndirect(false) {
-    kind = CONST;
-    u.Const = C;
-  }
-
+  SDDbgOperand(const Value *C) : kind(CONST) { u.Const = C; }
   /// Constructor for virtual registers and frame indices.
-  SDDbgValue(DIVariable *Var, DIExpression *Expr, unsigned VRegOrFrameIdx,
-             bool IsIndirect, DebugLoc DL, unsigned Order,
-             enum DbgValueKind Kind)
-      : Var(Var), Expr(Expr), DL(DL), Order(Order), IsIndirect(IsIndirect) {
+  SDDbgOperand(unsigned VRegOrFrameIdx, Kind Kind) : kind(Kind) {
     assert((Kind == VREG || Kind == FRAMEIX) &&
            "Invalid SDDbgValue constructor");
-    kind = Kind;
     if (kind == VREG)
       u.VReg = VRegOrFrameIdx;
     else
       u.FrameIx = VRegOrFrameIdx;
   }
+};
+
+/// Holds the information from a dbg_value node through SDISel.
+/// We do not use SDValue here to avoid including its header.
+class SDDbgValue {
+public:
+  // FIXME: These SmallVector sizes were chosen without any kind of performance
+  // testing.
+  using LocOpVector = SmallVector<SDDbgOperand, 2>;
+  using SDNodeVector = SmallVector<SDNode *, 2>;
+
+private:
+  LocOpVector LocationOps;
+  SDNodeVector SDNodes;
+  DIVariable *Var;
+  DIExpression *Expr;
+  DebugLoc DL;
+  unsigned Order;
+  bool IsIndirect;
+  bool IsVariadic;
+  bool Invalid = false;
+  bool Emitted = false;
 
-  /// Returns the kind.
-  DbgValueKind getKind() const { return kind; }
+public:
+  SDDbgValue(DIVariable *Var, DIExpression *Expr, ArrayRef<SDDbgOperand> L,
+             ArrayRef<SDNode *> Dependencies, bool IsIndirect, DebugLoc DL,
+             unsigned O, bool IsVariadic)
+      : LocationOps(L.begin(), L.end()),
+        SDNodes(Dependencies.begin(), Dependencies.end()), Var(Var), Expr(Expr),
+        DL(DL), Order(O), IsIndirect(IsIndirect), IsVariadic(IsVariadic) {
+    assert(IsVariadic || L.size() == 1);
+    assert(!(IsVariadic && IsIndirect));
+  }
 
   /// Returns the DIVariable pointer for the variable.
   DIVariable *getVariable() const { return Var; }
@@ -95,24 +166,20 @@ class SDDbgValue {
   /// Returns the DIExpression pointer for the expression.
   DIExpression *getExpression() const { return Expr; }
 
-  /// Returns the SDNode* for a register ref
-  SDNode *getSDNode() const { assert (kind==SDNODE); return u.s.Node; }
+  ArrayRef<SDDbgOperand> getLocationOps() const { return LocationOps; }
 
-  /// Returns the ResNo for a register ref
-  unsigned getResNo() const { assert (kind==SDNODE); return u.s.ResNo; }
+  LocOpVector copyLocationOps() const { return LocationOps; }
 
-  /// Returns the Value* for a constant
-  const Value *getConst() const { assert (kind==CONST); return u.Const; }
+  // Returns the SDNodes which this SDDbgValue depends on.
+  ArrayRef<SDNode *> getSDNodes() const { return SDNodes; }
 
-  /// Returns the FrameIx for a stack object
-  unsigned getFrameIx() const { assert (kind==FRAMEIX); return u.FrameIx; }
-
-  /// Returns the Virtual Register for a VReg
-  unsigned getVReg() const { assert (kind==VREG); return u.VReg; }
+  SDNodeVector copySDNodes() const { return SDNodes; }
 
   /// Returns whether this is an indirect value.
   bool isIndirect() const { return IsIndirect; }
 
+  bool isVariadic() const { return IsVariadic; }
+
   /// Returns the DebugLoc.
   DebugLoc getDebugLoc() const { return DL; }
 

diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 64ef4d6b5a952..fbcc0ed7d0e40 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -8449,7 +8449,8 @@ SDDbgValue *SelectionDAG::getDbgValue(DIVariable *Var, DIExpression *Expr,
   assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
          "Expected inlined-at fields to agree");
   return new (DbgInfo->getAlloc())
-      SDDbgValue(Var, Expr, N, R, IsIndirect, DL, O);
+      SDDbgValue(Var, Expr, SDDbgOperand::fromNode(N, R), N, IsIndirect, DL, O,
+                 /*IsVariadic=*/false);
 }
 
 /// Constant
@@ -8459,7 +8460,9 @@ SDDbgValue *SelectionDAG::getConstantDbgValue(DIVariable *Var,
                                               const DebugLoc &DL, unsigned O) {
   assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
          "Expected inlined-at fields to agree");
-  return new (DbgInfo->getAlloc()) SDDbgValue(Var, Expr, C, DL, O);
+  return new (DbgInfo->getAlloc()) SDDbgValue(
+      Var, Expr, SDDbgOperand::fromConst(C), {}, /*IsIndirect=*/false, DL, O,
+      /*IsVariadic=*/false);
 }
 
 /// FrameIndex
@@ -8471,7 +8474,8 @@ SDDbgValue *SelectionDAG::getFrameIndexDbgValue(DIVariable *Var,
   assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
          "Expected inlined-at fields to agree");
   return new (DbgInfo->getAlloc())
-      SDDbgValue(Var, Expr, FI, IsIndirect, DL, O, SDDbgValue::FRAMEIX);
+      SDDbgValue(Var, Expr, SDDbgOperand::fromFrameIdx(FI), {}, IsIndirect, DL,
+                 O, /*IsVariadic=*/false);
 }
 
 /// VReg
@@ -8482,7 +8486,8 @@ SDDbgValue *SelectionDAG::getVRegDbgValue(DIVariable *Var,
   assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
          "Expected inlined-at fields to agree");
   return new (DbgInfo->getAlloc())
-      SDDbgValue(Var, Expr, VReg, IsIndirect, DL, O, SDDbgValue::VREG);
+      SDDbgValue(Var, Expr, SDDbgOperand::fromVReg(VReg), {}, IsIndirect, DL, O,
+                 /*IsVariadic=*/false);
 }
 
 void SelectionDAG::transferDbgValues(SDValue From, SDValue To,
@@ -8503,13 +8508,14 @@ void SelectionDAG::transferDbgValues(SDValue From, SDValue To,
 
   SmallVector<SDDbgValue *, 2> ClonedDVs;
   for (SDDbgValue *Dbg : GetDbgValues(FromNode)) {
-    if (Dbg->getKind() != SDDbgValue::SDNODE || Dbg->isInvalidated())
+    SDDbgOperand DbgOperand = Dbg->getLocationOps()[0];
+    if (DbgOperand.getKind() != SDDbgOperand::SDNODE || Dbg->isInvalidated())
       continue;
 
     // TODO: assert(!Dbg->isInvalidated() && "Transfer of invalid dbg value");
 
     // Just transfer the dbg value attached to From.
-    if (Dbg->getResNo() != From.getResNo())
+    if (DbgOperand.getResNo() != From.getResNo())
       continue;
 
     DIVariable *Var = Dbg->getVariable();
@@ -8583,7 +8589,7 @@ void SelectionDAG::salvageDebugInfo(SDNode &N) {
   }
 
   for (SDDbgValue *Dbg : ClonedDVs)
-    AddDbgValue(Dbg, Dbg->getSDNode(), false);
+    AddDbgValue(Dbg, Dbg->getLocationOps()[0].getSDNode(), false);
 }
 
 /// Creates a SDDbgLabel node.

diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index f869b2c41f9fd..d88049506b718 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -1157,6 +1157,8 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
   for (auto &DDI : DDIV) {
     const DbgValueInst *DI = DDI.getDI();
     assert(DI && "Ill-formed DanglingDebugInfo");
+    assert(!DDI.getDI()->hasArgList() &&
+           "Variadic dbg.values should not yet be left dangling.");
     DebugLoc dl = DDI.getdl();
     unsigned ValSDNodeOrder = Val.getNode()->getIROrder();
     unsigned DbgSDNodeOrder = DDI.getSDNodeOrder();
@@ -1191,7 +1193,7 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
                           << "in EmitFuncArgumentDbgValue\n");
     } else {
       LLVM_DEBUG(dbgs() << "Dropping debug info for " << *DI << "\n");
-      auto Undef = UndefValue::get(DDI.getDI()->getValue()->getType());
+      auto Undef = UndefValue::get(DDI.getDI()->getValue(0)->getType());
       auto SDV =
           DAG.getConstantDbgValue(Variable, Expr, Undef, dl, DbgSDNodeOrder);
       DAG.AddDbgValue(SDV, nullptr, false);
@@ -1201,7 +1203,9 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
 }
 
 void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) {
-  Value *V = DDI.getDI()->getValue();
+  assert(!DDI.getDI()->hasArgList() &&
+         "Variadic dbg.values should not yet be left dangling.");
+  Value *V = DDI.getDI()->getValue(0);
   DILocalVariable *Var = DDI.getDI()->getVariable();
   DIExpression *Expr = DDI.getDI()->getExpression();
   DebugLoc DL = DDI.getdl();
@@ -1245,7 +1249,7 @@ void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) {
   // This was the final opportunity to salvage this debug information, and it
   // couldn't be done. Place an undef DBG_VALUE at this location to terminate
   // any earlier variable location.
-  auto Undef = UndefValue::get(DDI.getDI()->getValue()->getType());
+  auto Undef = UndefValue::get(DDI.getDI()->getValue(0)->getType());
   auto SDV = DAG.getConstantDbgValue(Var, Expr, Undef, DL, SDNodeOrder);
   DAG.AddDbgValue(SDV, nullptr, false);
 
@@ -5977,7 +5981,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
     DILocalVariable *Variable = DI.getVariable();
     DIExpression *Expression = DI.getExpression();
     dropDanglingDebugInfo(Variable, Expression);
-    const Value *V = DI.getValue();
+    const Value *V = DI.getValue(0);
     if (!V)
       return;
 

diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index c78d74585cbd3..20f29048179c2 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -832,26 +832,38 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
 
 LLVM_DUMP_METHOD void SDDbgValue::print(raw_ostream &OS) const {
   OS << " DbgVal(Order=" << getOrder() << ')';
-  if (isInvalidated()) OS << "(Invalidated)";
-  if (isEmitted()) OS << "(Emitted)";
-  switch (getKind()) {
-  case SDNODE:
-    if (getSDNode())
-      OS << "(SDNODE=" << PrintNodeId(*getSDNode()) << ':' <<  getResNo() << ')';
-    else
-      OS << "(SDNODE)";
-    break;
-  case CONST:
-    OS << "(CONST)";
-    break;
-  case FRAMEIX:
-    OS << "(FRAMEIX=" << getFrameIx() << ')';
-    break;
-  case VREG:
-    OS << "(VREG=" << getVReg() << ')';
-    break;
+  if (isInvalidated())
+    OS << "(Invalidated)";
+  if (isEmitted())
+    OS << "(Emitted)";
+  OS << "(";
+  bool Comma = false;
+  for (const SDDbgOperand &Op : getLocationOps()) {
+    if (Comma)
+      OS << ", ";
+    switch (Op.getKind()) {
+    case SDDbgOperand::SDNODE:
+      if (Op.getSDNode())
+        OS << "SDNODE=" << PrintNodeId(*Op.getSDNode()) << ':' << Op.getResNo();
+      else
+        OS << "SDNODE";
+      break;
+    case SDDbgOperand::CONST:
+      OS << "CONST";
+      break;
+    case SDDbgOperand::FRAMEIX:
+      OS << "FRAMEIX=" << Op.getFrameIx();
+      break;
+    case SDDbgOperand::VREG:
+      OS << "VREG=" << Op.getVReg();
+      break;
+    }
+    Comma = true;
   }
+  OS << ")";
   if (isIndirect()) OS << "(Indirect)";
+  if (isVariadic())
+    OS << "(Variadic)";
   OS << ":\"" << Var->getName() << '"';
 #ifndef NDEBUG
   if (Expr->getNumElements())


        


More information about the llvm-commits mailing list