Skip to content

Conversation

@CarlosAlbertoEnciso
Copy link
Member

@CarlosAlbertoEnciso CarlosAlbertoEnciso commented Nov 11, 2024

For the given C++ code:

  template <typename T> class Foo { T Member; };

  template <template <typename T> class TemplateType>
  class Bar {
    TemplateType<int> Int;
  };

  template <template <template <typename> class> class TemplateTemplateType>
  class Baz {
    TemplateTemplateType<Foo> Foo;
  };

  typedef Baz<Bar> Example;
  Example TT;

The '--attribute=encoded' option, will produce the logical view:

  {Class} 'Foo<int>'
    {Encoded} <int>
  {Class} 'Bar<Foo>'
    {Encoded} <>                 <-- Missing the template argument info (Foo)
  {Class} 'Baz<Bar>'
    {Encoded} <>                 <-- Missing the template argument info (Bar)

When the template argument is another template it is not included in the {Encoded} field. The correct output should be:

  {Class} 'Foo<int>'
    {Encoded} <int>
  {Class} 'Bar<Foo>'
    {Encoded} <Foo>
  {Class} 'Baz<Bar>'
    {Encoded} <Bar>

For the given C++ code:

  template <typename T> class Foo { T Member; };

  template <template <typename T> class TemplateType>
  class Bar {
    TemplateType<int> Int;
  };

  template <template <template <typename> class> class TemplateTemplateType>
  class Baz {
    TemplateTemplateType<Foo> Foo;
  };

  typedef Baz<Bar> Example;

  Example TT;

The '--attribute=encoded' option, will produce the logical view:

  {Class} 'Foo<int>'
    {Encoded} <int>
  {Class} 'Bar<Foo>'
    {Encoded} <>
  {Class} 'Baz<Bar>'
    {Encoded} <>

When the template argument is another template it is not included
in the {Encoded} field. The correct output should be:

  {Class} 'Foo<int>'
    {Encoded} <int>
  {Class} 'Bar<Foo>'
    {Encoded} <Foo>
  {Class} 'Baz<Bar>'
    {Encoded} <Bar>
@llvmbot
Copy link
Member

llvmbot commented Nov 11, 2024

@llvm/pr-subscribers-debuginfo

@llvm/pr-subscribers-llvm-binary-utilities

Author: Carlos Alberto Enciso (CarlosAlbertoEnciso)

Changes

For the given C++ code:

template <typename T> class Foo { T Member; };

template <template <typename T> class TemplateType>
class Bar {
TemplateType<int> Int;
};

template <template <template <typename> class> class TemplateTemplateType>
class Baz {
TemplateTemplateType<Foo> Foo;
};

typedef Baz<Bar> Example;

Example TT;

The '--attribute=encoded' option, will produce the logical view:

{Class} 'Foo<int>'
{Encoded} <int>
{Class} 'Bar<Foo>'
{Encoded} <>
{Class} 'Baz<Bar>'
{Encoded} <>

When the template argument is another template it is not included in the {Encoded} field. The correct output should be:

{Class} 'Foo<int>'
{Encoded} <int>
{Class} 'Bar<Foo>'
{Encoded} <Foo>
{Class} 'Baz<Bar>'
{Encoded} <Bar>


Full diff: https://github.com/llvm/llvm-project/pull/115724.diff

3 Files Affected:

  • (modified) llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp (+3)
  • (added) llvm/test/tools/llvm-debuginfo-analyzer/DWARF/DW_AT_GNU_template_name.test (+60)
  • (added) llvm/test/tools/llvm-debuginfo-analyzer/DWARF/Inputs/DW_AT_GNU_template_name.ll (+36)
diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp
index 1c523c01314977..404b9578933318 100644
--- a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp
@@ -369,6 +369,9 @@ void LVDWARFReader::processOneAttribute(const DWARFDie &Die,
   case dwarf::DW_AT_name:
     CurrentElement->setName(dwarf::toStringRef(FormValue));
     break;
+  case dwarf::DW_AT_GNU_template_name:
+    CurrentElement->setValue(dwarf::toStringRef(FormValue));
+    break;
   case dwarf::DW_AT_linkage_name:
   case dwarf::DW_AT_MIPS_linkage_name:
     CurrentElement->setLinkageName(dwarf::toStringRef(FormValue));
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/DW_AT_GNU_template_name.test b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/DW_AT_GNU_template_name.test
new file mode 100644
index 00000000000000..bafa5ba1502177
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/DW_AT_GNU_template_name.test
@@ -0,0 +1,60 @@
+; REQUIRES: x86-registered-target
+
+; For the given test case:
+
+;  1 // Template Template parameters.
+;  2 // Simple template class
+;  3 template <typename T> class Foo { T Member; };
+;  4
+;  5 // Template template class
+;  6 template <template <typename T> class TemplateType>
+;  7 class Bar {
+;  8   TemplateType<int> Int;
+;  9 };
+; 10
+; 11 template <template <template <typename> class> class TemplateTemplateType>
+; 12 class Baz {
+; 13   TemplateTemplateType<Foo> Foo;
+; 14 };
+; 15
+; 16 typedef Baz<Bar> Example;
+; 17
+; 18 Example TT;
+
+; The llvm-debuginfo-analyzer does not support the DW_AT_GNU_template_name
+; attribute. When using '--attribute=encoded' and the template argument is
+; another template, it will show:
+;   {Encoded} <>
+
+; The object file is generated using the following commands:
+;
+; clang++ -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes
+;         -fno-discard-value-names -emit-llvm -S -g -O0
+;         DW_AT_GNU_template_name.cpp -o DW_AT_GNU_template_name.ll
+; llc --filetype=obj DW_AT_GNU_template_name.ll -o DW_AT_GNU_template_name.o
+;
+; llvm-debuginfo-analyzer --attribute=encoded --print=symbols
+;                         DW_AT_GNU_template_name.o
+
+; RUN: llc --filetype=obj \
+; RUN:     %p/Inputs/DW_AT_GNU_template_name.ll -o %t.DW_AT_GNU_template_name.o
+
+; RUN: llvm-debuginfo-analyzer --attribute=encoded \
+; RUN:                         --print=symbols \
+; RUN:                         %t.DW_AT_GNU_template_name.o 2>&1 | \
+; RUN: FileCheck --strict-whitespace %s
+
+; CHECK: Logical View:
+; CHECK:            {File} '{{.*}}dw_at_gnu_template_name.o'
+; CHECK-EMPTY:
+; CHECK:              {CompileUnit} 'dw_at_gnu_template_name.cpp'
+; CHECK:      3         {Class} 'Foo<int>'
+; CHECK:                  {Encoded} <int>
+; CHECK:      3           {Member} private 'Member' -> 'int'
+; CHECK:      7         {Class} 'Bar<Foo>'
+; CHECK:                  {Encoded} <Foo>
+; CHECK:      8           {Member} private 'Int' -> 'Foo<int>'
+; CHECK:     12         {Class} 'Baz<Bar>'
+; CHECK:                  {Encoded} <Bar>
+; CHECK:     13           {Member} private 'Foo' -> 'Bar<Foo>'
+; CHECK:     18         {Variable} extern 'TT' -> 'Example'
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/Inputs/DW_AT_GNU_template_name.ll b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/Inputs/DW_AT_GNU_template_name.ll
new file mode 100644
index 00000000000000..cfe1f182ae880b
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/Inputs/DW_AT_GNU_template_name.ll
@@ -0,0 +1,36 @@
+source_filename = "DW_AT_GNU_template_name.cpp"
+target triple = "x86_64-pc-linux-gnu"
+
+%class.Baz = type { %class.Bar }
+%class.Bar = type { %class.Foo }
+%class.Foo = type { i32 }
+
+@TT = dso_local global %class.Baz zeroinitializer, align 4, !dbg !0
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!22, !23}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "TT", scope: !2, file: !3, line: 18, type: !5, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, emissionKind: FullDebug, globals: !4)
+!3 = !DIFile(filename: "DW_AT_GNU_template_name.cpp", directory: "")
+!4 = !{!0}
+!5 = !DIDerivedType(tag: DW_TAG_typedef, name: "Example", file: !3, line: 16, baseType: !6)
+!6 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "Baz<Bar>", file: !3, line: 12, size: 32, flags: DIFlagTypePassByValue, elements: !7, templateParams: !20, identifier: "_ZTS3BazI3BarE")
+!7 = !{!8}
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "Foo", scope: !6, file: !3, line: 13, baseType: !9, size: 32)
+!9 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "Bar<Foo>", file: !3, line: 7, size: 32, flags: DIFlagTypePassByValue, elements: !10, templateParams: !18, identifier: "_ZTS3BarI3FooE")
+!10 = !{!11}
+!11 = !DIDerivedType(tag: DW_TAG_member, name: "Int", scope: !9, file: !3, line: 8, baseType: !12, size: 32)
+!12 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "Foo<int>", file: !3, line: 3, size: 32, flags: DIFlagTypePassByValue, elements: !13, templateParams: !16, identifier: "_ZTS3FooIiE")
+!13 = !{!14}
+!14 = !DIDerivedType(tag: DW_TAG_member, name: "Member", scope: !12, file: !3, line: 3, baseType: !15, size: 32)
+!15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!16 = !{!17}
+!17 = !DITemplateTypeParameter(name: "T", type: !15)
+!18 = !{!19}
+!19 = !DITemplateValueParameter(tag: DW_TAG_GNU_template_template_param, name: "TemplateType", value: !"Foo")
+!20 = !{!21}
+!21 = !DITemplateValueParameter(tag: DW_TAG_GNU_template_template_param, name: "TemplateTemplateType", value: !"Bar")
+!22 = !{i32 7, !"Dwarf Version", i32 5}
+!23 = !{i32 2, !"Debug Info Version", i32 3}

