diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h --- a/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -74,6 +74,7 @@ class OptimizationRemarkEmitter; class ProfileSummaryInfo; class SDDbgValue; +class SDDbgOperand; class SDDbgLabel; class SelectionDAG; class SelectionDAGTargetInfo; @@ -159,17 +160,9 @@ SDDbgInfo(const SDDbgInfo &) = delete; SDDbgInfo &operator=(const SDDbgInfo &) = delete; - void add(SDDbgValue *V, const SDNode *Node, bool isParameter) { - if (isParameter) { - ByvalParmDbgValues.push_back(V); - } else DbgValues.push_back(V); - if (Node) - DbgValMap[Node].push_back(V); - } + void add(SDDbgValue *V, bool isParameter); - void add(SDDbgLabel *L) { - DbgLabels.push_back(L); - } + void add(SDDbgLabel *L) { DbgLabels.push_back(L); } /// Invalidate all DbgValues attached to the node and remove /// it from the Node-to-DbgValues map. @@ -1534,11 +1527,24 @@ unsigned FI, bool IsIndirect, const DebugLoc &DL, unsigned O); + /// Creates a FrameIndex SDDbgValue node. + SDDbgValue *getFrameIndexDbgValue(DIVariable *Var, DIExpression *Expr, + unsigned FI, + ArrayRef Dependencies, + bool IsIndirect, const DebugLoc &DL, + unsigned O); + /// Creates a VReg SDDbgValue node. SDDbgValue *getVRegDbgValue(DIVariable *Var, DIExpression *Expr, unsigned VReg, bool IsIndirect, const DebugLoc &DL, unsigned O); + /// Creates a SDDbgValue node from a list of locations. + SDDbgValue *getDbgValueList(DIVariable *Var, DIExpression *Expr, + ArrayRef Locs, + ArrayRef Dependencies, bool IsIndirect, + const DebugLoc &DL, unsigned O, bool IsVariadic); + /// Creates a SDDbgLabel node. SDDbgLabel *getDbgLabel(DILabel *Label, const DebugLoc &DL, unsigned O); @@ -1629,7 +1635,7 @@ /// Add a dbg_value SDNode. If SD is non-null that means the /// value is produced by SD. - void AddDbgValue(SDDbgValue *DB, SDNode *SD, bool isParameter); + void AddDbgValue(SDDbgValue *DB, bool isParameter); /// Add a dbg_label SDNode. void AddDbgLabel(SDDbgLabel *DB); 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 @@ -94,6 +94,7 @@ case FRAMEIX: return getFrameIx() == Other.getFrameIx(); } + return false; } private: 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 @@ -879,6 +879,17 @@ DeallocateNode(N); } +void SDDbgInfo::add(SDDbgValue *V, bool isParameter) { + assert(!(V->isVariadic() && isParameter)); + if (isParameter) + ByvalParmDbgValues.push_back(V); + else + DbgValues.push_back(V); + for (const SDNode *Node : V->getSDNodes()) + if (Node) + DbgValMap[Node].push_back(V); +} + void SDDbgInfo::erase(const SDNode *Node) { DbgValMapType::iterator I = DbgValMap.find(Node); if (I == DbgValMap.end()) @@ -8473,14 +8484,26 @@ unsigned O) { assert(cast(Var)->isValidLocationForIntrinsic(DL) && "Expected inlined-at fields to agree"); + return getFrameIndexDbgValue(Var, Expr, FI, {}, IsIndirect, DL, O); +} + +/// FrameIndex with dependencies +SDDbgValue *SelectionDAG::getFrameIndexDbgValue(DIVariable *Var, + DIExpression *Expr, unsigned FI, + ArrayRef Dependencies, + bool IsIndirect, + const DebugLoc &DL, + unsigned O) { + assert(cast(Var)->isValidLocationForIntrinsic(DL) && + "Expected inlined-at fields to agree"); return new (DbgInfo->getAlloc()) - SDDbgValue(Var, Expr, SDDbgOperand::fromFrameIdx(FI), {}, IsIndirect, DL, - O, /*IsVariadic=*/false); + SDDbgValue(Var, Expr, SDDbgOperand::fromFrameIdx(FI), Dependencies, + IsIndirect, DL, O, + /*IsVariadic=*/false); } /// VReg -SDDbgValue *SelectionDAG::getVRegDbgValue(DIVariable *Var, - DIExpression *Expr, +SDDbgValue *SelectionDAG::getVRegDbgValue(DIVariable *Var, DIExpression *Expr, unsigned VReg, bool IsIndirect, const DebugLoc &DL, unsigned O) { assert(cast(Var)->isValidLocationForIntrinsic(DL) && @@ -8490,6 +8513,17 @@ /*IsVariadic=*/false); } +SDDbgValue *SelectionDAG::getDbgValueList(DIVariable *Var, DIExpression *Expr, + ArrayRef Locs, + ArrayRef Dependencies, + bool IsIndirect, const DebugLoc &DL, + unsigned O, bool IsVariadic) { + assert(cast(Var)->isValidLocationForIntrinsic(DL) && + "Expected inlined-at fields to agree"); + return new (DbgInfo->getAlloc()) + SDDbgValue(Var, Expr, Locs, Dependencies, IsIndirect, DL, O, IsVariadic); +} + void SelectionDAG::transferDbgValues(SDValue From, SDValue To, unsigned OffsetInBits, unsigned SizeInBits, bool InvalidateDbg) { @@ -8506,16 +8540,31 @@ if (!FromNode->getHasDebugValue()) return; + SDDbgOperand FromLocOp = + SDDbgOperand::fromNode(From.getNode(), From.getResNo()); + SDDbgOperand ToLocOp = SDDbgOperand::fromNode(To.getNode(), To.getResNo()); + SmallVector ClonedDVs; for (SDDbgValue *Dbg : GetDbgValues(FromNode)) { - SDDbgOperand DbgOperand = Dbg->getLocationOps()[0]; - if (DbgOperand.getKind() != SDDbgOperand::SDNODE || Dbg->isInvalidated()) + if (Dbg->isInvalidated()) continue; // TODO: assert(!Dbg->isInvalidated() && "Transfer of invalid dbg value"); - // Just transfer the dbg value attached to From. - if (DbgOperand.getResNo() != From.getResNo()) + // Create a new location ops vector that is equal to the old vector, but + // with each instance of FromLocOp replaced with ToLocOp. + bool Changed = false; + auto NewLocOps = Dbg->copyLocationOps(); + std::replace_if( + NewLocOps.begin(), NewLocOps.end(), + [&Changed, FromLocOp](const SDDbgOperand &Op) { + bool Match = Op == FromLocOp; + Changed |= Match; + return Match; + }, + ToLocOp); + // Ignore this SDDbgValue if we didn't find a matching location. + if (!Changed) continue; DIVariable *Var = Dbg->getVariable(); @@ -8534,10 +8583,15 @@ continue; Expr = *Fragment; } + + auto NewDependencies = Dbg->copySDNodes(); + std::replace(NewDependencies.begin(), NewDependencies.end(), FromNode, + ToNode); // Clone the SDDbgValue and move it to To. - SDDbgValue *Clone = getDbgValue( - Var, Expr, ToNode, To.getResNo(), Dbg->isIndirect(), Dbg->getDebugLoc(), - std::max(ToNode->getIROrder(), Dbg->getOrder())); + SDDbgValue *Clone = getDbgValueList( + Var, Expr, NewLocOps, NewDependencies, Dbg->isIndirect(), + Dbg->getDebugLoc(), std::max(ToNode->getIROrder(), Dbg->getOrder()), + Dbg->isVariadic()); ClonedDVs.push_back(Clone); if (InvalidateDbg) { @@ -8547,8 +8601,11 @@ } } - for (SDDbgValue *Dbg : ClonedDVs) - AddDbgValue(Dbg, ToNode, false); + for (SDDbgValue *Dbg : ClonedDVs) { + assert(is_contained(Dbg->getSDNodes(), ToNode) && + "Transferred DbgValues should depend on the new SDNode"); + AddDbgValue(Dbg, false); + } } void SelectionDAG::salvageDebugInfo(SDNode &N) { @@ -8568,16 +8625,37 @@ if (!isConstantIntBuildVectorOrConstantInt(N0) && isConstantIntBuildVectorOrConstantInt(N1)) { uint64_t Offset = N.getConstantOperandVal(1); + // Rewrite an ADD constant node into a DIExpression. Since we are // performing arithmetic to compute the variable's *value* in the // DIExpression, we need to mark the expression with a // DW_OP_stack_value. auto *DIExpr = DV->getExpression(); - DIExpr = - DIExpression::prepend(DIExpr, DIExpression::StackValue, Offset); - SDDbgValue *Clone = - getDbgValue(DV->getVariable(), DIExpr, N0.getNode(), N0.getResNo(), - DV->isIndirect(), DV->getDebugLoc(), DV->getOrder()); + auto NewLocOps = DV->copyLocationOps(); + bool Changed = false; + for (size_t i = 0; i < NewLocOps.size(); ++i) { + // We're not given a ResNo to compare against because the whole + // node is going away. We know that any ISD::ADD only has one + // result, so we can assume any node match is using the result. + if (NewLocOps[i].getKind() != SDDbgOperand::SDNODE || + NewLocOps[i].getSDNode() != &N) + continue; + NewLocOps[i] = SDDbgOperand::fromNode(N0.getNode(), N0.getResNo()); + SmallVector ExprOps; + DIExpression::appendOffset(ExprOps, Offset); + DIExpr = DIExpression::appendOpsToArg(DIExpr, ExprOps, i, true); + Changed = true; + } + (void)Changed; + assert(Changed && "Salvage target doesn't use N"); + + auto NewDependencies = DV->copySDNodes(); + std::replace(NewDependencies.begin(), NewDependencies.end(), &N, + N0.getNode()); + SDDbgValue *Clone = getDbgValueList(DV->getVariable(), DIExpr, + NewLocOps, NewDependencies, + DV->isIndirect(), DV->getDebugLoc(), + DV->getOrder(), DV->isVariadic()); ClonedDVs.push_back(Clone); DV->setIsInvalidated(); DV->setIsEmitted(); @@ -8588,8 +8666,11 @@ } } - for (SDDbgValue *Dbg : ClonedDVs) - AddDbgValue(Dbg, Dbg->getLocationOps()[0].getSDNode(), false); + for (SDDbgValue *Dbg : ClonedDVs) { + assert(!Dbg->getSDNodes().empty() && + "Salvaged DbgValue should depend on a new SDNode"); + AddDbgValue(Dbg, false); + } } /// Creates a SDDbgLabel node. @@ -9070,17 +9151,17 @@ /// AddDbgValue - Add a dbg_value SDNode. If SD is non-null that means the /// value is produced by SD. -void SelectionDAG::AddDbgValue(SDDbgValue *DB, SDNode *SD, bool isParameter) { - if (SD) { +void SelectionDAG::AddDbgValue(SDDbgValue *DB, bool isParameter) { + for (SDNode *SD : DB->getSDNodes()) { + if (!SD) + continue; assert(DbgInfo->getSDDbgValues(SD).empty() || SD->getHasDebugValue()); SD->setHasDebugValue(true); } - DbgInfo->add(DB, SD, isParameter); + DbgInfo->add(DB, isParameter); } -void SelectionDAG::AddDbgLabel(SDDbgLabel *DB) { - DbgInfo->add(DB); -} +void SelectionDAG::AddDbgLabel(SDDbgLabel *DB) { DbgInfo->add(DB); } SDValue SelectionDAG::makeEquivalentMemoryOrdering(SDValue OldChain, SDValue NewMemOpChain) { diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -492,6 +492,10 @@ /// of the specified type Ty. Return empty SDValue() otherwise. SDValue getCopyFromRegs(const Value *V, Type *Ty); + /// Register a dbg_value which relies on a Value which we have not yet seen. + void addDanglingDebugInfo(const DbgValueInst *DI, DebugLoc DL, + unsigned Order); + /// If we have dangling debug info that describes \p Variable, or an /// overlapping part of variable considering the \p Expr, then this method /// will drop that debug info as it isn't valid any longer. @@ -507,11 +511,11 @@ /// this cannot be done, produce an Undef debug value record. void salvageUnresolvedDbgValue(DanglingDebugInfo &DDI); - /// For a given Value, attempt to create and record a SDDbgValue in the - /// SelectionDAG. - bool handleDebugValue(const Value *V, DILocalVariable *Var, - DIExpression *Expr, DebugLoc CurDL, - DebugLoc InstDL, unsigned Order); + /// For a given list of Values, attempt to create and record a SDDbgValue in + /// the SelectionDAG. + bool handleDebugValue(ArrayRef Values, DILocalVariable *Var, + DIExpression *Expr, DebugLoc CurDL, DebugLoc InstDL, + unsigned Order, bool IsVariadic); /// Evict any dangling debug information, attempting to salvage it first. void resolveOrClearDbgInfo(); 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 @@ -1119,6 +1119,33 @@ } } +void SelectionDAGBuilder::addDanglingDebugInfo(const DbgValueInst *DI, + DebugLoc DL, unsigned Order) { + // We treat variadic dbg_values differently at this stage. + if (DI->hasArgList()) { + // For variadic dbg_values we will now insert an undef. + // FIXME: We can potentially recover these! + SmallVector Locs; + for (const Value *V : DI->getValues()) { + auto Undef = UndefValue::get(V->getType()); + Locs.push_back(SDDbgOperand::fromConst(Undef)); + } + SDDbgValue *SDV = DAG.getDbgValueList( + DI->getVariable(), DI->getExpression(), Locs, {}, + /*IsIndirect=*/false, DL, Order, /*IsVariadic=*/true); + DAG.AddDbgValue(SDV, /*isParameter=*/false); + } else { + // TODO: Dangling debug info will eventually either be resolved or produce + // an Undef DBG_VALUE. However in the resolution case, a gap may appear + // between the original dbg.value location and its resolved DBG_VALUE, + // which we should ideally fill with an extra Undef DBG_VALUE. + assert(DI->getNumVariableLocationOps() == 1 && + "DbgValueInst without an ArgList should have a single location " + "operand."); + DanglingDebugInfoMap[DI->getValue(0)].emplace_back(DI, DL, Order); + } +} + void SelectionDAGBuilder::dropDanglingDebugInfo(const DILocalVariable *Variable, const DIExpression *Expr) { auto isMatchingDbgValue = [&](DanglingDebugInfo &DDI) { @@ -1156,9 +1183,8 @@ DanglingDebugInfoVector &DDIV = DanglingDbgInfoIt->second; for (auto &DDI : DDIV) { const DbgValueInst *DI = DDI.getDI(); + assert(!DI->hasArgList() && "Not implemented for variadic dbg_values"); 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(); @@ -1187,7 +1213,7 @@ << ValSDNodeOrder << "\n"); SDV = getDbgValue(Val, Variable, Expr, dl, std::max(DbgSDNodeOrder, ValSDNodeOrder)); - DAG.AddDbgValue(SDV, Val.getNode(), false); + DAG.AddDbgValue(SDV, false); } else LLVM_DEBUG(dbgs() << "Resolved dangling debug info for " << *DI << "in EmitFuncArgumentDbgValue\n"); @@ -1196,7 +1222,7 @@ auto Undef = UndefValue::get(DDI.getDI()->getValue(0)->getType()); auto SDV = DAG.getConstantDbgValue(Variable, Expr, Undef, dl, DbgSDNodeOrder); - DAG.AddDbgValue(SDV, nullptr, false); + DAG.AddDbgValue(SDV, false); } } DDIV.clear(); @@ -1204,21 +1230,20 @@ void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) { assert(!DDI.getDI()->hasArgList() && - "Variadic dbg.values should not yet be left dangling."); + "Not implemented for variadic dbg_values"); Value *V = DDI.getDI()->getValue(0); DILocalVariable *Var = DDI.getDI()->getVariable(); DIExpression *Expr = DDI.getDI()->getExpression(); DebugLoc DL = DDI.getdl(); DebugLoc InstDL = DDI.getDI()->getDebugLoc(); unsigned SDOrder = DDI.getSDNodeOrder(); - // Currently we consider only dbg.value intrinsics -- we tell the salvager // that DW_OP_stack_value is desired. assert(isa(DDI.getDI())); bool StackValue = true; // Can this Value can be encoded without any further work? - if (handleDebugValue(V, Var, Expr, DL, InstDL, SDOrder)) + if (handleDebugValue(V, Var, Expr, DL, InstDL, SDOrder, /*IsVariadic=*/false)) return; // Attempt to salvage back through as many instructions as possible. Bail if @@ -1239,7 +1264,8 @@ // Some kind of simplification occurred: check whether the operand of the // salvaged debug expression can be encoded in this DAG. - if (handleDebugValue(V, Var, Expr, DL, InstDL, SDOrder)) { + if (handleDebugValue(V, Var, Expr, DL, InstDL, SDOrder, + /*IsVariadic=*/false)) { LLVM_DEBUG(dbgs() << "Salvaged debug location info for:\n " << DDI.getDI() << "\nBy stripping back to:\n " << V); return; @@ -1251,7 +1277,7 @@ // any earlier variable location. auto Undef = UndefValue::get(DDI.getDI()->getValue(0)->getType()); auto SDV = DAG.getConstantDbgValue(Var, Expr, Undef, DL, SDNodeOrder); - DAG.AddDbgValue(SDV, nullptr, false); + DAG.AddDbgValue(SDV, false); LLVM_DEBUG(dbgs() << "Dropping debug value info for:\n " << DDI.getDI() << "\n"); @@ -1259,53 +1285,72 @@ << "\n"); } -bool SelectionDAGBuilder::handleDebugValue(const Value *V, DILocalVariable *Var, +bool SelectionDAGBuilder::handleDebugValue(ArrayRef Values, + DILocalVariable *Var, DIExpression *Expr, DebugLoc dl, - DebugLoc InstDL, unsigned Order) { - const TargetLowering &TLI = DAG.getTargetLoweringInfo(); - SDDbgValue *SDV; - if (isa(V) || isa(V) || isa(V) || - isa(V)) { - SDV = DAG.getConstantDbgValue(Var, Expr, V, dl, SDNodeOrder); - DAG.AddDbgValue(SDV, nullptr, false); + DebugLoc InstDL, unsigned Order, + bool IsVariadic) { + if (Values.empty()) return true; - } + SDDbgValue::LocOpVector LocationOps; + SDDbgValue::SDNodeVector Dependencies; + for (const Value *V : Values) { + // Constant value. + if (isa(V) || isa(V) || isa(V) || + isa(V)) { + LocationOps.emplace_back(SDDbgOperand::fromConst(V)); + continue; + } - // If the Value is a frame index, we can create a FrameIndex debug value - // without relying on the DAG at all. - if (const AllocaInst *AI = dyn_cast(V)) { - auto SI = FuncInfo.StaticAllocaMap.find(AI); - if (SI != FuncInfo.StaticAllocaMap.end()) { - auto SDV = - DAG.getFrameIndexDbgValue(Var, Expr, SI->second, - /*IsIndirect*/ false, dl, SDNodeOrder); - // Do not attach the SDNodeDbgValue to an SDNode: this variable location - // is still available even if the SDNode gets optimized out. - DAG.AddDbgValue(SDV, nullptr, false); - return true; + // If the Value is a frame index, we can create a FrameIndex debug value + // without relying on the DAG at all. + if (const AllocaInst *AI = dyn_cast(V)) { + auto SI = FuncInfo.StaticAllocaMap.find(AI); + if (SI != FuncInfo.StaticAllocaMap.end()) { + LocationOps.emplace_back(SDDbgOperand::fromFrameIdx(SI->second)); + continue; + } } - } - // Do not use getValue() in here; we don't want to generate code at - // this point if it hasn't been done yet. - SDValue N = NodeMap[V]; - if (!N.getNode() && isa(V)) // Check unused arguments map. - N = UnusedArgNodeMap[V]; - if (N.getNode()) { - if (EmitFuncArgumentDbgValue(V, Var, Expr, dl, false, N)) - return true; - SDV = getDbgValue(N, Var, Expr, dl, SDNodeOrder); - DAG.AddDbgValue(SDV, N.getNode(), false); - return true; - } + // Do not use getValue() in here; we don't want to generate code at + // this point if it hasn't been done yet. + SDValue N = NodeMap[V]; + if (!N.getNode() && isa(V)) // Check unused arguments map. + N = UnusedArgNodeMap[V]; + if (N.getNode()) { + // Only emit func arg dbg value for non-variadic dbg.values for now. + if (!IsVariadic && EmitFuncArgumentDbgValue(V, Var, Expr, dl, false, N)) + return true; + Dependencies.push_back(N.getNode()); + if (auto *FISDN = dyn_cast(N.getNode())) { + // Construct a FrameIndexDbgValue for FrameIndexSDNodes so we can + // describe stack slot locations. + // + // Consider "int x = 0; int *px = &x;". There are two kinds of + // interesting debug values here after optimization: + // + // dbg.value(i32* %px, !"int *px", !DIExpression()), and + // dbg.value(i32* %px, !"int x", !DIExpression(DW_OP_deref)) + // + // Both describe the direct values of their associated variables. + LocationOps.emplace_back(SDDbgOperand::fromFrameIdx(FISDN->getIndex())); + continue; + } + LocationOps.emplace_back( + SDDbgOperand::fromNode(N.getNode(), N.getResNo())); + continue; + } + + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + // Special rules apply for the first dbg.values of parameter variables in a + // function. Identify them by the fact they reference Argument Values, that + // they're parameters, and they are parameters of the current function. We + // need to let them dangle until they get an SDNode. + bool IsParamOfFunc = + isa(V) && Var->isParameter() && !InstDL.getInlinedAt(); + if (IsParamOfFunc) + return false; - // Special rules apply for the first dbg.values of parameter variables in a - // function. Identify them by the fact they reference Argument Values, that - // they're parameters, and they are parameters of the current function. We - // need to let them dangle until they get an SDNode. - bool IsParamOfFunc = isa(V) && Var->isParameter() && - !InstDL.getInlinedAt(); - if (!IsParamOfFunc) { // The value is not used in this block yet (or it would have an SDNode). // We still want the value to appear for the user if possible -- if it has // an associated VReg, we can refer to that instead. @@ -1317,6 +1362,9 @@ RegsForValue RFV(V->getContext(), TLI, DAG.getDataLayout(), Reg, V->getType(), None); if (RFV.occupiesMultipleRegs()) { + // FIXME: We could potentially support variadic dbg_values here. + if (IsVariadic) + return false; unsigned Offset = 0; unsigned BitsToDescribe = 0; if (auto VarSize = Var->getSizeInBits()) @@ -1330,26 +1378,35 @@ // TODO: handle scalable vectors. unsigned RegisterSize = RegAndSize.second; unsigned FragmentSize = (Offset + RegisterSize > BitsToDescribe) - ? BitsToDescribe - Offset - : RegisterSize; + ? BitsToDescribe - Offset + : RegisterSize; auto FragmentExpr = DIExpression::createFragmentExpression( Expr, Offset, FragmentSize); if (!FragmentExpr) - continue; - SDV = DAG.getVRegDbgValue(Var, *FragmentExpr, RegAndSize.first, - false, dl, SDNodeOrder); - DAG.AddDbgValue(SDV, nullptr, false); + continue; + SDDbgValue *SDV = DAG.getVRegDbgValue( + Var, *FragmentExpr, RegAndSize.first, false, dl, SDNodeOrder); + DAG.AddDbgValue(SDV, false); Offset += RegisterSize; } - } else { - SDV = DAG.getVRegDbgValue(Var, Expr, Reg, false, dl, SDNodeOrder); - DAG.AddDbgValue(SDV, nullptr, false); + return true; } - return true; + // We can use simple vreg locations for variadic dbg_values as well. + LocationOps.emplace_back(SDDbgOperand::fromVReg(Reg)); + continue; } + // We failed to create a SDDbgOperand for V. + return false; } - return false; + // We have created a SDDbgOperand for each Value in Values. + // Should use Order instead of SDNodeOrder? + assert(!LocationOps.empty()); + SDDbgValue *SDV = + DAG.getDbgValueList(Var, Expr, LocationOps, Dependencies, + /*IsIndirect=*/false, dl, SDNodeOrder, IsVariadic); + DAG.AddDbgValue(SDV, /*isParameter=*/false); + return true; } void SelectionDAGBuilder::resolveOrClearDbgInfo() { @@ -5398,6 +5455,8 @@ /// If the DbgValueInst is a dbg_value of a function argument, create the /// corresponding DBG_VALUE machine instruction for it now. At the end of /// instruction selection, they will be inserted to the entry BB. +/// We don't currently support this for variadic dbg_values, as they shouldn't +/// appear for function arguments or in the prologue. bool SelectionDAGBuilder::EmitFuncArgumentDbgValue( const Value *V, DILocalVariable *Variable, DIExpression *Expr, DILocation *DL, bool IsDbgDeclare, const SDValue &N) { @@ -5539,7 +5598,7 @@ if (!FragmentExpr) { SDDbgValue *SDV = DAG.getConstantDbgValue( Variable, Expr, UndefValue::get(V->getType()), DL, SDNodeOrder); - DAG.AddDbgValue(SDV, nullptr, false); + DAG.AddDbgValue(SDV, false); continue; } assert(!IsDbgDeclare && "DbgDeclare operand is not in memory?"); @@ -5880,7 +5939,10 @@ } case Intrinsic::dbg_addr: case Intrinsic::dbg_declare: { + // Assume dbg.addr and dbg.declare can not currently use DIArgList, i.e. + // they are non-variadic. const auto &DI = cast(I); + assert(!DI.hasArgList() && "Only dbg.value should currently use DIArgList"); DILocalVariable *Variable = DI.getVariable(); DIExpression *Expression = DI.getExpression(); dropDanglingDebugInfo(Variable, Expression); @@ -5919,8 +5981,9 @@ if (FI != std::numeric_limits::max()) { if (Intrinsic == Intrinsic::dbg_addr) { SDDbgValue *SDV = DAG.getFrameIndexDbgValue( - Variable, Expression, FI, /*IsIndirect*/ true, dl, SDNodeOrder); - DAG.AddDbgValue(SDV, getRoot().getNode(), isParameter); + Variable, Expression, FI, getRoot().getNode(), /*IsIndirect*/ true, + dl, SDNodeOrder); + DAG.AddDbgValue(SDV, isParameter); } else { LLVM_DEBUG(dbgs() << "Skipping " << DI << " (variable info stashed in MF side table)\n"); @@ -5952,7 +6015,7 @@ SDV = DAG.getDbgValue(Variable, Expression, N.getNode(), N.getResNo(), true, dl, SDNodeOrder); } - DAG.AddDbgValue(SDV, N.getNode(), isParameter); + DAG.AddDbgValue(SDV, isParameter); } else { // If Address is an argument then try to emit its dbg value using // virtual register info from the FuncInfo.ValueMap. @@ -5981,20 +6044,17 @@ DILocalVariable *Variable = DI.getVariable(); DIExpression *Expression = DI.getExpression(); dropDanglingDebugInfo(Variable, Expression); - const Value *V = DI.getValue(0); - if (!V) + SmallVector Values(DI.getValues()); + if (Values.empty()) return; - if (handleDebugValue(V, Variable, Expression, dl, DI.getDebugLoc(), - SDNodeOrder)) + if (std::count(Values.begin(), Values.end(), nullptr)) return; - // TODO: Dangling debug info will eventually either be resolved or produce - // an Undef DBG_VALUE. However in the resolution case, a gap may appear - // between the original dbg.value location and its resolved DBG_VALUE, which - // we should ideally fill with an extra Undef DBG_VALUE. - - DanglingDebugInfoMap[V].emplace_back(&DI, dl, SDNodeOrder); + bool IsVariadic = DI.hasArgList(); + if (!handleDebugValue(Values, Variable, Expression, dl, DI.getDebugLoc(), + SDNodeOrder, IsVariadic)) + addDanglingDebugInfo(&DI, dl, SDNodeOrder); return; }