From 1b77448d37ebeadab60e0630f328d00693d3458f Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Wed, 3 Jun 2020 17:46:16 -0700 Subject: [PATCH] Add path remapping with -coverage-prefix-map to coverage data Previously the path to covered files in the __LLVM_COV / __llvm_covmap section were absolute. This made remote builds with coverage information difficult because all machines would have to have the same build root. This change uses the values for `-coverage-prefix-map` to remap files in the coverage info to relative paths. These paths work correctly with llvm-cov when it is run from the same source directory as the compilation, or from a different directory using the `-path-equivalence` argument. This is analogous to this change in clang https://reviews.llvm.org/D81122 --- include/swift/AST/DiagnosticsFrontend.def | 3 +++ include/swift/AST/IRGenOptions.h | 3 +++ include/swift/Option/Options.td | 3 +++ lib/Driver/Driver.cpp | 6 ++++++ lib/Driver/ToolChains.cpp | 1 + lib/Frontend/CompilerInvocation.cpp | 5 +++++ lib/IRGen/GenCoverage.cpp | 4 +++- test/Driver/coverage-prefix-map.swift | 9 +++++++++ test/Profiler/coverage_relative_path.swift | 16 ++++++++++++++++ 9 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 test/Driver/coverage-prefix-map.swift create mode 100644 test/Profiler/coverage_relative_path.swift diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def index 7aa018966646b..42bc9c823bc83 100644 --- a/include/swift/AST/DiagnosticsFrontend.def +++ b/include/swift/AST/DiagnosticsFrontend.def @@ -299,6 +299,9 @@ ERROR(error_optimization_remark_pattern, none, "%0 in '%1'", ERROR(error_invalid_debug_prefix_map, none, "invalid argument '%0' to -debug-prefix-map; it must be of the form " "'original=remapped'", (StringRef)) +ERROR(error_invalid_coverage_prefix_map, none, + "invalid argument '%0' to -coverage-prefix-map; it must be of the form " + "'original=remapped'", (StringRef)) ERROR(error_unable_to_write_swift_ranges_file, none, diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h index 279fdcefb3c4e..9b55d54d28d6a 100644 --- a/include/swift/AST/IRGenOptions.h +++ b/include/swift/AST/IRGenOptions.h @@ -169,6 +169,9 @@ class IRGenOptions { /// Path prefixes that should be rewritten in debug info. PathRemapper DebugPrefixMap; + /// Path prefixes that should be rewritten in coverage info. + PathRemapper CoveragePrefixMap; + /// What level of debug info to generate. IRGenDebugInfoLevel DebugInfoLevel : 2; diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index edaf19bdc3559..8fe0347dec253 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -724,6 +724,9 @@ def gdwarf_types : Flag<["-"], "gdwarf-types">, def debug_prefix_map : Separate<["-"], "debug-prefix-map">, Flags<[FrontendOption]>, HelpText<"Remap source paths in debug info">; +def coverage_prefix_map : Separate<["-"], "coverage-prefix-map">, + Flags<[FrontendOption]>, + HelpText<"Remap source paths in coverage info">; def debug_info_format : Joined<["-"], "debug-info-format=">, Flags<[FrontendOption]>, diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index d0be6bc80fd3a..d0bee08f8318d 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -179,6 +179,12 @@ static void validateDebugInfoArgs(DiagnosticEngine &diags, for (auto A : args.getAllArgValues(options::OPT_debug_prefix_map)) if (A.find('=') == StringRef::npos) diags.diagnose(SourceLoc(), diag::error_invalid_debug_prefix_map, A); + + // Check for any -coverage-prefix-map options that aren't of the form + // 'original=remapped' (either side can be empty, however). + for (auto A : args.getAllArgValues(options::OPT_coverage_prefix_map)) + if (A.find('=') == StringRef::npos) + diags.diagnose(SourceLoc(), diag::error_invalid_coverage_prefix_map, A); } static void validateVerifyIncrementalDependencyArgs(DiagnosticEngine &diags, diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index b1d6f97b0e887..5e2d1fe29309d 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -262,6 +262,7 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, // Pass on file paths that should be remapped in debug info. inputArgs.AddAllArgs(arguments, options::OPT_debug_prefix_map); + inputArgs.AddAllArgs(arguments, options::OPT_coverage_prefix_map); // Pass through the values passed to -Xfrontend. inputArgs.AddAllArgValues(arguments, options::OPT_Xfrontend); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index c1fc9ac970bf5..f471f9605af5c 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1307,6 +1307,11 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, Opts.DebugPrefixMap.addMapping(SplitMap.first, SplitMap.second); } + for (auto A : Args.getAllArgValues(options::OPT_coverage_prefix_map)) { + auto SplitMap = StringRef(A).split('='); + Opts.CoveragePrefixMap.addMapping(SplitMap.first, SplitMap.second); + } + for (const Arg *A : Args.filtered(OPT_Xcc)) { StringRef Opt = A->getValue(); if (Opt.startswith("-D") || Opt.startswith("-U")) diff --git a/lib/IRGen/GenCoverage.cpp b/lib/IRGen/GenCoverage.cpp index 699d1584e4eb1..a5d2e6d512f6e 100644 --- a/lib/IRGen/GenCoverage.cpp +++ b/lib/IRGen/GenCoverage.cpp @@ -18,6 +18,7 @@ #include "IRGenModule.h" #include "SwiftTargetInfo.h" +#include "swift/AST/IRGenOptions.h" #include "swift/SIL/SILModule.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Module.h" @@ -60,6 +61,7 @@ void IRGenModule::emitCoverageMapping() { if (std::find(Files.begin(), Files.end(), M->getFile()) == Files.end()) Files.push_back(M->getFile()); + auto remapper = getOptions().CoveragePrefixMap; // Awkwardly munge absolute filenames into a vector of StringRefs. // TODO: This is heinous - the same thing is happening in clang, but the API // really needs to be cleaned up for both. @@ -68,7 +70,7 @@ void IRGenModule::emitCoverageMapping() { for (StringRef Name : Files) { llvm::SmallString<256> Path(Name); llvm::sys::fs::make_absolute(Path); - FilenameStrs.push_back(std::string(Path.begin(), Path.end())); + FilenameStrs.push_back(remapper.remapPath(Path)); FilenameRefs.push_back(FilenameStrs.back()); } diff --git a/test/Driver/coverage-prefix-map.swift b/test/Driver/coverage-prefix-map.swift new file mode 100644 index 0000000000000..fd2ff8a5cbc2c --- /dev/null +++ b/test/Driver/coverage-prefix-map.swift @@ -0,0 +1,9 @@ +// RUN: not %target-swiftc_driver -coverage-prefix-map old %s 2>&1 | %FileCheck %s -check-prefix CHECK-INVALID +// RUN: %target-swiftc_driver -### -coverage-prefix-map old=new %s 2>&1 | %FileCheck %s -check-prefix CHECK-SIMPLE +// RUN: %target-swiftc_driver -### -coverage-prefix-map old=n=ew %s 2>&1 | %FileCheck %s -check-prefix CHECK-COMPLEX +// RUN: %target-swiftc_driver -### -coverage-prefix-map old= %s 2>&1 | %FileCheck %s -check-prefix CHECK-EMPTY + +// CHECK-INVALID: error: invalid argument 'old' to -coverage-prefix-map +// CHECK-SIMPLE: coverage-prefix-map old=new +// CHECK-COMPLEX: coverage-prefix-map old=n=ew +// CHECK-EMPTY: coverage-prefix-map old= diff --git a/test/Profiler/coverage_relative_path.swift b/test/Profiler/coverage_relative_path.swift new file mode 100644 index 0000000000000..b6b1db136dd9a --- /dev/null +++ b/test/Profiler/coverage_relative_path.swift @@ -0,0 +1,16 @@ +// %s expands to an absolute path, so to test relative paths we need to create a +// clean directory, put the source there, and cd into it. +// RUN: rm -rf %t +// RUN: mkdir -p %t/foo/bar/baz +// RUN: cp %s %t/foo/bar/baz/coverage_relative_path.swift +// RUN: cd %t/foo/bar + +// RUN: %target-swift-frontend -profile-generate -profile-coverage-mapping -Xllvm -enable-name-compression=false -emit-ir baz/coverage_relative_path.swift | %FileCheck -check-prefix=ABSOLUTE %s +// +// ABSOLUTE: @__llvm_coverage_mapping = {{.*"\\01.*foo.*bar.*baz.*coverage_relative_path\.swift}} + +// RUN: %target-swift-frontend -profile-generate -profile-coverage-mapping -Xllvm -enable-name-compression=false -coverage-prefix-map $PWD=. -emit-ir baz/coverage_relative_path.swift | %FileCheck -check-prefix=RELATIVE %s +// +// RELATIVE: @__llvm_coverage_mapping = {{.*"\\01[^/]*}}.{{/|\\}}baz{{.*coverage_relative_path\.swift}} + +func coverage() {}