[Coverage] Avoid emitting duplicate coverage mappings (#15835)

* [Coverage] Only instrument ClosureExprs once

ClosureExprs should only be visited for profiling purposes once, when
the SILFunction definition for the closure is being emitted.

This fixes an issue where the coverage tooling can't figure out how to
attribute the code coverage data of a closure to the right function.

rdar://39200851

* [Coverage] Assert that we don't emit duplicate coverage mappings

While generating SIL for a function with a default argument, we don't
need to emit two identical coverage mappings for the function body. The
same goes for functions which reference foreign functions.

This PR introduces an assertion which should catch similar problems in
the future.

rdar://39297172

* [Coverage] Only instrument nested functions once

Coverage counters for a nested function can be assigned once (in its
parent's scope), and then again (in its own scope). Nested functions
should only be visited for coverage mapping purposes once.

This is related to r://39200851, which is the same bug but for closures.

* [Coverage] Remove special handling of autoclosures

Treating AutoClosureExprs the same as ClosureExprs allows for some nice
code simplifications, and should be more robust.

* [Coverage] Only instrument curried instance methods once

Another fix related to r://39297172, in which we avoid instrumenting the
function associated with a curried thunk more than once.
This commit is contained in:
Vedant Kumar
2018-04-10 15:50:36 -07:00
committed by GitHub
parent 06f39702c7
commit b36a551550
12 changed files with 213 additions and 78 deletions

View File

@@ -15,6 +15,7 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/STLExtras.h"
#include "swift/SIL/SILCoverageMap.h"
#include "swift/SIL/SILModule.h"
@@ -40,6 +41,13 @@ SILCoverageMap::create(SILModule &M, StringRef Filename, StringRef Name,
CM->MappedRegions = M.allocateCopy(MappedRegions);
CM->Expressions = M.allocateCopy(Expressions);
// Assert that this coverage map is unique.
assert(llvm::none_of(M.coverageMaps,
[&](const SILCoverageMap &OtherCM) {
return OtherCM.PGOFuncName == CM->PGOFuncName;
}) &&
"Duplicate coverage mapping for function");
M.coverageMaps.push_back(CM);
return CM;
}