[clang] [llvm] Template as type (PR #127654)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 18 13:53:30 PST 2025
https://github.com/ykhatav updated https://github.com/llvm/llvm-project/pull/127654
>From 2714184615ef06027941c7bccee3a2453d76c24b Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Tue, 18 Feb 2025 06:44:49 -0800
Subject: [PATCH 1/3] Support template as type
---
clang/include/clang/Basic/CodeGenOptions.def | 1 +
clang/include/clang/Driver/Options.td | 5 +
clang/lib/CodeGen/CGDebugInfo.cpp | 19 ++-
clang/lib/CodeGen/CGDebugInfo.h | 2 +
.../debug-info-temp-param-as-type.cpp | 52 ++++++++
llvm/include/llvm/IR/DIBuilder.h | 6 +
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 2 +
llvm/lib/IR/DIBuilder.cpp | 8 ++
llvm/lib/IR/Verifier.cpp | 8 +-
.../DebugInfo/X86/template-as-type-param.ll | 124 ++++++++++++++++++
10 files changed, 222 insertions(+), 5 deletions(-)
create mode 100644 clang/test/CodeGenCXX/debug-info-temp-param-as-type.cpp
create mode 100644 llvm/test/DebugInfo/X86/template-as-type-param.ll
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index 386652d2efa9e..79c3df2e43eef 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -468,6 +468,7 @@ CODEGENOPT(CtorDtorReturnThis, 1, 0)
/// Enables emitting Import Call sections on supported targets that can be used
/// by the Windows kernel to enable import call optimization.
CODEGENOPT(ImportCallOptimization, 1, 0)
+CODEGENOPT(DebugTemplateParameterAsType, 1, 0)
/// FIXME: Make DebugOptions its own top-level .def file.
#include "DebugOptions.def"
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index d8123cc39fdc9..32a88d42dde49 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -9028,3 +9028,8 @@ def wasm_opt : Flag<["--"], "wasm-opt">,
Group<m_Group>,
HelpText<"Enable the wasm-opt optimizer (default)">,
MarshallingInfoNegativeFlag<LangOpts<"NoWasmOpt">>;
+defm debug_template_parameter_as_type
+ : BoolFOption<"debug-template-parameter-as-type",
+ CodeGenOpts<"DebugTemplateParameterAsType">,
+ DefaultFalse, PosFlag<SetTrue>, NegFlag<SetFalse>,
+ BothFlags<[], [CC1Option]>>;
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index db595796c067e..d464a629443a4 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1003,6 +1003,13 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
return DBuilder.createBasicType(BTName, Size, Encoding);
}
+llvm::DIType *CGDebugInfo::CreateType(const SubstTemplateTypeParmType *Ty,
+ llvm::DIFile *U) {
+ llvm::DIType *debugType = getOrCreateType(Ty->getReplacementType(), U);
+ return DBuilder.createTemplateTypeParameterAsType(
+ U, Ty->getReplacedParameter()->getName(), debugType);
+}
+
llvm::DIType *CGDebugInfo::CreateType(const BitIntType *Ty) {
StringRef Name = Ty->isUnsigned() ? "unsigned _BitInt" : "_BitInt";
@@ -3611,7 +3618,8 @@ llvm::DILocation *CGDebugInfo::CreateTrapFailureMessageFor(
/*Scope=*/TrapSP, /*InlinedAt=*/TrapLocation);
}
-static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
+static QualType UnwrapTypeForDebugInfo(QualType T, const CodeGenModule &CGM) {
+ const ASTContext &C = CGM.getContext();
Qualifiers Quals;
do {
Qualifiers InnerQuals = T.getLocalQualifiers();
@@ -3664,6 +3672,8 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
T = cast<MacroQualifiedType>(T)->getUnderlyingType();
break;
case Type::SubstTemplateTypeParm:
+ if (CGM.getCodeGenOpts().DebugTemplateParameterAsType)
+ return C.getQualifiedType(T.getTypePtr(), Quals);
T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
break;
case Type::Auto:
@@ -3690,7 +3700,7 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
}
llvm::DIType *CGDebugInfo::getTypeOrNull(QualType Ty) {
- assert(Ty == UnwrapTypeForDebugInfo(Ty, CGM.getContext()));
+ assert(Ty == UnwrapTypeForDebugInfo(Ty, CGM));
auto It = TypeCache.find(Ty.getAsOpaquePtr());
if (It != TypeCache.end()) {
// Verify that the debug info still exists.
@@ -3729,7 +3739,7 @@ llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
});
// Unwrap the type as needed for debug information.
- Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
+ Ty = UnwrapTypeForDebugInfo(Ty, CGM);
if (auto *T = getTypeOrNull(Ty))
return T;
@@ -3866,6 +3876,9 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
case Type::Decltype:
case Type::PackIndexing:
case Type::UnaryTransform:
+ if (Ty->getTypeClass() == Type::SubstTemplateTypeParm &&
+ CGM.getCodeGenOpts().DebugTemplateParameterAsType)
+ return CreateType(cast<SubstTemplateTypeParmType>(Ty), Unit);
break;
}
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index 38f73eca561b7..5e28fd5bf9039 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -228,6 +228,8 @@ class CGDebugInfo {
llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const AtomicType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const PipeType *Ty, llvm::DIFile *F);
+ llvm::DIType *CreateType(const SubstTemplateTypeParmType *Ty,
+ llvm::DIFile *F);
/// Get enumeration type.
llvm::DIType *CreateEnumType(const EnumType *Ty);
llvm::DIType *CreateTypeDefinition(const EnumType *Ty);
diff --git a/clang/test/CodeGenCXX/debug-info-temp-param-as-type.cpp b/clang/test/CodeGenCXX/debug-info-temp-param-as-type.cpp
new file mode 100644
index 0000000000000..3422ce8f1e2bd
--- /dev/null
+++ b/clang/test/CodeGenCXX/debug-info-temp-param-as-type.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -fdebug-template-parameter-as-type -triple x86_64-apple-darwin %s -o - | FileCheck %s
+
+
+template <typename T>
+struct TClass {
+ TClass();
+ void foo();
+ T val_;
+ int val2_;
+};
+
+template <typename T>
+void TClass<T>::foo() {
+ T tVar = 1;
+ T* pT = &tVar;
+ tVar++;
+}
+
+template <typename T>
+T bar(T tp) {
+ return tp;
+}
+
+int main () {
+ TClass<int> a;
+ a.val2_ = 3;
+ a.foo();
+ auto A = bar(42);
+ TClass<double> b;
+ return 0;
+}
+
+// CHECK: [[INT:![0-9]+]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TClass<int>"
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "val_",{{.*}}baseType: [[TPARAM:![0-9]+]]
+// CHECK: [[TPARAM]] = !DIDerivedType(tag: DW_TAG_template_type_parameter, name: "T", {{.*}}baseType: [[INT]])
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "val2_",{{.*}}baseType: [[INT]]
+
+// CHECK: !DILocalVariable(name: "A",{{.*}}type: [[TPARAM]])
+
+// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TClass<double>"
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "val_",{{.*}}baseType: [[TPARAM2:![0-9]+]]
+// CHECK: [[TPARAM2]] = !DIDerivedType(tag: DW_TAG_template_type_parameter, name: "T", {{.*}}baseType: [[DOUBLE:![0-9]+]])
+// CHECK: [[DOUBLE]] = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float)
+
+// CHECK: distinct !DISubprogram(name: "foo"
+// CHECK: !DILocalVariable(name: "tVar",{{.*}}type: [[TPARAM]])
+// CHECK: !DILocalVariable(name: "pT",{{.*}}type: [[TPTR:![0-9]+]]
+// CHECK: [[TPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[TPARAM]]
+
+// CHECK: distinct !DISubprogram(name: "bar<int>"
+// CHECK: !DILocalVariable(name: "tp",{{.*}}type: [[TPARAM]])
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index 6c479415b9ed2..342b6d94c71f7 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -550,6 +550,12 @@ namespace llvm {
StringRef Name,
DIType *Ty,
bool IsDefault);
+ /// \param Scope Scope in which this type is defined.
+ /// \param Name Type parameter name.
+ /// \param Ty Parameter type.
+ DIDerivedType *createTemplateTypeParameterAsType(DIScope *Scope,
+ StringRef Name,
+ DIType *Ty);
/// Create debugging information for template
/// value parameter.
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 0a8a1ad38c959..8557d833dfb0e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -520,6 +520,8 @@ void DwarfUnit::addTemplateParams(DIE &Buffer, DINodeArray TParams) {
constructTemplateTypeParameterDIE(Buffer, TTP);
else if (auto *TVP = dyn_cast<DITemplateValueParameter>(Element))
constructTemplateValueParameterDIE(Buffer, TVP);
+ else if (auto *TDT = dyn_cast<DIDerivedType>(Element))
+ createTypeDIE(TDT->getScope(), Buffer, TDT);
}
}
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index 8f9462ab46d88..8dc5677459bac 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -458,6 +458,14 @@ DIBuilder::createObjCProperty(StringRef Name, DIFile *File, unsigned LineNumber,
SetterName, PropertyAttributes, Ty);
}
+DIDerivedType *DIBuilder::createTemplateTypeParameterAsType(DIScope *Context,
+ StringRef Name,
+ DIType *Ty) {
+ return DIDerivedType::get(VMContext, dwarf::DW_TAG_template_type_parameter,
+ Name, nullptr, 0, Context, Ty, 0, 0, 0, std::nullopt,
+ std::nullopt, DINode::FlagZero, nullptr);
+}
+
DITemplateTypeParameter *
DIBuilder::createTemplateTypeParameter(DIScope *Context, StringRef Name,
DIType *Ty, bool isDefault) {
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 8432779c107de..c7435a629e23a 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1241,6 +1241,7 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
N.getTag() == dwarf::DW_TAG_inheritance ||
N.getTag() == dwarf::DW_TAG_friend ||
N.getTag() == dwarf::DW_TAG_set_type ||
+ N.getTag() == dwarf::DW_TAG_template_type_parameter ||
N.getTag() == dwarf::DW_TAG_template_alias,
"invalid tag", &N);
if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) {
@@ -1288,8 +1289,11 @@ void Verifier::visitTemplateParams(const MDNode &N, const Metadata &RawParams) {
auto *Params = dyn_cast<MDTuple>(&RawParams);
CheckDI(Params, "invalid template params", &N, &RawParams);
for (Metadata *Op : Params->operands()) {
- CheckDI(Op && isa<DITemplateParameter>(Op), "invalid template parameter",
- &N, Params, Op);
+ CheckDI(((Op) && (isa<DITemplateParameter>(Op))) ||
+ ((isa<DIDerivedType>(Op)) &&
+ (dyn_cast<DIDerivedType>(Op)->getTag() ==
+ dwarf::DW_TAG_template_type_parameter)),
+ "invalid template parameter", &N, Params, Op);
}
}
diff --git a/llvm/test/DebugInfo/X86/template-as-type-param.ll b/llvm/test/DebugInfo/X86/template-as-type-param.ll
new file mode 100644
index 0000000000000..b237a6630ee7b
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/template-as-type-param.ll
@@ -0,0 +1,124 @@
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu %s -o %t -filetype=obj
+; RUN:llvm-dwarfdump %t | FileCheck %s
+;Source code for the IR below:
+;template <typename T>
+;struct A
+;{
+; A () : val_ (), val2_ () { }
+; T val_;
+; int val2_;
+;};
+
+;int main (void)
+;{
+; A<int> a;
+; a.val2_ = 3;
+; return 0;
+;}
+
+;CHECK: DW_TAG_structure_type
+;CHECK: DW_AT_name ("A<int>")
+;CHECK-NEXT: DW_AT_byte_size (0x08)
+;CHECK-NEXT: DW_AT_decl_file ("/path/to{{/|\\}}test.cpp")
+;CHECK-NEXT: DW_AT_decl_line (2)
+
+;CHECK-NOT: NULL
+
+;CHECK:[[TEMPLATE:0x[0-9a-f]*]]: DW_TAG_template_type_parameter
+;CHECK-NEXT: DW_AT_type {{.*}} "int"
+;CHECK-NEXT: DW_AT_name ("T")
+
+;CHECK: DW_TAG_member
+;CHECK-NEXT: DW_AT_name ("val_")
+;CHECK-NEXT: DW_AT_type ([[TEMPLATE]] "T")
+
+;CHECK: DW_TAG_member
+;CHECK-NEXT: DW_AT_name ("val2_")
+;CHECK-NEXT: DW_AT_type {{.*}} "int"
+
+
+; ModuleID = '<stdin>'
+source_filename = "test.cpp"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.A = type { i32, i32 }
+
+$_ZN1AIiEC2Ev = comdat any
+
+; Function Attrs: mustprogress noinline norecurse optnone uwtable
+define dso_local noundef i32 @main() #0 !dbg !20 {
+entry:
+ %retval = alloca i32, align 4
+ %a = alloca %struct.A, align 4
+ store i32 0, i32* %retval, align 4
+ call void @llvm.dbg.declare(metadata %struct.A* %a, metadata !24, metadata !DIExpression()), !dbg !25
+ call void @_ZN1AIiEC2Ev(%struct.A* noundef nonnull align 4 dereferenceable(8) %a), !dbg !25
+ %val2_ = getelementptr inbounds %struct.A, %struct.A* %a, i32 0, i32 1, !dbg !26
+ store i32 3, i32* %val2_, align 4, !dbg !27
+ ret i32 0, !dbg !28
+}
+
+; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+; Function Attrs: noinline nounwind optnone uwtable
+define linkonce_odr dso_local void @_ZN1AIiEC2Ev(%struct.A* noundef nonnull align 4 dereferenceable(8) %this) unnamed_addr #2 comdat align 2 !dbg !29 {
+
+entry:
+ %this.addr = alloca %struct.A*, align 8
+ store %struct.A* %this, %struct.A** %this.addr, align 8
+ call void @llvm.dbg.declare(metadata %struct.A** %this.addr, metadata !30, metadata !DIExpression()), !dbg !32
+ %this1 = load %struct.A*, %struct.A** %this.addr, align 8
+ %val_ = getelementptr inbounds %struct.A, %struct.A* %this1, i32 0, i32 0, !dbg !33
+ store i32 0, i32* %val_, align 4, !dbg !33
+ %val2_ = getelementptr inbounds %struct.A, %struct.A* %this1, i32 0, i32 1, !dbg !34
+ store i32 0, i32* %val2_, align 4, !dbg !34
+ ret void, !dbg !35
+}
+
+attributes #0 = { mustprogress noinline norecurse optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn }
+attributes #2 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!14, !15, !16, !17, !18}
+!llvm.ident = !{!19}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "", isOptimized: false, flags: " -S -g -O0 -emit-llvm reproducer.cxx -o reproducer.ll", runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test.cpp", directory: "/path/to")
+!2 = !{!3}
+!3 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A<int>", file: !1, line: 2, size: 64, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !4, templateParams: !12, identifier: "_ZTS1AIiE")
+!4 = !{!5, !7, !8}
+!5 = !DIDerivedType(tag: DW_TAG_member, name: "val_", scope: !3, file: !1, line: 5, baseType: !36, size: 32,offset: 32)
+!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!7 = !DIDerivedType(tag: DW_TAG_member, name: "val2_", scope: !3, file: !1, line: 6, baseType: !6, size: 32, offset: 32)
+!8 = !DISubprogram(name: "A", scope: !3, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped, spFlags: 0)
+!9 = !DISubroutineType(types: !10)
+!10 = !{null, !11}
+!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!12 = !{!36}
+!13 = !DITemplateTypeParameter(name: "T", type: !6)
+!14 = !{i32 7, !"Dwarf Version", i32 4}
+!15 = !{i32 2, !"Debug Info Version", i32 3}
+!16 = !{i32 1, !"wchar_size", i32 4}
+!17 = !{i32 7, !"uwtable", i32 2}
+!18 = !{i32 7, !"frame-pointer", i32 2}
+!19 = !{!""}
+!20 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 10, type: !21, scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !23)
+!21 = !DISubroutineType(types: !22)
+!22 = !{!6}
+!23 = !{}
+!24 = !DILocalVariable(name: "a", scope: !20, file: !1, line: 12, type: !3)
+!25 = !DILocation(line: 12, column: 10, scope: !20)
+!26 = !DILocation(line: 13, column: 5, scope: !20)
+!27 = !DILocation(line: 13, column: 11, scope: !20)
+!28 = !DILocation(line: 15, column: 3, scope: !20)
+!29 = distinct !DISubprogram(name: "A", linkageName: "_ZN1AIiEC2Ev", scope: !3, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, declaration: !8, retainedNodes: !23)
+!30 = !DILocalVariable(name: "this", arg: 1, scope: !29, type: !31, flags: DIFlagArtificial | DIFlagObjectPointer)
+!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3, size: 64)
+!32 = !DILocation(line: 0, scope: !29)
+!33 = !DILocation(line: 4, column: 10, scope: !29)
+!34 = !DILocation(line: 4, column: 19, scope: !29)
+!35 = !DILocation(line: 4, column: 30, scope: !29)
+!36 = !DIDerivedType(tag: DW_TAG_template_type_parameter,name:"T",scope:!3, baseType: !6)
>From ed4c4a6abbebdbf5496cc74cc4aad688df534a9f Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Tue, 18 Feb 2025 07:31:53 -0800
Subject: [PATCH 2/3] Apply clang-format
---
clang/lib/CodeGen/CGDebugInfo.cpp | 2 +-
llvm/include/llvm/IR/DIBuilder.h | 4 ++--
llvm/lib/IR/DIBuilder.cpp | 5 +++--
llvm/lib/IR/Verifier.cpp | 4 ++--
4 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index d464a629443a4..ce2d34dcd4ce3 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -3672,7 +3672,7 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const CodeGenModule &CGM) {
T = cast<MacroQualifiedType>(T)->getUnderlyingType();
break;
case Type::SubstTemplateTypeParm:
- if (CGM.getCodeGenOpts().DebugTemplateParameterAsType)
+ if (CGM.getCodeGenOpts().DebugTemplateParameterAsType)
return C.getQualifiedType(T.getTypePtr(), Quals);
T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
break;
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index 342b6d94c71f7..bb9b9490fdcdd 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -550,11 +550,11 @@ namespace llvm {
StringRef Name,
DIType *Ty,
bool IsDefault);
- /// \param Scope Scope in which this type is defined.
+ /// \param Scope Scope in which this type is defined.
/// \param Name Type parameter name.
/// \param Ty Parameter type.
DIDerivedType *createTemplateTypeParameterAsType(DIScope *Scope,
- StringRef Name,
+ StringRef Name,
DIType *Ty);
/// Create debugging information for template
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index 8dc5677459bac..fc50077ba8736 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -462,8 +462,9 @@ DIDerivedType *DIBuilder::createTemplateTypeParameterAsType(DIScope *Context,
StringRef Name,
DIType *Ty) {
return DIDerivedType::get(VMContext, dwarf::DW_TAG_template_type_parameter,
- Name, nullptr, 0, Context, Ty, 0, 0, 0, std::nullopt,
- std::nullopt, DINode::FlagZero, nullptr);
+ Name, nullptr, 0, Context, Ty, 0, 0, 0,
+ std::nullopt, std::nullopt, DINode::FlagZero,
+ nullptr);
}
DITemplateTypeParameter *
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index c7435a629e23a..669c3370d9fc4 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1241,7 +1241,7 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
N.getTag() == dwarf::DW_TAG_inheritance ||
N.getTag() == dwarf::DW_TAG_friend ||
N.getTag() == dwarf::DW_TAG_set_type ||
- N.getTag() == dwarf::DW_TAG_template_type_parameter ||
+ N.getTag() == dwarf::DW_TAG_template_type_parameter ||
N.getTag() == dwarf::DW_TAG_template_alias,
"invalid tag", &N);
if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) {
@@ -1289,7 +1289,7 @@ void Verifier::visitTemplateParams(const MDNode &N, const Metadata &RawParams) {
auto *Params = dyn_cast<MDTuple>(&RawParams);
CheckDI(Params, "invalid template params", &N, &RawParams);
for (Metadata *Op : Params->operands()) {
- CheckDI(((Op) && (isa<DITemplateParameter>(Op))) ||
+ CheckDI(((Op) && (isa<DITemplateParameter>(Op))) ||
((isa<DIDerivedType>(Op)) &&
(dyn_cast<DIDerivedType>(Op)->getTag() ==
dwarf::DW_TAG_template_type_parameter)),
>From 022a8eb85929e7b5572483ee2d52ce60331417a6 Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Tue, 18 Feb 2025 13:53:02 -0800
Subject: [PATCH 3/3] Update test to refelect review comment
---
.../DebugInfo/X86/template-as-type-param.ll | 143 +++++++++---------
1 file changed, 69 insertions(+), 74 deletions(-)
diff --git a/llvm/test/DebugInfo/X86/template-as-type-param.ll b/llvm/test/DebugInfo/X86/template-as-type-param.ll
index b237a6630ee7b..25eaeb92fec3e 100644
--- a/llvm/test/DebugInfo/X86/template-as-type-param.ll
+++ b/llvm/test/DebugInfo/X86/template-as-type-param.ll
@@ -1,5 +1,5 @@
; RUN: llc -mtriple=x86_64-unknown-linux-gnu %s -o %t -filetype=obj
-; RUN:llvm-dwarfdump %t | FileCheck %s
+; RUN: llvm-dwarfdump %t | FileCheck %s
;Source code for the IR below:
;template <typename T>
;struct A
@@ -16,30 +16,28 @@
; return 0;
;}
-;CHECK: DW_TAG_structure_type
-;CHECK: DW_AT_name ("A<int>")
-;CHECK-NEXT: DW_AT_byte_size (0x08)
-;CHECK-NEXT: DW_AT_decl_file ("/path/to{{/|\\}}test.cpp")
-;CHECK-NEXT: DW_AT_decl_line (2)
+; CHECK: DW_TAG_structure_type
+; CHECK: DW_AT_name ("A<int>")
+; CHECK-NEXT: DW_AT_byte_size (0x08)
+; CHECK-NEXT: DW_AT_decl_file ("test.cpp")
+; CHECK-NEXT: DW_AT_decl_line (2)
-;CHECK-NOT: NULL
+; CHECK-NOT: NULL
-;CHECK:[[TEMPLATE:0x[0-9a-f]*]]: DW_TAG_template_type_parameter
-;CHECK-NEXT: DW_AT_type {{.*}} "int"
-;CHECK-NEXT: DW_AT_name ("T")
+; CHECK:[[TEMPLATE:0x[0-9a-f]*]]: DW_TAG_template_type_parameter
+; CHECK-NEXT: DW_AT_type {{.*}} "int"
+; CHECK-NEXT: DW_AT_name ("T")
-;CHECK: DW_TAG_member
-;CHECK-NEXT: DW_AT_name ("val_")
-;CHECK-NEXT: DW_AT_type ([[TEMPLATE]] "T")
+; CHECK: DW_TAG_member
+; CHECK-NEXT: DW_AT_name ("val_")
+; CHECK-NEXT: DW_AT_type ([[TEMPLATE]] "T")
-;CHECK: DW_TAG_member
-;CHECK-NEXT: DW_AT_name ("val2_")
-;CHECK-NEXT: DW_AT_type {{.*}} "int"
-
-
-; ModuleID = '<stdin>'
+; CHECK: DW_TAG_member
+; CHECK-NEXT: DW_AT_name ("val2_")
+; CHECK-NEXT: DW_AT_type {{.*}} "int"
+; ModuleID = 'test.cpp'
source_filename = "test.cpp"
-target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
%struct.A = type { i32, i32 }
@@ -47,78 +45,75 @@ target triple = "x86_64-unknown-linux-gnu"
$_ZN1AIiEC2Ev = comdat any
; Function Attrs: mustprogress noinline norecurse optnone uwtable
-define dso_local noundef i32 @main() #0 !dbg !20 {
+define dso_local noundef i32 @main() #0 !dbg !22 {
entry:
%retval = alloca i32, align 4
%a = alloca %struct.A, align 4
- store i32 0, i32* %retval, align 4
- call void @llvm.dbg.declare(metadata %struct.A* %a, metadata !24, metadata !DIExpression()), !dbg !25
- call void @_ZN1AIiEC2Ev(%struct.A* noundef nonnull align 4 dereferenceable(8) %a), !dbg !25
- %val2_ = getelementptr inbounds %struct.A, %struct.A* %a, i32 0, i32 1, !dbg !26
- store i32 3, i32* %val2_, align 4, !dbg !27
- ret i32 0, !dbg !28
+ store i32 0, ptr %retval, align 4
+ #dbg_declare(ptr %a, !26, !DIExpression(), !27)
+ call void @_ZN1AIiEC2Ev(ptr noundef nonnull align 4 dereferenceable(8) %a), !dbg !27
+ %val2_ = getelementptr inbounds nuw %struct.A, ptr %a, i32 0, i32 1, !dbg !28
+ store i32 3, ptr %val2_, align 4, !dbg !29
+ ret i32 0, !dbg !30
}
-; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
-declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
-
-; Function Attrs: noinline nounwind optnone uwtable
-define linkonce_odr dso_local void @_ZN1AIiEC2Ev(%struct.A* noundef nonnull align 4 dereferenceable(8) %this) unnamed_addr #2 comdat align 2 !dbg !29 {
-
+; Function Attrs: mustprogress noinline nounwind optnone uwtable
+define linkonce_odr dso_local void @_ZN1AIiEC2Ev(ptr noundef nonnull align 4 dereferenceable(8) %this) unnamed_addr #1 comdat align 2 !dbg !31 {
entry:
- %this.addr = alloca %struct.A*, align 8
- store %struct.A* %this, %struct.A** %this.addr, align 8
- call void @llvm.dbg.declare(metadata %struct.A** %this.addr, metadata !30, metadata !DIExpression()), !dbg !32
- %this1 = load %struct.A*, %struct.A** %this.addr, align 8
- %val_ = getelementptr inbounds %struct.A, %struct.A* %this1, i32 0, i32 0, !dbg !33
- store i32 0, i32* %val_, align 4, !dbg !33
- %val2_ = getelementptr inbounds %struct.A, %struct.A* %this1, i32 0, i32 1, !dbg !34
- store i32 0, i32* %val2_, align 4, !dbg !34
- ret void, !dbg !35
+ %this.addr = alloca ptr, align 8
+ store ptr %this, ptr %this.addr, align 8
+ #dbg_declare(ptr %this.addr, !32, !DIExpression(), !34)
+ %this1 = load ptr, ptr %this.addr, align 8
+ %val_ = getelementptr inbounds nuw %struct.A, ptr %this1, i32 0, i32 0, !dbg !35
+ store i32 0, ptr %val_, align 4, !dbg !35
+ %val2_ = getelementptr inbounds nuw %struct.A, ptr %this1, i32 0, i32 1, !dbg !36
+ store i32 0, ptr %val2_, align 4, !dbg !36
+ ret void, !dbg !37
}
-attributes #0 = { mustprogress noinline norecurse optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
-attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn }
-attributes #2 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #0 = { mustprogress noinline norecurse optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #1 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!14, !15, !16, !17, !18}
-!llvm.ident = !{!19}
+!llvm.module.flags = !{!14, !15, !16, !17, !18, !19, !20}
+!llvm.ident = !{!21}
-!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "", isOptimized: false, flags: " -S -g -O0 -emit-llvm reproducer.cxx -o reproducer.ll", runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2, splitDebugInlining: false, nameTableKind: None)
-!1 = !DIFile(filename: "test.cpp", directory: "/path/to")
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test.cpp", directory: "", checksumkind: CSK_MD5, checksum: "451371997e00e9e85d610a4e9d44a9b5")
!2 = !{!3}
!3 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A<int>", file: !1, line: 2, size: 64, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !4, templateParams: !12, identifier: "_ZTS1AIiE")
!4 = !{!5, !7, !8}
-!5 = !DIDerivedType(tag: DW_TAG_member, name: "val_", scope: !3, file: !1, line: 5, baseType: !36, size: 32,offset: 32)
+!5 = !DIDerivedType(tag: DW_TAG_member, name: "val_", scope: !3, file: !1, line: 4, baseType: !38, size: 32)
!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!7 = !DIDerivedType(tag: DW_TAG_member, name: "val2_", scope: !3, file: !1, line: 6, baseType: !6, size: 32, offset: 32)
-!8 = !DISubprogram(name: "A", scope: !3, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped, spFlags: 0)
+!7 = !DIDerivedType(tag: DW_TAG_member, name: "val2_", scope: !3, file: !1, line: 5, baseType: !6, size: 32, offset: 32)
+!8 = !DISubprogram(name: "A", scope: !3, file: !1, line: 3, type: !9, scopeLine: 3, flags: DIFlagPrototyped, spFlags: 0)
!9 = !DISubroutineType(types: !10)
!10 = !{null, !11}
!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
-!12 = !{!36}
+!12 = !{!38}
!13 = !DITemplateTypeParameter(name: "T", type: !6)
-!14 = !{i32 7, !"Dwarf Version", i32 4}
+!14 = !{i32 7, !"Dwarf Version", i32 5}
!15 = !{i32 2, !"Debug Info Version", i32 3}
!16 = !{i32 1, !"wchar_size", i32 4}
-!17 = !{i32 7, !"uwtable", i32 2}
-!18 = !{i32 7, !"frame-pointer", i32 2}
-!19 = !{!""}
-!20 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 10, type: !21, scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !23)
-!21 = !DISubroutineType(types: !22)
-!22 = !{!6}
-!23 = !{}
-!24 = !DILocalVariable(name: "a", scope: !20, file: !1, line: 12, type: !3)
-!25 = !DILocation(line: 12, column: 10, scope: !20)
-!26 = !DILocation(line: 13, column: 5, scope: !20)
-!27 = !DILocation(line: 13, column: 11, scope: !20)
-!28 = !DILocation(line: 15, column: 3, scope: !20)
-!29 = distinct !DISubprogram(name: "A", linkageName: "_ZN1AIiEC2Ev", scope: !3, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, declaration: !8, retainedNodes: !23)
-!30 = !DILocalVariable(name: "this", arg: 1, scope: !29, type: !31, flags: DIFlagArtificial | DIFlagObjectPointer)
-!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3, size: 64)
-!32 = !DILocation(line: 0, scope: !29)
-!33 = !DILocation(line: 4, column: 10, scope: !29)
-!34 = !DILocation(line: 4, column: 19, scope: !29)
-!35 = !DILocation(line: 4, column: 30, scope: !29)
-!36 = !DIDerivedType(tag: DW_TAG_template_type_parameter,name:"T",scope:!3, baseType: !6)
+!17 = !{i32 8, !"PIC Level", i32 2}
+!18 = !{i32 7, !"PIE Level", i32 2}
+!19 = !{i32 7, !"uwtable", i32 2}
+!20 = !{i32 7, !"frame-pointer", i32 2}
+!21 = !{!"clang"}
+!22 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 7, type: !23, scopeLine: 7, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !25)
+!23 = !DISubroutineType(types: !24)
+!24 = !{!6}
+!25 = !{}
+!26 = !DILocalVariable(name: "a", scope: !22, file: !1, line: 8, type: !3)
+!27 = !DILocation(line: 8, column: 8, scope: !22)
+!28 = !DILocation(line: 9, column: 3, scope: !22)
+!29 = !DILocation(line: 9, column: 9, scope: !22)
+!30 = !DILocation(line: 10, column: 1, scope: !22)
+!31 = distinct !DISubprogram(name: "A", linkageName: "_ZN1AIiEC2Ev", scope: !3, file: !1, line: 3, type: !9, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, declaration: !8, retainedNodes: !25)
+!32 = !DILocalVariable(name: "this", arg: 1, scope: !31, type: !33, flags: DIFlagArtificial | DIFlagObjectPointer)
+!33 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3, size: 64)
+!34 = !DILocation(line: 0, scope: !31)
+!35 = !DILocation(line: 3, column: 8, scope: !31)
+!36 = !DILocation(line: 3, column: 17, scope: !31)
+!37 = !DILocation(line: 3, column: 28, scope: !31)
+!38 = !DIDerivedType(tag: DW_TAG_template_type_parameter,name:"T",scope:!3, baseType: !6)
More information about the llvm-commits
mailing list