[llvm] 8573c28 - Add debug support for set types

Adrian Prantl via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 29 18:04:59 PDT 2021


Author: Adrian Prantl
Date: 2021-03-29T18:04:48-07:00
New Revision: 8573c28a514f5d06bd5a8854093e461fa6e467a4

URL: https://github.com/llvm/llvm-project/commit/8573c28a514f5d06bd5a8854093e461fa6e467a4
DIFF: https://github.com/llvm/llvm-project/commit/8573c28a514f5d06bd5a8854093e461fa6e467a4.diff

LOG: Add debug support for set types

This commit adds debugging support for set types defined in languages
such as Pascal and Modula-2.

Patch by Peter McKinna!

Differential Revision: https://reviews.llvm.org/D76115

Added: 
    llvm/test/DebugInfo/Generic/set.ll
    llvm/test/Verifier/set1.ll

Modified: 
    llvm/include/llvm/BinaryFormat/Dwarf.def
    llvm/include/llvm/IR/DIBuilder.h
    llvm/lib/IR/DIBuilder.cpp
    llvm/lib/IR/Verifier.cpp
    llvm/unittests/IR/DebugInfoTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index dedbaa184334b..c863cf7d66b45 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -162,7 +162,7 @@ HANDLE_DW_TAG(0x001c, inheritance, 2, DWARF, DW_KIND_NONE)
 HANDLE_DW_TAG(0x001d, inlined_subroutine, 2, DWARF, DW_KIND_NONE)
 HANDLE_DW_TAG(0x001e, module, 2, DWARF, DW_KIND_NONE)
 HANDLE_DW_TAG(0x001f, ptr_to_member_type, 2, DWARF, DW_KIND_TYPE)
-HANDLE_DW_TAG(0x0020, set_type, 2, DWARF, DW_KIND_NONE)
+HANDLE_DW_TAG(0x0020, set_type, 2, DWARF, DW_KIND_TYPE)
 HANDLE_DW_TAG(0x0021, subrange_type, 2, DWARF, DW_KIND_TYPE)
 HANDLE_DW_TAG(0x0022, with_stmt, 2, DWARF, DW_KIND_NONE)
 HANDLE_DW_TAG(0x0023, access_declaration, 2, DWARF, DW_KIND_NONE)

diff  --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index e0238567f2512..9cb1729cfe9bc 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -538,6 +538,18 @@ namespace llvm {
         uint64_t SizeInBits, uint32_t AlignInBits, DINodeArray Elements,
         DIType *UnderlyingType, StringRef UniqueIdentifier = "", bool IsScoped = false);
 
+    /// Create debugging information entry for a set.
+    /// \param Scope          Scope in which this set is defined.
+    /// \param Name           Set name.
+    /// \param File           File where this set is defined.
+    /// \param LineNumber     Line number.
+    /// \param SizeInBits     Set size.
+    /// \param AlignInBits    Set alignment.
+    /// \param Ty             Base type of the set.
+    DIDerivedType *createSetType(DIScope *Scope, StringRef Name, DIFile *File,
+                                 unsigned LineNo, uint64_t SizeInBits,
+                                 uint32_t AlignInBits, DIType *Ty);
+
     /// Create subroutine type.
     /// \param ParameterTypes  An array of subroutine parameter types. This
     ///                        includes return type at 0th index.

diff  --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index 5104dc349d0b5..1256749b74972 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -525,6 +525,18 @@ DICompositeType *DIBuilder::createEnumerationType(
   return CTy;
 }
 
+DIDerivedType *DIBuilder::createSetType(DIScope *Scope, StringRef Name,
+                                        DIFile *File, unsigned LineNo,
+                                        uint64_t SizeInBits,
+                                        uint32_t AlignInBits, DIType *Ty) {
+  auto *R =
+      DIDerivedType::get(VMContext, dwarf::DW_TAG_set_type, Name, File, LineNo,
+                         getNonCompileUnitScope(Scope), Ty, SizeInBits,
+                         AlignInBits, 0, None, DINode::FlagZero);
+  trackIfUnresolved(R);
+  return R;
+}
+
 DICompositeType *DIBuilder::createArrayType(
     uint64_t Size, uint32_t AlignInBits, DIType *Ty, DINodeArray Subscripts,
     PointerUnion<DIExpression *, DIVariable *> DL,

diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index b6952f7030416..84f95f726b8e4 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1000,13 +1000,29 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
                N.getTag() == dwarf::DW_TAG_atomic_type ||
                N.getTag() == dwarf::DW_TAG_member ||
                N.getTag() == dwarf::DW_TAG_inheritance ||
-               N.getTag() == dwarf::DW_TAG_friend,
+               N.getTag() == dwarf::DW_TAG_friend ||
+               N.getTag() == dwarf::DW_TAG_set_type,
            "invalid tag", &N);
   if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) {
     AssertDI(isType(N.getRawExtraData()), "invalid pointer to member type", &N,
              N.getRawExtraData());
   }
 
+  if (N.getTag() == dwarf::DW_TAG_set_type) {
+    if (auto *T = N.getRawBaseType()) {
+      auto *Enum = dyn_cast_or_null<DICompositeType>(T);
+      auto *Basic = dyn_cast_or_null<DIBasicType>(T);
+      AssertDI(
+          (Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type) ||
+              (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned ||
+                         Basic->getEncoding() == dwarf::DW_ATE_signed ||
+                         Basic->getEncoding() == dwarf::DW_ATE_unsigned_char ||
+                         Basic->getEncoding() == dwarf::DW_ATE_signed_char ||
+                         Basic->getEncoding() == dwarf::DW_ATE_boolean)),
+          "invalid set base type", &N, T);
+    }
+  }
+
   AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope());
   AssertDI(isType(N.getRawBaseType()), "invalid base type", &N,
            N.getRawBaseType());

