forked from OSchip/llvm-project
[DebugInfo] Handle dbg.values with multiple variable location operands in ISel
This patch adds partial support in Instruction Selection for dbg.values that use a DIArgList. This patch does not add support for producing DBG_VALUE_LIST, but adds the logic for processing DIArgLists within the ISel pass. This change is largely focused on handleDebugValue and some of the functions that it calls. Outside of this, salvageDebugInfo and transferDbgValues have been modified to replace individual operands instead of the entire value; dangling debug info for variadic debug values is not currently supported (but may be added later). Differential Revision: https://reviews.llvm.org/D88589
This commit is contained in:
parent
cf806d91d5
commit
93b170ea24
|
@ -74,6 +74,7 @@ class MCSymbol;
|
||||||
class OptimizationRemarkEmitter;
|
class OptimizationRemarkEmitter;
|
||||||
class ProfileSummaryInfo;
|
class ProfileSummaryInfo;
|
||||||
class SDDbgValue;
|
class SDDbgValue;
|
||||||
|
class SDDbgOperand;
|
||||||
class SDDbgLabel;
|
class SDDbgLabel;
|
||||||
class SelectionDAG;
|
class SelectionDAG;
|
||||||
class SelectionDAGTargetInfo;
|
class SelectionDAGTargetInfo;
|
||||||
|
@ -159,17 +160,9 @@ public:
|
||||||
SDDbgInfo(const SDDbgInfo &) = delete;
|
SDDbgInfo(const SDDbgInfo &) = delete;
|
||||||
SDDbgInfo &operator=(const SDDbgInfo &) = delete;
|
SDDbgInfo &operator=(const SDDbgInfo &) = delete;
|
||||||
|
|
||||||
void add(SDDbgValue *V, const SDNode *Node, bool isParameter) {
|
void add(SDDbgValue *V, bool isParameter);
|
||||||
if (isParameter) {
|
|
||||||
ByvalParmDbgValues.push_back(V);
|
|
||||||
} else DbgValues.push_back(V);
|
|
||||||
if (Node)
|
|
||||||
DbgValMap[Node].push_back(V);
|
|
||||||
}
|
|
||||||
|
|
||||||
void add(SDDbgLabel *L) {
|
void add(SDDbgLabel *L) { DbgLabels.push_back(L); }
|
||||||
DbgLabels.push_back(L);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Invalidate all DbgValues attached to the node and remove
|
/// Invalidate all DbgValues attached to the node and remove
|
||||||
/// it from the Node-to-DbgValues map.
|
/// it from the Node-to-DbgValues map.
|
||||||
|
@ -1534,11 +1527,24 @@ public:
|
||||||
unsigned FI, bool IsIndirect,
|
unsigned FI, bool IsIndirect,
|
||||||
const DebugLoc &DL, unsigned O);
|
const DebugLoc &DL, unsigned O);
|
||||||
|
|
||||||
|
/// Creates a FrameIndex SDDbgValue node.
|
||||||
|
SDDbgValue *getFrameIndexDbgValue(DIVariable *Var, DIExpression *Expr,
|
||||||
|
unsigned FI,
|
||||||
|
ArrayRef<SDNode *> Dependencies,
|
||||||
|
bool IsIndirect, const DebugLoc &DL,
|
||||||
|
unsigned O);
|
||||||
|
|
||||||
/// Creates a VReg SDDbgValue node.
|
/// Creates a VReg SDDbgValue node.
|
||||||
SDDbgValue *getVRegDbgValue(DIVariable *Var, DIExpression *Expr,
|
SDDbgValue *getVRegDbgValue(DIVariable *Var, DIExpression *Expr,
|
||||||
unsigned VReg, bool IsIndirect,
|
unsigned VReg, bool IsIndirect,
|
||||||
const DebugLoc &DL, unsigned O);
|
const DebugLoc &DL, unsigned O);
|
||||||
|
|
||||||
|
/// Creates a SDDbgValue node from a list of locations.
|
||||||
|
SDDbgValue *getDbgValueList(DIVariable *Var, DIExpression *Expr,
|
||||||
|
ArrayRef<SDDbgOperand> Locs,
|
||||||
|
ArrayRef<SDNode *> Dependencies, bool IsIndirect,
|
||||||
|
const DebugLoc &DL, unsigned O, bool IsVariadic);
|
||||||
|
|
||||||
/// Creates a SDDbgLabel node.
|
/// Creates a SDDbgLabel node.
|
||||||
SDDbgLabel *getDbgLabel(DILabel *Label, const DebugLoc &DL, unsigned O);
|
SDDbgLabel *getDbgLabel(DILabel *Label, const DebugLoc &DL, unsigned O);
|
||||||
|
|
||||||
|
@ -1629,7 +1635,7 @@ public:
|
||||||
|
|
||||||
/// Add a dbg_value SDNode. If SD is non-null that means the
|
/// Add a dbg_value SDNode. If SD is non-null that means the
|
||||||
/// value is produced by SD.
|
/// value is produced by SD.
|
||||||
void AddDbgValue(SDDbgValue *DB, SDNode *SD, bool isParameter);
|
void AddDbgValue(SDDbgValue *DB, bool isParameter);
|
||||||
|
|
||||||
/// Add a dbg_label SDNode.
|
/// Add a dbg_label SDNode.
|
||||||
void AddDbgLabel(SDDbgLabel *DB);
|
void AddDbgLabel(SDDbgLabel *DB);
|
||||||
|
|
|
@ -94,6 +94,7 @@ public:
|
||||||
case FRAMEIX:
|
case FRAMEIX:
|
||||||
return getFrameIx() == Other.getFrameIx();
|
return getFrameIx() == Other.getFrameIx();
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -879,6 +879,17 @@ void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *N) {
|
||||||
DeallocateNode(N);
|
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) {
|
void SDDbgInfo::erase(const SDNode *Node) {
|
||||||
DbgValMapType::iterator I = DbgValMap.find(Node);
|
DbgValMapType::iterator I = DbgValMap.find(Node);
|
||||||
if (I == DbgValMap.end())
|
if (I == DbgValMap.end())
|
||||||
|
@ -8473,14 +8484,26 @@ SDDbgValue *SelectionDAG::getFrameIndexDbgValue(DIVariable *Var,
|
||||||
unsigned O) {
|
unsigned O) {
|
||||||
assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
|
assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
|
||||||
"Expected inlined-at fields to agree");
|
"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<SDNode *> Dependencies,
|
||||||
|
bool IsIndirect,
|
||||||
|
const DebugLoc &DL,
|
||||||
|
unsigned O) {
|
||||||
|
assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
|
||||||
|
"Expected inlined-at fields to agree");
|
||||||
return new (DbgInfo->getAlloc())
|
return new (DbgInfo->getAlloc())
|
||||||
SDDbgValue(Var, Expr, SDDbgOperand::fromFrameIdx(FI), {}, IsIndirect, DL,
|
SDDbgValue(Var, Expr, SDDbgOperand::fromFrameIdx(FI), Dependencies,
|
||||||
O, /*IsVariadic=*/false);
|
IsIndirect, DL, O,
|
||||||
|
/*IsVariadic=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// VReg
|
/// VReg
|
||||||
SDDbgValue *SelectionDAG::getVRegDbgValue(DIVariable *Var,
|
SDDbgValue *SelectionDAG::getVRegDbgValue(DIVariable *Var, DIExpression *Expr,
|
||||||
DIExpression *Expr,
|
|
||||||
unsigned VReg, bool IsIndirect,
|
unsigned VReg, bool IsIndirect,
|
||||||
const DebugLoc &DL, unsigned O) {
|
const DebugLoc &DL, unsigned O) {
|
||||||
assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
|
assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
|
||||||
|
@ -8490,6 +8513,17 @@ SDDbgValue *SelectionDAG::getVRegDbgValue(DIVariable *Var,
|
||||||
/*IsVariadic=*/false);
|
/*IsVariadic=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDDbgValue *SelectionDAG::getDbgValueList(DIVariable *Var, DIExpression *Expr,
|
||||||
|
ArrayRef<SDDbgOperand> Locs,
|
||||||
|
ArrayRef<SDNode *> Dependencies,
|
||||||
|
bool IsIndirect, const DebugLoc &DL,
|
||||||
|
unsigned O, bool IsVariadic) {
|
||||||
|
assert(cast<DILocalVariable>(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,
|
void SelectionDAG::transferDbgValues(SDValue From, SDValue To,
|
||||||
unsigned OffsetInBits, unsigned SizeInBits,
|
unsigned OffsetInBits, unsigned SizeInBits,
|
||||||
bool InvalidateDbg) {
|
bool InvalidateDbg) {
|
||||||
|
@ -8506,16 +8540,31 @@ void SelectionDAG::transferDbgValues(SDValue From, SDValue To,
|
||||||
if (!FromNode->getHasDebugValue())
|
if (!FromNode->getHasDebugValue())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
SDDbgOperand FromLocOp =
|
||||||
|
SDDbgOperand::fromNode(From.getNode(), From.getResNo());
|
||||||
|
SDDbgOperand ToLocOp = SDDbgOperand::fromNode(To.getNode(), To.getResNo());
|
||||||
|
|
||||||
SmallVector<SDDbgValue *, 2> ClonedDVs;
|
SmallVector<SDDbgValue *, 2> ClonedDVs;
|
||||||
for (SDDbgValue *Dbg : GetDbgValues(FromNode)) {
|
for (SDDbgValue *Dbg : GetDbgValues(FromNode)) {
|
||||||
SDDbgOperand DbgOperand = Dbg->getLocationOps()[0];
|
if (Dbg->isInvalidated())
|
||||||
if (DbgOperand.getKind() != SDDbgOperand::SDNODE || Dbg->isInvalidated())
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// TODO: assert(!Dbg->isInvalidated() && "Transfer of invalid dbg value");
|
// TODO: assert(!Dbg->isInvalidated() && "Transfer of invalid dbg value");
|
||||||
|
|
||||||
// Just transfer the dbg value attached to From.
|
// Create a new location ops vector that is equal to the old vector, but
|
||||||
if (DbgOperand.getResNo() != From.getResNo())
|
// 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;
|
continue;
|
||||||
|
|
||||||
DIVariable *Var = Dbg->getVariable();
|
DIVariable *Var = Dbg->getVariable();
|
||||||
|
@ -8534,10 +8583,15 @@ void SelectionDAG::transferDbgValues(SDValue From, SDValue To,
|
||||||
continue;
|
continue;
|
||||||
Expr = *Fragment;
|
Expr = *Fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto NewDependencies = Dbg->copySDNodes();
|
||||||
|
std::replace(NewDependencies.begin(), NewDependencies.end(), FromNode,
|
||||||
|
ToNode);
|
||||||
// Clone the SDDbgValue and move it to To.
|
// Clone the SDDbgValue and move it to To.
|
||||||
SDDbgValue *Clone = getDbgValue(
|
SDDbgValue *Clone = getDbgValueList(
|
||||||
Var, Expr, ToNode, To.getResNo(), Dbg->isIndirect(), Dbg->getDebugLoc(),
|
Var, Expr, NewLocOps, NewDependencies, Dbg->isIndirect(),
|
||||||
std::max(ToNode->getIROrder(), Dbg->getOrder()));
|
Dbg->getDebugLoc(), std::max(ToNode->getIROrder(), Dbg->getOrder()),
|
||||||
|
Dbg->isVariadic());
|
||||||
ClonedDVs.push_back(Clone);
|
ClonedDVs.push_back(Clone);
|
||||||
|
|
||||||
if (InvalidateDbg) {
|
if (InvalidateDbg) {
|
||||||
|
@ -8547,8 +8601,11 @@ void SelectionDAG::transferDbgValues(SDValue From, SDValue To,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SDDbgValue *Dbg : ClonedDVs)
|
for (SDDbgValue *Dbg : ClonedDVs) {
|
||||||
AddDbgValue(Dbg, ToNode, false);
|
assert(is_contained(Dbg->getSDNodes(), ToNode) &&
|
||||||
|
"Transferred DbgValues should depend on the new SDNode");
|
||||||
|
AddDbgValue(Dbg, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SelectionDAG::salvageDebugInfo(SDNode &N) {
|
void SelectionDAG::salvageDebugInfo(SDNode &N) {
|
||||||
|
@ -8568,16 +8625,37 @@ void SelectionDAG::salvageDebugInfo(SDNode &N) {
|
||||||
if (!isConstantIntBuildVectorOrConstantInt(N0) &&
|
if (!isConstantIntBuildVectorOrConstantInt(N0) &&
|
||||||
isConstantIntBuildVectorOrConstantInt(N1)) {
|
isConstantIntBuildVectorOrConstantInt(N1)) {
|
||||||
uint64_t Offset = N.getConstantOperandVal(1);
|
uint64_t Offset = N.getConstantOperandVal(1);
|
||||||
|
|
||||||
// Rewrite an ADD constant node into a DIExpression. Since we are
|
// Rewrite an ADD constant node into a DIExpression. Since we are
|
||||||
// performing arithmetic to compute the variable's *value* in the
|
// performing arithmetic to compute the variable's *value* in the
|
||||||
// DIExpression, we need to mark the expression with a
|
// DIExpression, we need to mark the expression with a
|
||||||
// DW_OP_stack_value.
|
// DW_OP_stack_value.
|
||||||
auto *DIExpr = DV->getExpression();
|
auto *DIExpr = DV->getExpression();
|
||||||
DIExpr =
|
auto NewLocOps = DV->copyLocationOps();
|
||||||
DIExpression::prepend(DIExpr, DIExpression::StackValue, Offset);
|
bool Changed = false;
|
||||||
SDDbgValue *Clone =
|
for (size_t i = 0; i < NewLocOps.size(); ++i) {
|
||||||
getDbgValue(DV->getVariable(), DIExpr, N0.getNode(), N0.getResNo(),
|
// We're not given a ResNo to compare against because the whole
|
||||||
DV->isIndirect(), DV->getDebugLoc(), DV->getOrder());
|
// 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<uint64_t, 3> 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);
|
ClonedDVs.push_back(Clone);
|
||||||
DV->setIsInvalidated();
|
DV->setIsInvalidated();
|
||||||
DV->setIsEmitted();
|
DV->setIsEmitted();
|
||||||
|
@ -8588,8 +8666,11 @@ void SelectionDAG::salvageDebugInfo(SDNode &N) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SDDbgValue *Dbg : ClonedDVs)
|
for (SDDbgValue *Dbg : ClonedDVs) {
|
||||||
AddDbgValue(Dbg, Dbg->getLocationOps()[0].getSDNode(), false);
|
assert(!Dbg->getSDNodes().empty() &&
|
||||||
|
"Salvaged DbgValue should depend on a new SDNode");
|
||||||
|
AddDbgValue(Dbg, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a SDDbgLabel node.
|
/// Creates a SDDbgLabel node.
|
||||||
|
@ -9070,17 +9151,17 @@ unsigned SelectionDAG::AssignTopologicalOrder() {
|
||||||
|
|
||||||
/// AddDbgValue - Add a dbg_value SDNode. If SD is non-null that means the
|
/// AddDbgValue - Add a dbg_value SDNode. If SD is non-null that means the
|
||||||
/// value is produced by SD.
|
/// value is produced by SD.
|
||||||
void SelectionDAG::AddDbgValue(SDDbgValue *DB, SDNode *SD, bool isParameter) {
|
void SelectionDAG::AddDbgValue(SDDbgValue *DB, bool isParameter) {
|
||||||
if (SD) {
|
for (SDNode *SD : DB->getSDNodes()) {
|
||||||
|
if (!SD)
|
||||||
|
continue;
|
||||||
assert(DbgInfo->getSDDbgValues(SD).empty() || SD->getHasDebugValue());
|
assert(DbgInfo->getSDDbgValues(SD).empty() || SD->getHasDebugValue());
|
||||||
SD->setHasDebugValue(true);
|
SD->setHasDebugValue(true);
|
||||||
}
|
}
|
||||||
DbgInfo->add(DB, SD, isParameter);
|
DbgInfo->add(DB, isParameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SelectionDAG::AddDbgLabel(SDDbgLabel *DB) {
|
void SelectionDAG::AddDbgLabel(SDDbgLabel *DB) { DbgInfo->add(DB); }
|
||||||
DbgInfo->add(DB);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDValue SelectionDAG::makeEquivalentMemoryOrdering(SDValue OldChain,
|
SDValue SelectionDAG::makeEquivalentMemoryOrdering(SDValue OldChain,
|
||||||
SDValue NewMemOpChain) {
|
SDValue NewMemOpChain) {
|
||||||
|
|
|
@ -1119,6 +1119,33 @@ void SelectionDAGBuilder::visit(unsigned Opcode, const User &I) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<SDDbgOperand, 2> 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,
|
void SelectionDAGBuilder::dropDanglingDebugInfo(const DILocalVariable *Variable,
|
||||||
const DIExpression *Expr) {
|
const DIExpression *Expr) {
|
||||||
auto isMatchingDbgValue = [&](DanglingDebugInfo &DDI) {
|
auto isMatchingDbgValue = [&](DanglingDebugInfo &DDI) {
|
||||||
|
@ -1156,9 +1183,8 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
|
||||||
DanglingDebugInfoVector &DDIV = DanglingDbgInfoIt->second;
|
DanglingDebugInfoVector &DDIV = DanglingDbgInfoIt->second;
|
||||||
for (auto &DDI : DDIV) {
|
for (auto &DDI : DDIV) {
|
||||||
const DbgValueInst *DI = DDI.getDI();
|
const DbgValueInst *DI = DDI.getDI();
|
||||||
|
assert(!DI->hasArgList() && "Not implemented for variadic dbg_values");
|
||||||
assert(DI && "Ill-formed DanglingDebugInfo");
|
assert(DI && "Ill-formed DanglingDebugInfo");
|
||||||
assert(!DDI.getDI()->hasArgList() &&
|
|
||||||
"Variadic dbg.values should not yet be left dangling.");
|
|
||||||
DebugLoc dl = DDI.getdl();
|
DebugLoc dl = DDI.getdl();
|
||||||
unsigned ValSDNodeOrder = Val.getNode()->getIROrder();
|
unsigned ValSDNodeOrder = Val.getNode()->getIROrder();
|
||||||
unsigned DbgSDNodeOrder = DDI.getSDNodeOrder();
|
unsigned DbgSDNodeOrder = DDI.getSDNodeOrder();
|
||||||
|
@ -1187,7 +1213,7 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
|
||||||
<< ValSDNodeOrder << "\n");
|
<< ValSDNodeOrder << "\n");
|
||||||
SDV = getDbgValue(Val, Variable, Expr, dl,
|
SDV = getDbgValue(Val, Variable, Expr, dl,
|
||||||
std::max(DbgSDNodeOrder, ValSDNodeOrder));
|
std::max(DbgSDNodeOrder, ValSDNodeOrder));
|
||||||
DAG.AddDbgValue(SDV, Val.getNode(), false);
|
DAG.AddDbgValue(SDV, false);
|
||||||
} else
|
} else
|
||||||
LLVM_DEBUG(dbgs() << "Resolved dangling debug info for " << *DI
|
LLVM_DEBUG(dbgs() << "Resolved dangling debug info for " << *DI
|
||||||
<< "in EmitFuncArgumentDbgValue\n");
|
<< "in EmitFuncArgumentDbgValue\n");
|
||||||
|
@ -1196,7 +1222,7 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
|
||||||
auto Undef = UndefValue::get(DDI.getDI()->getValue(0)->getType());
|
auto Undef = UndefValue::get(DDI.getDI()->getValue(0)->getType());
|
||||||
auto SDV =
|
auto SDV =
|
||||||
DAG.getConstantDbgValue(Variable, Expr, Undef, dl, DbgSDNodeOrder);
|
DAG.getConstantDbgValue(Variable, Expr, Undef, dl, DbgSDNodeOrder);
|
||||||
DAG.AddDbgValue(SDV, nullptr, false);
|
DAG.AddDbgValue(SDV, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DDIV.clear();
|
DDIV.clear();
|
||||||
|
@ -1204,21 +1230,20 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
|
||||||
|
|
||||||
void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) {
|
void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) {
|
||||||
assert(!DDI.getDI()->hasArgList() &&
|
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);
|
Value *V = DDI.getDI()->getValue(0);
|
||||||
DILocalVariable *Var = DDI.getDI()->getVariable();
|
DILocalVariable *Var = DDI.getDI()->getVariable();
|
||||||
DIExpression *Expr = DDI.getDI()->getExpression();
|
DIExpression *Expr = DDI.getDI()->getExpression();
|
||||||
DebugLoc DL = DDI.getdl();
|
DebugLoc DL = DDI.getdl();
|
||||||
DebugLoc InstDL = DDI.getDI()->getDebugLoc();
|
DebugLoc InstDL = DDI.getDI()->getDebugLoc();
|
||||||
unsigned SDOrder = DDI.getSDNodeOrder();
|
unsigned SDOrder = DDI.getSDNodeOrder();
|
||||||
|
|
||||||
// Currently we consider only dbg.value intrinsics -- we tell the salvager
|
// Currently we consider only dbg.value intrinsics -- we tell the salvager
|
||||||
// that DW_OP_stack_value is desired.
|
// that DW_OP_stack_value is desired.
|
||||||
assert(isa<DbgValueInst>(DDI.getDI()));
|
assert(isa<DbgValueInst>(DDI.getDI()));
|
||||||
bool StackValue = true;
|
bool StackValue = true;
|
||||||
|
|
||||||
// Can this Value can be encoded without any further work?
|
// 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;
|
return;
|
||||||
|
|
||||||
// Attempt to salvage back through as many instructions as possible. Bail if
|
// Attempt to salvage back through as many instructions as possible. Bail if
|
||||||
|
@ -1239,7 +1264,8 @@ void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) {
|
||||||
|
|
||||||
// Some kind of simplification occurred: check whether the operand of the
|
// Some kind of simplification occurred: check whether the operand of the
|
||||||
// salvaged debug expression can be encoded in this DAG.
|
// 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 "
|
LLVM_DEBUG(dbgs() << "Salvaged debug location info for:\n "
|
||||||
<< DDI.getDI() << "\nBy stripping back to:\n " << V);
|
<< DDI.getDI() << "\nBy stripping back to:\n " << V);
|
||||||
return;
|
return;
|
||||||
|
@ -1251,7 +1277,7 @@ void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) {
|
||||||
// any earlier variable location.
|
// any earlier variable location.
|
||||||
auto Undef = UndefValue::get(DDI.getDI()->getValue(0)->getType());
|
auto Undef = UndefValue::get(DDI.getDI()->getValue(0)->getType());
|
||||||
auto SDV = DAG.getConstantDbgValue(Var, Expr, Undef, DL, SDNodeOrder);
|
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()
|
LLVM_DEBUG(dbgs() << "Dropping debug value info for:\n " << DDI.getDI()
|
||||||
<< "\n");
|
<< "\n");
|
||||||
|
@ -1259,16 +1285,21 @@ void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) {
|
||||||
<< "\n");
|
<< "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SelectionDAGBuilder::handleDebugValue(const Value *V, DILocalVariable *Var,
|
bool SelectionDAGBuilder::handleDebugValue(ArrayRef<const Value *> Values,
|
||||||
|
DILocalVariable *Var,
|
||||||
DIExpression *Expr, DebugLoc dl,
|
DIExpression *Expr, DebugLoc dl,
|
||||||
DebugLoc InstDL, unsigned Order) {
|
DebugLoc InstDL, unsigned Order,
|
||||||
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
|
bool IsVariadic) {
|
||||||
SDDbgValue *SDV;
|
if (Values.empty())
|
||||||
|
return true;
|
||||||
|
SDDbgValue::LocOpVector LocationOps;
|
||||||
|
SDDbgValue::SDNodeVector Dependencies;
|
||||||
|
for (const Value *V : Values) {
|
||||||
|
// Constant value.
|
||||||
if (isa<ConstantInt>(V) || isa<ConstantFP>(V) || isa<UndefValue>(V) ||
|
if (isa<ConstantInt>(V) || isa<ConstantFP>(V) || isa<UndefValue>(V) ||
|
||||||
isa<ConstantPointerNull>(V)) {
|
isa<ConstantPointerNull>(V)) {
|
||||||
SDV = DAG.getConstantDbgValue(Var, Expr, V, dl, SDNodeOrder);
|
LocationOps.emplace_back(SDDbgOperand::fromConst(V));
|
||||||
DAG.AddDbgValue(SDV, nullptr, false);
|
continue;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the Value is a frame index, we can create a FrameIndex debug value
|
// If the Value is a frame index, we can create a FrameIndex debug value
|
||||||
|
@ -1276,13 +1307,8 @@ bool SelectionDAGBuilder::handleDebugValue(const Value *V, DILocalVariable *Var,
|
||||||
if (const AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
|
if (const AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
|
||||||
auto SI = FuncInfo.StaticAllocaMap.find(AI);
|
auto SI = FuncInfo.StaticAllocaMap.find(AI);
|
||||||
if (SI != FuncInfo.StaticAllocaMap.end()) {
|
if (SI != FuncInfo.StaticAllocaMap.end()) {
|
||||||
auto SDV =
|
LocationOps.emplace_back(SDDbgOperand::fromFrameIdx(SI->second));
|
||||||
DAG.getFrameIndexDbgValue(Var, Expr, SI->second,
|
continue;
|
||||||
/*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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1292,20 +1318,39 @@ bool SelectionDAGBuilder::handleDebugValue(const Value *V, DILocalVariable *Var,
|
||||||
if (!N.getNode() && isa<Argument>(V)) // Check unused arguments map.
|
if (!N.getNode() && isa<Argument>(V)) // Check unused arguments map.
|
||||||
N = UnusedArgNodeMap[V];
|
N = UnusedArgNodeMap[V];
|
||||||
if (N.getNode()) {
|
if (N.getNode()) {
|
||||||
if (EmitFuncArgumentDbgValue(V, Var, Expr, dl, false, N))
|
// Only emit func arg dbg value for non-variadic dbg.values for now.
|
||||||
return true;
|
if (!IsVariadic && EmitFuncArgumentDbgValue(V, Var, Expr, dl, false, N))
|
||||||
SDV = getDbgValue(N, Var, Expr, dl, SDNodeOrder);
|
|
||||||
DAG.AddDbgValue(SDV, N.getNode(), false);
|
|
||||||
return true;
|
return true;
|
||||||
|
Dependencies.push_back(N.getNode());
|
||||||
|
if (auto *FISDN = dyn_cast<FrameIndexSDNode>(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
|
// Special rules apply for the first dbg.values of parameter variables in a
|
||||||
// function. Identify them by the fact they reference Argument Values, that
|
// function. Identify them by the fact they reference Argument Values, that
|
||||||
// they're parameters, and they are parameters of the current function. We
|
// they're parameters, and they are parameters of the current function. We
|
||||||
// need to let them dangle until they get an SDNode.
|
// need to let them dangle until they get an SDNode.
|
||||||
bool IsParamOfFunc = isa<Argument>(V) && Var->isParameter() &&
|
bool IsParamOfFunc =
|
||||||
!InstDL.getInlinedAt();
|
isa<Argument>(V) && Var->isParameter() && !InstDL.getInlinedAt();
|
||||||
if (!IsParamOfFunc) {
|
if (IsParamOfFunc)
|
||||||
|
return false;
|
||||||
|
|
||||||
// The value is not used in this block yet (or it would have an SDNode).
|
// 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
|
// We still want the value to appear for the user if possible -- if it has
|
||||||
// an associated VReg, we can refer to that instead.
|
// an associated VReg, we can refer to that instead.
|
||||||
|
@ -1317,6 +1362,9 @@ bool SelectionDAGBuilder::handleDebugValue(const Value *V, DILocalVariable *Var,
|
||||||
RegsForValue RFV(V->getContext(), TLI, DAG.getDataLayout(), Reg,
|
RegsForValue RFV(V->getContext(), TLI, DAG.getDataLayout(), Reg,
|
||||||
V->getType(), None);
|
V->getType(), None);
|
||||||
if (RFV.occupiesMultipleRegs()) {
|
if (RFV.occupiesMultipleRegs()) {
|
||||||
|
// FIXME: We could potentially support variadic dbg_values here.
|
||||||
|
if (IsVariadic)
|
||||||
|
return false;
|
||||||
unsigned Offset = 0;
|
unsigned Offset = 0;
|
||||||
unsigned BitsToDescribe = 0;
|
unsigned BitsToDescribe = 0;
|
||||||
if (auto VarSize = Var->getSizeInBits())
|
if (auto VarSize = Var->getSizeInBits())
|
||||||
|
@ -1336,20 +1384,29 @@ bool SelectionDAGBuilder::handleDebugValue(const Value *V, DILocalVariable *Var,
|
||||||
Expr, Offset, FragmentSize);
|
Expr, Offset, FragmentSize);
|
||||||
if (!FragmentExpr)
|
if (!FragmentExpr)
|
||||||
continue;
|
continue;
|
||||||
SDV = DAG.getVRegDbgValue(Var, *FragmentExpr, RegAndSize.first,
|
SDDbgValue *SDV = DAG.getVRegDbgValue(
|
||||||
false, dl, SDNodeOrder);
|
Var, *FragmentExpr, RegAndSize.first, false, dl, SDNodeOrder);
|
||||||
DAG.AddDbgValue(SDV, nullptr, false);
|
DAG.AddDbgValue(SDV, false);
|
||||||
Offset += RegisterSize;
|
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() {
|
void SelectionDAGBuilder::resolveOrClearDbgInfo() {
|
||||||
|
@ -5398,6 +5455,8 @@ getUnderlyingArgRegs(SmallVectorImpl<std::pair<unsigned, TypeSize>> &Regs,
|
||||||
/// If the DbgValueInst is a dbg_value of a function argument, create the
|
/// 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
|
/// corresponding DBG_VALUE machine instruction for it now. At the end of
|
||||||
/// instruction selection, they will be inserted to the entry BB.
|
/// 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(
|
bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
|
||||||
const Value *V, DILocalVariable *Variable, DIExpression *Expr,
|
const Value *V, DILocalVariable *Variable, DIExpression *Expr,
|
||||||
DILocation *DL, bool IsDbgDeclare, const SDValue &N) {
|
DILocation *DL, bool IsDbgDeclare, const SDValue &N) {
|
||||||
|
@ -5539,7 +5598,7 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
|
||||||
if (!FragmentExpr) {
|
if (!FragmentExpr) {
|
||||||
SDDbgValue *SDV = DAG.getConstantDbgValue(
|
SDDbgValue *SDV = DAG.getConstantDbgValue(
|
||||||
Variable, Expr, UndefValue::get(V->getType()), DL, SDNodeOrder);
|
Variable, Expr, UndefValue::get(V->getType()), DL, SDNodeOrder);
|
||||||
DAG.AddDbgValue(SDV, nullptr, false);
|
DAG.AddDbgValue(SDV, false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
assert(!IsDbgDeclare && "DbgDeclare operand is not in memory?");
|
assert(!IsDbgDeclare && "DbgDeclare operand is not in memory?");
|
||||||
|
@ -5880,7 +5939,10 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
|
||||||
}
|
}
|
||||||
case Intrinsic::dbg_addr:
|
case Intrinsic::dbg_addr:
|
||||||
case Intrinsic::dbg_declare: {
|
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<DbgVariableIntrinsic>(I);
|
const auto &DI = cast<DbgVariableIntrinsic>(I);
|
||||||
|
assert(!DI.hasArgList() && "Only dbg.value should currently use DIArgList");
|
||||||
DILocalVariable *Variable = DI.getVariable();
|
DILocalVariable *Variable = DI.getVariable();
|
||||||
DIExpression *Expression = DI.getExpression();
|
DIExpression *Expression = DI.getExpression();
|
||||||
dropDanglingDebugInfo(Variable, Expression);
|
dropDanglingDebugInfo(Variable, Expression);
|
||||||
|
@ -5919,8 +5981,9 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
|
||||||
if (FI != std::numeric_limits<int>::max()) {
|
if (FI != std::numeric_limits<int>::max()) {
|
||||||
if (Intrinsic == Intrinsic::dbg_addr) {
|
if (Intrinsic == Intrinsic::dbg_addr) {
|
||||||
SDDbgValue *SDV = DAG.getFrameIndexDbgValue(
|
SDDbgValue *SDV = DAG.getFrameIndexDbgValue(
|
||||||
Variable, Expression, FI, /*IsIndirect*/ true, dl, SDNodeOrder);
|
Variable, Expression, FI, getRoot().getNode(), /*IsIndirect*/ true,
|
||||||
DAG.AddDbgValue(SDV, getRoot().getNode(), isParameter);
|
dl, SDNodeOrder);
|
||||||
|
DAG.AddDbgValue(SDV, isParameter);
|
||||||
} else {
|
} else {
|
||||||
LLVM_DEBUG(dbgs() << "Skipping " << DI
|
LLVM_DEBUG(dbgs() << "Skipping " << DI
|
||||||
<< " (variable info stashed in MF side table)\n");
|
<< " (variable info stashed in MF side table)\n");
|
||||||
|
@ -5952,7 +6015,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
|
||||||
SDV = DAG.getDbgValue(Variable, Expression, N.getNode(), N.getResNo(),
|
SDV = DAG.getDbgValue(Variable, Expression, N.getNode(), N.getResNo(),
|
||||||
true, dl, SDNodeOrder);
|
true, dl, SDNodeOrder);
|
||||||
}
|
}
|
||||||
DAG.AddDbgValue(SDV, N.getNode(), isParameter);
|
DAG.AddDbgValue(SDV, isParameter);
|
||||||
} else {
|
} else {
|
||||||
// If Address is an argument then try to emit its dbg value using
|
// If Address is an argument then try to emit its dbg value using
|
||||||
// virtual register info from the FuncInfo.ValueMap.
|
// virtual register info from the FuncInfo.ValueMap.
|
||||||
|
@ -5981,20 +6044,17 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
|
||||||
DILocalVariable *Variable = DI.getVariable();
|
DILocalVariable *Variable = DI.getVariable();
|
||||||
DIExpression *Expression = DI.getExpression();
|
DIExpression *Expression = DI.getExpression();
|
||||||
dropDanglingDebugInfo(Variable, Expression);
|
dropDanglingDebugInfo(Variable, Expression);
|
||||||
const Value *V = DI.getValue(0);
|
SmallVector<Value *> Values(DI.getValues());
|
||||||
if (!V)
|
if (Values.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (handleDebugValue(V, Variable, Expression, dl, DI.getDebugLoc(),
|
if (std::count(Values.begin(), Values.end(), nullptr))
|
||||||
SDNodeOrder))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: Dangling debug info will eventually either be resolved or produce
|
bool IsVariadic = DI.hasArgList();
|
||||||
// an Undef DBG_VALUE. However in the resolution case, a gap may appear
|
if (!handleDebugValue(Values, Variable, Expression, dl, DI.getDebugLoc(),
|
||||||
// between the original dbg.value location and its resolved DBG_VALUE, which
|
SDNodeOrder, IsVariadic))
|
||||||
// we should ideally fill with an extra Undef DBG_VALUE.
|
addDanglingDebugInfo(&DI, dl, SDNodeOrder);
|
||||||
|
|
||||||
DanglingDebugInfoMap[V].emplace_back(&DI, dl, SDNodeOrder);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -492,6 +492,10 @@ public:
|
||||||
/// of the specified type Ty. Return empty SDValue() otherwise.
|
/// of the specified type Ty. Return empty SDValue() otherwise.
|
||||||
SDValue getCopyFromRegs(const Value *V, Type *Ty);
|
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
|
/// If we have dangling debug info that describes \p Variable, or an
|
||||||
/// overlapping part of variable considering the \p Expr, then this method
|
/// overlapping part of variable considering the \p Expr, then this method
|
||||||
/// will drop that debug info as it isn't valid any longer.
|
/// will drop that debug info as it isn't valid any longer.
|
||||||
|
@ -507,11 +511,11 @@ public:
|
||||||
/// this cannot be done, produce an Undef debug value record.
|
/// this cannot be done, produce an Undef debug value record.
|
||||||
void salvageUnresolvedDbgValue(DanglingDebugInfo &DDI);
|
void salvageUnresolvedDbgValue(DanglingDebugInfo &DDI);
|
||||||
|
|
||||||
/// For a given Value, attempt to create and record a SDDbgValue in the
|
/// For a given list of Values, attempt to create and record a SDDbgValue in
|
||||||
/// SelectionDAG.
|
/// the SelectionDAG.
|
||||||
bool handleDebugValue(const Value *V, DILocalVariable *Var,
|
bool handleDebugValue(ArrayRef<const Value *> Values, DILocalVariable *Var,
|
||||||
DIExpression *Expr, DebugLoc CurDL,
|
DIExpression *Expr, DebugLoc CurDL, DebugLoc InstDL,
|
||||||
DebugLoc InstDL, unsigned Order);
|
unsigned Order, bool IsVariadic);
|
||||||
|
|
||||||
/// Evict any dangling debug information, attempting to salvage it first.
|
/// Evict any dangling debug information, attempting to salvage it first.
|
||||||
void resolveOrClearDbgInfo();
|
void resolveOrClearDbgInfo();
|
||||||
|
|
Loading…
Reference in New Issue