aprantl created this revision. aprantl added reviewers: dblaikie, probinson. aprantl added a project: debug-info.
As discussed on llvm-dev today, Clang currently emits redundant directories in DIFile entries, such as `.file 1 "/Volumes/Data/llvm" "/Volumes/Data/llvm/tools/clang/test/CodeGen/debug-info-abspath.c"` This patch looks at any common prefix between the compilation directory and the (absolute) file path and strips the redundant part. More importantly it leaves the compilation directory empty if the two paths have no common prefix. After this patch the above entry is (assuming a compilation dir of "/Volumes/Data/llvm/_build"): `.file 1 "/Volumes/Data/llvm" "tools/clang/test/CodeGen/debug-info-abspath.c"` When building the `FileCheck` binary with debug info, this patch makes the build artifacts ~1kb smaller. https://reviews.llvm.org/D55085 Files: lib/CodeGen/CGDebugInfo.cpp test/CodeGen/debug-info-abspath.c test/CodeGen/debug-prefix-map.c
Index: test/CodeGen/debug-prefix-map.c =================================================================== --- test/CodeGen/debug-prefix-map.c +++ test/CodeGen/debug-prefix-map.c @@ -17,18 +17,22 @@ } // CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "/var/empty{{/|\\5C}}<stdin>" -// CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "/var/empty{{[/\\]}}{{.*}}" -// CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "/var/empty{{[/\\]}}Inputs/stdio.h" +// CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "var/empty{{[/\\]}}{{.*}}", +// CHECK-NO-MAIN-FILE-NAME-SAME: directory: "/") +// CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "var/empty{{[/\\]}}Inputs/stdio.h", +// CHECK-NO-MAIN-FILE-NAME-SAME: directory: "/") // CHECK-NO-MAIN-FILE-NAME-NOT: !DIFile(filename: // CHECK-EVIL: !DIFile(filename: "/var=empty{{[/\\]}}{{.*}}" -// CHECK-EVIL: !DIFile(filename: "/var=empty{{[/\\]}}Inputs/stdio.h" +// CHECK-EVIL: !DIFile(filename: "var=empty{{[/\\]}}{{.*}}Inputs/stdio.h", +// CHECK-EVIL-SAME: directory: "/") // CHECK-EVIL-NOT: !DIFile(filename: // CHECK: !DIFile(filename: "/var/empty{{[/\\]}}{{.*}}" -// CHECK: !DIFile(filename: "/var/empty{{[/\\]}}Inputs/stdio.h" +// CHECK: !DIFile(filename: "var/empty{{[/\\]}}{{.*}}Inputs/stdio.h", +// CHECK-SAME: directory: "/") // CHECK-NOT: !DIFile(filename: -// CHECK-COMPILATION-DIR: !DIFile(filename: "/var/empty{{[/\\]}}{{.*}}", directory: "/var/empty") -// CHECK-COMPILATION-DIR: !DIFile(filename: "/var/empty{{[/\\]}}Inputs/stdio.h", directory: "/var/empty") +// CHECK-COMPILATION-DIR: !DIFile(filename: "{{.*}}", directory: "/var/empty") +// CHECK-COMPILATION-DIR: !DIFile(filename: "Inputs/stdio.h", directory: "/var/empty") // CHECK-COMPILATION-DIR-NOT: !DIFile(filename: Index: test/CodeGen/debug-info-abspath.c =================================================================== --- /dev/null +++ test/CodeGen/debug-info-abspath.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \ +// RUN: %s -emit-llvm -o - | FileCheck %s + +// RUN: cp %s %t.c +// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \ +// RUN: %t.c -emit-llvm -o - | FileCheck %s --check-prefix=INTREE +void foo() {} + +// Since %s is an absolute path, directory should be a nonempty +// prefix, but the CodeGen part should be part of the filename. + +// CHECK: DIFile(filename: "{{.*}}CodeGen{{.*}}debug-info-abspath.c" +// CHECK-SAME: directory: "{{.+}}") + +// INTREE: DIFile({{.*}}directory: "{{.+}}CodeGen{{.*}}") Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -407,13 +407,13 @@ SourceManager &SM = CGM.getContext().getSourceManager(); PresumedLoc PLoc = SM.getPresumedLoc(Loc); - if (PLoc.isInvalid() || StringRef(PLoc.getFilename()).empty()) + StringRef FileName = PLoc.getFilename(); + if (PLoc.isInvalid() || FileName.empty()) // If the location is not valid then use main input file. return getOrCreateMainFile(); // Cache the results. - const char *fname = PLoc.getFilename(); - auto It = DIFileCache.find(fname); + auto It = DIFileCache.find(FileName.data()); if (It != DIFileCache.end()) { // Verify that the information still exists. @@ -428,11 +428,34 @@ if (CSKind) CSInfo.emplace(*CSKind, Checksum); - llvm::DIFile *F = DBuilder.createFile( - remapDIPath(PLoc.getFilename()), remapDIPath(getCurrentDirname()), CSInfo, - getSource(SM, SM.getFileID(Loc))); + StringRef Dir; + StringRef File; + std::string RemappedFile = remapDIPath(FileName); + std::string CurDir = remapDIPath(getCurrentDirname()); + SmallString<128> DirBuf; + SmallString<128> FileBuf; + if (llvm::sys::path::is_absolute(RemappedFile)) { + // Strip the common prefix from current directory and FileName for + // a more space-efficient encoding. + auto FileIt = llvm::sys::path::begin(RemappedFile); + auto FileE = llvm::sys::path::end(RemappedFile); + auto CurDirIt = llvm::sys::path::begin(CurDir); + auto CurDirE = llvm::sys::path::end(CurDir); + for (; CurDirIt != CurDirE && *CurDirIt == *FileIt; ++CurDirIt, ++FileIt) + llvm::sys::path::append(DirBuf, *CurDirIt); + for (; FileIt != FileE; ++FileIt) + llvm::sys::path::append(FileBuf, *FileIt); + Dir = DirBuf; + File = FileBuf; + } else { + Dir = CurDir; + File = RemappedFile; + } + llvm::DIFile *F = + DBuilder.createFile(File, Dir, CSInfo, + getSource(SM, SM.getFileID(Loc))); - DIFileCache[fname].reset(F); + DIFileCache[FileName.data()].reset(F); return F; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits