jmmartinez updated this revision to Diff 506611. jmmartinez added a comment.
- Updated to use `elements` array to avoid the complicated loop. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D144870/new/ https://reviews.llvm.org/D144870 Files: clang/lib/CodeGen/CGDebugInfo.cpp clang/lib/CodeGen/CGDebugInfo.h clang/lib/CodeGen/TargetInfo.cpp clang/lib/CodeGen/TargetInfo.h clang/test/CodeGen/debug-info-bitfield-0-struct.c
Index: clang/test/CodeGen/debug-info-bitfield-0-struct.c =================================================================== --- /dev/null +++ clang/test/CodeGen/debug-info-bitfield-0-struct.c @@ -0,0 +1,119 @@ +// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=limited %s | FileCheck --check-prefixes NOSEPARATOR,BOTH %s +// RUN: %clang_cc1 -triple amdgcn-unk-unk -o - -emit-llvm -debug-info-kind=limited %s | FileCheck --check-prefixes SEPARATOR,BOTH %s + +struct First { + // BOTH-DAG: ![[FIRST:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "First", file: !{{[0-9]+}}, line: {{[0-9]+}}, size: 32, elements: ![[FIRST_ELEMENTS:[0-9]+]]) + // BOTH-DAG: ![[FIRST_ELEMENTS]] = !{![[FIRST_X:[0-9]+]], ![[FIRST_Y:[0-9]+]]} + // BOTH-DAG: ![[FIRST_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: ![[FIRST]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 4, flags: DIFlagBitField, extraData: i64 0) + // BOTH-DAG: ![[FIRST_Y]] = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: ![[FIRST]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 4, offset: 4, flags: DIFlagBitField, extraData: i64 0) + int : 0; + int x : 4; + int y : 4; +}; + +struct FirstDuplicate { + // BOTH-DAG: ![[FIRSTD:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "FirstDuplicate", file: !{{[0-9]+}}, line: {{[0-9]+}}, size: 32, elements: ![[FIRSTD_ELEMENTS:[0-9]+]]) + // BOTH-DAG: ![[FIRSTD_ELEMENTS]] = !{![[FIRSTD_X:[0-9]+]], ![[FIRSTD_Y:[0-9]+]]} + // BOTH-DAG: ![[FIRSTD_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: ![[FIRSTD]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 4, flags: DIFlagBitField, extraData: i64 0) + // BOTH-DAG: ![[FIRSTD_Y]] = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: ![[FIRSTD]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 4, offset: 4, flags: DIFlagBitField, extraData: i64 0) + int : 0; + int : 0; + int x : 4; + int y : 4; +}; + +struct Second { + // BOTH-DAG: ![[SECOND:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Second", file: !{{[0-9]+}}, line: {{[0-9]+}}, size: 64, elements: ![[SECOND_ELEMENTS:[0-9]+]]) + + // NOSEPARATOR-DAG: ![[SECOND_ELEMENTS]] = !{![[SECOND_X:[0-9]+]], ![[SECOND_Y:[0-9]+]]} + // SEPARATOR-DAG: ![[SECOND_ELEMENTS]] = !{![[SECOND_X:[0-9]+]], ![[SECOND_ZERO:[0-9]+]], ![[SECOND_Y:[0-9]+]]} + + // BOTH-DAG: ![[SECOND_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: ![[SECOND]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 4, flags: DIFlagBitField, extraData: i64 0) + // SEPARATOR-DAG: ![[SECOND_ZERO]] = !DIDerivedType(tag: DW_TAG_member, scope: ![[SECOND]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, offset: 32, flags: DIFlagBitField, extraData: i64 32) + // BOTH-DAG: ![[SECOND_Y]] = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: ![[SECOND]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 4, offset: 32, flags: DIFlagBitField, extraData: i64 32) + int x : 4; + int : 0; + int y : 4; +}; + +struct SecondDuplicate { + // BOTH-DAG: ![[SECONDD:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "SecondDuplicate", file: !{{[0-9]+}}, line: {{[0-9]+}}, size: 64, elements: ![[SECONDD_ELEMENTS:[0-9]+]]) + + // NOSEPARATOR-DAG: ![[SECONDD_ELEMENTS]] = !{![[SECONDD_X:[0-9]+]], ![[SECONDD_Y:[0-9]+]]} + // SEPARATOR-DAG: ![[SECONDD_ELEMENTS]] = !{![[SECONDD_X:[0-9]+]], ![[SECONDD_ZERO:[0-9]+]], ![[SECONDD_Y:[0-9]+]]} + + // BOTH-DAG: ![[SECONDD_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: ![[SECONDD]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 4, flags: DIFlagBitField, extraData: i64 0) + // SEPARATOR-DAG: ![[SECONDD_ZERO]] = !DIDerivedType(tag: DW_TAG_member, scope: ![[SECONDD]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, offset: 32, flags: DIFlagBitField, extraData: i64 32) + // BOTH-DAG: ![[SECONDD_Y]] = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: ![[SECONDD]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 4, offset: 32, flags: DIFlagBitField, extraData: i64 32) + int x : 4; + int : 0; + int : 0; + int y : 4; +}; + +struct Last { + // BOTH-DAG: ![[LAST:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Last", file: !{{[0-9]+}}, line: {{[0-9]+}}, size: 32, elements: ![[LAST_ELEMENTS:[0-9]+]]) + // BOTH-DAG: ![[LAST_ELEMENTS]] = !{![[LAST_X:[0-9]+]], ![[LAST_Y:[0-9]+]]} + // BOTH-DAG: ![[LAST_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: ![[LAST]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 4, flags: DIFlagBitField, extraData: i64 0) + // BOTH-DAG: ![[LAST_Y]] = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: ![[LAST]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 4, offset: 4, flags: DIFlagBitField, extraData: i64 0) + int x : 4; + int y : 4; + int : 0; +}; + +struct Several { + // BOTH-DAG: ![[SEVERAL:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Several", file: !{{[0-9]+}}, line: {{[0-9]+}}, size: 96, elements: ![[SEVERAL_ELEMENTS:[0-9]+]]) + + // SEPARATOR-DAG: ![[SEVERAL_ELEMENTS]] = !{![[SEVERAL_X:[0-9]+]], ![[SEVERAL_FIRST_ZERO:[0-9]+]], ![[SEVERAL_Y:[0-9]+]], ![[SEVERAL_SECOND_ZERO:[0-9]+]], ![[SEVERAL_Z:[0-9]+]]} + // NOSEPARATOR-DAG: ![[SEVERAL_ELEMENTS]] = !{![[SEVERAL_X:[0-9]+]], ![[SEVERAL_Y:[0-9]+]], ![[SEVERAL_Z:[0-9]+]]} + + // BOTH-DAG: ![[SEVERAL_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: ![[SEVERAL]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 4, flags: DIFlagBitField, extraData: i64 0) + // SEPARATOR-DAG: ![[SEVERAL_FIRST_ZERO]] = !DIDerivedType(tag: DW_TAG_member, scope: ![[SEVERAL]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, offset: 32, flags: DIFlagBitField, extraData: i64 32) + // BOTH-DAG: ![[SEVERAL_Y]] = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: ![[SEVERAL]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 4, offset: 32, flags: DIFlagBitField, extraData: i64 32) + // SEPARATOR-DAG: ![[SEVERAL_SECOND_ZERO]] = !DIDerivedType(tag: DW_TAG_member, scope: ![[SEVERAL]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, offset: 64, flags: DIFlagBitField, extraData: i64 64) + // BOTH-DAG: ![[SEVERAL_Z]] = !DIDerivedType(tag: DW_TAG_member, name: "z", scope: ![[SEVERAL]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 4, offset: 64, flags: DIFlagBitField, extraData: i64 64) + int x : 4; + int : 0; + int y : 4; + int : 0; + int z : 4; +}; + +struct None_A { + // BOTH-DAG: ![[NONE_A:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "None_A", file: !{{[0-9]+}}, line: {{[0-9]+}}, size: 64, elements: ![[NONE_A_ELEMENTS:[0-9]+]]) + // BOTH-DAG: ![[NONE_A_ELEMENTS]] = !{![[NONE_A_FIELD:[0-9]+]], ![[NONE_A_X:[0-9]+]]} + // BOTH-DAG: ![[NONE_A_FIELD]] = !DIDerivedType(tag: DW_TAG_member, name: "field", scope: ![[NONE_A]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 32) + // BOTH-DAG: ![[NONE_A_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: ![[NONE_A]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 4, offset: 32, flags: DIFlagBitField, extraData: i64 32) + int : 0; + int field; + int x : 4; +}; + +struct None_B { + // BOTH-DAG: ![[NONE_B:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "None_B", file: !{{[0-9]+}}, line: {{[0-9]+}}, size: 64, elements: ![[NONE_B_ELEMENTS:[0-9]+]]) + // BOTH-DAG: ![[NONE_B_ELEMENTS]] = !{![[NONE_B_FIELD:[0-9]+]], ![[NONE_B_X:[0-9]+]], ![[NONE_B_Y:[0-9]+]]} + // BOTH-DAG: ![[NONE_B_FIELD]] = !DIDerivedType(tag: DW_TAG_member, name: "field", scope: ![[NONE_B]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 32) + // BOTH-DAG: ![[NONE_B_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: ![[NONE_B]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 4, offset: 32, flags: DIFlagBitField, extraData: i64 32) + // BOTH-DAG: ![[NONE_B_Y]] = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: ![[NONE_B]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 4, offset: 36, flags: DIFlagBitField, extraData: i64 32) + int field; + int : 0; + int x : 4; + int y : 4; +}; + +struct None_C { + // BOTH-DAG: ![[NONE_C:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "None_C", file: !{{[0-9]+}}, line: {{[0-9]+}}, size: 32, elements: ![[NONE_C_ELEMENTS:[0-9]+]]) + // BOTH-DAG: ![[NONE_C_ELEMENTS]] = !{![[NONE_C_X:[0-9]+]], ![[NONE_C_Y:[0-9]+]], ![[NONE_C_A:[0-9]+]], ![[NONE_C_B:[0-9]+]]} + // BOTH-DAG: ![[NONE_C_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: ![[NONE_C]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 8, flags: DIFlagBitField, extraData: i64 0) + // BOTH-DAG: ![[NONE_C_Y]] = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: ![[NONE_C]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 8, offset: 8, flags: DIFlagBitField, extraData: i64 0) + // BOTH-DAG: ![[NONE_C_A]] = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[NONE_C]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 8, offset: 16, flags: DIFlagBitField, extraData: i64 0) + // BOTH-DAG: ![[NONE_C_B]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[NONE_C]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 8, offset: 24, flags: DIFlagBitField, extraData: i64 0) + char x : 8; + char y : 8; + char a : 8; + char b : 8; +}; + +void foo(struct First f, struct FirstDuplicate fs, struct Second s, struct SecondDuplicate sd, struct Last l, struct Several ss, struct None_A na, struct None_B nb, struct None_C nc) { + return; +} Index: clang/lib/CodeGen/TargetInfo.h =================================================================== --- clang/lib/CodeGen/TargetInfo.h +++ clang/lib/CodeGen/TargetInfo.h @@ -349,6 +349,11 @@ /// as 'used', and having internal linkage. virtual bool shouldEmitStaticExternCAliases() const { return true; } + /// \return true if annonymous zero-sized bitfields should be emitted to + /// correctly distinguish between struct types whose memory layout is the + /// same, but whose layout may differ when used as argument passed by value + virtual bool shouldEmitDWARFBitFieldSeparators() const { return false; } + virtual void setCUDAKernelCallingConvention(const FunctionType *&FT) const {} /// Return the device-side type for the CUDA device builtin surface type. Index: clang/lib/CodeGen/TargetInfo.cpp =================================================================== --- clang/lib/CodeGen/TargetInfo.cpp +++ clang/lib/CodeGen/TargetInfo.cpp @@ -9469,6 +9469,7 @@ llvm::Function *BlockInvokeFunc, llvm::Type *BlockTy) const override; bool shouldEmitStaticExternCAliases() const override; + bool shouldEmitDWARFBitFieldSeparators() const override; void setCUDAKernelCallingConvention(const FunctionType *&FT) const override; }; } @@ -9686,6 +9687,10 @@ return false; } +bool AMDGPUTargetCodeGenInfo::shouldEmitDWARFBitFieldSeparators() const { + return true; +} + void AMDGPUTargetCodeGenInfo::setCUDAKernelCallingConvention( const FunctionType *&FT) const { FT = getABIInfo().getContext().adjustFunctionType( Index: clang/lib/CodeGen/CGDebugInfo.h =================================================================== --- clang/lib/CodeGen/CGDebugInfo.h +++ clang/lib/CodeGen/CGDebugInfo.h @@ -321,10 +321,16 @@ RD); } - /// Create new bit field member. - llvm::DIType *createBitFieldType(const FieldDecl *BitFieldDecl, - llvm::DIScope *RecordTy, - const RecordDecl *RD); + /// Create new bit field member + llvm::DIDerivedType *createBitFieldType(const FieldDecl *BitFieldDecl, + llvm::DIScope *RecordTy, + const RecordDecl *RD); + + /// Create an anonnymous zero-size separator for bit-field-decl if needed on + /// the target + llvm::DIDerivedType *createBitFieldSeparatorIfNeeded( + const FieldDecl *BitFieldDecl, const llvm::DIDerivedType *BitFieldDI, + llvm::ArrayRef<llvm::Metadata *> PreviousFieldsDI, const RecordDecl *RD); /// Helpers for collecting fields of a record. /// @{ Index: clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- clang/lib/CodeGen/CGDebugInfo.cpp +++ clang/lib/CodeGen/CGDebugInfo.cpp @@ -18,6 +18,7 @@ #include "CodeGenFunction.h" #include "CodeGenModule.h" #include "ConstantEmitter.h" +#include "TargetInfo.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclFriend.h" @@ -1483,9 +1484,9 @@ return F; } -llvm::DIType *CGDebugInfo::createBitFieldType(const FieldDecl *BitFieldDecl, - llvm::DIScope *RecordTy, - const RecordDecl *RD) { +llvm::DIDerivedType * +CGDebugInfo::createBitFieldType(const FieldDecl *BitFieldDecl, + llvm::DIScope *RecordTy, const RecordDecl *RD) { StringRef Name = BitFieldDecl->getName(); QualType Ty = BitFieldDecl->getType(); SourceLocation Loc = BitFieldDecl->getLocation(); @@ -1516,6 +1517,77 @@ Flags, DebugType, Annotations); } +llvm::DIDerivedType *CGDebugInfo::createBitFieldSeparatorIfNeeded( + const FieldDecl *BitFieldDecl, const llvm::DIDerivedType *BitFieldDI, + llvm::ArrayRef<llvm::Metadata *> PreviousFieldsDI, const RecordDecl *RD) { + + if (!CGM.getTargetCodeGenInfo().shouldEmitDWARFBitFieldSeparators()) + return nullptr; + + /* + Add a *single* zero-bitfield separator between two non-zero bitfields + separated by one or more zero-bitfields. This is used to distinguish between + structures such the ones below, where the memory layout is the same, but how + the ABI assigns fields to registers differs. + + struct foo { + int space[4]; + char a : 8; // on amdgpu, passed on v4 + char b : 8; + char x : 8; + char y : 8; + }; + struct bar { + int space[4]; + char a : 8; // on amdgpu, passed on v4 + char b : 8; + char : 0; + char x : 8; // passed on v5 + char y : 8; + }; + */ + if (PreviousFieldsDI.empty()) + return nullptr; + + auto *PreviousMDEntry = + PreviousFieldsDI.empty() ? nullptr : PreviousFieldsDI.back(); + auto *PreviousMDField = + dyn_cast_or_null<llvm::DIDerivedType>(PreviousMDEntry); + if (!PreviousMDField || !PreviousMDField->isBitField() || + PreviousMDField->getSizeInBits() == 0) + return nullptr; + + auto PreviousBitfield = RD->field_begin(); + std::advance(PreviousBitfield, BitFieldDecl->getFieldIndex() - 1); + + assert(PreviousBitfield->isBitField()); + + ASTContext &Context = CGM.getContext(); + if (!PreviousBitfield->isZeroLengthBitField(Context)) + return nullptr; + + QualType Ty = PreviousBitfield->getType(); + SourceLocation Loc = PreviousBitfield->getLocation(); + llvm::DIFile *VUnit = getOrCreateFile(Loc); + llvm::DIType *DebugType = getOrCreateType(Ty, VUnit); + llvm::DIScope *RecordTy = BitFieldDI->getScope(); + + llvm::DIFile *File = getOrCreateFile(Loc); + unsigned Line = getLineNumber(Loc); + + uint64_t StorageOffsetInBits = + cast<llvm::ConstantInt>(BitFieldDI->getStorageOffsetInBits()) + ->getZExtValue(); + + llvm::DINode::DIFlags Flags = + getAccessFlag(PreviousBitfield->getAccess(), RD); + llvm::DINodeArray Annotations = + CollectBTFDeclTagAnnotations(*PreviousBitfield); + return DBuilder.createBitFieldMemberType( + RecordTy, "", File, Line, 0, StorageOffsetInBits, StorageOffsetInBits, + Flags, DebugType, Annotations); +} + llvm::DIType *CGDebugInfo::createFieldType( StringRef name, QualType type, SourceLocation loc, AccessSpecifier AS, uint64_t offsetInBits, uint32_t AlignInBits, llvm::DIFile *tunit, @@ -1624,7 +1696,11 @@ llvm::DIType *FieldType; if (field->isBitField()) { - FieldType = createBitFieldType(field, RecordTy, RD); + llvm::DIDerivedType *BitFieldType; + FieldType = BitFieldType = createBitFieldType(field, RecordTy, RD); + if (llvm::DIType *Separator = + createBitFieldSeparatorIfNeeded(field, BitFieldType, elements, RD)) + elements.push_back(Separator); } else { auto Align = getDeclAlignIfRequired(field, CGM.getContext()); llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(field);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits