mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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
This commit is contained in:
@@ -27,16 +27,24 @@
|
||||
#include "llvm/ProfileData/InstrProf.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
|
||||
// This selects the coverage mapping format defined when `InstrProfData.inc`
|
||||
// is textually included.
|
||||
#define COVMAP_V3
|
||||
|
||||
using namespace swift;
|
||||
using namespace irgen;
|
||||
|
||||
using llvm::coverage::CounterMappingRegion;
|
||||
using llvm::coverage::CovMapVersion;
|
||||
|
||||
// This affects the coverage mapping format defined when `InstrProfData.inc`
|
||||
// is textually included. Note that it means 'version >= 3', not 'version == 3'.
|
||||
#define COVMAP_V3
|
||||
|
||||
/// This assert is here to make sure we make all the necessary code generation
|
||||
/// changes that are needed to support the new coverage mapping format. Note we
|
||||
/// cannot pin our version, as it must remain in sync with the version Clang is
|
||||
/// using.
|
||||
/// Do not bump without at least filing a bug and pinging a coverage maintainer.
|
||||
static_assert(CovMapVersion::CurrentVersion == CovMapVersion::Version6,
|
||||
"Coverage mapping emission needs updating");
|
||||
|
||||
static std::string getInstrProfSection(IRGenModule &IGM,
|
||||
llvm::InstrProfSectKind SK) {
|
||||
return llvm::getInstrProfSectionName(SK, IGM.Triple.getObjectFormat());
|
||||
@@ -77,18 +85,26 @@ void IRGenModule::emitCoverageMaps(ArrayRef<const SILCoverageMap *> Mappings) {
|
||||
}
|
||||
|
||||
std::vector<StringRef> Files;
|
||||
for (const auto &M : Mappings)
|
||||
for (const auto &M : Mappings) {
|
||||
if (std::find(Files.begin(), Files.end(), M->getFilename()) == Files.end())
|
||||
Files.push_back(M->getFilename());
|
||||
|
||||
auto remapper = getOptions().CoveragePrefixMap;
|
||||
}
|
||||
const auto &Remapper = getOptions().CoveragePrefixMap;
|
||||
|
||||
llvm::SmallVector<std::string, 8> FilenameStrs;
|
||||
for (StringRef Name : Files) {
|
||||
llvm::SmallString<256> Path(Name);
|
||||
llvm::sys::fs::make_absolute(Path);
|
||||
FilenameStrs.push_back(remapper.remapPath(Path));
|
||||
}
|
||||
FilenameStrs.reserve(Files.size() + 1);
|
||||
|
||||
// First element needs to be the current working directory. Note if this
|
||||
// scheme ever changes, the FileID computation below will need updating.
|
||||
SmallString<256> WorkingDirectory;
|
||||
llvm::sys::fs::current_path(WorkingDirectory);
|
||||
FilenameStrs.emplace_back(Remapper.remapPath(WorkingDirectory));
|
||||
|
||||
// Following elements are the filenames present. We use their relative path,
|
||||
// which llvm-cov will turn back into absolute paths using the working
|
||||
// directory element.
|
||||
for (auto Name : Files)
|
||||
FilenameStrs.emplace_back(Remapper.remapPath(Name));
|
||||
|
||||
// Encode the filenames.
|
||||
std::string Filenames;
|
||||
@@ -112,13 +128,21 @@ void IRGenModule::emitCoverageMaps(ArrayRef<const SILCoverageMap *> Mappings) {
|
||||
const uint64_t NameHash = llvm::IndexedInstrProf::ComputeHash(NameValue);
|
||||
std::string FuncRecordName = "__covrec_" + llvm::utohexstr(NameHash);
|
||||
|
||||
unsigned FileID =
|
||||
std::find(Files.begin(), Files.end(), M->getFilename()) - Files.begin();
|
||||
// The file ID needs to be bumped by 1 to account for the working directory
|
||||
// as the first element.
|
||||
unsigned FileID = 1 +
|
||||
std::find(Files.begin(), Files.end(), M->getFilename()) -
|
||||
Files.begin();
|
||||
assert(FileID < FilenameStrs.size());
|
||||
|
||||
std::vector<CounterMappingRegion> Regions;
|
||||
for (const auto &MR : M->getMappedRegions())
|
||||
for (const auto &MR : M->getMappedRegions()) {
|
||||
// The SubFileID here is 0, because it's an index into VirtualFileMapping,
|
||||
// and we only ever have a single file associated for a function.
|
||||
Regions.emplace_back(CounterMappingRegion::makeRegion(
|
||||
MR.Counter, /*FileID=*/0, MR.StartLine, MR.StartCol, MR.EndLine,
|
||||
MR.Counter, /*SubFileID*/ 0, MR.StartLine, MR.StartCol, MR.EndLine,
|
||||
MR.EndCol));
|
||||
}
|
||||
// Append each function's regions into the encoded buffer.
|
||||
ArrayRef<unsigned> VirtualFileMapping(FileID);
|
||||
llvm::coverage::CoverageMappingWriter W(VirtualFileMapping,
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
// To make sure this test is resilient to directory changes, we create nested directories inside of the
|
||||
// temporary test directory and assert those exist, or don't exist, in the emitted ir
|
||||
//
|
||||
// RUN: rm -rf %t
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: mkdir -p %t/root/nested
|
||||
// RUN: echo "func coverage() {}" > %t/root/nested/coverage_relative_path.swift
|
||||
// RUN: cd %t/root
|
||||
|
||||
// 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
|
||||
//
|
||||
// ABSOLUTE: @__llvm_coverage_mapping = {{.*"\\01.*root.*nested.*coverage_relative_path\.swift}}
|
||||
// ABSOLUTE: @__llvm_coverage_mapping = {{.*"\\02.*root[^/\\]*nested[/\\]*coverage_relative_path\.swift}}
|
||||
|
||||
// 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
|
||||
//
|
||||
// RELATIVE: @__llvm_coverage_mapping = {{.*"\\01[^/]*}}.{{/|\\}}nested{{.*coverage_relative_path\.swift}}
|
||||
// RELATIVE: @__llvm_coverage_mapping = {{.*"\\02.*\\01[^/]*\.[/\\]*nested[/\\]*coverage_relative_path\.swift}}
|
||||
|
||||
25
test/Profiler/coverage_relative_path_exec.swift
Normal file
25
test/Profiler/coverage_relative_path_exec.swift
Normal file
@@ -0,0 +1,25 @@
|
||||
// REQUIRES: profile_runtime
|
||||
// REQUIRES: executable_test
|
||||
// REQUIRES: OS=macosx
|
||||
|
||||
// This test is to make sure llvm-cov can deal with a coverage-prefix-map.
|
||||
|
||||
// To make sure this test is resilient to directory changes, we create nested directories inside of the
|
||||
// temporary test directory and assert those exist, or don't exist, in the emitted ir
|
||||
//
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: mkdir -p %t/root/nested
|
||||
// RUN: echo "func coverage() {}" > %t/root/nested/coverage_relative_path.swift
|
||||
// RUN: cd %t/root
|
||||
|
||||
// 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
|
||||
|
||||
// This unusual use of 'sh' allows the path of the profraw file to be
|
||||
// substituted by %target-run.
|
||||
// RUN: %target-codesign %t/main
|
||||
// RUN: %target-run sh -c 'env LLVM_PROFILE_FILE=$1 $2' -- %t/default.profraw %t/main
|
||||
|
||||
// RUN: %llvm-profdata merge %t/default.profraw -o %t/default.profdata
|
||||
// RUN: %llvm-cov show %t/main -instr-profile=%t/default.profdata | %FileCheck %s
|
||||
|
||||
// CHECK: func coverage
|
||||
Reference in New Issue
Block a user