Skip to content

Commit b55f972

Browse files
committed
[IRGen] Update coverage mapping for version 6
The coverage format version we use is automatically set to whatever the latest version LLVM has. This resulting in us outputting version 6 as our format without having made the changes necessary to reflect the new format. Update the emission logic to take account for [the new changes in version 6][1] (we need to include the current working directory as the first element of the list of files we output). Additionally, add a `static_assert` so we don't get caught out by version bumps in the future. Note we can't pin our version, as it must stay in sync with the version Clang is using. [1]: https://llvm.org/docs/CoverageMappingFormat.html#llvm-ir-representation
1 parent a3848c6 commit b55f972

File tree

3 files changed

+68
-19
lines changed

3 files changed

+68
-19
lines changed

lib/IRGen/GenCoverage.cpp

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,24 @@
2727
#include "llvm/ProfileData/InstrProf.h"
2828
#include "llvm/Support/FileSystem.h"
2929

30-
// This selects the coverage mapping format defined when `InstrProfData.inc`
31-
// is textually included.
32-
#define COVMAP_V3
33-
3430
using namespace swift;
3531
using namespace irgen;
3632

3733
using llvm::coverage::CounterMappingRegion;
3834
using llvm::coverage::CovMapVersion;
3935

36+
// This affects the coverage mapping format defined when `InstrProfData.inc`
37+
// is textually included. Note that it means 'version >= 3', not 'version == 3'.
38+
#define COVMAP_V3
39+
40+
/// This assert is here to make sure we make all the necessary code generation
41+
/// changes that are needed to support the new coverage mapping format. Note we
42+
/// cannot pin our version, as it must remain in sync with the version Clang is
43+
/// using.
44+
/// Do not bump without at least filing a bug and pinging a coverage maintainer.
45+
static_assert(CovMapVersion::CurrentVersion == CovMapVersion::Version6,
46+
"Coverage mapping emission needs updating");
47+
4048
static std::string getInstrProfSection(IRGenModule &IGM,
4149
llvm::InstrProfSectKind SK) {
4250
return llvm::getInstrProfSectionName(SK, IGM.Triple.getObjectFormat());
@@ -77,18 +85,26 @@ void IRGenModule::emitCoverageMaps(ArrayRef<const SILCoverageMap *> Mappings) {
7785
}
7886

7987
std::vector<StringRef> Files;
80-
for (const auto &M : Mappings)
88+
for (const auto &M : Mappings) {
8189
if (std::find(Files.begin(), Files.end(), M->getFilename()) == Files.end())
8290
Files.push_back(M->getFilename());
83-
84-
auto remapper = getOptions().CoveragePrefixMap;
91+
}
92+
const auto &Remapper = getOptions().CoveragePrefixMap;
8593

8694
llvm::SmallVector<std::string, 8> FilenameStrs;
87-
for (StringRef Name : Files) {
88-
llvm::SmallString<256> Path(Name);
89-
llvm::sys::fs::make_absolute(Path);
90-
FilenameStrs.push_back(remapper.remapPath(Path));
91-
}
95+
FilenameStrs.reserve(Files.size() + 1);
96+
97+
// First element needs to be the current working directory. Note if this
98+
// scheme ever changes, the FileID computation below will need updating.
99+
SmallString<256> WorkingDirectory;
100+
llvm::sys::fs::current_path(WorkingDirectory);
101+
FilenameStrs.emplace_back(Remapper.remapPath(WorkingDirectory));
102+
103+
// Following elements are the filenames present. We use their relative path,
104+
// which llvm-cov will turn back into absolute paths using the working
105+
// directory element.
106+
for (auto Name : Files)
107+
FilenameStrs.emplace_back(Remapper.remapPath(Name));
92108

93109
// Encode the filenames.
94110
std::string Filenames;
@@ -112,13 +128,21 @@ void IRGenModule::emitCoverageMaps(ArrayRef<const SILCoverageMap *> Mappings) {
112128
const uint64_t NameHash = llvm::IndexedInstrProf::ComputeHash(NameValue);
113129
std::string FuncRecordName = "__covrec_" + llvm::utohexstr(NameHash);
114130

115-
unsigned FileID =
116-
std::find(Files.begin(), Files.end(), M->getFilename()) - Files.begin();
131+
// The file ID needs to be bumped by 1 to account for the working directory
132+
// as the first element.
133+
unsigned FileID = 1 +
134+
std::find(Files.begin(), Files.end(), M->getFilename()) -
135+
Files.begin();
136+
assert(FileID < FilenameStrs.size());
137+
117138
std::vector<CounterMappingRegion> Regions;
118-
for (const auto &MR : M->getMappedRegions())
139+
for (const auto &MR : M->getMappedRegions()) {
140+
// The SubFileID here is 0, because it's an index into VirtualFileMapping,
141+
// and we only ever have a single file associated for a function.
119142
Regions.emplace_back(CounterMappingRegion::makeRegion(
120-
MR.Counter, /*FileID=*/0, MR.StartLine, MR.StartCol, MR.EndLine,
143+
MR.Counter, /*SubFileID*/ 0, MR.StartLine, MR.StartCol, MR.EndLine,
121144
MR.EndCol));
145+
}
122146
// Append each function's regions into the encoded buffer.
123147
ArrayRef<unsigned> VirtualFileMapping(FileID);
124148
llvm::coverage::CoverageMappingWriter W(VirtualFileMapping,
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
// To make sure this test is resilient to directory changes, we create nested directories inside of the
22
// temporary test directory and assert those exist, or don't exist, in the emitted ir
33
//
4-
// RUN: rm -rf %t
4+
// RUN: %empty-directory(%t)
55
// RUN: mkdir -p %t/root/nested
66
// RUN: echo "func coverage() {}" > %t/root/nested/coverage_relative_path.swift
77
// RUN: cd %t/root
88

99
// RUN: %target-swift-frontend -profile-generate -profile-coverage-mapping -Xllvm -enable-name-compression=false -emit-ir nested/coverage_relative_path.swift | %FileCheck -check-prefix=ABSOLUTE %s
1010
//
11-
// ABSOLUTE: @__llvm_coverage_mapping = {{.*"\\01.*root.*nested.*coverage_relative_path\.swift}}
11+
// ABSOLUTE: @__llvm_coverage_mapping = {{.*"\\02.*root[^/\\]*nested[/\\]*coverage_relative_path\.swift}}
1212

1313
// RUN: %target-swift-frontend -profile-generate -profile-coverage-mapping -Xllvm -enable-name-compression=false -coverage-prefix-map %/t/root=. -emit-ir %/t/root/nested/coverage_relative_path.swift | %FileCheck -check-prefix=RELATIVE %s
1414
//
15-
// RELATIVE: @__llvm_coverage_mapping = {{.*"\\01[^/]*}}.{{/|\\}}nested{{.*coverage_relative_path\.swift}}
15+
// RELATIVE: @__llvm_coverage_mapping = {{.*"\\02.*\\01[^/]*\.[/\\]*nested[/\\]*coverage_relative_path\.swift}}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// REQUIRES: profile_runtime
2+
// REQUIRES: executable_test
3+
// REQUIRES: OS=macosx
4+
5+
// This test is to make sure llvm-cov can deal with a coverage-prefix-map.
6+
7+
// To make sure this test is resilient to directory changes, we create nested directories inside of the
8+
// temporary test directory and assert those exist, or don't exist, in the emitted ir
9+
//
10+
// RUN: %empty-directory(%t)
11+
// RUN: mkdir -p %t/root/nested
12+
// RUN: echo "func coverage() {}" > %t/root/nested/coverage_relative_path.swift
13+
// RUN: cd %t/root
14+
15+
// RUN: %target-build-swift -profile-generate -profile-coverage-mapping -Xfrontend -coverage-prefix-map -Xfrontend %/t/root=. -Xfrontend -disable-incremental-llvm-codegen -o %t/main %/t/root/nested/coverage_relative_path.swift
16+
17+
// This unusual use of 'sh' allows the path of the profraw file to be
18+
// substituted by %target-run.
19+
// RUN: %target-codesign %t/main
20+
// RUN: %target-run sh -c 'env LLVM_PROFILE_FILE=$1 $2' -- %t/default.profraw %t/main
21+
22+
// RUN: %llvm-profdata merge %t/default.profraw -o %t/default.profdata
23+
// RUN: %llvm-cov show %t/main -instr-profile=%t/default.profdata | %FileCheck %s
24+
25+
// CHECK: func coverage

0 commit comments

Comments
 (0)