Skip to content

Commit bfabc95

Browse files
authored
[DebugInfo] Add flag to only emit referenced member functions (#87018)
Complete C++ type information can be quite expensive - and there's limited value in representing every member function, even those that can't be called (we don't do similarly for every non-member function anyway). So add a flag to opt out of this behavior for experimenting with this more terse behavior. I think Sony already does this by default, so perhaps with a change to the defaults, Sony can migrate to this rather than a downstream patch. This breaks current debuggers in some expected ways - but those breakages are visible without this feature too. Consider member function template instantiations - they can't be consistently enumerated in every translation unit: a.h: ``` struct t1 { template <int i> static int f1() { return i; } }; namespace ns { template <int i> int f1() { return i; } } // namespace ns ``` a.cpp: ``` void f1() { t1::f1<0>(); ns::f1<0>(); } ``` b.cpp: ``` void f1(); int main() { f1(); t1::f1<1>(); ns::f1<1>(); } ``` ``` (gdb) p ns::f1<0>() $1 = 0 (gdb) p ns::f1<1>() $2 = 1 (gdb) p t1::f1<0>() Couldn't find method t1::f1<0> (gdb) p t1::f1<1>() $3 = 1 (gdb) s f1 () at a.cpp:3 3 t1::f1<0>(); (gdb) p t1::f1<0>() $4 = 0 (gdb) p t1::f1<1>() Couldn't find method t1::f1<1> (gdb) ``` (other similar non-canonical features are implicit special members (copy/move ctor/assignment operator, default ctor) and nested types (eg: pimpl idiom, where the nested type is declared-but-not-defined in one TU, and defined in another TU)) lldb can't parse the template expressions above, so I'm not sure how to test it there, but I'd guess it has similar problems. ( https://stackoverflow.com/questions/64602475/how-to-print-value-returned-by-template-member-function-in-gdb-lldb-debugging so... I guess that's just totally not supported in lldb, how unfortunate. And implicit special members are instantiated implicitly by lldb, so missing those doesn't tickle the same issue) Some very rudimentary numbers for a clang debug build: .debug_info section size: -g: 476MiB -g -fdebug-types-section: 357MiB -g -gomit-unreferenced-members: 340MiB Though it also means a major reduction in .debug_str size, -fdebug-types-section doesn't reduce string usage (so the first two examples have the same .debug_str size, 247MiB), down to 175MiB. So for total clang binary size (I don't have a quick "debug section size reduction" on-hand): 1.45 (no type units) GiB -> 1.34 -> 1.22, so it saves about 120MiB of binary size. Also open to any riffing on the flag name for sure. @probinson - would this be an accurate upstreaming of your internal handling/would you use this functionality? If it wouldn't be useful to you, it's maybe not worth adding upstream yet - not sure we'll use it at Google, but if it was useful to you folks and meant other folks could test with it it seemed maybe useful. Original Differential Revision: https://reviews.llvm.org/D152017
1 parent 495bc3c commit bfabc95

File tree

6 files changed

+42
-1
lines changed

6 files changed

+42
-1
lines changed

clang/include/clang/Basic/DebugOptions.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ BENIGN_DEBUGOPT(NoInlineLineTables, 1, 0) ///< Whether debug info should contain
6868
///< inline line tables.
6969

7070
DEBUGOPT(DebugStrictDwarf, 1, 1) ///< Whether or not to use strict DWARF info.
71+
DEBUGOPT(DebugOmitUnreferencedMethods, 1, 0) ///< Omit unreferenced member
72+
///< functions in type debug info.
7173

7274
/// Control the Assignment Tracking debug info feature.
7375
BENIGN_ENUM_DEBUGOPT(AssignmentTrackingMode, AssignmentTrackingOpts, 2,

clang/include/clang/Driver/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4345,6 +4345,10 @@ defm strict_dwarf : BoolOption<"g", "strict-dwarf",
43454345
"the specified version, avoiding features from later versions.">,
43464346
NegFlag<SetFalse>, BothFlags<[], [ClangOption, CLOption, DXCOption]>>,
43474347
Group<g_flags_Group>;
4348+
defm omit_unreferenced_methods : BoolGOption<"omit-unreferenced-methods",
4349+
CodeGenOpts<"DebugOmitUnreferencedMethods">, DefaultFalse,
4350+
NegFlag<SetFalse>,
4351+
PosFlag<SetTrue, [], [CC1Option]>, BothFlags<[], [ClangOption, CLOption, DXCOption]>>;
43484352
defm column_info : BoolOption<"g", "column-info",
43494353
CodeGenOpts<"DebugColumnInfo">, DefaultTrue,
43504354
NegFlag<SetFalse, [], [ClangOption, CC1Option]>,

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2836,7 +2836,7 @@ CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
28362836

28372837
// Collect data fields (including static variables and any initializers).
28382838
CollectRecordFields(RD, DefUnit, EltTys, FwdDecl);
2839-
if (CXXDecl)
2839+
if (CXXDecl && !CGM.getCodeGenOpts().DebugOmitUnreferencedMethods)
28402840
CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl);
28412841

28422842
LexicalBlockStack.pop_back();

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "llvm/ADT/StringExtras.h"
4646
#include "llvm/BinaryFormat/Magic.h"
4747
#include "llvm/Config/llvm-config.h"
48+
#include "llvm/Frontend/Debug/Options.h"
4849
#include "llvm/Object/ObjectFile.h"
4950
#include "llvm/Option/ArgList.h"
5051
#include "llvm/Support/CodeGen.h"
@@ -4642,6 +4643,7 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T,
46424643
Args.addOptInFlag(CmdArgs, options::OPT_fforce_dwarf_frame,
46434644
options::OPT_fno_force_dwarf_frame);
46444645

4646+
bool EnableTypeUnits = false;
46454647
if (Args.hasFlag(options::OPT_fdebug_types_section,
46464648
options::OPT_fno_debug_types_section, false)) {
46474649
if (!(T.isOSBinFormatELF() || T.isOSBinFormatWasm())) {
@@ -4652,11 +4654,24 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T,
46524654
} else if (checkDebugInfoOption(
46534655
Args.getLastArg(options::OPT_fdebug_types_section), Args, D,
46544656
TC)) {
4657+
EnableTypeUnits = true;
46554658
CmdArgs.push_back("-mllvm");
46564659
CmdArgs.push_back("-generate-type-units");
46574660
}
46584661
}
46594662

4663+
if (const Arg *A =
4664+
Args.getLastArg(options::OPT_gomit_unreferenced_methods,
4665+
options::OPT_gno_omit_unreferenced_methods))
4666+
(void)checkDebugInfoOption(A, Args, D, TC);
4667+
if (Args.hasFlag(options::OPT_gomit_unreferenced_methods,
4668+
options::OPT_gno_omit_unreferenced_methods, false) &&
4669+
(DebugInfoKind == llvm::codegenoptions::DebugInfoConstructor ||
4670+
DebugInfoKind == llvm::codegenoptions::LimitedDebugInfo) &&
4671+
!EnableTypeUnits) {
4672+
CmdArgs.push_back("-gomit-unreferenced-methods");
4673+
}
4674+
46604675
// To avoid join/split of directory+filename, the integrated assembler prefers
46614676
// the directory form of .file on all DWARF versions. GNU as doesn't allow the
46624677
// form before DWARF v5.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %clang_cc1 -debug-info-kind=limited -gomit-unreferenced-methods %s -emit-llvm -o - | FileCheck %s
2+
3+
struct t1 {
4+
void f1();
5+
void f2();
6+
};
7+
8+
void t1::f1() { }
9+
10+
// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1"
11+
// CHECK-SAME: elements: [[ELEMENTS:![0-9]+]]
12+
// CHECK: [[ELEMENTS]] = !{}

clang/test/Driver/debug-options.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,11 @@
242242
// RUN: %clang -### -c %s 2>&1 | FileCheck -check-prefix=NORNGBSE %s
243243
// RUN: %clang -### -c -fdebug-ranges-base-address -fno-debug-ranges-base-address %s 2>&1 | FileCheck -check-prefix=NORNGBSE %s
244244
//
245+
// RUN: %clang -### -c -gomit-unreferenced-methods %s 2>&1 | FileCheck -check-prefix=INCTYPES %s
246+
// RUN: %clang -### -c %s 2>&1 | FileCheck -check-prefix=NOINCTYPES %s
247+
// RUN: %clang -### -c -gomit-unreferenced-methods -fdebug-types-section %s 2>&1 | FileCheck -check-prefix=NOINCTYPES %s
248+
// RUN: %clang -### -c -gomit-unreferenced-methods -fstandalone-debug %s 2>&1 | FileCheck -check-prefix=NOINCTYPES %s
249+
//
245250
// RUN: %clang -### -c -glldb %s 2>&1 | FileCheck -check-prefix=NOPUB %s
246251
// RUN: %clang -### -c -glldb -gno-pubnames %s 2>&1 | FileCheck -check-prefix=NOPUB %s
247252
//
@@ -381,6 +386,9 @@
381386
// RNGBSE: -fdebug-ranges-base-address
382387
// NORNGBSE-NOT: -fdebug-ranges-base-address
383388
//
389+
// INCTYPES: -gomit-unreferenced-methods
390+
// NOINCTYPES-NOT: -gomit-unreferenced-methods
391+
//
384392
// GARANGE-DAG: -generate-arange-section
385393
//
386394
// FDTS: "-mllvm" "-generate-type-units"

0 commit comments

Comments
 (0)