Skip to content

Commit aff6d6e

Browse files
committed
[SILProfiler] Skip exprs with invalid locations
Ignore exprs with invalid locations because we can't generate correct coverage information for them. Continue to visit their children. rdar://54312893&55913380&51612977
1 parent dbddb0d commit aff6d6e

File tree

2 files changed

+53
-2
lines changed

2 files changed

+53
-2
lines changed

lib/SIL/SILProfiler.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,12 @@ bool visitFunctionDecl(ASTWalker &Walker, AbstractFunctionDecl *AFD, F Func) {
177177
return continueWalk;
178178
}
179179

180+
/// Whether to skip visitation of an expression. Children of skipped exprs
181+
/// should still be visited.
182+
static bool skipExpr(Expr *E) {
183+
return !E->getStartLoc().isValid() || !E->getEndLoc().isValid();
184+
}
185+
180186
/// An ASTWalker that maps ASTNodes to profiling counters.
181187
struct MapRegionCounters : public ASTWalker {
182188
/// The next counter value to assign.
@@ -238,6 +244,9 @@ struct MapRegionCounters : public ASTWalker {
238244
}
239245

240246
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
247+
if (skipExpr(E))
248+
return {true, E};
249+
241250
// If AST visitation begins with an expression, the counter map must be
242251
// empty. Set up a counter for the root.
243252
if (Parent.isNull()) {
@@ -400,7 +409,10 @@ class SourceMappingRegion {
400409

401410
bool hasStartLoc() const { return StartLoc.hasValue(); }
402411

403-
void setStartLoc(SourceLoc Loc) { StartLoc = Loc; }
412+
void setStartLoc(SourceLoc Loc) {
413+
assert(Loc.isValid());
414+
StartLoc = Loc;
415+
}
404416

405417
const SourceLoc &getStartLoc() const {
406418
assert(StartLoc && "Region has no start location");
@@ -409,7 +421,10 @@ class SourceMappingRegion {
409421

410422
bool hasEndLoc() const { return EndLoc.hasValue(); }
411423

412-
void setEndLoc(SourceLoc Loc) { EndLoc = Loc; }
424+
void setEndLoc(SourceLoc Loc) {
425+
assert(Loc.isValid());
426+
EndLoc = Loc;
427+
}
413428

414429
const SourceLoc &getEndLoc() const {
415430
assert(EndLoc && "Region has no end location");
@@ -573,6 +588,9 @@ struct PGOMapping : public ASTWalker {
573588
}
574589

575590
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
591+
if (skipExpr(E))
592+
return {true, E};
593+
576594
unsigned parent = getParentCounter();
577595

578596
if (Parent.isNull()) {
@@ -996,6 +1014,9 @@ struct CoverageMapping : public ASTWalker {
9961014
}
9971015

9981016
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
1017+
if (skipExpr(E))
1018+
return {true, E};
1019+
9991020
if (!RegionStack.empty())
10001021
extendRegion(E);
10011022

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %target-swift-frontend -disable-sil-ownership-verifier -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sorted-sil -emit-sil -module-name coverage_invalid_loc %s | %FileCheck %s
2+
3+
// The implicit tuple and array exprs formed to call `dynamicallyCall`
4+
// happen to have invalid source locations (n.b. this may not always be true,
5+
// but it was true at the time this test was written).
6+
//
7+
// The coverage pass must skip exprs with invalid locations because there is
8+
// no better alternative: creating fake locations for exprs may make coverage
9+
// reporting incorrect, and not all implicit exprs have valid locations.
10+
//
11+
// Test that a) the coverage pass *can* skip exprs with invalid locations and
12+
// that b) this does not result in the children of implicit exprs being skipped.
13+
14+
@dynamicCallable
15+
public struct Callable {
16+
func dynamicallyCall(withArguments: [(Int) -> Int]) {}
17+
}
18+
19+
// CHECK: sil_coverage_map {{.*}} closure #1 (Swift.Int) -> Swift.Int in coverage_invalid_loc.foo(a: coverage_invalid_loc.Callable) -> ()
20+
// CHECK-NEXT: [[@LINE+9]]:5 -> {{.*}}:30 : 0
21+
// CHECK-NEXT: }
22+
23+
// CHECK: sil_coverage_map {{.*}} "foo" "foo" 0 {
24+
// CHECK-NEXT: [[@LINE+4]]:30 -> {{.*}}:2 : 0
25+
// CHECK-NEXT: }
26+
27+
@_silgen_name("foo")
28+
public func foo(a: Callable) {
29+
a({ (x : Int) -> Int in x })
30+
}

0 commit comments

Comments
 (0)