diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -206,7 +206,7 @@ /// if non-empty. std::string RecordCommandLine; - std::map DebugPrefixMap; + llvm::SmallVector, 0> DebugPrefixMap; std::map CoveragePrefixMap; /// The ABI to use for passing floating point arguments. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3218,7 +3218,8 @@ def fdebug_prefix_map_EQ : Joined<["-"], "fdebug-prefix-map=">, Group, Flags<[CC1Option,CC1AsOption]>, - HelpText<"remap file source paths in debug info">; + MetaVarName<"=">, + HelpText<"For paths in debug info, remap directory to . If multiple options match a path, the last option wins">; def fcoverage_prefix_map_EQ : Joined<["-"], "fcoverage-prefix-map=">, Group, Flags<[CC1Option]>, diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -86,9 +86,6 @@ /// Cache of previously constructed Types. llvm::DenseMap TypeCache; - std::map> - DebugPrefixMap; - /// Cache that maps VLA types to size expressions for that type, /// represented by instantiated Metadata nodes. llvm::SmallDenseMap SizeExprCache; diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -73,8 +73,6 @@ : CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()), DebugTypeExtRefs(CGM.getCodeGenOpts().DebugTypeExtRefs), DBuilder(CGM.getModule()) { - for (const auto &KV : CGM.getCodeGenOpts().DebugPrefixMap) - DebugPrefixMap[KV.first] = KV.second; CreateCompileUnit(); } @@ -470,12 +468,9 @@ } std::string CGDebugInfo::remapDIPath(StringRef Path) const { - if (DebugPrefixMap.empty()) - return Path.str(); - SmallString<256> P = Path; - for (const auto &Entry : DebugPrefixMap) - if (llvm::sys::path::replace_path_prefix(P, Entry.first, Entry.second)) + for (auto &[From, To] : llvm::reverse(CGM.getCodeGenOpts().DebugPrefixMap)) + if (llvm::sys::path::replace_path_prefix(P, From, To)) break; return P.str().str(); } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1696,8 +1696,7 @@ for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) { auto Split = StringRef(Arg).split('='); - Opts.DebugPrefixMap.insert( - {std::string(Split.first), std::string(Split.second)}); + Opts.DebugPrefixMap.emplace_back(Split.first, Split.second); } for (const auto &Arg : Args.getAllArgValues(OPT_fcoverage_prefix_map_EQ)) { diff --git a/clang/test/CodeGen/debug-prefix-map.c b/clang/test/CodeGen/debug-prefix-map.c --- a/clang/test/CodeGen/debug-prefix-map.c +++ b/clang/test/CodeGen/debug-prefix-map.c @@ -9,6 +9,10 @@ // RUN: %clang -g -fdebug-prefix-map=%p=./UNLIKELY_PATH/empty -S -c %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-REL // RUN: %clang -g -ffile-prefix-map=%p=./UNLIKELY_PATH/empty -S -c %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-REL +// RUN: rm -rf %t && mkdir -p %t/a/b && cp %s %t/a/b/c.c +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -I%S -fdebug-prefix-map=%t/a/b=y -fdebug-prefix-map=%t/a=x %t/a/b/c.c -o - | FileCheck %s --check-prefix=CHECK-X +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -I%S -fdebug-prefix-map=%t/a=x -fdebug-prefix-map=%t/a/b=y %t/a/b/c.c -o - | FileCheck %s --check-prefix=CHECK-Y + #include "Inputs/stdio.h" int main(int argc, char **argv) { @@ -47,3 +51,6 @@ // CHECK-REL: !DIFile(filename: "./UNLIKELY_PATH/empty{{/|\\\\}}{{.*}}", // CHECK-REL: !DIFile(filename: "./UNLIKELY_PATH/empty{{/|\\\\}}{{.*}}Inputs/stdio.h", // CHECK-REL-SAME: directory: "" + +// CHECK-X: !DIFile(filename: "x{{/|\\\\}}b{{/|\\\\}}c.c", directory: "") +// CHECK-Y: !DIFile(filename: "y{{/|\\\\}}c.c", directory: "") diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -97,7 +97,7 @@ std::string DwarfDebugFlags; std::string DwarfDebugProducer; std::string DebugCompilationDir; - std::map DebugPrefixMap; + llvm::SmallVector, 0> DebugPrefixMap; llvm::DebugCompressionType CompressDebugSections = llvm::DebugCompressionType::None; std::string MainFileName; @@ -275,8 +275,7 @@ for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) { auto Split = StringRef(Arg).split('='); - Opts.DebugPrefixMap.insert( - {std::string(Split.first), std::string(Split.second)}); + Opts.DebugPrefixMap.emplace_back(Split.first, Split.second); } // Frontend Options diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -190,7 +190,7 @@ SmallString<128> CompilationDir; /// Prefix replacement map for source file information. - std::map> DebugPrefixMap; + SmallVector, 0> DebugPrefixMap; /// The main file name if passed in explicitly. std::string MainFileName; diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -881,11 +881,11 @@ void MCContext::addDebugPrefixMapEntry(const std::string &From, const std::string &To) { - DebugPrefixMap.insert(std::make_pair(From, To)); + DebugPrefixMap.emplace_back(From, To); } void MCContext::remapDebugPath(SmallVectorImpl &Path) { - for (const auto &[From, To] : DebugPrefixMap) + for (const auto &[From, To] : llvm::reverse(DebugPrefixMap)) if (llvm::sys::path::replace_path_prefix(Path, From, To)) break; } diff --git a/llvm/test/MC/ELF/debug-prefix-map.s b/llvm/test/MC/ELF/debug-prefix-map.s --- a/llvm/test/MC/ELF/debug-prefix-map.s +++ b/llvm/test/MC/ELF/debug-prefix-map.s @@ -14,9 +14,13 @@ # RUN: cd %t.foo/bar # RUN: llvm-mc -triple=x86_64 -g -dwarf-version=4 %t.foo%{fs-sep}bar%{fs-sep}src.s -filetype=obj -o mapabs.4.o -fdebug-prefix-map=%t.foo=/broken_root -fdebug-prefix-map=%t.foo%{fs-sep}bar=/src_root # RUN: llvm-dwarfdump -v -debug-info -debug-line mapabs.4.o | FileCheck --check-prefix=MAPABS_V4 %s -# RUN: llvm-mc -triple=x86_64 -g -dwarf-version=5 %t.foo%{fs-sep}bar%{fs-sep}src.s -filetype=obj -o mapabs.5.o -fdebug-prefix-map=%t.foo%{fs-sep}bar=/src_root -fdebug-prefix-map=%t.foo=/broken_root +# RUN: llvm-mc -triple=x86_64 -g -dwarf-version=5 %t.foo%{fs-sep}bar%{fs-sep}src.s -filetype=obj -o mapabs.5.o -fdebug-prefix-map=%t.foo=/broken_root -fdebug-prefix-map=%t.foo%{fs-sep}bar=/src_root # RUN: llvm-dwarfdump -v -debug-info -debug-line mapabs.5.o | FileCheck --check-prefix=MAPABS_V5 %s +## The last -fdebug-prefix-map= wins even if the prefix is shorter. +# RUN: llvm-mc -triple=x86_64 -g -dwarf-version=5 %t.foo%{fs-sep}bar%{fs-sep}src.s -filetype=obj -o mapabs.5.o -fdebug-prefix-map=%t.foo%{fs-sep}bar=/broken_root -fdebug-prefix-map=%t.foo=/src_root +# RUN: llvm-dwarfdump -v -debug-info -debug-line mapabs.5.o | FileCheck --check-prefix=MAPABS_V5_A %s + f: nop @@ -46,3 +50,6 @@ # MAPABS_V5: DW_AT_comp_dir [DW_FORM_string] ("{{(/|\\)+}}src_root") # MAPABS_V5: DW_AT_decl_file [DW_FORM_data4] ("/src_root{{(/|\\)+}}src.s") # MAPABS_V5: include_directories[ 0] = .debug_line_str[0x00000000] = "/src_root" + +# MAPABS_V5_A: DW_AT_comp_dir [DW_FORM_string] ("{{(/|\\)+}}src_root/bar") +# MAPABS_V5_A: DW_AT_decl_file [DW_FORM_data4] ("/src_root{{(/|\\)+}}bar{{(/|\\)+}}src.s")