Skip to content

Commit 15cab3a

Browse files
authored
Merge pull request #73555 from Snowy1803/complete-getvarinfo
[DebugInfo] Return complete variable info from getVarInfo by default
2 parents ace752b + 9984d1d commit 15cab3a

30 files changed

+242
-120
lines changed

docs/HowToUpdateDebugInfo.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ debug_value %0 : $*T, let, name "address", type $UnsafeRawPointer
108108
The variable will usually have an associated expression yielding the correct
109109
type.
110110

111+
> [!Note]
112+
> As there are no pointers in Swift, the type should never be an address type.
113+
111114
### Variable expressions
112115

113116
A variable can have an associated expression if the value needs computation.

include/swift/SIL/DebugUtils.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -437,16 +437,24 @@ struct DebugVarCarryingInst : VarDeclCarryingInst {
437437

438438
Kind getKind() const { return Kind(VarDeclCarryingInst::getKind()); }
439439

440-
std::optional<SILDebugVariable> getVarInfo() const {
440+
/// Returns the debug variable information attached to the instruction.
441+
///
442+
/// \param complete If true, always retrieve the complete variable with
443+
/// location and scope, and the type if possible. If false, only return the
444+
/// values if they are stored (if they are different from the instruction's
445+
/// location, scope, and type). This should only be set to false in
446+
/// SILPrinter. Incomplete var info is unpredictable, as it will sometimes
447+
/// have location and scope and sometimes not.
448+
std::optional<SILDebugVariable> getVarInfo(bool complete = true) const {
441449
switch (getKind()) {
442450
case Kind::Invalid:
443451
llvm_unreachable("Invalid?!");
444452
case Kind::DebugValue:
445-
return cast<DebugValueInst>(**this)->getVarInfo();
453+
return cast<DebugValueInst>(**this)->getVarInfo(complete);
446454
case Kind::AllocStack:
447-
return cast<AllocStackInst>(**this)->getVarInfo();
455+
return cast<AllocStackInst>(**this)->getVarInfo(complete);
448456
case Kind::AllocBox:
449-
return cast<AllocBoxInst>(**this)->getVarInfo();
457+
return cast<AllocBoxInst>(**this)->getVarInfo(complete);
450458
}
451459
llvm_unreachable("covered switch");
452460
}

include/swift/SIL/SILBuilder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ class SILBuilder {
425425
#endif
426426
// Don't apply location overrides on variables.
427427
if (Var && !Var->Loc)
428-
Var->Loc = Loc;
428+
Var->Loc = Loc.strippedForDebugVariable();
429429
return insert(AllocStackInst::create(
430430
getSILDebugLocation(Loc, true), elementType, getFunction(),
431431
substituteAnonymousArgs(Name, Var, Loc), dynamic, isLexical,

include/swift/SIL/SILDebugInfoExpression.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,16 @@ class SILDebugInfoExpression {
296296
return Elements.size() &&
297297
Elements[0].getAsOperator() == SILDIExprOperator::Dereference;
298298
}
299+
300+
/// Return the part of this SILDebugInfoExpression corresponding to fragments
301+
SILDebugInfoExpression getFragmentPart() const {
302+
for (auto it = element_begin(), end = element_end(); it != end; ++it) {
303+
if (it->getAsOperator() == SILDIExprOperator::Fragment
304+
|| it->getAsOperator() == SILDIExprOperator::TupleFragment)
305+
return SILDebugInfoExpression(ArrayRef(it, element_end()));
306+
}
307+
return {};
308+
}
299309
};
300310

301311
/// Returns the hashcode for the di expr element.

include/swift/SIL/SILInstruction.h

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1875,9 +1875,9 @@ class TailAllocatedDebugVariable {
18751875
bool isLet() const { return Bits.Data.Constant; }
18761876

18771877
std::optional<SILDebugVariable>
1878-
get(VarDecl *VD, const char *buf, std::optional<SILType> AuxVarType = {},
1879-
std::optional<SILLocation> DeclLoc = {},
1880-
const SILDebugScope *DeclScope = nullptr,
1878+
get(VarDecl *VD, const char *buf, std::optional<SILType> AuxVarType,
1879+
std::optional<SILLocation> DeclLoc,
1880+
const SILDebugScope *DeclScope,
18811881
llvm::ArrayRef<SILDIExprElement> DIExprElements = {}) const {
18821882
if (!Bits.Data.HasValue)
18831883
return std::nullopt;
@@ -2087,11 +2087,18 @@ class AllocStackInst final
20872087
SILLocation getVarLoc() const {
20882088
if (hasAuxDebugLocation())
20892089
return *getTrailingObjects<SILLocation>();
2090-
return getLoc();
2090+
return getLoc().strippedForDebugVariable();
20912091
}
20922092

20932093
/// Return the debug variable information attached to this instruction.
2094-
std::optional<SILDebugVariable> getVarInfo() const {
2094+
///
2095+
/// \param complete If true, always retrieve the complete variable with
2096+
/// location, scope, and element type. If false, only return the
2097+
/// values if they are stored (if they are different from the instruction's
2098+
/// location, scope, and type). This should only be set to false in
2099+
/// SILPrinter. Incomplete var info is unpredictable, as it will sometimes
2100+
/// have location and scope and sometimes not.
2101+
std::optional<SILDebugVariable> getVarInfo(bool complete = true) const {
20952102
// If we used to have debug info attached but our debug info is now
20962103
// invalidated, just bail.
20972104
if (sharedUInt8().AllocStackInst.hasInvalidatedVarInfo) {
@@ -2103,11 +2110,18 @@ class AllocStackInst final
21032110
const SILDebugScope *VarDeclScope = nullptr;
21042111
if (HasAuxDebugVariableType)
21052112
AuxVarType = *getTrailingObjects<SILType>();
2113+
else if (complete)
2114+
AuxVarType = getElementType();
21062115

21072116
if (hasAuxDebugLocation())
21082117
VarDeclLoc = *getTrailingObjects<SILLocation>();
2118+
else if (complete)
2119+
VarDeclLoc = getLoc().strippedForDebugVariable();
2120+
21092121
if (hasAuxDebugScope())
21102122
VarDeclScope = *getTrailingObjects<const SILDebugScope *>();
2123+
else if (complete)
2124+
VarDeclScope = getDebugScope();
21112125

21122126
llvm::ArrayRef<SILDIExprElement> DIExprElements(
21132127
getTrailingObjects<SILDIExprElement>(), NumDIExprOperands);
@@ -2509,8 +2523,13 @@ class AllocBoxInst final
25092523
SILType getAddressType() const;
25102524

25112525
/// Return the debug variable information attached to this instruction.
2512-
std::optional<SILDebugVariable> getVarInfo() const {
2513-
return VarInfo.get(getDecl(), getTrailingObjects<char>());
2526+
std::optional<SILDebugVariable> getVarInfo(bool complete = true) const {
2527+
if (complete)
2528+
return VarInfo.get(getDecl(), getTrailingObjects<char>(),
2529+
getAddressType().getObjectType(),
2530+
getLoc().strippedForDebugVariable(),
2531+
getDebugScope());
2532+
return VarInfo.get(getDecl(), getTrailingObjects<char>(), {}, {}, nullptr);
25142533
};
25152534

25162535
void setUsesMoveableValueDebugInfo() {
@@ -5385,21 +5404,41 @@ class DebugValueInst final
53855404
SILLocation getVarLoc() const {
53865405
if (hasAuxDebugLocation())
53875406
return *getTrailingObjects<SILLocation>();
5388-
return getLoc();
5407+
return getLoc().strippedForDebugVariable();
53895408
}
53905409

53915410
/// Return the debug variable information attached to this instruction.
5392-
std::optional<SILDebugVariable> getVarInfo() const {
5411+
///
5412+
/// \param complete If true, always retrieve the complete variable with
5413+
/// location and scope, and the type if possible. If false, only return the
5414+
/// values if they are stored (if they are different from the instruction's
5415+
/// location, scope, and type). This should only be set to false in
5416+
/// SILPrinter. Incomplete var info is unpredictable, as it will sometimes
5417+
/// have location and scope and sometimes not.
5418+
///
5419+
/// \note The type is not included because it can change during a pass.
5420+
/// Passes must make sure to not lose the type information.
5421+
std::optional<SILDebugVariable> getVarInfo(bool complete = true) const {
53935422
std::optional<SILType> AuxVarType;
53945423
std::optional<SILLocation> VarDeclLoc;
53955424
const SILDebugScope *VarDeclScope = nullptr;
5425+
53965426
if (HasAuxDebugVariableType)
53975427
AuxVarType = *getTrailingObjects<SILType>();
5428+
// TODO: passes break if we set the type here, as the type of the operand
5429+
// can be changed during a pass.
5430+
// else if (complete)
5431+
// AuxVarType = getOperand()->getType().getObjectType();
53985432

53995433
if (hasAuxDebugLocation())
54005434
VarDeclLoc = *getTrailingObjects<SILLocation>();
5435+
else if (complete)
5436+
VarDeclLoc = getLoc().strippedForDebugVariable();
5437+
54015438
if (hasAuxDebugScope())
54025439
VarDeclScope = *getTrailingObjects<const SILDebugScope *>();
5440+
else if (complete)
5441+
VarDeclScope = getDebugScope();
54035442

54045443
llvm::ArrayRef<SILDIExprElement> DIExprElements(
54055444
getTrailingObjects<SILDIExprElement>(), NumDIExprOperands);

include/swift/SIL/SILLocation.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,8 +520,13 @@ class SILLocation {
520520
};
521521

522522
inline llvm::hash_code hash_value(const SILLocation &R) {
523-
return llvm::hash_combine(R.kindAndFlags.packedKindAndFlags,
524-
*R.storage.filePositionLoc);
523+
if (R.isFilenameAndLocation()) {
524+
return llvm::hash_combine(R.kindAndFlags.packedKindAndFlags,
525+
*R.storage.filePositionLoc);
526+
} else {
527+
return llvm::hash_combine(R.kindAndFlags.packedKindAndFlags,
528+
R.storage.filePositionLoc);
529+
}
525530
}
526531

527532
inline llvm::hash_code hash_value(const SILLocation::FilenameAndLocation &R) {

lib/IRGen/IRGenSIL.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ class IRGenSILFunction :
679679
if (!VarInfo)
680680
return StringRef();
681681

682-
StringRef Name = i->getVarInfo()->Name;
682+
StringRef Name = VarInfo->Name;
683683
// The $match variables generated by the type checker are not
684684
// guaranteed to be unique within their scope, but they have
685685
// unique VarDecls.

lib/SIL/IR/SILBasicBlock.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,10 @@ transferNodesFromList(llvm::ilist_traits<SILBasicBlock> &SrcTraits,
342342

343343
II.setDebugScope(ScopeCloner.getOrCreateClonedScope(II.getDebugScope()));
344344
// Special handling for SILDebugVariable.
345+
// Fetch incomplete var info to avoid calling setDebugVarScope on
346+
// alloc_box, crashing.
345347
if (auto DVI = DebugVarCarryingInst(&II))
346-
if (auto VarInfo = DVI.getVarInfo())
348+
if (auto VarInfo = DVI.getVarInfo(false))
347349
if (VarInfo->Scope)
348350
DVI.setDebugVarScope(
349351
ScopeCloner.getOrCreateClonedScope(VarInfo->Scope));

lib/SIL/IR/SILInstructions.cpp

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -199,26 +199,10 @@ StringRef TailAllocatedDebugVariable::getName(const char *buf) const {
199199

200200
std::optional<SILDebugVariable>
201201
SILDebugVariable::createFromAllocation(const AllocationInst *AI) {
202-
std::optional<SILDebugVariable> VarInfo;
203202
if (const auto *ASI = dyn_cast_or_null<AllocStackInst>(AI))
204-
VarInfo = ASI->getVarInfo();
203+
return ASI->getVarInfo();
205204
// TODO: Support AllocBoxInst
206-
207-
if (!VarInfo)
208-
return {};
209-
210-
// Coalesce the debug loc attached on AI into VarInfo
211-
SILType Type = AI->getType();
212-
SILLocation InstLoc = AI->getLoc();
213-
const SILDebugScope *InstDS = AI->getDebugScope();
214-
if (!VarInfo->Type)
215-
VarInfo->Type = Type;
216-
if (!VarInfo->Loc)
217-
VarInfo->Loc = InstLoc;
218-
if (!VarInfo->Scope)
219-
VarInfo->Scope = InstDS;
220-
221-
return VarInfo;
205+
return {};
222206
}
223207

224208
AllocStackInst::AllocStackInst(
@@ -268,7 +252,7 @@ AllocStackInst *AllocStackInst::create(SILDebugLocation Loc,
268252
UsesMoveableValueDebugInfo_t wasMoved) {
269253
// Don't store the same information twice.
270254
if (Var) {
271-
if (Var->Loc == Loc.getLocation())
255+
if (Var->Loc == Loc.getLocation().strippedForDebugVariable())
272256
Var->Loc = {};
273257
if (Var->Scope == Loc.getScope())
274258
Var->Scope = nullptr;
@@ -473,7 +457,7 @@ DebugValueInst *DebugValueInst::create(SILDebugLocation DebugLoc,
473457
UsesMoveableValueDebugInfo_t wasMoved,
474458
bool trace) {
475459
// Don't store the same information twice.
476-
if (Var.Loc == DebugLoc.getLocation())
460+
if (Var.Loc == DebugLoc.getLocation().strippedForDebugVariable())
477461
Var.Loc = {};
478462
if (Var.Scope == DebugLoc.getScope())
479463
Var.Scope = nullptr;

lib/SIL/IR/SILPrinter.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,7 +1446,7 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
14461446
if (AVI->usesMoveableValueDebugInfo() && !AVI->getType().isMoveOnly())
14471447
*this << "[moveable_value_debuginfo] ";
14481448
*this << AVI->getElementType();
1449-
printDebugVar(AVI->getVarInfo(),
1449+
printDebugVar(AVI->getVarInfo(false),
14501450
&AVI->getModule().getASTContext().SourceMgr);
14511451
}
14521452
void visitAllocVectorInst(AllocVectorInst *AVI) {
@@ -1503,7 +1503,7 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
15031503
}
15041504

15051505
*this << ABI->getType();
1506-
printDebugVar(ABI->getVarInfo(),
1506+
printDebugVar(ABI->getVarInfo(false),
15071507
&ABI->getModule().getASTContext().SourceMgr);
15081508
}
15091509

@@ -1915,7 +1915,7 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
19151915
if (DVI->hasTrace())
19161916
*this << "[trace] ";
19171917
*this << getIDAndType(DVI->getOperand());
1918-
printDebugVar(DVI->getVarInfo(),
1918+
printDebugVar(DVI->getVarInfo(false),
19191919
&DVI->getModule().getASTContext().SourceMgr);
19201920
}
19211921

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1473,39 +1473,34 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
14731473

14741474
void checkDebugVariable(SILInstruction *inst) {
14751475
std::optional<SILDebugVariable> varInfo;
1476-
if (auto *di = dyn_cast<AllocStackInst>(inst))
1477-
varInfo = di->getVarInfo();
1478-
else if (auto *di = dyn_cast<AllocBoxInst>(inst))
1479-
varInfo = di->getVarInfo();
1480-
else if (auto *di = dyn_cast<DebugValueInst>(inst))
1481-
varInfo = di->getVarInfo();
1476+
if (auto di = DebugVarCarryingInst(inst))
1477+
varInfo = di.getVarInfo();
14821478

14831479
if (!varInfo)
14841480
return;
14851481

14861482
// Retrieve debug variable type
1487-
SILType DebugVarTy;
1488-
if (varInfo->Type)
1489-
DebugVarTy = *varInfo->Type;
1490-
else {
1491-
// Fetch from related SSA value
1492-
switch (inst->getKind()) {
1493-
case SILInstructionKind::AllocStackInst:
1494-
case SILInstructionKind::AllocBoxInst:
1495-
DebugVarTy = inst->getResult(0)->getType();
1496-
break;
1497-
case SILInstructionKind::DebugValueInst:
1498-
DebugVarTy = inst->getOperand(0)->getType();
1499-
if (DebugVarTy.isAddress()) {
1500-
// FIXME: op_deref could be applied to address types only.
1501-
// FIXME: Add this check
1502-
if (varInfo->DIExpr.startsWithDeref())
1503-
DebugVarTy = DebugVarTy.getObjectType();
1504-
}
1505-
break;
1506-
default:
1507-
llvm_unreachable("impossible instruction kind");
1508-
}
1483+
SILType SSAType;
1484+
switch (inst->getKind()) {
1485+
case SILInstructionKind::AllocStackInst:
1486+
case SILInstructionKind::AllocBoxInst:
1487+
// TODO: unwrap box for AllocBox
1488+
SSAType = inst->getResult(0)->getType().getObjectType();
1489+
break;
1490+
case SILInstructionKind::DebugValueInst:
1491+
SSAType = inst->getOperand(0)->getType();
1492+
break;
1493+
default:
1494+
llvm_unreachable("impossible instruction kind");
1495+
}
1496+
1497+
SILType DebugVarTy = varInfo->Type ? *varInfo->Type :
1498+
SSAType.getObjectType();
1499+
if (!varInfo->DIExpr && !isa<AllocBoxInst>(inst)) {
1500+
// FIXME: Remove getObjectType() below when we fix create/createAddr
1501+
require(DebugVarTy.removingMoveOnlyWrapper()
1502+
== SSAType.getObjectType().removingMoveOnlyWrapper(),
1503+
"debug type mismatch without a DIExpr");
15091504
}
15101505

15111506
auto *debugScope = inst->getDebugScope();

lib/SILOptimizer/Differentiation/Common.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,12 +266,12 @@ void collectMinimalIndicesForFunctionCall(
266266
std::optional<std::pair<SILDebugLocation, SILDebugVariable>>
267267
findDebugLocationAndVariable(SILValue originalValue) {
268268
if (auto *asi = dyn_cast<AllocStackInst>(originalValue))
269-
return swift::transform(asi->getVarInfo(), [&](SILDebugVariable var) {
269+
return swift::transform(asi->getVarInfo(false), [&](SILDebugVariable var) {
270270
return std::make_pair(asi->getDebugLocation(), var);
271271
});
272272
for (auto *use : originalValue->getUses()) {
273273
if (auto *dvi = dyn_cast<DebugValueInst>(use->getUser()))
274-
return swift::transform(dvi->getVarInfo(), [&](SILDebugVariable var) {
274+
return swift::transform(dvi->getVarInfo(false), [&](SILDebugVariable var) {
275275
// We need to drop `op_deref` here as we're transferring debug info
276276
// location from debug_value instruction (which describes how to get value)
277277
// into alloc_stack (which describes the location)

lib/SILOptimizer/Differentiation/JVPCloner.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,9 +1000,16 @@ class JVPCloner::Implementation final
10001000
/// Tangent: tan[y] = alloc_stack $T.Tangent
10011001
CLONE_AND_EMIT_TANGENT(AllocStack, asi) {
10021002
auto &diffBuilder = getDifferentialBuilder();
1003+
auto varInfo = asi->getVarInfo();
1004+
if (varInfo) {
1005+
// This is a new variable, it shouldn't keep the old scope, type, etc.
1006+
varInfo->Type = {};
1007+
varInfo->DIExpr = {};
1008+
varInfo->Loc = {};
1009+
varInfo->Scope = nullptr;
1010+
}
10031011
auto *mappedAllocStackInst = diffBuilder.createAllocStack(
1004-
asi->getLoc(), getRemappedTangentType(asi->getElementType()),
1005-
asi->getVarInfo());
1012+
asi->getLoc(), getRemappedTangentType(asi->getElementType()), varInfo);
10061013
setTangentBuffer(asi->getParent(), asi, mappedAllocStackInst);
10071014
}
10081015

lib/SILOptimizer/Differentiation/PullbackCloner.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,11 @@ class PullbackCloner::Implementation final
665665
}
666666
adjNameStream << " (scope #" << origBB->getDebugID() << ")";
667667
dv.Name = adjName;
668+
// We have no meaningful debug location, and the type is different.
669+
dv.Scope = nullptr;
670+
dv.Loc = {};
671+
dv.Type = {};
672+
dv.DIExpr = {};
668673
return dv;
669674
}));
670675
return (insertion.first->getSecond() = newBuf);

0 commit comments

Comments
 (0)