nickdesaulniers added inline comments.
================ Comment at: clang/lib/CodeGen/CodeGenModule.cpp:5385 + if (getCodeGenOpts().hasMaybeUnusedDebugInfo() && CRD->hasDefinition()) + DI->completeUnusedClass(*CRD); + else if (auto *ES = D->getASTContext().getExternalSource()) ---------------- dblaikie wrote: > nickdesaulniers wrote: > > dblaikie wrote: > > > I think this might not work as intended if the type trips over the other > > > class deduplication optimizations (try manually testing with a type that > > > has an external VTable?) - and perhaps this codepath should use the > > > EmitAndRetain functionality. > > completeUnusedClass eventually calls into CGDebugInfo::completeClass which > > makes use of the TypeCache. What does it mean for a class to have "an > > external vtable?" Can you give me an example? > Here's some sample code that uses a type in the DWARF but due to the vtable > being external (an external vtable is one that's guaranteed to be emitted in > some other object file - due to the key function optimization in the Itanium > ABI - since all virtual functions must be defined if a type is ODR used, the > compiler can make a shared assumption that the vtable will only be emitted > with a single consistently chosen virtual function (ideally: the first > non-inline one) and emit the vtable only in that object and nowhere else) the > type is emitted as a declaration (when using "-fno-standalone-debug"): > > ``` > struct t1 { > virtual void f1(); > }; > t1 v1; > ``` Cool, thanks for the example. For your example: `clang -g -emit-llvm -S foo.cpp -o -`: ``` ... DIGlobalVariable(name: "v1" ... DICompositeType(tag: DW_TAG_structure_type, name: "t1" ... ``` `clang -g -fno-eliminate-unused-debug-types -emit-llvm -S foo.cpp -o -`: ``` ... DIGlobalVariable(name: "v1" ... DICompositeType(tag: DW_TAG_structure_type, name: "t1" ... DIDerivedType(tag: DW_TAG_member, name: "_vptr$t1" DIDerivedType(tag: DW_TAG_pointer_type DIDerivedType(tag: DW_TAG_pointer_type, name: "__vtbl_ptr_type" DIBasicType(name: "int" DISubprogram(name: "f1" DISubroutineType DIDerivedType(tag: DW_TAG_pointer_type ... ``` So even though `f1` was not defined, we still emit debug info for it. Comparing the output of `llvm-dwarfdump` on `$CC -g -fno-eliminate-unused-debug-types -c <example.cpp>` for `g++` vs `clang++`; we're definitely producing more debug info (the vtable info). That said, the creation of `v1` technically means that `t1` is no longer an "unused type." If we comment out its creation, then compare `$CC -g -fno-eliminate-unused-debug-types -c <example.cpp>` for `g++` vs `clang++`, `g++` produces no debug info (That seems like a bug in `g++` to me), while `clang++` with this patch produces the debug info for the `CXXRecord`, and additional info for the vtable ptr and signature of `f1`. I'm not sure what's expected in this case (we should at least emit the `DW_TAG_structure_type` for `t1`, but I'm not sure about the `DW_TAG_subprogram` for `f1`. I assume that's because we've enabled more-than-full-debuginfo behavior? WDYT? ================ Comment at: clang/lib/Driver/ToolChains/Clang.cpp:3825-3828 + if (EmitDwarf && + Args.hasFlag(options::OPT_fno_eliminate_unused_debug_types, + options::OPT_feliminate_unused_debug_types, false)) + DebugInfoKind = codegenoptions::UnusedTypeInfo; ---------------- dblaikie wrote: > How does GCC compose this with -gmlt, for instance? I'd suspect that the > desired behavior might be for -gmlt to override this -f flag? So maybe this > should be predicated on "if (EmitDwarf && DebugInfoKind >= > codegenoptions::LimitedDebugInfo && ... "? > > (so if someone wants to use only -gmlt in certain parts of their build that > doesn't get upgraded by the presence of this -f flag) GCC does not yet support `-gmlt`. https://godbolt.org/z/Wrv6sK IIUC, `-gmlt` ("minimum line tables") is meant to minimize the amount of debug info produced. I'm not sure what the user expects if they simultaneous ask for more debug info (via `-fno-eliminate-unused-types`) and less debug info (via `-gmlt`). The current behavior is that `-fno-eliminate-unused-types` "wins" out over `-gmlt`, resulting in the "fullest" amount of debug info being produced. (Would you like me to add tests for this behavior to clang/test/Driver/debug-options.c for this behavior?) If we don't want that behavior, we should reconsider whether we want `UnusedTypeInfo` to be part of the `DebugInfoKind` "progression." I also don't understand what the suggested added condition to the predicate is supposed to do; if `EmitDebugInfo` is set, doesn't the default value of `DebugInfoConstructor` (after 227db86a1b7dd6f96f7df14890fcd071bc4fe1f5, rebased this patch on top of) mean that we wouldn't use `UnusedTypeInfo` with `-g -fno-eliminate-unused-type-info? Or am I misunderstanding the suggestion? ================ Comment at: clang/test/CodeGen/debug-info-unused-types.cpp:15-21 +// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "baz" +// CHECK: !DIEnumerator(name: "BAZ" +// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "z" +// CHECK: !DIEnumerator(name: "Z" +// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "foo" +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "bar" +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "y" ---------------- dblaikie wrote: > Probably good to check these end up in the retained types list What's the best way to check this? In particular, I worry about the `!<number>` number changing in the future, resulting in this test spuriously failing. For this test case, we have: ``` !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "Nick Desaulniers clang version 12.0.0 (g...@github.com:llvm/llvm-project.git e541558d11ca82b3664b907b350da5187f23c0c9)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !15, splitDebugInlining: false, nameTableKind: None) ``` which tells us the `retainedTypes` is `!15`. `!15` looks like: ``` !15 = !{!16, !17, !3, !5, !18, !8} ``` In this case, should I just add the numbers? If we used regex patterns `[0-9]`, I worry that we couldn't ensure the list would match. Is it ok to just hardcode these? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D80242/new/ https://reviews.llvm.org/D80242 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits