Sfoglia il codice sorgente

Make debug info of HLSL vectors more user friendly (#2018)

The clang type we generate for HLSL vectors contains a single field h of type DependentSizedExtVectorType, which shows up as an int[4] in DWARF. This change specifically emits debug info for x, y, z and w fields instead.

With this change, we also stop emitting a vector member for operator[], whose implementation was marked "external" so I don't think it'll have any impact.
Tristan Labelle 6 anni fa
parent
commit
e487566946

+ 45 - 13
tools/clang/lib/CodeGen/CGDebugInfo.cpp

@@ -1023,6 +1023,34 @@ void CGDebugInfo::CollectRecordFields(
   }
 }
 
+// HLSL Change Begins
+bool CGDebugInfo::TryCollectHLSLRecordElements(const RecordType *Ty,
+    llvm::DICompositeType *DITy,
+    SmallVectorImpl<llvm::Metadata *> &Elements) {
+  QualType QualTy(Ty, 0);
+  if (hlsl::IsHLSLVecType(QualTy)) {
+    // The HLSL vector type is defined as containing a field 'h' of
+    // extended vector type, which is represented as an array in DWARF.
+    // However, we logically represent it as one field per component.
+    QualType ElemQualTy = hlsl::GetHLSLVecElementType(QualTy);
+    unsigned VecSize = hlsl::GetHLSLVecSize(QualTy);
+    unsigned ElemSizeInBits = CGM.getContext().getTypeSize(ElemQualTy);
+    for (unsigned ElemIdx = 0; ElemIdx < VecSize; ++ElemIdx) {
+      StringRef FieldName = StringRef("xyzw" + ElemIdx, 1);
+      unsigned OffsetInBits = ElemSizeInBits * ElemIdx;
+      llvm::DIType *FieldType = createFieldType(FieldName, ElemQualTy, 0,
+        SourceLocation(), AccessSpecifier::AS_public, OffsetInBits,
+        /* tunit */ nullptr, DITy, Ty->getDecl());
+      Elements.emplace_back(FieldType);
+    }
+
+    return true;
+  }
+
+  return false;
+}
+// HLSL Chage Ends
+
 llvm::DISubroutineType *
 CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
                                    llvm::DIFile *Unit) {
@@ -1564,20 +1592,24 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
   SmallVector<llvm::Metadata *, 16> EltTys;
   // what about nested types?
 
-  // Note: The split of CXXDecl information here is intentional, the
-  // gdb tests will depend on a certain ordering at printout. The debug
-  // information offsets are still correct if we merge them all together
-  // though.
-  const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
-  if (CXXDecl) {
-    CollectCXXBases(CXXDecl, DefUnit, EltTys, FwdDecl);
-    CollectVTableInfo(CXXDecl, DefUnit, EltTys);
-  }
+  if (!TryCollectHLSLRecordElements(Ty, FwdDecl, EltTys)) { // HLSL Change
 
-  // Collect data fields (including static variables and any initializers).
-  CollectRecordFields(RD, DefUnit, EltTys, FwdDecl);
-  if (CXXDecl)
-    CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl);
+    // Note: The split of CXXDecl information here is intentional, the
+    // gdb tests will depend on a certain ordering at printout. The debug
+    // information offsets are still correct if we merge them all together
+    // though.
+    const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
+    if (CXXDecl) {
+      CollectCXXBases(CXXDecl, DefUnit, EltTys, FwdDecl);
+      CollectVTableInfo(CXXDecl, DefUnit, EltTys);
+    }
+
+    // Collect data fields (including static variables and any initializers).
+    CollectRecordFields(RD, DefUnit, EltTys, FwdDecl);
+    if (CXXDecl)
+      CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl);
+
+  } // HLSL Change
 
   LexicalBlockStack.pop_back();
   RegionMap.erase(Ty->getDecl());

+ 7 - 0
tools/clang/lib/CodeGen/CGDebugInfo.h

@@ -255,6 +255,13 @@ class CGDebugInfo {
   /// Create a new lexical block node and push it on the stack.
   void CreateLexicalBlock(SourceLocation Loc);
 
+  // HLSL Change Begins
+private:
+  bool TryCollectHLSLRecordElements(const RecordType *Ty,
+                                    llvm::DICompositeType *DITy,
+                                    SmallVectorImpl<llvm::Metadata *> &Elements);
+  // HLSL Change Ends
+
 public:
   CGDebugInfo(CodeGenModule &CGM);
   ~CGDebugInfo();

+ 9 - 0
tools/clang/test/CodeGenHLSL/debug/vector_members.hlsl

@@ -0,0 +1,9 @@
+// RUN: %dxc -T vs_6_0 -E main -Od -Zi %s | FileCheck %s
+
+// Test that the debug info for HLSL vectors exposes per-component fields.
+
+// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "int2"
+// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "vector<int, 2>", {{.*}}, size: 64, align: 32
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x", {{.*}}, size: 32, align: 32
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "y", {{.*}}, size: 32, align: 32, offset: 32
+int2 main(int2 v : IN) : OUT { return v; }

+ 10 - 0
tools/clang/test/CodeGenHLSL/debug/vector_members_bool.hlsl

@@ -0,0 +1,10 @@
+// RUN: %dxc -T vs_6_0 -E main -Od -Zi %s | FileCheck %s
+
+// Test that the debug info for HLSL bool vectors exposes per-component fields
+// in the memory representation of bools (32-bits)
+
+// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "bool2"
+// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "vector<bool, 2>", {{.*}}, size: 64, align: 32
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x", {{.*}}, size: 32, align: 32
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "y", {{.*}}, size: 32, align: 32, offset: 32
+bool2 main(bool2 v : IN) : OUT { return v; }