Skip to content

Commit a3848c6

Browse files
committed
[Profiler] Don't profile generated buffers
We may want to revisit this in the future, but for now let's avoid profiling code in generated buffers. To make this work we'll need to come up with a scheme for writing out the generated buffers such that tools like `llvm-cov` can reference them. rdar://109562235
1 parent f97d1f2 commit a3848c6

File tree

4 files changed

+75
-2
lines changed

4 files changed

+75
-2
lines changed

include/swift/Basic/SourceManager.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ class SourceManager {
191191
/// Set the generated source information associated with a given buffer.
192192
void setGeneratedSourceInfo(unsigned bufferID, GeneratedSourceInfo);
193193

194+
/// Checks whether the given buffer has generated source information.
195+
bool hasGeneratedSourceInfo(unsigned bufferID);
196+
194197
/// Retrieve the generated source information for the given buffer.
195198
Optional<GeneratedSourceInfo> getGeneratedSourceInfo(unsigned bufferID) const;
196199

lib/Basic/SourceLoc.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,10 @@ void SourceManager::setGeneratedSourceInfo(
394394
}
395395
}
396396

397+
bool SourceManager::hasGeneratedSourceInfo(unsigned bufferID) {
398+
return GeneratedSourceInfos.count(bufferID);
399+
}
400+
397401
Optional<GeneratedSourceInfo> SourceManager::getGeneratedSourceInfo(
398402
unsigned bufferID
399403
) const {

lib/SIL/IR/SILProfiler.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,18 +86,35 @@ static NodeToProfile getNodeToProfile(SILDeclRef Constant) {
8686
/// Check whether we should profile a given SILDeclRef.
8787
static bool shouldProfile(SILDeclRef Constant) {
8888
auto Root = getNodeToProfile(Constant);
89+
auto *DC = Constant.getInnermostDeclContext();
8990

90-
// Do not profile AST nodes with invalid source locations.
9191
if (auto N = Root.getAsNode()) {
92+
// Do not profile AST nodes with invalid source locations.
9293
if (N.getStartLoc().isInvalid() || N.getEndLoc().isInvalid()) {
9394
LLVM_DEBUG(llvm::dbgs()
9495
<< "Skipping ASTNode: invalid start/end locations\n");
9596
return false;
9697
}
98+
99+
// Do not profile generated code. This includes macro expansions, which we
100+
// otherwise consider to be "written by the user", because they wrote the
101+
// macro attribute or expr. We may want to revist this in the future. We'll
102+
// need to figure out how we'll be writing out the macro expansions though,
103+
// such that they can be referenced by llvm-cov.
104+
// Note we check `getSourceFileContainingLocation` instead of
105+
// `getParentSourceFile` to make sure initializer exprs are correctly
106+
// handled.
107+
auto *M = DC->getParentModule();
108+
if (auto *SF = M->getSourceFileContainingLocation(N.getStartLoc())) {
109+
auto &SM = M->getASTContext().SourceMgr;
110+
if (SM.hasGeneratedSourceInfo(*SF->getBufferID())) {
111+
LLVM_DEBUG(llvm::dbgs() << "Skipping ASTNode: generated code\n");
112+
return false;
113+
}
114+
}
97115
}
98116

99117
// Do not profile AST nodes in unavailable contexts.
100-
auto *DC = Constant.getInnermostDeclContext();
101118
if (auto *D = DC->getInnermostDeclarationDeclContext()) {
102119
if (D->getSemanticUnavailableAttr()) {
103120
LLVM_DEBUG(llvm::dbgs() << "Skipping ASTNode: unavailable context\n");

test/Profiler/coverage_macros.swift

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %empty-directory(%t)
4+
5+
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/../Macros/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath
6+
7+
// RUN: %target-swift-frontend -emit-sil -emit-sorted-sil -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -module-name coverage_macros %s -load-plugin-library %t/%target-library-name(MacroDefinition) | %FileCheck %s --implicit-check-not sil_coverage_map
8+
// RUN: %target-swift-frontend -emit-ir -profile-generate -profile-coverage-mapping -load-plugin-library %t/%target-library-name(MacroDefinition) %s
9+
10+
@attached(accessor)
11+
macro accessViaStorage() = #externalMacro(module: "MacroDefinition", type: "AccessViaStorageMacro")
12+
13+
@attached(
14+
member,
15+
names: named(`init`), named(Storage), named(storage), named(getStorage()), named(method)
16+
)
17+
macro addMembers() = #externalMacro(module: "MacroDefinition", type: "AddMembers")
18+
19+
@freestanding(expression)
20+
macro nestedDeclInExpr() -> () -> Void = #externalMacro(module: "MacroDefinition", type: "NestedDeclInExprMacro")
21+
22+
// Note we use implicit-check-not, so this test ensures we don't emit
23+
// coverage maps for the macro expansions.
24+
25+
struct S1 {
26+
// CHECK: sil_coverage_map{{.*}}variable initialization expression of coverage_macros.S1.x
27+
var x: Int = 0
28+
29+
// CHECK: sil_coverage_map{{.*}}variable initialization expression of coverage_macros.S1.y
30+
var y: Int = 0
31+
}
32+
33+
@addMembers
34+
struct S2 {
35+
// CHECK: sil_coverage_map{{.*}}variable initialization expression of coverage_macros.S2.(_storage
36+
private var _storage = S1()
37+
38+
@accessViaStorage
39+
var x: Int
40+
41+
// No coverage map for the initializer, as it gets subsumed.
42+
@accessViaStorage
43+
var y: Int = 17
44+
}
45+
46+
// CHECK: sil_coverage_map{{.*}}s15coverage_macros3fooyyF
47+
func foo() {
48+
_ = #nestedDeclInExpr()
49+
}

0 commit comments

Comments
 (0)