@CarlosAlbertoEnciso
Copy link
Member Author

Note: the '--attribute=encoded' option collects the template arguments and it is used for toolchains that have the ability to omit the template arguments from the template name.
For those toolchains:

{Class} 'Foo<int>'    -->    {Class} 'Foo' 
  {Encoded} <int>              {Encoded} <int>
{Class} 'Bar<Foo>'           {Class} 'Bar'
  {Encoded} <Foo>              {Encoded} <Foo>
{Class} 'Baz<Bar>'           {Class} 'Baz'
  {Encoded} <Bar>              {Encoded} <Bar>

@CarlosAlbertoEnciso
Copy link
Member Author

CarlosAlbertoEnciso commented Nov 25, 2024

Ping.
Thanks

Copy link
Contributor

@SLTozer SLTozer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty straightforward, I've just one question: there are two attributes given to DW_TAG_GNU_template_template_param, DW_TAG_name and DW_TAG_template_name. I see in the test you demonstrate printing the DW_TAG_template_name value, which is what this commit adds, but does the logical viewer print out the DW_TAG_name at any point?

Comment on lines 24 to 26
; The llvm-debuginfo-analyzer does not support the DW_AT_GNU_template_name
; attribute. When using '--attribute=encoded' and the template argument is
; another template, it will show:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small suggestion to change this to either past tense ("The llvm-debuginfo-analyzer did not support"), or to otherwise indicate that support has been added ("The llvm-debuginfo-analyzer should support..."); right now this seems to indicate that as-of this patch, there is no support for this tag, which is slightly confusing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good observation. Changed to The llvm-debuginfo-analyzer did not support.

@CarlosAlbertoEnciso
Copy link
Member Author

For the given test case, GCC and Clang generate the following DWARF

...
DW_TAG_GNU_template_template_param
     DW_AT_name	("TemplateTemplateType")
     DW_AT_GNU_template_name	("Bar")
...
DW_TAG_GNU_template_template_param
     DW_AT_name	("TemplateType")
     DW_AT_GNU_template_name	("Foo")
...

The --attribute=typename adds the DW_AT_name to the printed logical view.

