Skip to content

Commit 8e733f5

Browse files
committed
Add a verify-di-hole assertion to SILBuilder.
The verify-di-hole SILVerifier pass is very useful in catching incorrectly set SILDebugScopes, but it can be very tedious to track down the root cause of a verification failure. This patch replicates much of its functionality inside an assertion in SILBuilder, which will result in a backtrace pointing directly to where the offending scope is being set.
1 parent d7c90fb commit 8e733f5

File tree

7 files changed

+78
-23
lines changed

7 files changed

+78
-23
lines changed

include/swift/SIL/SILBuilder.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,16 @@ class SILBuilder {
106106
/// are not auto-inserted.
107107
SILBasicBlock *BB;
108108
SILBasicBlock::iterator InsertPt;
109+
#ifndef NDEBUG
110+
/// Used in the di-hole verifier assertion.
111+
/// \{
112+
protected:
113+
bool EnableDIHoleVerification = false;
114+
115+
private:
116+
const SILDebugScope *PrevDebugScope = nullptr;
117+
/// \}
118+
#endif
109119
const SILDebugScope *CurDebugScope = nullptr;
110120
Optional<SILLocation> CurDebugLocOverride = None;
111121

@@ -115,7 +125,8 @@ class SILBuilder {
115125

116126
SILBuilder(SILFunction &F, SmallVectorImpl<SILInstruction *> *InsertedInstrs)
117127
: TempContext(F.getModule(), InsertedInstrs), C(TempContext), F(&F),
118-
BB(nullptr) {}
128+
BB(nullptr) {
129+
}
119130

120131
explicit SILBuilder(SILInstruction *I,
121132
SmallVectorImpl<SILInstruction *> *InsertedInstrs = 0)
@@ -222,7 +233,7 @@ class SILBuilder {
222233
return getModule().Types.getTypeLowering(T, expansion);
223234
}
224235

225-
void setCurrentDebugScope(const SILDebugScope *DS) { CurDebugScope = DS; }
236+
void setCurrentDebugScope(const SILDebugScope *DS);
226237
const SILDebugScope *getCurrentDebugScope() const { return CurDebugScope; }
227238

228239
/// Apply a debug location override. If loc is None, the current override is
@@ -279,10 +290,18 @@ class SILBuilder {
279290

280291
/// clearInsertionPoint - Clear the insertion point: created instructions will
281292
/// not be inserted into a block.
282-
void clearInsertionPoint() { BB = nullptr; }
293+
void clearInsertionPoint() {
294+
#ifndef NDEBUG
295+
PrevDebugScope = nullptr;
296+
#endif
297+
BB = nullptr;
298+
}
283299

284300
/// setInsertionPoint - Set the insertion point.
285301
void setInsertionPoint(SILBasicBlock *BB, SILBasicBlock::iterator insertPt) {
302+
#ifndef NDEBUG
303+
PrevDebugScope = nullptr;
304+
#endif
286305
this->BB = BB;
287306
this->InsertPt = insertPt;
288307
assert(insertPt == BB->end() || insertPt->getParent() == BB);

include/swift/SIL/SILDebugScope.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ class SILDebugScope : public SILAllocated<SILDebugScope> {
6666
/// into.
6767
SILFunction *getParentFunction() const;
6868

69+
/// Determine whether other is an (indirect) parent of this scope.
70+
bool isAncestor(const SILDebugScope *other) const;
71+
6972
/// If this is a debug scope associated with an inlined call site, return the
7073
/// SILLocation associated with the call site resulting from the final
7174
/// inlining.

lib/SIL/IR/SILBuilder.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,22 @@ SILBuilder::SILBuilder(SILGlobalVariable *GlobVar,
2828
setInsertionPoint(&GlobVar->StaticInitializerBlock);
2929
}
3030

31+
void SILBuilder::setCurrentDebugScope(const SILDebugScope *DS) {
32+
#ifndef NDEBUG
33+
if (EnableDIHoleVerification && DS != CurDebugScope) {
34+
// Detect a situation where:
35+
// PrevDebugScope = sil_scope(parent: CurDebugScope)
36+
// CurDebugScope = sil_scope(parent:)
37+
// DS = PrevDebugScope
38+
if (DS && DS == PrevDebugScope)
39+
assert(!CurDebugScope->isAncestor(PrevDebugScope) &&
40+
"attempting to re-enter scope within same basic block");
41+
PrevDebugScope = CurDebugScope;
42+
}
43+
#endif
44+
CurDebugScope = DS;
45+
}
46+
3147
IntegerLiteralInst *SILBuilder::createIntegerLiteral(IntegerLiteralExpr *E) {
3248
return insert(IntegerLiteralInst::create(E, getSILDebugLocation(E),
3349
getModule()));
@@ -241,6 +257,9 @@ void SILBuilder::emitBlock(SILBasicBlock *BB, SILLocation BranchLoc) {
241257
/// instruction) then split the block at that instruction and return the
242258
/// continuation block.
243259
SILBasicBlock *SILBuilder::splitBlockForFallthrough() {
260+
#ifndef NDEBUG
261+
PrevDebugScope = nullptr;
262+
#endif
244263
// If we are concatenating, just create and return a new block.
245264
if (insertingAtEndOfBlock()) {
246265
return getFunction().createBasicBlockAfter(BB);

lib/SIL/IR/SILDebugScope.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ SILDebugScope::SILDebugScope(SILLocation Loc, SILFunction *SILFn,
3737
SILDebugScope::SILDebugScope(SILLocation Loc)
3838
: Loc(Loc), InlinedCallSite(nullptr) {}
3939

40+
bool SILDebugScope::isAncestor(const SILDebugScope *other) const {
41+
while (other) {
42+
auto Parent = other->Parent;
43+
auto *ParentScope = Parent.dyn_cast<const SILDebugScope *>();
44+
if (ParentScope == this)
45+
return true;
46+
other = ParentScope;
47+
}
48+
return false;
49+
}
50+
4051
SILFunction *SILDebugScope::getInlinedFunction() const {
4152
if (Parent.isNull())
4253
return nullptr;

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6273,22 +6273,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
62736273

62746274
// Otherwise, we're allowed to re-enter a scope only if
62756275
// the scope is an ancestor of the scope we're currently leaving.
6276-
auto isAncestorScope = [](const SILDebugScope *Cur,
6277-
const SILDebugScope *Previous) {
6278-
assert(Cur && "null current scope queried");
6279-
assert(Previous && "null previous scope queried");
6280-
const SILDebugScope *Tmp = Previous;
6281-
while (Tmp) {
6282-
auto Parent = Tmp->Parent;
6283-
auto *ParentScope = Parent.dyn_cast<const SILDebugScope *>();
6284-
if (ParentScope == Cur)
6285-
return true;
6286-
Tmp = ParentScope;
6287-
}
6288-
return false;
6289-
};
6290-
6291-
if (isAncestorScope(DS, LastSeenScope)) {
6276+
if (DS->isAncestor(LastSeenScope)) {
62926277
LastSeenScope = DS;
62936278
LastSeenScopeInst = &SI;
62946279
continue;

lib/SILGen/SILGenBuilder.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
2+
13
//===--- SILGenBuilder.cpp ------------------------------------------------===//
24
//
35
// This source file is part of the Swift.org open source project
@@ -36,15 +38,27 @@ SILGenModule &SILGenBuilder::getSILGenModule() const { return SGF.SGM; }
3638
//===----------------------------------------------------------------------===//
3739

3840
SILGenBuilder::SILGenBuilder(SILGenFunction &SGF)
39-
: SILBuilder(SGF.F), SGF(SGF) {}
41+
: SILBuilder(SGF.F), SGF(SGF) {
42+
#ifndef NDEBUG
43+
EnableDIHoleVerification = true;
44+
#endif
45+
}
4046

4147
SILGenBuilder::SILGenBuilder(SILGenFunction &SGF, SILBasicBlock *insertBB,
4248
SmallVectorImpl<SILInstruction *> *insertedInsts)
43-
: SILBuilder(insertBB, insertedInsts), SGF(SGF) {}
49+
: SILBuilder(insertBB, insertedInsts), SGF(SGF) {
50+
#ifndef NDEBUG
51+
EnableDIHoleVerification = true;
52+
#endif
53+
}
4454

4555
SILGenBuilder::SILGenBuilder(SILGenFunction &SGF, SILBasicBlock *insertBB,
4656
SILBasicBlock::iterator insertInst)
47-
: SILBuilder(insertBB, insertInst), SGF(SGF) {}
57+
: SILBuilder(insertBB, insertInst), SGF(SGF) {
58+
#ifndef NDEBUG
59+
EnableDIHoleVerification = true;
60+
#endif
61+
}
4862

4963
//===----------------------------------------------------------------------===//
5064
// Managed Value APIs

lib/SILGen/SILGenBuilder.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ class SILGenBuilder : public SILBuilder {
5555
SILGenBuilder(SILGenBuilder &builder, SILBasicBlock *insertBB)
5656
: SILBuilder(insertBB, builder.getCurrentDebugScope(),
5757
builder.getBuilderContext()),
58-
SGF(builder.SGF) {}
58+
SGF(builder.SGF) {
59+
#ifndef NDEBUG
60+
EnableDIHoleVerification = true;
61+
#endif
62+
}
5963

6064
SILGenModule &getSILGenModule() const;
6165
SILGenFunction &getSILGenFunction() const { return SGF; }

0 commit comments

Comments
 (0)