diff options
author | Amjad Aboud <amjad.aboud@intel.com> | 2016-07-12 12:06:34 +0000 |
---|---|---|
committer | Amjad Aboud <amjad.aboud@intel.com> | 2016-07-12 12:06:34 +0000 |
commit | acee56854533780d94b1aa38c5aaa33720b3a596 (patch) | |
tree | 825f1bca4a20d5e9eb6f6fc0ce01711cc681c1be /llvm/lib/CodeGen/AsmPrinter | |
parent | 6892afaa2df7c88d7913a1253e7b3b810994a9ef (diff) | |
download | bcm5719-llvm-acee56854533780d94b1aa38c5aaa33720b3a596.tar.gz bcm5719-llvm-acee56854533780d94b1aa38c5aaa33720b3a596.zip |
[codeview] Improved array type support.
Added support for:
1. Multi dimension array.
2. Array of structure type, which previously was declared incompletely.
3. Dynamic size array.
4. Array where element type is a typedef, volatile or constant (this should resolve PR28311).
Differential Revision: http://reviews.llvm.org/D21526
llvm-svn: 275167
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 60 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp | 29 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h | 3 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 28 |
4 files changed, 87 insertions, 33 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index bb959e26a8e..b0ba5712220 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -271,8 +271,9 @@ TypeIndex CodeViewDebug::getMemberFunctionType(const DISubprogram *SP, return recordTypeIndexForDINode(SP, TI, Class); } -TypeIndex CodeViewDebug::recordTypeIndexForDINode(const DINode *Node, TypeIndex TI, - const DIType *ClassTy) { +TypeIndex CodeViewDebug::recordTypeIndexForDINode(const DINode *Node, + TypeIndex TI, + const DIType *ClassTy) { auto InsertResult = TypeIndices.insert({{Node, ClassTy}, TI}); (void)InsertResult; assert(InsertResult.second && "DINode was already assigned a type index"); @@ -987,9 +988,55 @@ TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) { TypeIndex IndexType = Asm->MAI->getPointerSize() == 8 ? TypeIndex(SimpleTypeKind::UInt64Quad) : TypeIndex(SimpleTypeKind::UInt32Long); - uint64_t Size = Ty->getSizeInBits() / 8; - ArrayRecord Record(ElementTypeIndex, IndexType, Size, Ty->getName()); - return TypeTable.writeArray(Record); + + uint64_t ElementSize = getBaseTypeSize(ElementTypeRef) / 8; + + bool UndefinedSubrange = false; + + // FIXME: + // There is a bug in the front-end where an array of a structure, which was + // declared as incomplete structure first, ends up not getting a size assigned + // to it. (PR28303) + // Example: + // struct A(*p)[3]; + // struct A { int f; } a[3]; + // + // This needs to be fixed in the front-end, but in the meantime we don't want + // to trigger an assertion because of this. + if (Ty->getSizeInBits() == 0) { + UndefinedSubrange = true; + } + + // Add subranges to array type. + DINodeArray Elements = Ty->getElements(); + for (int i = Elements.size() - 1; i >= 0; --i) { + const DINode *Element = Elements[i]; + assert(Element->getTag() == dwarf::DW_TAG_subrange_type); + + const DISubrange *Subrange = cast<DISubrange>(Element); + assert(Subrange->getLowerBound() == 0 && + "codeview doesn't support subranges with lower bounds"); + int64_t Count = Subrange->getCount(); + + // Variable Length Array (VLA) has Count equal to '-1'. + // Replace with Count '1', assume it is the minimum VLA length. + // FIXME: Make front-end support VLA subrange and emit LF_DIMVARLU. + if (Count == -1) { + Count = 1; + UndefinedSubrange = true; + } + + StringRef Name = (i == 0) ? Ty->getName() : ""; + // Update the element size and element type index for subsequent subranges. + ElementSize *= Count; + ElementTypeIndex = TypeTable.writeArray( + ArrayRecord(ElementTypeIndex, IndexType, ElementSize, Name)); + } + + (void)UndefinedSubrange; + assert(UndefinedSubrange || ElementSize == (Ty->getSizeInBits() / 8)); + + return ElementTypeIndex; } TypeIndex CodeViewDebug::lowerTypeBasic(const DIBasicType *Ty) { @@ -1771,7 +1818,8 @@ TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) { } /// Emit all the deferred complete record types. Try to do this in FIFO order, -/// and do this until fixpoint, as each complete record type typically references +/// and do this until fixpoint, as each complete record type typically +/// references /// many other record types. void CodeViewDebug::emitDeferredCompleteTypes() { SmallVector<const DICompositeType *, 4> TypesToEmit; diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp index c1300774c4f..16ffe2e15ac 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp @@ -85,6 +85,35 @@ bool DebugHandlerBase::piecesOverlap(const DIExpression *P1, const DIExpression return pieceCmp(P1, P2) == 0; } +/// If this type is derived from a base type then return base type size. +uint64_t DebugHandlerBase::getBaseTypeSize(const DITypeRef TyRef) { + DIType *Ty = TyRef.resolve(); + assert(Ty); + DIDerivedType *DDTy = dyn_cast<DIDerivedType>(Ty); + if (!DDTy) + return Ty->getSizeInBits(); + + unsigned Tag = DDTy->getTag(); + + if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef && + Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type && + Tag != dwarf::DW_TAG_restrict_type) + return DDTy->getSizeInBits(); + + DIType *BaseType = DDTy->getBaseType().resolve(); + + assert(BaseType && "Unexpected invalid base type"); + + // If this is a derived type, go ahead and get the base type, unless it's a + // reference then it's just the size of the field. Pointer types have no need + // of this since they're a different type of qualification on the type. + if (BaseType->getTag() == dwarf::DW_TAG_reference_type || + BaseType->getTag() == dwarf::DW_TAG_rvalue_reference_type) + return Ty->getSizeInBits(); + + return getBaseTypeSize(BaseType); +} + void DebugHandlerBase::beginFunction(const MachineFunction *MF) { // Grab the lexical scopes for the function, if we don't have any of those // then we're not going to be able to do anything. diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h index 826023602c1..b8bbcec133f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h +++ b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h @@ -99,6 +99,9 @@ public: /// Determine whether two variable pieces overlap. static bool piecesOverlap(const DIExpression *P1, const DIExpression *P2); + + /// If this type is derived from a base type then return base type size. + static uint64_t getBaseTypeSize(const DITypeRef TyRef); }; } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index e2e6954bd1c..4100d728a53 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -561,32 +561,6 @@ static bool isUnsignedDIType(DwarfDebug *DD, const DIType *Ty) { Ty->getTag() == dwarf::DW_TAG_unspecified_type; } -/// If this type is derived from a base type then return base type size. -static uint64_t getBaseTypeSize(DwarfDebug *DD, const DIDerivedType *Ty) { - unsigned Tag = Ty->getTag(); - - if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef && - Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type && - Tag != dwarf::DW_TAG_restrict_type) - return Ty->getSizeInBits(); - - auto *BaseType = DD->resolve(Ty->getBaseType()); - - assert(BaseType && "Unexpected invalid base type"); - - // If this is a derived type, go ahead and get the base type, unless it's a - // reference then it's just the size of the field. Pointer types have no need - // of this since they're a different type of qualification on the type. - if (BaseType->getTag() == dwarf::DW_TAG_reference_type || - BaseType->getTag() == dwarf::DW_TAG_rvalue_reference_type) - return Ty->getSizeInBits(); - - if (auto *DT = dyn_cast<DIDerivedType>(BaseType)) - return getBaseTypeSize(DD, DT); - - return BaseType->getSizeInBits(); -} - void DwarfUnit::addConstantFPValue(DIE &Die, const MachineOperand &MO) { assert(MO.isFPImm() && "Invalid machine operand!"); DIEBlock *Block = new (DIEValueAllocator) DIEBlock; @@ -1408,7 +1382,7 @@ void DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) { addBlock(MemberDie, dwarf::DW_AT_data_member_location, VBaseLocationDie); } else { uint64_t Size = DT->getSizeInBits(); - uint64_t FieldSize = getBaseTypeSize(DD, DT); + uint64_t FieldSize = DD->getBaseTypeSize(DT); uint64_t OffsetInBytes; bool IsBitfield = FieldSize && Size != FieldSize; |