[llvm] d91ed80 - [codeview] Reference types in type parent scopes

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 7 13:58:08 PST 2019


Author: Reid Kleckner
Date: 2019-11-07T13:58:01-08:00
New Revision: d91ed80e97ac9bfcfb02440874ed8b9a51c9491e

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

LOG: [codeview] Reference types in type parent scopes

Without this change, when a nested tag type of any kind (enum, class,
struct, union) is used as a variable type, it is emitted without
emitting the parent type. In CodeView, parent types point to their inner
types, and inner types do not point back to their parents. We already
walk over all of the parent scopes to build the fully qualified name.
This change simply requests their type indices as we go along to enusre
they are all emitted.

Fixes PR43905

Reviewers: akhuang, amccarth

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

Added: 
    llvm/test/DebugInfo/COFF/parent-type-scopes.ll

Modified: 
    llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
    llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
    llvm/test/DebugInfo/COFF/global-constants.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 62ad356e7f8f..3829dd4eff16 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -303,12 +303,19 @@ static StringRef getPrettyScopeName(const DIScope *Scope) {
   return StringRef();
 }
 
-static const DISubprogram *getQualifiedNameComponents(
+const DISubprogram *CodeViewDebug::collectParentScopeNames(
     const DIScope *Scope, SmallVectorImpl<StringRef> &QualifiedNameComponents) {
   const DISubprogram *ClosestSubprogram = nullptr;
   while (Scope != nullptr) {
     if (ClosestSubprogram == nullptr)
       ClosestSubprogram = dyn_cast<DISubprogram>(Scope);
+
+    // If a type appears in a scope chain, make sure it gets emitted. The
+    // frontend will be responsible for deciding if this should be a forward
+    // declaration or a complete type.
+    if (const auto *Ty = dyn_cast<DIType>(Scope))
+      (void)getTypeIndex(Ty);
+
     StringRef ScopeName = getPrettyScopeName(Scope);
     if (!ScopeName.empty())
       QualifiedNameComponents.push_back(ScopeName);
@@ -317,8 +324,9 @@ static const DISubprogram *getQualifiedNameComponents(
   return ClosestSubprogram;
 }
 
-static std::string getQualifiedName(ArrayRef<StringRef> QualifiedNameComponents,
-                                    StringRef TypeName) {
+std::string
+CodeViewDebug::formatNestedName(ArrayRef<StringRef> QualifiedNameComponents,
+                                StringRef TypeName) {
   std::string FullyQualifiedName;
   for (StringRef QualifiedNameComponent :
        llvm::reverse(QualifiedNameComponents)) {
@@ -329,10 +337,15 @@ static std::string getQualifiedName(ArrayRef<StringRef> QualifiedNameComponents,
   return FullyQualifiedName;
 }
 
-static std::string getFullyQualifiedName(const DIScope *Scope, StringRef Name) {
+std::string CodeViewDebug::getFullyQualifiedName(const DIScope *Scope, StringRef Name) {
   SmallVector<StringRef, 5> QualifiedNameComponents;
-  getQualifiedNameComponents(Scope, QualifiedNameComponents);
-  return getQualifiedName(QualifiedNameComponents, Name);
+  collectParentScopeNames(Scope, QualifiedNameComponents);
+  return formatNestedName(QualifiedNameComponents, Name);
+}
+
+std::string CodeViewDebug::getFullyQualifiedName(const DIScope *Ty) {
+  const DIScope *Scope = Ty->getScope();
+  return getFullyQualifiedName(Scope, getPrettyScopeName(Ty));
 }
 
 struct CodeViewDebug::TypeLoweringScope {
@@ -347,11 +360,6 @@ struct CodeViewDebug::TypeLoweringScope {
   CodeViewDebug &CVD;
 };
 
-static std::string getFullyQualifiedName(const DIScope *Ty) {
-  const DIScope *Scope = Ty->getScope();
-  return getFullyQualifiedName(Scope, getPrettyScopeName(Ty));
-}
-
 TypeIndex CodeViewDebug::getScopeIndex(const DIScope *Scope) {
   // No scope means global scope and that uses the zero index.
   if (!Scope || isa<DIFile>(Scope))
@@ -1468,12 +1476,12 @@ void CodeViewDebug::addToUDTs(const DIType *Ty) {
   if (!shouldEmitUdt(Ty))
     return;
 
-  SmallVector<StringRef, 5> QualifiedNameComponents;
+  SmallVector<StringRef, 5> ParentScopeNames;
   const DISubprogram *ClosestSubprogram =
-      getQualifiedNameComponents(Ty->getScope(), QualifiedNameComponents);
+      collectParentScopeNames(Ty->getScope(), ParentScopeNames);
 
   std::string FullyQualifiedName =
-      getQualifiedName(QualifiedNameComponents, getPrettyScopeName(Ty));
+      formatNestedName(ParentScopeNames, getPrettyScopeName(Ty));
 
   if (ClosestSubprogram == nullptr) {
     GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);

diff  --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
index b56b9047e1a9..e32d62674304 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -443,6 +443,19 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
                                                codeview::TypeIndex TI,
                                                const DIType *ClassTy = nullptr);
 
+  /// Collect the names of parent scopes, innermost to outermost. Return the
+  /// innermost subprogram scope if present. Ensure that parent type scopes are
+  /// inserted into the type table.
+  const DISubprogram *
+  collectParentScopeNames(const DIScope *Scope,
+                          SmallVectorImpl<StringRef> &ParentScopeNames);
+
+  std::string formatNestedName(ArrayRef<StringRef> ParentScopeNames,
+                               StringRef TypeName);
+
+  std::string getFullyQualifiedName(const DIScope *Scope, StringRef Name);
+  std::string getFullyQualifiedName(const DIScope *Scope);
+
   unsigned getPointerSizeInBytes();
 
 protected:

diff  --git a/llvm/test/DebugInfo/COFF/global-constants.ll b/llvm/test/DebugInfo/COFF/global-constants.ll
index e4b4cdaacd43..aeca54d52e52 100644
--- a/llvm/test/DebugInfo/COFF/global-constants.ll
+++ b/llvm/test/DebugInfo/COFF/global-constants.ll
@@ -36,7 +36,7 @@
 ; ASM-NEXT:   .asciz "S::TestConst2"        # Name
 ; ASM:        .short {{.*-.*}}              # Record length
 ; ASM:        .short 4359                   # Record kind: S_CONSTANT
-; ASM-NEXT:   .long 4105                    # Type
+; ASM-NEXT:   .long 4113                    # Type
 ; ASM-NEXT:   .byte 0x0a, 0x80, 0x40, 0x61  # Value
 ; ASM-NEXT:   .byte 0x07, 0x80, 0xff, 0xff
 ; ASM-NEXT:   .byte 0xff, 0xff
@@ -62,7 +62,7 @@
 ; OBJ-NEXT:       }
 ; OBJ-NEXT:       ConstantSym {
 ; OBJ-NEXT:         Kind: S_CONSTANT (0x1107)
-; OBJ-NEXT:         Type: TestEnum (0x1009)
+; OBJ-NEXT:         Type: TestEnum (0x1011)
 ; OBJ-NEXT:         Value: 18446744071562551616
 ; OBJ-NEXT:         Name: ENUM_B
 ; OBJ-NEXT:       }

diff  --git a/llvm/test/DebugInfo/COFF/parent-type-scopes.ll b/llvm/test/DebugInfo/COFF/parent-type-scopes.ll
new file mode 100644
index 000000000000..9d1ba6d51db5
--- /dev/null
+++ b/llvm/test/DebugInfo/COFF/parent-type-scopes.ll
@@ -0,0 +1,133 @@
+; RUN: llc < %s -filetype=obj -o %t.o
+; RUN: llvm-pdbutil dump -types %t.o | FileCheck %s
+
+; C++ source:
+; // Note that MSVC doesn't emit anything about WrapTypedef or WrapTypedef::Inner!
+; struct WrapTypedef {
+;   typedef int Inner;
+; };
+; struct WrapStruct {
+;   struct Inner { int x; };
+; };
+; struct WrapClass {
+;   class Inner { public: int x; };
+; };
+; struct WrapEnum {
+;   enum Inner { One, Two };
+; };
+; struct WrapUnion {
+;   union Inner { int x; float y; };
+; };
+; void useInnerTypes() {
+;   WrapTypedef::Inner v1;
+;   WrapStruct::Inner v2;
+;   WrapClass::Inner v3;
+;   WrapEnum::Inner v4;
+;   WrapUnion::Inner v5;
+; }
+
+; There should be two LF_STRUCTURE records for each wrapped type, forward decl
+; and complete type. For every inner record type, there should be two. Enums
+; don't get forward decls.
+
+; CHECK-DAG: | LF_STRUCTURE {{.*}} `WrapStruct`
+; CHECK-DAG: | LF_STRUCTURE {{.*}} `WrapStruct`
+; CHECK-DAG: | LF_STRUCTURE {{.*}} `WrapStruct::Inner`
+; CHECK-DAG: | LF_STRUCTURE {{.*}} `WrapStruct::Inner`
+; CHECK-DAG: | LF_STRUCTURE {{.*}} `WrapClass`
+; CHECK-DAG: | LF_STRUCTURE {{.*}} `WrapClass`
+; CHECK-DAG: | LF_CLASS {{.*}} `WrapClass::Inner`
+; CHECK-DAG: | LF_CLASS {{.*}} `WrapClass::Inner`
+; CHECK-DAG: | LF_STRUCTURE {{.*}} `WrapEnum`
+; CHECK-DAG: | LF_STRUCTURE {{.*}} `WrapEnum`
+; CHECK-DAG: | LF_ENUM {{.*}} `WrapEnum::Inner`
+; CHECK-DAG: | LF_STRUCTURE {{.*}} `WrapUnion`
+; CHECK-DAG: | LF_STRUCTURE {{.*}} `WrapUnion`
+; CHECK-DAG: | LF_UNION {{.*}} `WrapUnion::Inner`
+; CHECK-DAG: | LF_UNION {{.*}} `WrapUnion::Inner`
+
+; ModuleID = 't.cpp'
+source_filename = "t.cpp"
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.23.28106"
+
+%"struct.WrapStruct::Inner" = type { i32 }
+%"class.WrapClass::Inner" = type { i32 }
+%"union.WrapUnion::Inner" = type { i32 }
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local void @"?useInnerTypes@@YAXXZ"() #0 !dbg !15 {
+entry:
+  %v1 = alloca i32, align 4
+  %v2 = alloca %"struct.WrapStruct::Inner", align 4
+  %v3 = alloca %"class.WrapClass::Inner", align 4
+  %v4 = alloca i32, align 4
+  %v5 = alloca %"union.WrapUnion::Inner", align 4
+  call void @llvm.dbg.declare(metadata i32* %v1, metadata !19, metadata !DIExpression()), !dbg !23
+  call void @llvm.dbg.declare(metadata %"struct.WrapStruct::Inner"* %v2, metadata !24, metadata !DIExpression()), !dbg !30
+  call void @llvm.dbg.declare(metadata %"class.WrapClass::Inner"* %v3, metadata !31, metadata !DIExpression()), !dbg !37
+  call void @llvm.dbg.declare(metadata i32* %v4, metadata !38, metadata !DIExpression()), !dbg !39
+  call void @llvm.dbg.declare(metadata %"union.WrapUnion::Inner"* %v5, metadata !40, metadata !DIExpression()), !dbg !48
+  ret void, !dbg !49
+}
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone speculatable willreturn }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!10, !11, !12, !13}
+!llvm.ident = !{!14}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 10.0.0 (git at github.com:llvm/llvm-project.git a8ccb48f697d3fbe85c593248ff1053fdf522a6e)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "t.cpp", directory: "C:\\src\\llvm-project\\build", checksumkind: CSK_MD5, checksum: "4228f12f516cd3d6dd76462be09ec111")
+!2 = !{!3, !3}
+!3 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Inner", scope: !4, file: !1, line: 11, baseType: !6, size: 32, elements: !7, identifier: ".?AW4Inner at WrapEnum@@")
+!4 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "WrapEnum", file: !1, line: 10, size: 8, flags: DIFlagTypePassByValue, elements: !5, identifier: ".?AUWrapEnum@@")
+!5 = !{!3}
+!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!7 = !{!8, !9}
+!8 = !DIEnumerator(name: "One", value: 0)
+!9 = !DIEnumerator(name: "Two", value: 1)
+!10 = !{i32 2, !"CodeView", i32 1}
+!11 = !{i32 2, !"Debug Info Version", i32 3}
+!12 = !{i32 1, !"wchar_size", i32 2}
+!13 = !{i32 7, !"PIC Level", i32 2}
+!14 = !{!"clang version 10.0.0 (git at github.com:llvm/llvm-project.git a8ccb48f697d3fbe85c593248ff1053fdf522a6e)"}
+!15 = distinct !DISubprogram(name: "useInnerTypes", linkageName: "?useInnerTypes@@YAXXZ", scope: !1, file: !1, line: 16, type: !16, scopeLine: 16, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !18)
+!16 = !DISubroutineType(types: !17)
+!17 = !{null}
+!18 = !{}
+!19 = !DILocalVariable(name: "v1", scope: !15, file: !1, line: 17, type: !20)
+!20 = !DIDerivedType(tag: DW_TAG_typedef, name: "Inner", scope: !21, file: !1, line: 2, baseType: !6)
+!21 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "WrapTypedef", file: !1, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !22, identifier: ".?AUWrapTypedef@@")
+!22 = !{!20}
+!23 = !DILocation(line: 17, scope: !15)
+!24 = !DILocalVariable(name: "v2", scope: !15, file: !1, line: 18, type: !25)
+!25 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Inner", scope: !26, file: !1, line: 5, size: 32, flags: DIFlagTypePassByValue, elements: !28, identifier: ".?AUInner at WrapStruct@@")
+!26 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "WrapStruct", file: !1, line: 4, size: 8, flags: DIFlagTypePassByValue, elements: !27, identifier: ".?AUWrapStruct@@")
+!27 = !{!25}
+!28 = !{!29}
+!29 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !25, file: !1, line: 5, baseType: !6, size: 32)
+!30 = !DILocation(line: 18, scope: !15)
+!31 = !DILocalVariable(name: "v3", scope: !15, file: !1, line: 19, type: !32)
+!32 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "Inner", scope: !33, file: !1, line: 8, size: 32, flags: DIFlagTypePassByValue, elements: !35, identifier: ".?AVInner at WrapClass@@")
+!33 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "WrapClass", file: !1, line: 7, size: 8, flags: DIFlagTypePassByValue, elements: !34, identifier: ".?AUWrapClass@@")
+!34 = !{!32}
+!35 = !{!36}
+!36 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !32, file: !1, line: 8, baseType: !6, size: 32, flags: DIFlagPublic)
+!37 = !DILocation(line: 19, scope: !15)
+!38 = !DILocalVariable(name: "v4", scope: !15, file: !1, line: 20, type: !3)
+!39 = !DILocation(line: 20, scope: !15)
+!40 = !DILocalVariable(name: "v5", scope: !15, file: !1, line: 21, type: !41)
+!41 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "Inner", scope: !42, file: !1, line: 14, size: 32, flags: DIFlagTypePassByValue, elements: !44, identifier: ".?ATInner at WrapUnion@@")
+!42 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "WrapUnion", file: !1, line: 13, size: 8, flags: DIFlagTypePassByValue, elements: !43, identifier: ".?AUWrapUnion@@")
+!43 = !{!41}
+!44 = !{!45, !46}
+!45 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !41, file: !1, line: 14, baseType: !6, size: 32)
+!46 = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !41, file: !1, line: 14, baseType: !47, size: 32)
+!47 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
+!48 = !DILocation(line: 21, scope: !15)
+!49 = !DILocation(line: 22, scope: !15)


        


More information about the llvm-commits mailing list