diff  --git a/llvm/test/DebugInfo/Generic/set.ll b/llvm/test/DebugInfo/Generic/set.ll
new file mode 100644
index 0000000000000..21a106713d2fb
--- /dev/null
+++ b/llvm/test/DebugInfo/Generic/set.ll
@@ -0,0 +1,116 @@
+; Test set representation in DWARF debug info:
+
+; RUN: llc -debugger-tune=gdb -dwarf-version=4 -filetype=obj -o %t.o < %s
+; RUN: llvm-dwarfdump -debug-info %t.o | FileCheck %s --check-prefix=CHECK
+
+; ModuleID = 'Main.mb'
+source_filename = "../src/Main.m3"
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-linux-gnu"
+
+%M_Const_struct = type { [7 x i8], [1 x i8], [4 x i8], [4 x i8], i8* (i64)*, i8*, void ()*, i8*, [8 x i8], [14 x i8], [2 x i8] }
+%M_Main_struct = type { i8*, [32 x i8], i8*, [24 x i8], i8*, [8 x i8], i8* (i64)*, i64, [8 x i8], i8* ()*, i8*, [8 x i8], i8* ()*, [8 x i8] }
+
+ at M_Const = internal constant %M_Const_struct { [7 x i8] c"Main_M3", [1 x i8] zeroinitializer, [4 x i8] c"Test", [4 x i8] zeroinitializer, i8* (i64)* @Main_M3, i8* getelementptr inbounds (%M_Const_struct, %M_Const_struct* @M_Const, i32 0, i32 0, i32 0), void ()* @Main__Test, i8* getelementptr inbounds (i8, i8* getelementptr inbounds (%M_Const_struct, %M_Const_struct* @M_Const, i32 0, i32 0, i32 0), i64 8), [8 x i8] zeroinitializer, [14 x i8] c"../src/Main.m3", [2 x i8] zeroinitializer }, align 8
+ at M_Main = internal global %M_Main_struct { i8* getelementptr inbounds (i8, i8* getelementptr inbounds (%M_Const_struct, %M_Const_struct* @M_Const, i32 0, i32 0, i32 0), i64 56), [32 x i8] zeroinitializer, i8* getelementptr inbounds (i8, i8* getelementptr inbounds (%M_Const_struct, %M_Const_struct* @M_Const, i32 0, i32 0, i32 0), i64 16), [24 x i8] zeroinitializer, i8* getelementptr inbounds (i8, i8* bitcast (%M_Main_struct* @M_Main to i8*), i64 104), [8 x i8] zeroinitializer, i8* (i64)* @Main_M3, i64 3, [8 x i8] zeroinitializer, i8* ()* @Main_I3, i8* getelementptr inbounds (i8, i8* bitcast (%M_Main_struct* @M_Main to i8*), i64 128), [8 x i8] zeroinitializer, i8* ()* @RTHooks_I3, [8 x i8] zeroinitializer }, align 8
+ at m3_jmpbuf_size = external global i64, align 8
+
+declare i8* @Main_I3()
+
+declare i8* @RTHooks_I3()
+
+; Function Attrs: uwtable
+define void @Main__Test() #0 !dbg !5 {
+entry:
+  %as = alloca i64, align 8
+  %bs = alloca i64, align 8
+  br label %second, !dbg !21
+
+second:                                           ; preds = %entry
+  call void @llvm.dbg.declare(metadata i64* %as, metadata !22, metadata !DIExpression()), !dbg !25
+  call void @llvm.dbg.declare(metadata i64* %bs, metadata !26, metadata !DIExpression()), !dbg !25
+  store i64 36028797018972298, i64* %as, align 8, !dbg !28
+  store i64 197, i64* %bs, align 8, !dbg !29
+  ret void, !dbg !21
+}
+
+; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+declare i8* @alloca()
+
+; Function Attrs: uwtable
+define i8* @Main_M3(i64 %mode) #0 !dbg !30 {
+entry:
+  %mode1 = alloca i64, align 8
+  store i64 %mode, i64* %mode1, align 8
+  br label %second, !dbg !36
+
+second:                                           ; preds = %entry
+  call void @llvm.dbg.declare(metadata i64* %mode1, metadata !37, metadata !DIExpression()), !dbg !38
+  %v.3 = load i64, i64* %mode1, align 8, !dbg !38
+  %icmp = icmp eq i64 %v.3, 0, !dbg !38
+  br i1 %icmp, label %if_1, label %else_1, !dbg !38
+
+else_1:                                           ; preds = %second
+  call void @Main__Test(), !dbg !36
+  br label %if_1, !dbg !36
+
+if_1:                                             ; preds = %else_1, %second
+  ret i8* bitcast (%M_Main_struct* @M_Main to i8*), !dbg !36
+}
+
+attributes #0 = { uwtable "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nofree nosync nounwind readnone speculatable willreturn }
+
+!llvm.ident = !{!0}
+!llvm.dbg.cu = !{!1}
+!llvm.module.flags = !{!18, !19, !20}
+
+!0 = !{!"versions- cm3: d5.10.0 llvm: 9.0"}
+!1 = distinct !DICompileUnit(language: DW_LANG_Modula3, file: !2, producer: "cm3", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3)
+!2 = !DIFile(filename: "Main.m3", directory: "/home/cm3/settest/src")
+!3 = !{!4}
+!4 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum", scope: !5, file: !2, line: 11, size: 8, align: 8, elements: !9)
+!5 = distinct !DISubprogram(name: "Test", linkageName: "Main__Test", scope: !2, file: !2, line: 11, type: !6, scopeLine: 11, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !8)
+!6 = !DISubroutineType(types: !7)
+!7 = !{null}
+!8 = !{}
+!9 = !{!10, !11, !12, !13, !14, !15, !16, !17}
+!10 = !DIEnumerator(name: "alpha", value: 0)
+!11 = !DIEnumerator(name: "beta", value: 1)
+!12 = !DIEnumerator(name: "gamma", value: 2)
+!13 = !DIEnumerator(name: "delta", value: 3)
+!14 = !DIEnumerator(name: "epsilon", value: 4)
+!15 = !DIEnumerator(name: "theta", value: 5)
+!16 = !DIEnumerator(name: "psi", value: 6)
+!17 = !DIEnumerator(name: "zeta", value: 7)
+!18 = !{i64 2, !"Dwarf Version", i64 4}
+!19 = !{i64 2, !"Debug Info Version", i64 3}
+!20 = !{i64 2, !"wchar_size", i64 2}
+!21 = !DILocation(line: 20, scope: !5)
+!22 = !DILocalVariable(name: "as", scope: !5, file: !2, line: 11, type: !23)
+!23 = !DIDerivedType(tag: DW_TAG_set_type, name: "SS", scope: !2, file: !2, line: 11, baseType: !24, size: 64, align: 64)
+!24 = !DIBasicType(name: "SR", size: 8, encoding: DW_ATE_signed)
+; CHECK:         DW_TAG_set_type
+; CHECK:           DW_AT_type{{.*}}"SR"
+; CHECK:           DW_AT_name      ("SS")
+; CHECK:           DW_AT_byte_size (0x08)
+!25 = !DILocation(line: 11, scope: !5)
+!26 = !DILocalVariable(name: "bs", scope: !5, file: !2, line: 11, type: !27)
+!27 = !DIDerivedType(tag: DW_TAG_set_type, name: "ST", scope: !2, file: !2, line: 11, baseType: !4, size: 64, align: 64)
+; CHECK:         DW_TAG_set_type
+; CHECK:           DW_AT_type{{.*}}"Enum"
+; CHECK:           DW_AT_name      ("ST")
+; CHECK:           DW_AT_byte_size (0x08)
+!28 = !DILocation(line: 17, scope: !5)
+!29 = !DILocation(line: 18, scope: !5)
+!30 = distinct !DISubprogram(name: "Main_M3", linkageName: "Main_M3", scope: !2, file: !2, line: 22, type: !31, scopeLine: 22, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !8)
+!31 = !DISubroutineType(types: !32)
+!32 = !{!33, !35}
+!33 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "ADDR", baseType: !34, size: 64, align: 64)
+!34 = !DICompositeType(tag: DW_TAG_class_type, name: "ADDR__HeapObject", scope: !5, file: !2, line: 22, size: 64, align: 64, elements: !7, identifier: "AJWxb1")
+!35 = !DIBasicType(name: "INTEGER", size: 64, encoding: DW_ATE_signed)
+!36 = !DILocation(line: 23, scope: !30)
+!37 = !DILocalVariable(name: "mode", arg: 1, scope: !30, file: !2, line: 22, type: !35)
+!38 = !DILocation(line: 22, scope: !30)

