Skip to content

Commit 329e428

Browse files
committed
Compute VarDeclScopeMap up front.
The previous lazy discovery did not always work because sometimes a debug_value is emitted before the first SIL instruction in the variable's scope. rdar://110841130
1 parent 874ba08 commit 329e428

10 files changed

+83
-51
lines changed

lib/SILGen/SILGenFunction.cpp

+42-29
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,51 @@ SILGenFunction::SILGenFunction(SILGenModule &SGM, SILFunction &F,
5555
assert(DC && "creating SGF without a DeclContext?");
5656
B.setInsertionPoint(createBasicBlock());
5757
B.setCurrentDebugScope(F.getDebugScope());
58+
59+
// Populate VarDeclScopeMap.
5860
SourceLoc SLoc = F.getLocation().getSourceLoc();
5961
if (SF && SLoc) {
6062
FnASTScope = ast_scope::ASTScopeImpl::findStartingScopeForLookup(SF, SLoc);
6163
ScopeMap.insert({{FnASTScope, nullptr}, F.getDebugScope()});
64+
65+
// Collect all variable declarations in this scope.
66+
struct Consumer : public namelookup::AbstractASTScopeDeclConsumer {
67+
const ast_scope::ASTScopeImpl *ASTScope;
68+
VarDeclScopeMapTy &VarDeclScopeMap;
69+
Consumer(const ast_scope::ASTScopeImpl *ASTScope,
70+
VarDeclScopeMapTy &VarDeclScopeMap)
71+
: ASTScope(ASTScope), VarDeclScopeMap(VarDeclScopeMap) {}
72+
73+
bool consume(ArrayRef<ValueDecl *> values,
74+
NullablePtr<DeclContext> baseDC) override {
75+
LLVM_DEBUG(ASTScope->print(llvm::errs(), 0, false, false));
76+
for (auto &value : values) {
77+
LLVM_DEBUG({
78+
if (value->hasName())
79+
llvm::dbgs() << "+ " << value->getBaseIdentifier() << "\n";
80+
});
81+
82+
assert((VarDeclScopeMap.count(value) == 0 ||
83+
VarDeclScopeMap[value] == ASTScope) &&
84+
"VarDecl appears twice");
85+
VarDeclScopeMap.insert({value, ASTScope});
86+
}
87+
return false;
88+
}
89+
bool lookInMembers(const DeclContext *) const override { return false; }
90+
#ifndef NDEBUG
91+
void startingNextLookupStep() override {}
92+
void finishingLookup(std::string) const override {}
93+
bool isTargetLookup() const override { return false; }
94+
#endif
95+
};
96+
const_cast<ast_scope::ASTScopeImpl *>(FnASTScope)
97+
->preOrderChildrenDo([&](ast_scope::ASTScopeImpl *ASTScope) {
98+
if (!ASTScope->ignoreInDebugInfo()) {
99+
Consumer consumer(ASTScope, VarDeclScopeMap);
100+
ASTScope->lookupLocalsOrMembers(consumer);
101+
}
102+
});
62103
}
63104
}
64105

@@ -202,8 +243,6 @@ const SILDebugScope *SILGenFunction::getScopeOrNull(SILLocation Loc,
202243
SourceLoc SLoc = Loc.getSourceLoc();
203244
if (!SF || LastSourceLoc == SLoc)
204245
return nullptr;
205-
// Prime VarDeclScopeMap.
206-
auto Scope = getOrCreateScope(SLoc);
207246
if (ForMetaInstruction)
208247
if (ValueDecl *ValDecl = Loc.getAsASTNode<ValueDecl>()) {
209248
// The source location of a VarDecl isn't necessarily in the same scope
@@ -212,7 +251,7 @@ const SILDebugScope *SILGenFunction::getScopeOrNull(SILLocation Loc,
212251
if (ValueScope != VarDeclScopeMap.end())
213252
return getOrCreateScope(ValueScope->second, F.getDebugScope());
214253
}
215-
return Scope;
254+
return getOrCreateScope(SLoc);
216255
}
217256

218257
const SILDebugScope *SILGenFunction::getOrCreateScope(SourceLoc SLoc) {
@@ -406,32 +445,6 @@ SILGenFunction::getOrCreateScope(const ast_scope::ASTScopeImpl *ASTScope,
406445
return ParentScope->InlinedCallSite != InlinedAt ? FnScope : ParentScope;
407446
}
408447

409-
// Collect all variable declarations in this scope.
410-
struct Consumer : public namelookup::AbstractASTScopeDeclConsumer {
411-
const ast_scope::ASTScopeImpl *ASTScope;
412-
VarDeclScopeMapTy &VarDeclScopeMap;
413-
Consumer(const ast_scope::ASTScopeImpl *ASTScope,
414-
VarDeclScopeMapTy &VarDeclScopeMap)
415-
: ASTScope(ASTScope), VarDeclScopeMap(VarDeclScopeMap) {}
416-
417-
bool consume(ArrayRef<ValueDecl *> values,
418-
NullablePtr<DeclContext> baseDC) override {
419-
for (auto &value : values) {
420-
assert(VarDeclScopeMap.count(value) == 0 && "VarDecl appears twice");
421-
VarDeclScopeMap.insert({value, ASTScope});
422-
}
423-
return false;
424-
}
425-
bool lookInMembers(const DeclContext *) const override { return false; }
426-
#ifndef NDEBUG
427-
void startingNextLookupStep() override {}
428-
void finishingLookup(std::string) const override {}
429-
bool isTargetLookup() const override { return false; }
430-
#endif
431-
};
432-
Consumer consumer(ASTScope, VarDeclScopeMap);
433-
ASTScope->lookupLocalsOrMembers(consumer);
434-
435448
// Collapse BraceStmtScopes whose parent is a .*BodyScope.
436449
if (auto Parent = ASTScope->getParent().getPtrOrNull())
437450
if (Parent->getSourceRangeOfThisASTNode() ==

test/DebugInfo/case-scope2.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ func consume<T>(_ t: T) {}
99
public func f(_ s1: Set<Int>?, _ s2: Set<Int>?) {
1010
switch (s1, s2) {
1111
case (nil, let a), (let a, nil):
12-
// CHECK: debug_value {{.*}} $Optional<Set<Int>>, let, name "a", {{.*}}:[[@LINE-1]]:18, scope [[S1]]
12+
// CHECK: debug_value {{.*}} $Optional<Set<Int>>, let, name "a", {{.*}}:11:18, scope [[S2]]
1313
consume(a)
1414
case (let a?, _):
15-
// CHECK: debug_value {{.*}} $Set<Int>, let, name "a", {{.*}}:[[@LINE-1]]:13, scope [[S3]]
15+
// CHECK: debug_value {{.*}} $Set<Int>, let, name "a", {{.*}}:14:13, scope [[S3]]
1616
consume((a))
1717
}
1818
}

test/DebugInfo/case-scope3.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ func f() -> Int {
1414
// CHECK: sil_scope [[S2:[0-9]+]] { loc "{{.*}}":10:44 parent [[S0]] }
1515
// CHECK: sil_scope [[S3:[0-9]+]] { loc "{{.*}}":10:68 parent [[S2]] }
1616
// CHECK: sil_scope [[S4:[0-9]+]] { loc "{{.*}}":10:78 parent [[S3]] }
17-
// CHECK: debug_value {{.*}}: $Optional<Int>, let, name "nextValue", {{.*}}:10:31, scope [[S0]]
18-
// CHECK: debug_value {{.*}}: $Int, let, name "nextValue", {{.*}}:10:56, scope [[S2]]
17+
// CHECK: debug_value {{.*}}: $Optional<Int>, let, name "nextValue", {{.*}}:10:31, scope [[S2]]
18+
// CHECK: debug_value {{.*}}: $Int, let, name "nextValue", {{.*}}:10:56, scope [[S3]]
1919
return nextValue
2020
}
2121
return 0

test/DebugInfo/for-scope.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public func f(_ xs: [String?]) {
1515
// CHECK: sil_scope [[S5:[0-9]+]] { loc "{{.*}}":7:13 parent [[S4]] }
1616
// CHECK: sil_scope [[S6:[0-9]+]] { loc "{{.*}}":7:9 parent [[S4]] }
1717

18-
// CHECK: debug_value %[[X:.*]] : $Optional<String>, let, name "x", {{.*}}, scope [[S3]]
18+
// CHECK: debug_value %[[X:.*]] : $Optional<String>, let, name "x", {{.*}}, scope [[S4]]
1919
// CHECK: retain_value %[[X]] : $Optional<String>, {{.*}}, scope [[S5]]
2020
// CHECK: debug_value %[[X1:[0-9]+]] : $String, let, name "x", {{.*}}, scope [[S6]]
2121
// CHECK: release_value %[[X1]] : $String, {{.*}}, scope [[S6]]

test/DebugInfo/guard-let-scope.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ func f(c: AnyObject??) {
1414
// CHECK: sil_scope [[S9:[0-9]+]] { loc "{{.*}}":7:28 parent [[S8]] }
1515
// CHECK: sil_scope [[S10:[0-9]+]] { loc "{{.*}}":7:28 parent [[S8]] }
1616
// CHECK: debug_value %{{.*}} : $Optional<Optional<AnyObject>>, let, name "x"{{.*}} scope [[S5]]
17-
// CHECK: debug_value %{{.*}} : $Optional<AnyObject>, let, name "x", {{.*}} scope [[S6]]
18-
// CHECK: debug_value %{{.*}} : $AnyObject, let, name "x", {{.*}} scope [[S8]]
17+
// CHECK: debug_value %{{.*}} : $Optional<AnyObject>, let, name "x", {{.*}} scope [[S8]]
18+
// CHECK: debug_value %{{.*}} : $AnyObject, let, name "x", {{.*}} scope [[S10]]
1919
fatalError()
2020
}
2121
// CHECK: function_ref {{.*3use.*}} scope [[S10]]

test/DebugInfo/guard-let-scope2.swift

+6-5
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ public func f(x: String?) throws {
1616
s = SomeObject()
1717
return s != nil
1818
}
19-
// CHECK: sil_scope [[S1:[0-9]+]] { {{.*}} parent @{{.*}}1f
20-
// CHECK: sil_scope [[S2:[0-9]+]] { {{.*}} parent [[S1]] }
21-
// CHECK: sil_scope [[S3:[0-9]+]] { {{.*}} parent [[S1]] }
22-
// CHECK: sil_scope [[S4:[0-9]+]] { {{.*}} parent [[S2]] }
23-
// CHECK: alloc_stack {{.*}} $SomeObject, let, name "s", {{.*}} scope [[S4]]
19+
// CHECK: sil_scope [[S1:[0-9]+]] { {{.*}}:13:13 parent @{{.*}}1f
20+
// CHECK: sil_scope [[S2:[0-9]+]] { {{.*}}:14:7 parent [[S1]] }
21+
// CHECK: sil_scope [[S3:[0-9]+]] { {{.*}}:14:26 parent [[S1]] }
22+
// CHECK: sil_scope [[S4:[0-9]+]] { {{.*}}:25:3 parent [[S2]] }
23+
// CHECK: sil_scope [[S5:[0-9]+]] { {{.*}}:25:17 parent [[S4]] }
24+
// CHECK: alloc_stack {{.*}} $SomeObject, let, name "s", {{.*}} scope [[S5]]
2425
guard let s = s else {
2526
assert(false)
2627
return

test/DebugInfo/guard-let-scope3.swift

+4-5
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,14 @@ public class S {
88
public func f(_ i: Int) throws -> C {
99
guard let x = c[i], let x else {
1010
// CHECK: sil_scope [[P:[0-9]+]] { loc "{{.*}}":9:5
11-
// CHECK: sil_scope [[X1_:[0-9]+]] { loc "{{.*}}":9:19 parent [[P]]
11+
// CHECK: sil_scope [[X1_RHS:[0-9]+]] { loc "{{.*}}":9:19 parent [[P]]
1212
// CHECK: sil_scope [[X1:[0-9]+]] { loc "{{.*}}":9:19 parent [[P]]
1313
// CHECK: sil_scope [[X2:[0-9]+]] { loc "{{.*}}":9:29 parent [[X1]]
14-
// CHECK: sil_scope [[X2_:[0-9]+]] { loc "{{.*}}":9:29 parent [[X1]]
1514
// CHECK: sil_scope [[GUARD:[0-9]+]] { loc "{{.*}}":9:36 parent [[P]]
16-
// CHECK: debug_value {{.*}} : $Optional<C>, let, name "x", {{.*}}, scope [[P]]
15+
// CHECK: debug_value {{.*}} : $Optional<C>, let, name "x", {{.*}}, scope [[X1]]
1716
// CHECK: debug_value {{.*}} : $C, let, name "x", {{.*}}, scope [[X2]]
18-
// FIXME: This source location & scope are a little wild.
19-
// CHECK-NEXT: strong_retain{{.*}}:[[@LINE+4]]:12, scope [[X2_]]
17+
// FIXME: This source location is a little wild.
18+
// CHECK-NEXT: strong_retain{{.*}}:[[@LINE+4]]:12, scope [[X2]]
2019
throw MyError()
2120
// CHECK: function_ref {{.*}}MyError{{.*}}:[[@LINE-1]]:13, scope [[GUARD]]
2221
}

test/DebugInfo/guard-let-scope4.swift

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %target-swift-frontend -g -emit-sil %s -parse-as-library -module-name a | %FileCheck %s
2+
open class C {
3+
public func fun() {}
4+
5+
public func run() {
6+
{ [weak self] in
7+
guard let self else { fatalError("cannot happen") }
8+
// CHECK: sil_scope [[LAMBDA:[0-9]+]] { loc "{{.*}}":6:5
9+
// CHECK: sil_scope [[BODY:[0-9]+]] { loc "{{.*}}":6:19 parent [[LAMBDA]]
10+
// CHECK: sil_scope [[LET:[0-9]+]] { loc "{{.*}}":7:7 parent [[BODY]]
11+
// CHECK: sil_scope [[GUARD:[0-9]+]] { loc "{{.*}}":7:17 parent [[LET]]
12+
// CHECK: debug_value {{.*}} : $C, let, name "self", {{.*}}, scope [[GUARD]]
13+
// CHECK: function_ref {{.*}}3fun{{.*}}, scope [[GUARD]]
14+
// CHECK-NEXT: apply {{.*}}, scope [[GUARD]]
15+
self.fun()
16+
}()
17+
}
18+
}

test/DebugInfo/if-let-scope.swift

+4-3
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ func use<T>(_ t: T) {}
33
public func f(value: String?) {
44
// CHECK: sil_scope [[S0:[0-9]+]] { loc "{{.*}}":3:13
55
if let value, let value = Int(value) {
6-
// CHECK: sil_scope [[S1:[0-9]+]] { loc "{{.*}}":5:10
6+
// CHECK: sil_scope [[S1:[0-9]+]] { loc "{{.*}}":5:3
77
// CHECK: sil_scope [[S2:[0-9]+]] { loc "{{.*}}":5:10
88
// CHECK: sil_scope [[S3:[0-9]+]] { loc "{{.*}}":5:29 parent [[S2]] }
99
// CHECK: sil_scope [[S4:[0-9]+]] { loc "{{.*}}":5:29 parent [[S2]] }
10+
// CHECK: sil_scope [[S5:[0-9]+]] { loc "{{.*}}":5:40 parent [[S4]] }
1011
// CHECK: debug_value {{.*}} : $Optional<String>, let, name "value", {{.*}}, scope [[S0]]
11-
// CHECK: debug_value {{.*}} : $String, let, name "value", {{.*}}, scope [[S1]]
12-
// CHECK: debug_value {{.*}} : $Int, let, name "value", {{.*}}, scope [[S2]]
12+
// CHECK: debug_value {{.*}} : $String, let, name "value", {{.*}}, scope [[S2]]
13+
// CHECK: debug_value {{.*}} : $Int, let, name "value", {{.*}}, scope [[S4]]
1314
use((value))
1415
}
1516
}

test/SILGen/switch-case-debug-descriptions.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ enum E {
99
func test1(_ e: E) {
1010
switch e { // SCOPE: sil_scope [[test1_switch:[0-9]+]] {{.*}}:[[@LINE]]:3
1111
case .one(let payload), .two(let payload): // SCOPE-NEXT: sil_scope [[test1_case1:[0-9]+]] {{.*}}:[[@LINE]]:3 parent [[test1_switch]]
12-
print(payload)
12+
print(payload) // SCOPE-NEXT: sil_scope {{.*}}:[[@LINE]]:5 parent [[test1_case1]]
1313
case .three(let payload): // SCOPE-NEXT: sil_scope [[test1_case2:[0-9]+]] {{.*}}:[[@LINE]]:3 parent [[test1_switch]]
1414
print(payload)
1515
}
@@ -43,7 +43,7 @@ func test4(_ e: E) {
4343
print(x) // SCOPE-NEXT: sil_scope {{.*}}:[[@LINE]]:5 parent [[test4_case1]]
4444
fallthrough
4545
case .two(let x): // SCOPE-NEXT: sil_scope [[test4_case2:[0-9]+]] {{.*}}:[[@LINE]]:3 parent [[test4_switch]]
46-
print(x)
46+
print(x) // SCOPE-NEXT: {{.*}}:[[@LINE]]:5 parent [[test4_case2]]
4747
fallthrough
4848
default: // SCOPE-NEXT: sil_scope [[test4_default:[0-9]+]] {{.*}}:[[@LINE]]:3 parent [[test4_switch]]
4949
print("default") // SCOPE: sil_scope [[test4_default1:[0-9]+]] {{.*}}:[[@LINE]]:5

0 commit comments

Comments
 (0)