Skip to content

Commit 5e74cda

Browse files
authored
Merge pull request #15773 from vedantk/cov-decls
2 parents d2f5f6b + 88a966d commit 5e74cda

File tree

6 files changed

+78
-37
lines changed

6 files changed

+78
-37
lines changed

include/swift/SIL/SILFunction.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,9 +266,9 @@ class SILFunction
266266
Profiler = InheritedProfiler;
267267
}
268268

269-
void createProfiler(ASTNode Root) {
269+
void createProfiler(ASTNode Root, ForDefinition_t forDefinition) {
270270
assert(!Profiler && "Function already has a profiler");
271-
Profiler = SILProfiler::create(Module, Root);
271+
Profiler = SILProfiler::create(Module, forDefinition, Root);
272272
}
273273

274274
void discardProfiler() { Profiler = nullptr; }

include/swift/SIL/SILProfiler.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@
2222
#include "swift/AST/Stmt.h"
2323
#include "swift/Basic/ProfileCounter.h"
2424
#include "swift/SIL/SILAllocated.h"
25+
#include "swift/SIL/SILDeclRef.h"
2526
#include "llvm/ADT/DenseMap.h"
2627

2728
namespace swift {
2829

2930
class AbstractFunctionDecl;
3031
class SILCoverageMap;
32+
class SILFunction;
3133
class SILModule;
3234

3335
/// SILProfiler - Maps AST nodes to profile counters.
@@ -61,7 +63,8 @@ class SILProfiler : public SILAllocated<SILProfiler> {
6163
: M(M), Root(Root), EmitCoverageMapping(EmitCoverageMapping) {}
6264

6365
public:
64-
static SILProfiler *create(SILModule &M, ASTNode N);
66+
static SILProfiler *create(SILModule &M, ForDefinition_t forDefinition,
67+
ASTNode N);
6568

6669
/// Check if the function is set up for profiling.
6770
bool hasRegionCounters() const { return NumRegionCounters != 0; }

lib/SIL/SILProfiler.cpp

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,22 @@ static void walkForProfiling(ASTNode N, ASTWalker &Walker) {
100100
}
101101
}
102102

103-
SILProfiler *SILProfiler::create(SILModule &M, ASTNode N) {
103+
/// Check that the input AST has at least been type-checked.
104+
static bool hasASTBeenTypeChecked(ASTNode N) {
105+
DeclContext *DC = N.getAsDeclContext();
106+
assert(DC && "Invalid AST node for profiling");
107+
SourceFile *SF = DC->getParentSourceFile();
108+
return !SF || SF->ASTStage >= SourceFile::TypeChecked;
109+
}
110+
111+
SILProfiler *SILProfiler::create(SILModule &M, ForDefinition_t forDefinition,
112+
ASTNode N) {
113+
// Avoid generating profiling state for declarations.
114+
if (!forDefinition)
115+
return nullptr;
116+
117+
assert(hasASTBeenTypeChecked(N) && "Cannot use this AST for code coverage");
118+
104119
if (auto *D = N.dyn_cast<Decl *>()) {
105120
assert(isa<AbstractFunctionDecl>(D) ||
106121
isa<TopLevelCodeDecl>(D) && "Cannot create profiler");
@@ -465,21 +480,21 @@ struct PGOMapping : public ASTWalker {
465480
CounterMap[thenExpr] = NextCounter++;
466481
auto thenCount = loadExecutionCount(thenExpr);
467482
LoadedCounterMap[thenExpr] = thenCount;
468-
if (auto elseExpr = IE->getElseExpr()) {
469-
CounterMap[elseExpr] = parent;
470-
auto count = loadExecutionCount(elseExpr);
471-
if (!parent) {
472-
auto thenVal = thenCount.getValue();
473-
for (auto pCount = NextCounter - 1; pCount > 0; --pCount) {
474-
auto cCount = LoadedCounts->Counts[pCount];
475-
if (cCount > thenVal) {
476-
count = cCount;
477-
break;
478-
}
483+
auto elseExpr = IE->getElseExpr();
484+
assert(elseExpr && "An if-expr must have an else subexpression");
485+
CounterMap[elseExpr] = parent;
486+
auto count = loadExecutionCount(elseExpr);
487+
if (!parent) {
488+
auto thenVal = thenCount.getValue();
489+
for (auto pCount = NextCounter - 1; pCount > 0; --pCount) {
490+
auto cCount = LoadedCounts->Counts[pCount];
491+
if (cCount > thenVal) {
492+
count = cCount;
493+
break;
479494
}
480495
}
481-
LoadedCounterMap[elseExpr] = subtract(count, thenCount);
482496
}
497+
LoadedCounterMap[elseExpr] = subtract(count, thenCount);
483498
} else if (isa<AutoClosureExpr>(E) || isa<ClosureExpr>(E)) {
484499
CounterMap[E] = NextCounter++;
485500
auto eCount = loadExecutionCount(E);

lib/SILGen/SILGen.cpp

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ SILFunction *SILGenModule::getFunction(SILDeclRef constant,
500500
if (auto *fd = constant.getFuncDecl()) {
501501
if (hasSILBody(fd)) {
502502
// Set up the function for profiling instrumentation.
503-
F->createProfiler(fd);
503+
F->createProfiler(fd, forDefinition);
504504
profiledNode = fd->getBody(/*canSynthesize=*/false);
505505
}
506506
}
@@ -519,7 +519,7 @@ SILFunction *SILGenModule::getFunction(SILDeclRef constant,
519519

520520
if (!profiledNode) {
521521
if (auto *ce = dyn_cast<ClosureExpr>(ace)) {
522-
F->createProfiler(ce);
522+
F->createProfiler(ce, forDefinition);
523523
profiledNode = ce;
524524
}
525525
}
@@ -747,19 +747,23 @@ void SILGenModule::emitConstructor(ConstructorDecl *decl) {
747747

748748
SILDeclRef constant(decl);
749749

750-
bool ForCoverageMapping = M.getOptions().EmitProfileCoverageMapping;
750+
ForDefinition_t ForCoverageMapping = M.getOptions().EmitProfileCoverageMapping
751+
? ForDefinition
752+
: NotForDefinition;
751753

752754
if (decl->getDeclContext()->getAsClassOrClassExtensionContext()) {
753755
// Class constructors have separate entry points for allocation and
754756
// initialization.
755-
emitOrDelayFunction(*this, constant, [this,constant,decl](SILFunction *f){
756-
preEmitFunction(constant, decl, f, decl);
757-
PrettyStackTraceSILFunction X("silgen emitConstructor", f);
758-
f->createProfiler(decl);
759-
SILGenFunction(*this, *f)
760-
.emitClassConstructorAllocator(decl);
761-
postEmitFunction(constant, f);
762-
}, /*forceEmission=*/ForCoverageMapping);
757+
emitOrDelayFunction(
758+
*this, constant,
759+
[this, constant, decl, ForCoverageMapping](SILFunction *f) {
760+
preEmitFunction(constant, decl, f, decl);
761+
PrettyStackTraceSILFunction X("silgen emitConstructor", f);
762+
f->createProfiler(decl, ForCoverageMapping);
763+
SILGenFunction(*this, *f).emitClassConstructorAllocator(decl);
764+
postEmitFunction(constant, f);
765+
},
766+
/*forceEmission=*/ForCoverageMapping);
763767

764768
// If this constructor was imported, we don't need the initializing
765769
// constructor to be emitted.
@@ -775,13 +779,16 @@ void SILGenModule::emitConstructor(ConstructorDecl *decl) {
775779
}
776780
} else {
777781
// Struct and enum constructors do everything in a single function.
778-
emitOrDelayFunction(*this, constant, [this,constant,decl](SILFunction *f) {
779-
preEmitFunction(constant, decl, f, decl);
780-
PrettyStackTraceSILFunction X("silgen emitConstructor", f);
781-
f->createProfiler(decl);
782-
SILGenFunction(*this, *f).emitValueConstructor(decl);
783-
postEmitFunction(constant, f);
784-
}, /*forceEmission=*/ForCoverageMapping);
782+
emitOrDelayFunction(
783+
*this, constant,
784+
[this, constant, decl, ForCoverageMapping](SILFunction *f) {
785+
preEmitFunction(constant, decl, f, decl);
786+
PrettyStackTraceSILFunction X("silgen emitConstructor", f);
787+
f->createProfiler(decl, ForCoverageMapping);
788+
SILGenFunction(*this, *f).emitValueConstructor(decl);
789+
postEmitFunction(constant, f);
790+
},
791+
/*forceEmission=*/ForCoverageMapping);
785792
}
786793
}
787794

@@ -865,7 +872,7 @@ void SILGenModule::emitObjCAllocatorDestructor(ClassDecl *cd,
865872
SILFunction *f = getFunction(dealloc, ForDefinition);
866873
preEmitFunction(dealloc, dd, f, dd);
867874
PrettyStackTraceSILFunction X("silgen emitDestructor -dealloc", f);
868-
f->createProfiler(dd);
875+
f->createProfiler(dd, ForDefinition);
869876
SILGenFunction(*this, *f).emitObjCDestructor(dealloc);
870877
postEmitFunction(dealloc, f);
871878
}
@@ -935,7 +942,7 @@ void SILGenModule::emitDestructor(ClassDecl *cd, DestructorDecl *dd) {
935942
SILFunction *f = getFunction(deallocator, ForDefinition);
936943
preEmitFunction(deallocator, dd, f, dd);
937944
PrettyStackTraceSILFunction X("silgen emitDeallocatingDestructor", f);
938-
f->createProfiler(dd);
945+
f->createProfiler(dd, ForDefinition);
939946
SILGenFunction(*this, *f).emitDeallocatingDestructor(dd);
940947
f->setDebugScope(new (M) SILDebugScope(dd, f));
941948
postEmitFunction(deallocator, f);
@@ -1303,7 +1310,7 @@ void SILGenModule::visitTopLevelCodeDecl(TopLevelCodeDecl *td) {
13031310
// A single SILFunction may be used to lower multiple top-level decls. When
13041311
// this happens, fresh profile counters must be assigned to the new decl.
13051312
TopLevelSGF->F.discardProfiler();
1306-
TopLevelSGF->F.createProfiler(td);
1313+
TopLevelSGF->F.createProfiler(td, ForDefinition);
13071314

13081315
TopLevelSGF->emitProfilerIncrement(td->getBody());
13091316

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
public struct Box {
2+
public lazy var x: Int = {
3+
return true ? 0 : 1
4+
}()
5+
6+
public init() {}
7+
}

test/SILGen/coverage_decls.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sorted-sil -emit-sil -module-name coverage_decls -primary-file %s %S/Inputs/coverage_imports.swift | %FileCheck %s
2+
3+
// CHECK: sil_coverage_map {{.*}} $S14coverage_decls4mainyyF
4+
// CHECK-NOT: sil_coverage_map
5+
6+
func main() {
7+
var b = Box()
8+
let _ = b.x
9+
}

0 commit comments

Comments
 (0)