diff  --git a/llvm/test/Verifier/set1.ll b/llvm/test/Verifier/set1.ll
new file mode 100644
index 0000000000000..9f8f116b9e371
--- /dev/null
+++ b/llvm/test/Verifier/set1.ll
@@ -0,0 +1,63 @@
+; RUN: llvm-as -disable-output <%s 2>&1 | FileCheck %s
+
+define void @Main__Test() #0 !dbg !17 {
+entry:
+  %as = alloca i64, align 8
+  %bs = alloca i64, align 8
+  br label %second, !dbg !21
+
+second:                                           ; preds = %entry
+  call void @llvm.dbg.declare(metadata i64* %as, metadata !22, metadata !DIExpression()), !dbg !25
+  call void @llvm.dbg.declare(metadata i64* %bs, metadata !26, metadata !DIExpression()), !dbg !25
+  store i64 36028797018972298, i64* %as, align 8, !dbg !28
+  store i64 85, i64* %bs, align 8, !dbg !29
+  ret void, !dbg !21
+}
+
+; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+!llvm.ident = !{!0}
+!llvm.dbg.cu = !{!1}
+!llvm.module.flags = !{!14, !15, !16}
+
+!0 = !{!"versions- cm3: d5.10.0 llvm: 12.0"}
+!1 = distinct !DICompileUnit(language: DW_LANG_Modula3, file: !2, producer: "cm3", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3)
+!2 = !DIFile(filename: "Main.m3", directory: "/home/peter/cm3/settest/src")
+!3 = !{!4}
+!4 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum", scope: !2, file: !2, line: 11, size: 8, align: 8, elements: !5)
+!5 = !{!6, !7, !8, !9, !10, !11, !12, !13}
+!6 = !DIEnumerator(name: "alpha", value: 0)
+!7 = !DIEnumerator(name: "beta", value: 1)
+!8 = !DIEnumerator(name: "gamma", value: 2)
+!9 = !DIEnumerator(name: "delta", value: 3)
+!10 = !DIEnumerator(name: "epsilon", value: 4)
+!11 = !DIEnumerator(name: "theta", value: 5)
+!12 = !DIEnumerator(name: "psi", value: 6)
+!13 = !DIEnumerator(name: "zeta", value: 7)
+!14 = !{i64 2, !"Dwarf Version", i64 4}
+!15 = !{i64 2, !"Debug Info Version", i64 3}
+!16 = !{i64 2, !"wchar_size", i64 2}
+!17 = distinct !DISubprogram(name: "Test", linkageName: "Main__Test", scope: !2, file: !2, line: 11, type: !18, scopeLine: 11, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !20)
+!18 = !DISubroutineType(types: !19)
+!19 = !{null}
+!20 = !{}
+!21 = !DILocation(line: 20, scope: !17)
+!22 = !DILocalVariable(name: "as", scope: !17, file: !2, line: 11, type: !23)
+; CHECK: invalid set base type
+!23 = !DIDerivedType(tag: DW_TAG_set_type, name: "SS", scope: !2, file: !2, line: 11, baseType: !24, size: 64, align: 64)
+!24 = !DIBasicType(name: "SR", size: 8, encoding: DW_ATE_signed)
+!25 = !DILocation(line: 11, scope: !17)
+!26 = !DILocalVariable(name: "bs", scope: !17, file: !2, line: 11, type: !27)
+!27 = !DIDerivedType(tag: DW_TAG_set_type, name: "ST", scope: !2, file: !2, line: 11, baseType: !23, size: 64, align: 64)
+!28 = !DILocation(line: 17, scope: !17)
+!29 = !DILocation(line: 18, scope: !17)
+!30 = distinct !DISubprogram(name: "Main_M3", linkageName: "Main_M3", scope: !2, file: !2, line: 22, type: !31, scopeLine: 22, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !20)
+!31 = !DISubroutineType(types: !32)
+!32 = !{!33, !35}
+!33 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "ADDR", baseType: !34, size: 64, align: 64)
+!34 = !DICompositeType(tag: DW_TAG_class_type, name: "ADDR__HeapObject", scope: !2, file: !2, line: 22, size: 64, align: 64, elements: !19, identifier: "AJWxb1")
+!35 = !DIBasicType(name: "INTEGER", size: 64, encoding: DW_ATE_signed)
+!36 = !DILocation(line: 23, scope: !30)
+!37 = !DILocalVariable(name: "mode", arg: 1, scope: !30, file: !2, line: 22, type: !35)
+!38 = !DILocation(line: 22, scope: !30)

