From e487566946de1e695a7b6ffa1b4215d8169f403c Mon Sep 17 00:00:00 2001 From: Tristan Labelle Date: Mon, 18 Mar 2019 14:12:49 -0700 Subject: [PATCH] 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. --- tools/clang/lib/CodeGen/CGDebugInfo.cpp | 58 ++++++++++++++----- tools/clang/lib/CodeGen/CGDebugInfo.h | 7 +++ .../CodeGenHLSL/debug/vector_members.hlsl | 9 +++ .../debug/vector_members_bool.hlsl | 10 ++++ 4 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 tools/clang/test/CodeGenHLSL/debug/vector_members.hlsl create mode 100644 tools/clang/test/CodeGenHLSL/debug/vector_members_bool.hlsl diff --git a/tools/clang/lib/CodeGen/CGDebugInfo.cpp b/tools/clang/lib/CodeGen/CGDebugInfo.cpp index 112161243..4c661a43c 100644 --- a/tools/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/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 &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 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(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(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()); diff --git a/tools/clang/lib/CodeGen/CGDebugInfo.h b/tools/clang/lib/CodeGen/CGDebugInfo.h index 82680a84d..1446eadf8 100644 --- a/tools/clang/lib/CodeGen/CGDebugInfo.h +++ b/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 &Elements); + // HLSL Change Ends + public: CGDebugInfo(CodeGenModule &CGM); ~CGDebugInfo(); diff --git a/tools/clang/test/CodeGenHLSL/debug/vector_members.hlsl b/tools/clang/test/CodeGenHLSL/debug/vector_members.hlsl new file mode 100644 index 000000000..bcccdc914 --- /dev/null +++ b/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", {{.*}}, 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; } \ No newline at end of file diff --git a/tools/clang/test/CodeGenHLSL/debug/vector_members_bool.hlsl b/tools/clang/test/CodeGenHLSL/debug/vector_members_bool.hlsl new file mode 100644 index 000000000..c260d60af --- /dev/null +++ b/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", {{.*}}, 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; } \ No newline at end of file