clang++ -c -g -O0 template.cpp -o template-clang.o
llvm-debuginfo-analyzer --print=elements --attribute=typename template-clang.o
Logical View:
           {File} 'template-clang.o'

             {CompileUnit} 'template.cpp'
     1         {Class} 'Foo<int>'
                 {TemplateType} 'T' -> 'int'
     1           {Member} private 'Member' -> 'int'
     4         {Class} 'Bar<Foo>'
                 {TemplateTemplate} 'TemplateType' -> 'Foo'          <-- DW_AT_name value
     5           {Member} private 'Int' -> 'Foo<int>'
     9         {Class} 'Baz<Bar>'
                 {TemplateTemplate} 'TemplateTemplateType' -> 'Bar'  <-- DW_AT_name value
    10           {Member} private 'Foo' -> 'Bar<Foo>'
    13         {TypeAlias} 'Example' -> 'Baz<Bar>'
    14         {Variable} extern 'TT' -> 'Example'

Address reviewer feedback.
- Change the comment to add clarity to the patch.
Copy link
Contributor

@SLTozer SLTozer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would the full {TemplateTemplate} line be printed before this patch, or has the output there changed? If the latter, then I think a test should be added for that output as well; otherwise this LGTM.

Comment on lines 24 to 26
; The llvm-debuginfo-analyzer did not support the DW_AT_GNU_template_name
; attribute. When using '--attribute=encoded' and the template argument is
; another template, it will show:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
; The llvm-debuginfo-analyzer did not support the DW_AT_GNU_template_name
; attribute. When using '--attribute=encoded' and the template argument is
; another template, it will show:
; The llvm-debuginfo-analyzer did not support the DW_AT_GNU_template_name
; attribute. When using '--attribute=encoded' and the template argument is
; another template, it would show:

@CarlosAlbertoEnciso
Copy link
Member Author

The {TemplateTemplate} line was printed before this patch.

Address reviewer feedback.
- Change the comment to add clarity to the patch.
@CarlosAlbertoEnciso
Copy link
Member Author

@SLTozer Thanks very much for your valuable review.

@CarlosAlbertoEnciso CarlosAlbertoEnciso merged commit c4fbb65 into llvm:main Nov 28, 2024
5 of 7 checks passed
@CarlosAlbertoEnciso CarlosAlbertoEnciso deleted the DW_AT_GNU_template_name branch November 28, 2024 15:10
@llvm-ci
Copy link
Collaborator

llvm-ci commented Nov 28, 2024

LLVM Buildbot has detected a new failure on builder libc-aarch64-ubuntu-fullbuild-dbg running on libc-aarch64-ubuntu while building llvm at step 4 "annotate".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/71/builds/11522