diff  --git a/llvm/unittests/IR/DebugInfoTest.cpp b/llvm/unittests/IR/DebugInfoTest.cpp
index 58936fb2b00c4..d3e025a6edcea 100644
--- a/llvm/unittests/IR/DebugInfoTest.cpp
+++ b/llvm/unittests/IR/DebugInfoTest.cpp
@@ -230,4 +230,23 @@ TEST(DIBuilder, CreateFortranArrayTypeWithAttributes) {
   DIVariable::deleteTemporary(DataLocation);
 }
 
+DISubprogram *getSubprogram() {
+  LLVMContext Context;
+  return DISubprogram::getDistinct(Context, nullptr, "", "", nullptr, 0,
+                                   nullptr, 0, nullptr, 0, 0, DINode::FlagZero,
+                                   DISubprogram::SPFlagZero, nullptr);
+}
+
+TEST(DIBuilder, CreateSetType) {
+  LLVMContext Ctx;
+  std::unique_ptr<Module> M(new Module("MyModule", Ctx));
+  DIBuilder DIB(*M);
+  DIScope *Scope = getSubprogram();
+  DIType *Type = DIB.createBasicType("Int", 64, dwarf::DW_ATE_signed);
+  DIFile *F = DIB.createFile("main.c", "/");
+
+  DIDerivedType *SetType = DIB.createSetType(Scope, "set1", F, 1, 64, 64, Type);
+  EXPECT_TRUE(isa_and_nonnull<DIDerivedType>(SetType));
+}
+
 } // end namespace


        


More information about the llvm-commits mailing list