rnk created this revision. rnk added reviewers: thakis, hans, dblaikie. rnk added a subscriber: cfe-commits.
PDB-based debuggers do not support looking up type names across type stream boundaries. There are two ways where users end up being unable to look into variables with types that were required to be complete: 1. The type was provided by another DLL, but was not marked dllimport. In this case, the type stream is in the PDB, and it will contain all types that had complete definitions within the DLL. If the type had a vtable that was only emitted in another DLL, we will not have type information for it. 2. The user is using /DEBUG:FASTLINK. This flag tells the linker to leave debug information in object files, similar to the default build flow on MacOS. When /DEBUG:FASTLINK is used with /Z7, each individual object file needs to have complete definitions of all types required to be complete in that TU. This isn't so bad for MSVC because it supports using type servers with /Zi, so they still get some amount of type deduplication. I did an experiment some time ago on Chrome and found that changing the default here increased the object file sizes in a Chrome debug build by 17%[1], which is quite significant. If those savings are important to users and they aren't using /DEBUG:FASTLINK, they can opt into limited debug info by passing -flimit-debug-info. [1] https://bugs.chromium.org/p/chromium/issues/detail?id=642812#c15 https://reviews.llvm.org/D27858 Files: lib/Driver/MSVCToolChain.cpp lib/Driver/ToolChains.h test/Driver/cl-options.c Index: test/Driver/cl-options.c =================================================================== --- test/Driver/cl-options.c +++ test/Driver/cl-options.c @@ -452,11 +452,11 @@ // RUN: %clang_cl /Zi /c -### -- %s 2>&1 | FileCheck -check-prefix=Zi %s // Zi: "-gcodeview" -// Zi: "-debug-info-kind=limited" +// Zi: "-debug-info-kind=standalone" // RUN: %clang_cl /Z7 /c -### -- %s 2>&1 | FileCheck -check-prefix=Z7 %s // Z7: "-gcodeview" -// Z7: "-debug-info-kind=limited" +// Z7: "-debug-info-kind=standalone" // RUN: %clang_cl /Zd /c -### -- %s 2>&1 | FileCheck -check-prefix=Z7GMLT %s // Z7GMLT: "-gcodeview" @@ -466,6 +466,10 @@ // ZGMLT: "-gcodeview" // ZGMLT: "-debug-info-kind=line-tables-only" +// RUN: %clang_cl /Z7 -flimit-debug-info /c -### -- %s 2>&1 | FileCheck -check-prefix=Z7LIMITED %s +// Z7LIMITED: "-gcodeview" +// Z7LIMITED: "-debug-info-kind=limited" + // RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=BreproDefault %s // BreproDefault: "-mincremental-linker-compatible" @@ -485,7 +489,7 @@ // which made it "win". This test could not detect that bug. // RUN: %clang_cl /Z7 -gdwarf /c -### -- %s 2>&1 | FileCheck -check-prefix=Z7_gdwarf %s // Z7_gdwarf: "-gcodeview" -// Z7_gdwarf: "-debug-info-kind=limited" +// Z7_gdwarf: "-debug-info-kind=standalone" // Z7_gdwarf: "-dwarf-version=4" // RUN: %clang_cl -fmsc-version=1800 -TP -### -- %s 2>&1 | FileCheck -check-prefix=CXX11 %s Index: lib/Driver/ToolChains.h =================================================================== --- lib/Driver/ToolChains.h +++ lib/Driver/ToolChains.h @@ -1139,6 +1139,7 @@ bool isPICDefault() const override; bool isPIEDefault() const override; bool isPICDefaultForced() const override; + bool GetDefaultStandaloneDebug() const override; void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, Index: lib/Driver/MSVCToolChain.cpp =================================================================== --- lib/Driver/MSVCToolChain.cpp +++ lib/Driver/MSVCToolChain.cpp @@ -94,6 +94,18 @@ return getArch() == llvm::Triple::x86_64; } +bool MSVCToolChain::GetDefaultStandaloneDebug() const { + // Microsoft debuggers can't lookup type names across type stream boundaries. + // This means that types implemented in b.dll used by a.dll sometimes can't be + // found when debugging a.dll. Clang will emit types marked with dllimport to + // try to cope with this case, but is not a complete heuristic. Non-standalone + // type info is also incompatble with /DEBUG:FASTLINK, which leaves all debug + // info, including types, in object files. In this case, the type stream is + // limited to the TU, and every TU needs to have all the types required to be + // complete by that TU for debugging. + return true; +} + #ifdef USE_WIN32 static bool readFullStringValue(HKEY hkey, const char *valueName, std::string &value) {
Index: test/Driver/cl-options.c =================================================================== --- test/Driver/cl-options.c +++ test/Driver/cl-options.c @@ -452,11 +452,11 @@ // RUN: %clang_cl /Zi /c -### -- %s 2>&1 | FileCheck -check-prefix=Zi %s // Zi: "-gcodeview" -// Zi: "-debug-info-kind=limited" +// Zi: "-debug-info-kind=standalone" // RUN: %clang_cl /Z7 /c -### -- %s 2>&1 | FileCheck -check-prefix=Z7 %s // Z7: "-gcodeview" -// Z7: "-debug-info-kind=limited" +// Z7: "-debug-info-kind=standalone" // RUN: %clang_cl /Zd /c -### -- %s 2>&1 | FileCheck -check-prefix=Z7GMLT %s // Z7GMLT: "-gcodeview" @@ -466,6 +466,10 @@ // ZGMLT: "-gcodeview" // ZGMLT: "-debug-info-kind=line-tables-only" +// RUN: %clang_cl /Z7 -flimit-debug-info /c -### -- %s 2>&1 | FileCheck -check-prefix=Z7LIMITED %s +// Z7LIMITED: "-gcodeview" +// Z7LIMITED: "-debug-info-kind=limited" + // RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=BreproDefault %s // BreproDefault: "-mincremental-linker-compatible" @@ -485,7 +489,7 @@ // which made it "win". This test could not detect that bug. // RUN: %clang_cl /Z7 -gdwarf /c -### -- %s 2>&1 | FileCheck -check-prefix=Z7_gdwarf %s // Z7_gdwarf: "-gcodeview" -// Z7_gdwarf: "-debug-info-kind=limited" +// Z7_gdwarf: "-debug-info-kind=standalone" // Z7_gdwarf: "-dwarf-version=4" // RUN: %clang_cl -fmsc-version=1800 -TP -### -- %s 2>&1 | FileCheck -check-prefix=CXX11 %s Index: lib/Driver/ToolChains.h =================================================================== --- lib/Driver/ToolChains.h +++ lib/Driver/ToolChains.h @@ -1139,6 +1139,7 @@ bool isPICDefault() const override; bool isPIEDefault() const override; bool isPICDefaultForced() const override; + bool GetDefaultStandaloneDebug() const override; void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, Index: lib/Driver/MSVCToolChain.cpp =================================================================== --- lib/Driver/MSVCToolChain.cpp +++ lib/Driver/MSVCToolChain.cpp @@ -94,6 +94,18 @@ return getArch() == llvm::Triple::x86_64; } +bool MSVCToolChain::GetDefaultStandaloneDebug() const { + // Microsoft debuggers can't lookup type names across type stream boundaries. + // This means that types implemented in b.dll used by a.dll sometimes can't be + // found when debugging a.dll. Clang will emit types marked with dllimport to + // try to cope with this case, but is not a complete heuristic. Non-standalone + // type info is also incompatble with /DEBUG:FASTLINK, which leaves all debug + // info, including types, in object files. In this case, the type stream is + // limited to the TU, and every TU needs to have all the types required to be + // complete by that TU for debugging. + return true; +} + #ifdef USE_WIN32 static bool readFullStringValue(HKEY hkey, const char *valueName, std::string &value) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits