From 5cb210862be45da1025fa8a9db4f52388340eade Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Sun, 19 Sep 2021 21:03:20 -0700 Subject: [PATCH] DebugInfo: Use the signedness of the underlying enum when encoding enum non-type-template-parameters This improves the accuracy of the debug info and improves round tripping through -gsimple-template-names. --- llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp | 17 +-- llvm/test/DebugInfo/X86/template.ll | 151 +++++++++++++---------- 2 files changed, 96 insertions(+), 72 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp index c957ca8..4df34d2 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp @@ -185,14 +185,15 @@ bool DebugHandlerBase::isUnsignedDIType(const DIType *Ty) { } if (auto *CTy = dyn_cast(Ty)) { - // FIXME: Enums without a fixed underlying type have unknown signedness - // here, leading to incorrectly emitted constants. - if (CTy->getTag() == dwarf::DW_TAG_enumeration_type) - return false; - - // (Pieces of) aggregate types that get hacked apart by SROA may be - // represented by a constant. Encode them as unsigned bytes. - return true; + if (CTy->getTag() == dwarf::DW_TAG_enumeration_type) { + if (!(Ty = CTy->getBaseType())) + // FIXME: Enums without a fixed underlying type have unknown signedness + // here, leading to incorrectly emitted constants. + return false; + } else + // (Pieces of) aggregate types that get hacked apart by SROA may be + // represented by a constant. Encode them as unsigned bytes. + return true; } if (auto *DTy = dyn_cast(Ty)) { diff --git a/llvm/test/DebugInfo/X86/template.ll b/llvm/test/DebugInfo/X86/template.ll index 7256615..d071234 100644 --- a/llvm/test/DebugInfo/X86/template.ll +++ b/llvm/test/DebugInfo/X86/template.ll @@ -3,12 +3,14 @@ ; RUN: llc -mtriple=x86_64-linux -O0 -filetype=obj < %s | not llvm-dwarfdump -verify - | FileCheck %s --check-prefix VERIFY ; IR generated with `clang++ -g -emit-llvm -S` from the following code: -; template class y, decltype(nullptr) n, int ...z> int func() { +; template T var; +; enum e : unsigned char { E = (e)-1 }; +; template class y, decltype(nullptr) n, e, int ...z> int func() { ; var = 5; ; return var; ; } ; template struct y_impl { struct nested { }; }; -; int glbl = func<3, &glbl, y_impl, nullptr, 1, 2>(); +; int glbl = func<3, &glbl, y_impl, nullptr, E, 1, 2>(); ; y_impl::nested n; ; VERIFY-NOT: error: DIE has DW_AT_type with incompatible tag DW_TAG_unspecified_type @@ -30,7 +32,7 @@ ; CHECK-NEXT: DW_AT_name{{.*}}= "T" -; CHECK: DW_AT_name{{.*}}"func<3, &glbl, y_impl, nullptr, 1, 2>" +; CHECK: DW_AT_name{{.*}}"func<3, &glbl, y_impl, nullptr, E, 1, 2>" ; CHECK-NOT: NULL ; CHECK: DW_TAG_template_value_parameter ; CHECK-NEXT: DW_AT_type{{.*}}=> {[[INT]]} @@ -56,6 +58,10 @@ ; CHECK-NEXT: DW_AT_name{{.*}}= "n" ; CHECK-NEXT: DW_AT_const_value [DW_FORM_udata]{{.*}}(0) +; CHECK: DW_TAG_template_value_parameter +; CHECK: DW_AT_type [DW_FORM_ref4] {{.*}} "e") +; CHECK: DW_AT_const_value [DW_FORM_udata] (255) + ; CHECK: DW_TAG_GNU_template_parameter_pack ; CHECK-NOT: NULL ; CHECK: DW_TAG_template_value_parameter @@ -72,85 +78,102 @@ ; CHECK: [[NULLPTR]]:{{ *}}DW_TAG_unspecified_type ; CHECK-NEXT: DW_AT_name{{.*}}= "decltype(nullptr)" -source_filename = "test/DebugInfo/X86/template.ll" +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.y_impl::nested" = type { i8 } +$_Z4funcILi3EXadL_Z4glblEE6y_implLDn0EL1e255EJLi1ELi2EEEiv = comdat any + +$_Z3varIiE = comdat any + @glbl = dso_local global i32 0, align 4, !dbg !0 -@_Z3varIiE = linkonce_odr dso_local global i32 0, align 4, !dbg !13 -@n = dso_local global %"struct.y_impl::nested" zeroinitializer, align 1, !dbg !6 -@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_upstream_test.cpp, i8* null }] +@n = dso_local global %"struct.y_impl::nested" zeroinitializer, align 1, !dbg !10 +@_Z3varIiE = linkonce_odr dso_local global i32 0, comdat, align 4, !dbg !18 +@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_test.cpp, i8* null }] ; Function Attrs: noinline uwtable -define internal void @__cxx_global_var_init() #0 section ".text.startup" !dbg !21 { +define internal void @__cxx_global_var_init() #0 section ".text.startup" !dbg !28 { entry: - %call = call i32 @_Z4funcILi3EXadL_Z4glblEE6y_implLDn0EJLi1ELi2EEEiv(), !dbg !24 - store i32 %call, i32* @glbl, align 4, !dbg !24 - ret void, !dbg !24 + %call = call i32 @_Z4funcILi3EXadL_Z4glblEE6y_implLDn0EL1e255EJLi1ELi2EEEiv(), !dbg !31 + store i32 %call, i32* @glbl, align 4, !dbg !32 + ret void, !dbg !31 } -; Function Attrs: noinline nounwind optnone uwtable -define linkonce_odr dso_local i32 @_Z4funcILi3EXadL_Z4glblEE6y_implLDn0EJLi1ELi2EEEiv() #1 !dbg !25 { +; Function Attrs: mustprogress noinline nounwind optnone uwtable +define linkonce_odr dso_local i32 @_Z4funcILi3EXadL_Z4glblEE6y_implLDn0EL1e255EJLi1ELi2EEEiv() #1 comdat !dbg !33 { entry: - store i32 5, i32* @_Z3varIiE, align 4, !dbg !39 - %0 = load i32, i32* @_Z3varIiE, align 4, !dbg !40 - ret i32 %0, !dbg !41 + store i32 5, i32* @_Z3varIiE, align 4, !dbg !48 + %0 = load i32, i32* @_Z3varIiE, align 4, !dbg !49 + ret i32 %0, !dbg !50 } ; Function Attrs: noinline uwtable -define internal void @_GLOBAL__sub_I_upstream_test.cpp() #0 section ".text.startup" !dbg !42 { +define internal void @_GLOBAL__sub_I_test.cpp() #0 section ".text.startup" !dbg !51 { entry: - call void @__cxx_global_var_init(), !dbg !44 + call void @__cxx_global_var_init(), !dbg !53 ret void } -attributes #0 = { nounwind uwtable } -attributes #1 = { nounwind uwtable noinline optnone } +attributes #0 = { noinline 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 = { 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"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } !llvm.dbg.cu = !{!2} -!llvm.module.flags = !{!17, !18, !19} -!llvm.ident = !{!20} +!llvm.module.flags = !{!22, !23, !24, !25, !26} +!llvm.ident = !{!27} !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) -!1 = distinct !DIGlobalVariable(name: "glbl", scope: !2, file: !3, line: 7, type: !12, isLocal: false, isDefinition: true) -!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5) -!3 = !DIFile(filename: "upstream_test.cpp", directory: "/home/mvoss/src/92562") -!4 = !{} -!5 = !{!0, !6, !13} -!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) -!7 = distinct !DIGlobalVariable(name: "n", scope: !2, file: !3, line: 8, type: !8, isLocal: false, isDefinition: true)!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "nested", scope: !9, file: !3, line: 6, size: 8, flags: DIFlagTypePassByValue, elements: !4, identifier: "_ZTSN6y_implIiE6nestedE") -!9 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "y_impl", file: !3, line: 6, size: 8, flags: DIFlagTypePassByValue, elements: !4, templateParams: !10, identifier: "_ZTS6y_implIiE") -!10 = !{!11} -!11 = !DITemplateTypeParameter(type: !12) -!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -!13 = !DIGlobalVariableExpression(var: !14, expr: !DIExpression()) -!14 = distinct !DIGlobalVariable(name: "var", linkageName: "_Z3varIiE", scope: !2, file: !3, line: 1, type: !12, isLocal: false, isDefinition: true, templateParams: !15) +!1 = distinct !DIGlobalVariable(name: "glbl", scope: !2, file: !3, line: 8, type: !17, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 14.0.0 (git@github.com:llvm/llvm-project.git d0046d018934b284c995408a117371606472cd2a)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !9, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "test.cpp", directory: "") +!4 = !{!5} +!5 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "e", file: !3, line: 2, baseType: !6, size: 8, elements: !7, identifier: "_ZTS1e") +!6 = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char) +!7 = !{!8} +!8 = !DIEnumerator(name: "E", value: 255, isUnsigned: true) +!9 = !{!0, !10, !18} +!10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression()) +!11 = distinct !DIGlobalVariable(name: "n", scope: !2, file: !3, line: 9, type: !12, isLocal: false, isDefinition: true) +!12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "nested", scope: !13, file: !3, line: 7, size: 8, flags: DIFlagTypePassByValue, elements: !14, identifier: "_ZTSN6y_implIiE6nestedE") +!13 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "y_impl", file: !3, line: 7, size: 8, flags: DIFlagTypePassByValue, elements: !14, templateParams: !15, identifier: "_ZTS6y_implIiE") +!14 = !{} !15 = !{!16} -!16 = !DITemplateTypeParameter(name: "T", type: !12) -!17 = !{i32 2, !"Dwarf Version", i32 4} -!18 = !{i32 2, !"Debug Info Version", i32 3} -!19 = !{i32 1, !"wchar_size", i32 4} -!20 = !{!"clang version 7.0.0 "} -!21 = distinct !DISubprogram(name: "__cxx_global_var_init", scope: !3, file: !3, line: 7, type: !22, isLocal: true, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: false, unit: !2, retainedNodes: !4) -!22 = !DISubroutineType(types: !23) -!23 = !{null} -!24 = !DILocation(line: 7, column: 12, scope: !21) -!25 = distinct !DISubprogram(name: "func<3, &glbl, y_impl, nullptr, 1, 2>", linkageName: "_Z4funcILi3EXadL_Z4glblEE6y_implLDn0EJLi1ELi2EEEiv", scope: !3, file: !3, line: 2, type: !26, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !2, templateParams: !28, retainedNodes: !4) -!26 = !DISubroutineType(types: !27) -!27 = !{!12} -!28 = !{!29, !30, !32, !33, !35} -!29 = !DITemplateValueParameter(name: "x", type: !12, value: i32 3) -!30 = !DITemplateValueParameter(type: !31, value: i32* @glbl) -!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) -!32 = !DITemplateValueParameter(tag: DW_TAG_GNU_template_template_param, name: "y", value: !"y_impl") -!33 = !DITemplateValueParameter(name: "n", type: !34, value: i8 0) -!34 = !DIBasicType(tag: DW_TAG_unspecified_type, name: "decltype(nullptr)") -!35 = !DITemplateValueParameter(tag: DW_TAG_GNU_template_parameter_pack, name: "z", value: !36) -!36 = !{!37, !38} -!37 = !DITemplateValueParameter(type: !12, value: i32 1) -!38 = !DITemplateValueParameter(type: !12, value: i32 2) -!39 = !DILocation(line: 3, column: 12, scope: !25) -!40 = !DILocation(line: 4, column: 10, scope: !25) -!41 = !DILocation(line: 4, column: 3, scope: !25) -!42 = distinct !DISubprogram(linkageName: "_GLOBAL__sub_I_upstream_test.cpp", scope: !3, file: !3, type: !43, isLocal: true, isDefinition: true, flags: DIFlagArtificial, isOptimized: false, unit: !2, retainedNodes: !4) -!43 = !DISubroutineType(types: !4) -!44 = !DILocation(line: 0, scope: !42) +!16 = !DITemplateTypeParameter(type: !17) +!17 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!18 = !DIGlobalVariableExpression(var: !19, expr: !DIExpression()) +!19 = distinct !DIGlobalVariable(name: "var", linkageName: "_Z3varIiE", scope: !2, file: !3, line: 1, type: !17, isLocal: false, isDefinition: true, templateParams: !20) +!20 = !{!21} +!21 = !DITemplateTypeParameter(name: "T", type: !17) +!22 = !{i32 7, !"Dwarf Version", i32 4} +!23 = !{i32 2, !"Debug Info Version", i32 3} +!24 = !{i32 1, !"wchar_size", i32 4} +!25 = !{i32 7, !"uwtable", i32 1} +!26 = !{i32 7, !"frame-pointer", i32 2} +!27 = !{!"clang version 14.0.0 (git@github.com:llvm/llvm-project.git d0046d018934b284c995408a117371606472cd2a)"} +!28 = distinct !DISubprogram(name: "__cxx_global_var_init", scope: !3, file: !3, type: !29, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2, retainedNodes: !14) +!29 = !DISubroutineType(types: !30) +!30 = !{null} +!31 = !DILocation(line: 8, column: 12, scope: !28) +!32 = !DILocation(line: 0, scope: !28) +!33 = distinct !DISubprogram(name: "func<3, &glbl, y_impl, nullptr, E, 1, 2>", linkageName: "_Z4funcILi3EXadL_Z4glblEE6y_implLDn0EL1e255EJLi1ELi2EEEiv", scope: !3, file: !3, line: 3, type: !34, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, templateParams: !36, retainedNodes: !14) +!34 = !DISubroutineType(types: !35) +!35 = !{!17} +!36 = !{!37, !38, !40, !41, !43, !44} +!37 = !DITemplateValueParameter(name: "x", type: !17, value: i32 3) +!38 = !DITemplateValueParameter(type: !39, value: i32* @glbl) +!39 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !17, size: 64) +!40 = !DITemplateValueParameter(tag: DW_TAG_GNU_template_template_param, name: "y", value: !"y_impl") +!41 = !DITemplateValueParameter(name: "n", type: !42, value: i8 0) +!42 = !DIBasicType(tag: DW_TAG_unspecified_type, name: "decltype(nullptr)") +!43 = !DITemplateValueParameter(type: !5, value: i8 -1) +!44 = !DITemplateValueParameter(tag: DW_TAG_GNU_template_parameter_pack, name: "z", value: !45) +!45 = !{!46, !47} +!46 = !DITemplateValueParameter(type: !17, value: i32 1) +!47 = !DITemplateValueParameter(type: !17, value: i32 2) +!48 = !DILocation(line: 4, column: 11, scope: !33) +!49 = !DILocation(line: 5, column: 9, scope: !33) +!50 = !DILocation(line: 5, column: 2, scope: !33) +!51 = distinct !DISubprogram(linkageName: "_GLOBAL__sub_I_test.cpp", scope: !3, file: !3, type: !52, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2, retainedNodes: !14) +!52 = !DISubroutineType(types: !14) +!53 = !DILocation(line: 0, scope: !51) -- 2.7.4