Skip to content

Commit 0be63d0

Browse files
committed
[DebugInfo] Return complete variable info from getVarInfo by default
getVarInfo() now always returns a variable with a location and scope. To opt out of this change, getVarInfo(false) returns an incomplete variable. This can be used to work around bugs, but should only really be used for printing. The complete var info will also contain the type, except for debug_values, as its type depends on another instruction, which may be inconsistent if called mid-pass. All locations in debug variables are now also stripped of flags, to avoid issues when comparing or hashing debug variables.
1 parent ac865eb commit 0be63d0

18 files changed

+99
-76
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/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);

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/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/Transforms/DeadObjectElimination.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -871,9 +871,6 @@ DeadObjectElimination::buildDIExpression(SILInstruction *current) {
871871
return {};
872872
if (!var->Type)
873873
var->Type = dvci->getElementType();
874-
var->Loc = dvci->getVarLoc();
875-
if (!var->Scope)
876-
var->Scope = dvci->getDebugScope();
877874
return var;
878875
}
879876
if (auto *tupleAddr = dyn_cast<TupleElementAddrInst>(current)) {

0 commit comments

Comments
 (0)