Here is the relevant piece of the build log for the reference
Step 4 (annotate) failure: 'python ../llvm-zorg/zorg/buildbot/builders/annotated/libc-linux.py ...' (failure)
...
[ RUN      ] LlvmLibcStrtouint32Test.MessyBaseSixteenDecode
[       OK ] LlvmLibcStrtouint32Test.MessyBaseSixteenDecode (3 us)
[ RUN      ] LlvmLibcStrtouint32Test.AutomaticBaseSelection
[       OK ] LlvmLibcStrtouint32Test.AutomaticBaseSelection (3 us)
Ran 14 tests.  PASS: 14  FAIL: 0
[883/884] Running unit test libc.test.src.time.nanosleep_test.__unit__
[==========] Running 1 test from 1 test suite.
[ RUN      ] LlvmLibcNanosleep.SmokeTest
[       OK ] LlvmLibcNanosleep.SmokeTest (35 us)
Ran 1 tests.  PASS: 1  FAIL: 0
command timed out: 1200 seconds without output running [b'python', b'../llvm-zorg/zorg/buildbot/builders/annotated/libc-linux.py', b'--debug'], attempting to kill
process killed by signal 9
program finished with exit code -1
elapsedTime=1243.115396
Step 8 (libc-unit-tests) failure: libc-unit-tests (failure)
...
[ RUN      ] LlvmLibcStrtouint64Test.DecodeInOtherBases
[       OK ] LlvmLibcStrtouint64Test.DecodeInOtherBases (307 ms)
[ RUN      ] LlvmLibcStrtouint64Test.CleanBaseSixteenDecode
[       OK ] LlvmLibcStrtouint64Test.CleanBaseSixteenDecode (8 us)
[ RUN      ] LlvmLibcStrtouint64Test.MessyBaseSixteenDecode
[       OK ] LlvmLibcStrtouint64Test.MessyBaseSixteenDecode (2 us)
[ RUN      ] LlvmLibcStrtouint64Test.AutomaticBaseSelection
[       OK ] LlvmLibcStrtouint64Test.AutomaticBaseSelection (4 us)
Ran 14 tests.  PASS: 14  FAIL: 0
[882/884] Running unit test libc.test.src.stdlib.strtoint32_test.__unit__
[==========] Running 14 tests from 1 test suite.
[ RUN      ] LlvmLibcStrtoint32Test.InvalidBase
[       OK ] LlvmLibcStrtoint32Test.InvalidBase (2 us)
[ RUN      ] LlvmLibcStrtoint32Test.CleanBaseTenDecode
[       OK ] LlvmLibcStrtoint32Test.CleanBaseTenDecode (7 us)
[ RUN      ] LlvmLibcStrtoint32Test.MessyBaseTenDecode
[       OK ] LlvmLibcStrtoint32Test.MessyBaseTenDecode (6 us)
[ RUN      ] LlvmLibcStrtoint32Test.DecodeInOtherBases
[       OK ] LlvmLibcStrtoint32Test.DecodeInOtherBases (309 ms)
[ RUN      ] LlvmLibcStrtoint32Test.CleanBaseSixteenDecode
[       OK ] LlvmLibcStrtoint32Test.CleanBaseSixteenDecode (9 us)
[ RUN      ] LlvmLibcStrtoint32Test.MessyBaseSixteenDecode
[       OK ] LlvmLibcStrtoint32Test.MessyBaseSixteenDecode (2 us)
[ RUN      ] LlvmLibcStrtoint32Test.AutomaticBaseSelection
[       OK ] LlvmLibcStrtoint32Test.AutomaticBaseSelection (4 us)
[ RUN      ] LlvmLibcStrtouint32Test.InvalidBase
[       OK ] LlvmLibcStrtouint32Test.InvalidBase (1 us)
[ RUN      ] LlvmLibcStrtouint32Test.CleanBaseTenDecode
[       OK ] LlvmLibcStrtouint32Test.CleanBaseTenDecode (7 us)
[ RUN      ] LlvmLibcStrtouint32Test.MessyBaseTenDecode
[       OK ] LlvmLibcStrtouint32Test.MessyBaseTenDecode (5 us)
[ RUN      ] LlvmLibcStrtouint32Test.DecodeInOtherBases
[       OK ] LlvmLibcStrtouint32Test.DecodeInOtherBases (316 ms)
[ RUN      ] LlvmLibcStrtouint32Test.CleanBaseSixteenDecode
[       OK ] LlvmLibcStrtouint32Test.CleanBaseSixteenDecode (8 us)
[ RUN      ] LlvmLibcStrtouint32Test.MessyBaseSixteenDecode
[       OK ] LlvmLibcStrtouint32Test.MessyBaseSixteenDecode (3 us)
[ RUN      ] LlvmLibcStrtouint32Test.AutomaticBaseSelection
[       OK ] LlvmLibcStrtouint32Test.AutomaticBaseSelection (3 us)
Ran 14 tests.  PASS: 14  FAIL: 0
[883/884] Running unit test libc.test.src.time.nanosleep_test.__unit__
[==========] Running 1 test from 1 test suite.
[ RUN      ] LlvmLibcNanosleep.SmokeTest
[       OK ] LlvmLibcNanosleep.SmokeTest (35 us)
Ran 1 tests.  PASS: 1  FAIL: 0

command timed out: 1200 seconds without output running [b'python', b'../llvm-zorg/zorg/buildbot/builders/annotated/libc-linux.py', b'--debug'], attempting to kill
process killed by signal 9
program finished with exit code -1
elapsedTime=1243.115396

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants