[llvm] 2b8c6ac - Reland "[codeview] Reference types in type parent scopes"

Amy Huang via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 16 12:09:20 PDT 2020


Author: Amy Huang
Date: 2020-04-16T12:08:52-07:00
New Revision: 2b8c6acc3990872800d908b0ddf69229b21db1de

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

LOG: Reland "[codeview] Reference types in type parent scopes"

Summary:
Original description (https://reviews.llvm/org/D69924)
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.

Now, while walking over the parent scopes, add the types to
DeferredCompleteTypes, since they might already be in the process of
being emitted.

Fixes PR43905

Reviewers: rnk, amccarth

Subscribers: hiraditya, llvm-commits

Tags: #llvm

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

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

Modified: 
    llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
    llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index ca349cbdd0e0..7c2673a2d99a 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -310,12 +310,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<DICompositeType>(Scope))
+      DeferredCompleteTypes.push_back(Ty);
+
     StringRef ScopeName = getPrettyScopeName(Scope);
     if (!ScopeName.empty())
       QualifiedNameComponents.push_back(ScopeName);
@@ -324,7 +331,7 @@ static const DISubprogram *getQualifiedNameComponents(
   return ClosestSubprogram;
 }
 
-static std::string getQualifiedName(ArrayRef<StringRef> QualifiedNameComponents,
+static std::string formatNestedName(ArrayRef<StringRef> QualifiedNameComponents,
                                     StringRef TypeName) {
   std::string FullyQualifiedName;
   for (StringRef QualifiedNameComponent :
@@ -336,10 +343,16 @@ 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 {
@@ -354,11 +367,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))
@@ -1477,12 +1485,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..f690376ada89 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -443,6 +443,15 @@ 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 getFullyQualifiedName(const DIScope *Scope, StringRef Name);
+  std::string getFullyQualifiedName(const DIScope *Scope);
+
   unsigned getPointerSizeInBytes();
 
 protected:

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)

diff  --git a/llvm/test/DebugInfo/COFF/unnamed-nested.ll b/llvm/test/DebugInfo/COFF/unnamed-nested.ll
new file mode 100644
index 000000000000..6cb8671e299b
--- /dev/null
+++ b/llvm/test/DebugInfo/COFF/unnamed-nested.ll
@@ -0,0 +1,51 @@
+; RUN: llc < %s -filetype=obj -o %t.o
+; RUN: llvm-pdbutil dump -types %t.o | FileCheck %s
+
+; C source to regenerate:
+; $ clang -g -gcodeview -S -emit-llvm t.c
+; $ cat t.c
+; struct {
+;   union {
+;     struct {};
+;   };
+; } S;
+
+; Test that this compiles without errors.
+
+; CHECK: LF_STRUCTURE{{.*}}<unnamed-tag>::<unnamed-tag>::<unnamed-tag>
+; CHECK: LF_UNION{{.*}}<unnamed-tag>::<unnamed-tag>
+; CHECK: LF_STRUCTURE{{.*}}<unnamed-tag>
+
+; ModuleID = 't.c'
+source_filename = "t.c"
+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.24.28316"
+
+%struct.anon = type { %union.anon }
+%union.anon = type { %struct.anon.0 }
+%struct.anon.0 = type { [4 x i8] }
+
+ at S = dso_local global %struct.anon zeroinitializer, align 1, !dbg !0
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!13, !14, !15, !16}
+!llvm.ident = !{!17}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "S", scope: !2, file: !3, line: 5, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 11.0.0 (https://github.com/llvm/llvm-project.git 60d09bec7f8699728d38057430422d955d32a904)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
+!3 = !DIFile(filename: "t.c", directory: "C:\\src\\llvm-build", checksumkind: CSK_MD5, checksum: "c31fe86676dd2fb56f847f926c0f2c71")
+!4 = !{}
+!5 = !{!0}
+!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !3, line: 1, size: 32, elements: !7)
+!7 = !{!8, !12}
+!8 = distinct !DICompositeType(tag: DW_TAG_union_type, scope: !6, file: !3, line: 2, size: 32, elements: !9)
+!9 = !{!10, !11}
+!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, scope: !8, file: !3, line: 3, size: 32, elements: !4)
+!11 = !DIDerivedType(tag: DW_TAG_member, scope: !8, file: !3, line: 3, baseType: !10, size: 32)
+!12 = !DIDerivedType(tag: DW_TAG_member, scope: !6, file: !3, line: 2, baseType: !8, size: 32)
+!13 = !{i32 2, !"CodeView", i32 1}
+!14 = !{i32 2, !"Debug Info Version", i32 3}
+!15 = !{i32 1, !"wchar_size", i32 2}
+!16 = !{i32 7, !"PIC Level", i32 2}
+!17 = !{!"clang version 11.0.0 (https://github.com/llvm/llvm-project.git 60d09bec7f8699728d38057430422d955d32a904)"}


        


More information about the llvm-commits mailing list