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.khatav...@intel.com> Date: Tue, 18 Feb 2025 06:44:49 -0800 Subject: [PATCH 1/5] 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.khatav...@intel.com> Date: Tue, 18 Feb 2025 07:31:53 -0800 Subject: [PATCH 2/5] 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.khatav...@intel.com> Date: Tue, 18 Feb 2025 13:53:02 -0800 Subject: [PATCH 3/5] 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) >From 81da81b71efd25f74f0eb449fbddc0746e2e12d6 Mon Sep 17 00:00:00 2001 From: "Khatavkar, Yashasvi" <yashasvi.khatav...@intel.com> Date: Wed, 26 Feb 2025 12:50:40 -0800 Subject: [PATCH 4/5] Add DIDerived type to template params --- clang/lib/CodeGen/CGDebugInfo.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index ce2d34dcd4ce3..88936c4e8cc0e 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2296,10 +2296,16 @@ CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs, switch (TA.getKind()) { case TemplateArgument::Type: { - llvm::DIType *TTy = getOrCreateType(TA.getAsType(), Unit); + if (CGM.getCodeGenOpts().DebugTemplateParameterAsType) + { + llvm::DIType *debugType = getOrCreateType(TA.getAsType(), Unit); + llvm::DIType *TemplateType = DBuilder.createTemplateTypeParameterAsType(Unit, Name, debugType); + TemplateParams.push_back(TemplateType); + } + else {llvm::DIType *TTy = getOrCreateType(TA.getAsType(), Unit); TemplateParams.push_back(DBuilder.createTemplateTypeParameter( TheCU, Name, TTy, defaultParameter)); - + } } break; case TemplateArgument::Integral: { llvm::DIType *TTy = getOrCreateType(TA.getIntegralType(), Unit); >From d697eaafffb2d34ad01e60b2393e1d1eff2284aa Mon Sep 17 00:00:00 2001 From: "Khatavkar, Yashasvi" <yashasvi.khatav...@intel.com> Date: Thu, 27 Feb 2025 08:06:39 -0800 Subject: [PATCH 5/5] Apply clang-format --- clang/lib/CodeGen/CGDebugInfo.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 88936c4e8cc0e..8c6caee9bf705 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2296,15 +2296,15 @@ CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs, switch (TA.getKind()) { case TemplateArgument::Type: { - if (CGM.getCodeGenOpts().DebugTemplateParameterAsType) - { - llvm::DIType *debugType = getOrCreateType(TA.getAsType(), Unit); - llvm::DIType *TemplateType = DBuilder.createTemplateTypeParameterAsType(Unit, Name, debugType); - TemplateParams.push_back(TemplateType); - } - else {llvm::DIType *TTy = getOrCreateType(TA.getAsType(), Unit); - TemplateParams.push_back(DBuilder.createTemplateTypeParameter( - TheCU, Name, TTy, defaultParameter)); + if (CGM.getCodeGenOpts().DebugTemplateParameterAsType) { + llvm::DIType *debugType = getOrCreateType(TA.getAsType(), Unit); + llvm::DIType *TemplateType = + DBuilder.createTemplateTypeParameterAsType(Unit, Name, debugType); + TemplateParams.push_back(TemplateType); + } else { + llvm::DIType *TTy = getOrCreateType(TA.getAsType(), Unit); + TemplateParams.push_back(DBuilder.createTemplateTypeParameter( + TheCU, Name, TTy, defaultParameter)); } } break; case TemplateArgument::Integral: { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits