Skip to content

Commit 8d6a9c0

Browse files
authored
[DWARF] Add support for DW_TAG_template_alias for template aliases (#88943)
Part 1 of fix for issue #54624 Split from PR #87623. Clang front end changes to follow. Use DICompositeType to represent the template alias, using its extraData field as a tuple of DITemplateParameter to describe the template parameters. Added template-alias.ll - Check DWARF emission. Modified frame-types.s - Check llvm-symbolizer understands the DIE.
1 parent 3da0658 commit 8d6a9c0

File tree

11 files changed

+675
-418
lines changed

11 files changed

+675
-418
lines changed

llvm/include/llvm/IR/DIBuilder.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,24 @@ namespace llvm {
310310
DINode::DIFlags Flags = DINode::FlagZero,
311311
DINodeArray Annotations = nullptr);
312312

313+
/// Create debugging information entry for a template alias.
314+
/// \param Ty Original type.
315+
/// \param Name Alias name.
316+
/// \param File File where this type is defined.
317+
/// \param LineNo Line number.
318+
/// \param Context The surrounding context for the alias.
319+
/// \param TParams The template arguments.
320+
/// \param AlignInBits Alignment. (optional)
321+
/// \param Flags Flags to describe inheritance attribute (optional),
322+
/// e.g. private.
323+
/// \param Annotations Annotations. (optional)
324+
DIDerivedType *createTemplateAlias(DIType *Ty, StringRef Name, DIFile *File,
325+
unsigned LineNo, DIScope *Context,
326+
DINodeArray TParams,
327+
uint32_t AlignInBits = 0,
328+
DINode::DIFlags Flags = DINode::FlagZero,
329+
DINodeArray Annotations = nullptr);
330+
313331
/// Create debugging information entry for a 'friend'.
314332
DIDerivedType *createFriend(DIType *Ty, DIType *FriendTy);
315333

llvm/include/llvm/IR/DebugInfoMetadata.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,14 +1093,19 @@ class DIDerivedType : public DIType {
10931093
/// Get extra data associated with this derived type.
10941094
///
10951095
/// Class type for pointer-to-members, objective-c property node for ivars,
1096-
/// global constant wrapper for static members, or virtual base pointer offset
1097-
/// for inheritance.
1096+
/// global constant wrapper for static members, virtual base pointer offset
1097+
/// for inheritance, or a tuple of template parameters for template aliases.
10981098
///
10991099
/// TODO: Separate out types that need this extra operand: pointer-to-member
11001100
/// types and member fields (static members and ivars).
11011101
Metadata *getExtraData() const { return getRawExtraData(); }
11021102
Metadata *getRawExtraData() const { return getOperand(4); }
11031103

1104+
/// Get the template parameters from a template alias.
1105+
DITemplateParameterArray getTemplateParams() const {
1106+
return cast_or_null<MDTuple>(getExtraData());
1107+
}
1108+
11041109
/// Get annotations associated with this derived type.
11051110
DINodeArray getAnnotations() const {
11061111
return cast_or_null<MDTuple>(getRawAnnotations());

llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,8 @@ uint64_t DebugHandlerBase::getBaseTypeSize(const DIType *Ty) {
154154
if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef &&
155155
Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type &&
156156
Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_atomic_type &&
157-
Tag != dwarf::DW_TAG_immutable_type)
157+
Tag != dwarf::DW_TAG_immutable_type &&
158+
Tag != dwarf::DW_TAG_template_alias)
158159
return DDTy->getSizeInBits();
159160

160161
DIType *BaseType = DDTy->getBaseType();
@@ -210,7 +211,8 @@ bool DebugHandlerBase::isUnsignedDIType(const DIType *Ty) {
210211
assert(T == dwarf::DW_TAG_typedef || T == dwarf::DW_TAG_const_type ||
211212
T == dwarf::DW_TAG_volatile_type ||
212213
T == dwarf::DW_TAG_restrict_type || T == dwarf::DW_TAG_atomic_type ||
213-
T == dwarf::DW_TAG_immutable_type);
214+
T == dwarf::DW_TAG_immutable_type ||
215+
T == dwarf::DW_TAG_template_alias);
214216
assert(DTy->getBaseType() && "Expected valid base type");
215217
return isUnsignedDIType(DTy->getBaseType());
216218
}

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2483,6 +2483,7 @@ static dwarf::PubIndexEntryDescriptor computeIndexValue(DwarfUnit *CU,
24832483
case dwarf::DW_TAG_typedef:
24842484
case dwarf::DW_TAG_base_type:
24852485
case dwarf::DW_TAG_subrange_type:
2486+
case dwarf::DW_TAG_template_alias:
24862487
return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_TYPE, dwarf::GIEL_STATIC);
24872488
case dwarf::DW_TAG_namespace:
24882489
return dwarf::GIEK_TYPE;

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,11 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy) {
803803
if (DTy->getDWARFAddressSpace())
804804
addUInt(Buffer, dwarf::DW_AT_address_class, dwarf::DW_FORM_data4,
805805
*DTy->getDWARFAddressSpace());
806+
807+
// Add template alias template parameters.
808+
if (Tag == dwarf::DW_TAG_template_alias)
809+
addTemplateParams(Buffer, DTy->getTemplateParams());
810+
806811
if (auto PtrAuthData = DTy->getPtrAuthData()) {
807812
addUInt(Buffer, dwarf::DW_AT_LLVM_ptrauth_key, dwarf::DW_FORM_data1,
808813
PtrAuthData->key());

llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ static bool isTypeTag(uint16_t Tag) {
116116
case dwarf::DW_TAG_string_type:
117117
case dwarf::DW_TAG_structure_type:
118118
case dwarf::DW_TAG_subroutine_type:
119+
case dwarf::DW_TAG_template_alias:
119120
case dwarf::DW_TAG_typedef:
120121
case dwarf::DW_TAG_union_type:
121122
case dwarf::DW_TAG_ptr_to_member_type:

llvm/lib/DebugInfo/DWARF/DWARFDie.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ getTypeSizeImpl(DWARFDie Die, uint64_t PointerSize,
515515
case DW_TAG_immutable_type:
516516
case DW_TAG_volatile_type:
517517
case DW_TAG_restrict_type:
518+
case DW_TAG_template_alias:
518519
case DW_TAG_typedef: {
519520
if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type))
520521
return getTypeSizeImpl(BaseType, PointerSize, Visited);

llvm/lib/IR/DIBuilder.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,17 @@ DIDerivedType *DIBuilder::createTypedef(DIType *Ty, StringRef Name,
356356
nullptr, Annotations);
357357
}
358358

359+
DIDerivedType *
360+
DIBuilder::createTemplateAlias(DIType *Ty, StringRef Name, DIFile *File,
361+
unsigned LineNo, DIScope *Context,
362+
DINodeArray TParams, uint32_t AlignInBits,
363+
DINode::DIFlags Flags, DINodeArray Annotations) {
364+
return DIDerivedType::get(VMContext, dwarf::DW_TAG_template_alias, Name, File,
365+
LineNo, getNonCompileUnitScope(Context), Ty, 0,
366+
AlignInBits, 0, std::nullopt, std::nullopt, Flags,
367+
TParams.get(), Annotations);
368+
}
369+
359370
DIDerivedType *DIBuilder::createFriend(DIType *Ty, DIType *FriendTy) {
360371
assert(Ty && "Invalid type!");
361372
assert(FriendTy && "Invalid friend type!");

llvm/lib/IR/Verifier.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1240,7 +1240,8 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
12401240
(N.getTag() == dwarf::DW_TAG_variable && N.isStaticMember()) ||
12411241
N.getTag() == dwarf::DW_TAG_inheritance ||
12421242
N.getTag() == dwarf::DW_TAG_friend ||
1243-
N.getTag() == dwarf::DW_TAG_set_type,
1243+
N.getTag() == dwarf::DW_TAG_set_type ||
1244+
N.getTag() == dwarf::DW_TAG_template_alias,
12441245
"invalid tag", &N);
12451246
if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) {
12461247
CheckDI(isType(N.getRawExtraData()), "invalid pointer to member type", &N,
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
; RUN: llc %s -o - --filetype=obj | llvm-dwarfdump - --name A --show-children | FileCheck %s --check-prefix=TREE
2+
3+
;; -ggnu-pubnames (nameTableKind: GNU).
4+
; RUN: llc %s -o - --filetype=obj \
5+
; RUN: | llvm-dwarfdump - --debug-gnu-pubtypes \
6+
; RUN: | FileCheck %s --check-prefix=GNU-TYPES
7+
8+
;; -gpubnames (remove nameTableKind field from DICompileUnit).
9+
; RUN: sed 's/, nameTableKind: GNU//g' < %s \
10+
; RUN: | llc - -o - --filetype=obj \
11+
; RUN: | llvm-dwarfdump - --debug-pubtypes \
12+
; RUN: | FileCheck %s --check-prefix=PUB-TYPES
13+
14+
;; C++ source from clang/test/CodeGenCXX/template-alias.cpp, compiled with -gsce:
15+
;; template<typename Y, int Z>
16+
;; struct X {
17+
;; Y m1 = Z;
18+
;; };
19+
;;
20+
;; template<typename B, int C>
21+
;; using A = X<B, C>;
22+
;;
23+
;; A<int, 5> a;
24+
25+
;; Test emission of DIDerivedType with tag: DW_TAG_template_alias.
26+
27+
; TREE: DW_TAG_template_alias
28+
; TREE: DW_AT_type (0x{{[0-9a-f]+}} "X<int, 5>")
29+
; TREE: DW_AT_name ("A")
30+
; TREE: DW_TAG_template_type_parameter
31+
; TREE: DW_AT_type (0x{{[0-9a-f]+}} "int")
32+
; TREE: DW_AT_name ("B")
33+
; TREE: DW_TAG_template_value_parameter
34+
; TREE: DW_AT_type (0x{{[0-9a-f]+}} "int")
35+
; TREE: DW_AT_name ("C")
36+
; TREE: DW_AT_const_value (5)
37+
; TREE: NULL
38+
39+
; GNU-TYPES: STATIC TYPE "A"
40+
; PUB-TYPES: "A"
41+
42+
target triple = "x86_64-unknown-unkown"
43+
44+
%struct.X = type { i32 }
45+
46+
@a = global %struct.X { i32 5 }, align 4, !dbg !0
47+
48+
!llvm.dbg.cu = !{!2}
49+
!llvm.module.flags = !{!17, !18}
50+
!llvm.ident = !{!19}
51+
52+
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
53+
!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !5, line: 14, type: !6, isLocal: false, isDefinition: true)
54+
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 19.0.0git", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: GNU)
55+
!3 = !DIFile(filename: "<stdin>", directory: "/")
56+
!4 = !{!0}
57+
!5 = !DIFile(filename: "clang/test/CodeGenCXX/template-alias.cpp", directory: "/")
58+
!6 = !DIDerivedType(tag: DW_TAG_template_alias, name: "A", file: !5, line: 12, baseType: !7, extraData: !14)
59+
!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "X<int, 5>", file: !5, line: 7, size: 32, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !8, templateParams: !11, identifier: "_ZTS1XIiLi5EE")
60+
!8 = !{!9}
61+
!9 = !DIDerivedType(tag: DW_TAG_member, name: "m1", scope: !7, file: !5, line: 8, baseType: !10, size: 32)
62+
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
63+
!11 = !{!12, !13}
64+
!12 = !DITemplateTypeParameter(name: "Y", type: !10)
65+
!13 = !DITemplateValueParameter(name: "Z", type: !10, value: i32 5)
66+
!14 = !{!15, !16}
67+
!15 = !DITemplateTypeParameter(name: "B", type: !10)
68+
!16 = !DITemplateValueParameter(name: "C", type: !10, value: i32 5)
69+
!17 = !{i32 2, !"Debug Info Version", i32 3}
70+
!18 = !{i32 1, !"wchar_size", i32 4}
71+
!19 = !{!"clang version 19.0.0git"}

0 commit comments

Comments
 (0)