diff --git a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp --- a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -701,11 +701,12 @@ 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 @@ // 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 @@ 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(V)) { if (CI->getBitWidth() > 64) MIB.addCImm(CI); @@ -770,14 +771,18 @@ MachineInstr * InstrEmitter::EmitDbgInstrRef(SDDbgValue *SD, DenseMap &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::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 --- a/llvm/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h +++ b/llvm/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h @@ -25,69 +25,140 @@ 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; + using SDNodeVector = SmallVector; + +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 L, + ArrayRef 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 @@ /// 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 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 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 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -8449,7 +8449,8 @@ assert(cast(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 @@ const DebugLoc &DL, unsigned O) { assert(cast(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 @@ assert(cast(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 @@ assert(cast(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 @@ SmallVector 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 @@ } 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 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1157,6 +1157,8 @@ 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 @@ << "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::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 @@ // 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 @@ 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 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp @@ -832,26 +832,38 @@ 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())