Skip to content

[DWARF] Add support for DW_TAG_template_alias for template aliases #88943

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions llvm/include/llvm/IR/DIBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,24 @@ namespace llvm {
DINode::DIFlags Flags = DINode::FlagZero,
DINodeArray Annotations = nullptr);

/// Create debugging information entry for a template alias.
/// \param Ty Original type.
/// \param Name Alias name.
/// \param File File where this type is defined.
/// \param LineNo Line number.
/// \param Context The surrounding context for the alias.
/// \param TParams The template arguments.
/// \param AlignInBits Alignment. (optional)
/// \param Flags Flags to describe inheritance attribute (optional),
/// e.g. private.
/// \param Annotations Annotations. (optional)
DIDerivedType *createTemplateAlias(DIType *Ty, StringRef Name, DIFile *File,
unsigned LineNo, DIScope *Context,
DINodeArray TParams,
uint32_t AlignInBits = 0,
DINode::DIFlags Flags = DINode::FlagZero,
DINodeArray Annotations = nullptr);

/// Create debugging information entry for a 'friend'.
DIDerivedType *createFriend(DIType *Ty, DIType *FriendTy);

Expand Down
9 changes: 7 additions & 2 deletions llvm/include/llvm/IR/DebugInfoMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -1093,14 +1093,19 @@ class DIDerivedType : public DIType {
/// Get extra data associated with this derived type.
///
/// Class type for pointer-to-members, objective-c property node for ivars,
/// global constant wrapper for static members, or virtual base pointer offset
/// for inheritance.
/// global constant wrapper for static members, virtual base pointer offset
/// for inheritance, or a tuple of template parameters for template aliases.
///
/// TODO: Separate out types that need this extra operand: pointer-to-member
/// types and member fields (static members and ivars).
Metadata *getExtraData() const { return getRawExtraData(); }
Metadata *getRawExtraData() const { return getOperand(4); }

/// Get the template parameters from a template alias.
DITemplateParameterArray getTemplateParams() const {
return cast_or_null<MDTuple>(getExtraData());
}

/// Get annotations associated with this derived type.
DINodeArray getAnnotations() const {
return cast_or_null<MDTuple>(getRawAnnotations());
Expand Down
6 changes: 4 additions & 2 deletions llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ uint64_t DebugHandlerBase::getBaseTypeSize(const DIType *Ty) {
if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef &&
Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type &&
Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_atomic_type &&
Tag != dwarf::DW_TAG_immutable_type)
Tag != dwarf::DW_TAG_immutable_type &&
Tag != dwarf::DW_TAG_template_alias)
return DDTy->getSizeInBits();

DIType *BaseType = DDTy->getBaseType();
Expand Down Expand Up @@ -210,7 +211,8 @@ bool DebugHandlerBase::isUnsignedDIType(const DIType *Ty) {
assert(T == dwarf::DW_TAG_typedef || T == dwarf::DW_TAG_const_type ||
T == dwarf::DW_TAG_volatile_type ||
T == dwarf::DW_TAG_restrict_type || T == dwarf::DW_TAG_atomic_type ||
T == dwarf::DW_TAG_immutable_type);
T == dwarf::DW_TAG_immutable_type ||
T == dwarf::DW_TAG_template_alias);
assert(DTy->getBaseType() && "Expected valid base type");
return isUnsignedDIType(DTy->getBaseType());
}
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2483,6 +2483,7 @@ static dwarf::PubIndexEntryDescriptor computeIndexValue(DwarfUnit *CU,
case dwarf::DW_TAG_typedef:
case dwarf::DW_TAG_base_type:
case dwarf::DW_TAG_subrange_type:
case dwarf::DW_TAG_template_alias:
return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_TYPE, dwarf::GIEL_STATIC);
case dwarf::DW_TAG_namespace:
return dwarf::GIEK_TYPE;
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,11 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy) {
if (DTy->getDWARFAddressSpace())
addUInt(Buffer, dwarf::DW_AT_address_class, dwarf::DW_FORM_data4,
*DTy->getDWARFAddressSpace());

// Add template alias template parameters.
if (Tag == dwarf::DW_TAG_template_alias)
addTemplateParams(Buffer, DTy->getTemplateParams());

if (auto PtrAuthData = DTy->getPtrAuthData()) {
addUInt(Buffer, dwarf::DW_AT_LLVM_ptrauth_key, dwarf::DW_FORM_data1,
PtrAuthData->key());
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ static bool isTypeTag(uint16_t Tag) {
case dwarf::DW_TAG_string_type:
case dwarf::DW_TAG_structure_type:
case dwarf::DW_TAG_subroutine_type:
case dwarf::DW_TAG_template_alias:
case dwarf::DW_TAG_typedef:
case dwarf::DW_TAG_union_type:
case dwarf::DW_TAG_ptr_to_member_type:
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ getTypeSizeImpl(DWARFDie Die, uint64_t PointerSize,
case DW_TAG_immutable_type:
case DW_TAG_volatile_type:
case DW_TAG_restrict_type:
case DW_TAG_template_alias:
case DW_TAG_typedef: {
if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type))
return getTypeSizeImpl(BaseType, PointerSize, Visited);
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/IR/DIBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,17 @@ DIDerivedType *DIBuilder::createTypedef(DIType *Ty, StringRef Name,
nullptr, Annotations);
}

DIDerivedType *
DIBuilder::createTemplateAlias(DIType *Ty, StringRef Name, DIFile *File,
unsigned LineNo, DIScope *Context,
DINodeArray TParams, uint32_t AlignInBits,
DINode::DIFlags Flags, DINodeArray Annotations) {
return DIDerivedType::get(VMContext, dwarf::DW_TAG_template_alias, Name, File,
LineNo, getNonCompileUnitScope(Context), Ty, 0,
AlignInBits, 0, std::nullopt, std::nullopt, Flags,
TParams.get(), Annotations);
}

DIDerivedType *DIBuilder::createFriend(DIType *Ty, DIType *FriendTy) {
assert(Ty && "Invalid type!");
assert(FriendTy && "Invalid friend type!");
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1240,7 +1240,8 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
(N.getTag() == dwarf::DW_TAG_variable && N.isStaticMember()) ||
N.getTag() == dwarf::DW_TAG_inheritance ||
N.getTag() == dwarf::DW_TAG_friend ||
N.getTag() == dwarf::DW_TAG_set_type,
N.getTag() == dwarf::DW_TAG_set_type ||
N.getTag() == dwarf::DW_TAG_template_alias,
"invalid tag", &N);
if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) {
CheckDI(isType(N.getRawExtraData()), "invalid pointer to member type", &N,
Expand Down
71 changes: 71 additions & 0 deletions llvm/test/DebugInfo/X86/template-alias.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
; RUN: llc %s -o - --filetype=obj | llvm-dwarfdump - --name A --show-children | FileCheck %s --check-prefix=TREE

;; -ggnu-pubnames (nameTableKind: GNU).
; RUN: llc %s -o - --filetype=obj \
; RUN: | llvm-dwarfdump - --debug-gnu-pubtypes \
; RUN: | FileCheck %s --check-prefix=GNU-TYPES

;; -gpubnames (remove nameTableKind field from DICompileUnit).
; RUN: sed 's/, nameTableKind: GNU//g' < %s \
; RUN: | llc - -o - --filetype=obj \
; RUN: | llvm-dwarfdump - --debug-pubtypes \
; RUN: | FileCheck %s --check-prefix=PUB-TYPES

;; C++ source from clang/test/CodeGenCXX/template-alias.cpp, compiled with -gsce:
;; template<typename Y, int Z>
;; struct X {
;; Y m1 = Z;
;; };
;;
;; template<typename B, int C>
;; using A = X<B, C>;
;;
;; A<int, 5> a;

;; Test emission of DIDerivedType with tag: DW_TAG_template_alias.

; TREE: DW_TAG_template_alias
; TREE: DW_AT_type (0x{{[0-9a-f]+}} "X<int, 5>")
; TREE: DW_AT_name ("A")
; TREE: DW_TAG_template_type_parameter
; TREE: DW_AT_type (0x{{[0-9a-f]+}} "int")
; TREE: DW_AT_name ("B")
; TREE: DW_TAG_template_value_parameter
; TREE: DW_AT_type (0x{{[0-9a-f]+}} "int")
; TREE: DW_AT_name ("C")
; TREE: DW_AT_const_value (5)
; TREE: NULL

; GNU-TYPES: STATIC TYPE "A"
; PUB-TYPES: "A"

target triple = "x86_64-unknown-unkown"

%struct.X = type { i32 }

@a = global %struct.X { i32 5 }, align 4, !dbg !0

!llvm.dbg.cu = !{!2}
!llvm.module.flags = !{!17, !18}
!llvm.ident = !{!19}

!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !5, line: 14, type: !6, isLocal: false, isDefinition: true)
!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)
!3 = !DIFile(filename: "<stdin>", directory: "/")
!4 = !{!0}
!5 = !DIFile(filename: "clang/test/CodeGenCXX/template-alias.cpp", directory: "/")
!6 = !DIDerivedType(tag: DW_TAG_template_alias, name: "A", file: !5, line: 12, baseType: !7, extraData: !14)
!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")
!8 = !{!9}
!9 = !DIDerivedType(tag: DW_TAG_member, name: "m1", scope: !7, file: !5, line: 8, baseType: !10, size: 32)
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!11 = !{!12, !13}
!12 = !DITemplateTypeParameter(name: "Y", type: !10)
!13 = !DITemplateValueParameter(name: "Z", type: !10, value: i32 5)
!14 = !{!15, !16}
!15 = !DITemplateTypeParameter(name: "B", type: !10)
!16 = !DITemplateValueParameter(name: "C", type: !10, value: i32 5)
!17 = !{i32 2, !"Debug Info Version", i32 3}
!18 = !{i32 1, !"wchar_size", i32 4}
!19 = !{!"clang version 19.0.0git"}
Loading