diff options
| author | Sander de Smalen <sander.desmalen@arm.com> | 2018-01-24 09:56:07 +0000 |
|---|---|---|
| committer | Sander de Smalen <sander.desmalen@arm.com> | 2018-01-24 09:56:07 +0000 |
| commit | fdf40917d946e3b36fd67afb2aac4063af9fc85d (patch) | |
| tree | 9f0bac9e282261c26720ea14594ddb76e35f5d2f /llvm/lib | |
| parent | e8404780c38e44ccbbc1cd89873929ed4c49dac0 (diff) | |
| download | bcm5719-llvm-fdf40917d946e3b36fd67afb2aac4063af9fc85d.tar.gz bcm5719-llvm-fdf40917d946e3b36fd67afb2aac4063af9fc85d.zip | |
[Metadata] Extend 'count' field of DISubrange to take a metadata node
Summary:
This patch extends the DISubrange 'count' field to take either a
(signed) constant integer value or a reference to a DILocalVariable
or DIGlobalVariable.
This is patch [1/3] in a series to extend LLVM's DISubrange Metadata
node to support debugging of C99 variable length arrays and vectors with
runtime length like the Scalable Vector Extension for AArch64. It is
also a first step towards representing more complex cases like arrays
in Fortran.
Reviewers: echristo, pcc, aprantl, dexonsmith, clayborg, kristof.beyls, dblaikie
Reviewed By: aprantl
Subscribers: rnk, probinson, fhahn, aemerson, rengolin, JDevlieghere, llvm-commits
Differential Revision: https://reviews.llvm.org/D41695
llvm-svn: 323313
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/AsmParser/LLParser.cpp | 89 | ||||
| -rw-r--r-- | llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 25 | ||||
| -rw-r--r-- | llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/IR/AsmWriter.cpp | 11 | ||||
| -rw-r--r-- | llvm/lib/IR/DIBuilder.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/IR/DebugInfoMetadata.cpp | 13 | ||||
| -rw-r--r-- | llvm/lib/IR/LLVMContextImpl.h | 27 | ||||
| -rw-r--r-- | llvm/lib/IR/Verifier.cpp | 7 |
10 files changed, 164 insertions, 25 deletions
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index f94b616e596..9bc34f927e8 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -3492,6 +3492,39 @@ template <class FieldTy> struct MDFieldImpl { : Val(std::move(Default)), Seen(false) {} }; +/// Structure to represent an optional metadata field that +/// can be of either type (A or B) and encapsulates the +/// MD<typeofA>Field and MD<typeofB>Field structs, so not +/// to reimplement the specifics for representing each Field. +template <class FieldTypeA, class FieldTypeB> struct MDEitherFieldImpl { + typedef MDEitherFieldImpl<FieldTypeA, FieldTypeB> ImplTy; + FieldTypeA A; + FieldTypeB B; + bool Seen; + + enum { + IsInvalid = 0, + IsTypeA = 1, + IsTypeB = 2 + } WhatIs; + + void assign(FieldTypeA A) { + Seen = true; + this->A = std::move(A); + WhatIs = IsTypeA; + } + + void assign(FieldTypeB B) { + Seen = true; + this->B = std::move(B); + WhatIs = IsTypeB; + } + + explicit MDEitherFieldImpl(FieldTypeA DefaultA, FieldTypeB DefaultB) + : A(std::move(DefaultA)), B(std::move(DefaultB)), Seen(false), + WhatIs(IsInvalid) {} +}; + struct MDUnsignedField : public MDFieldImpl<uint64_t> { uint64_t Max; @@ -3582,6 +3615,26 @@ struct ChecksumKindField : public MDFieldImpl<DIFile::ChecksumKind> { ChecksumKindField(DIFile::ChecksumKind CSKind) : ImplTy(CSKind) {} }; +struct MDSignedOrMDField : MDEitherFieldImpl<MDSignedField, MDField> { + MDSignedOrMDField(int64_t Default = 0, bool AllowNull = true) + : ImplTy(MDSignedField(Default), MDField(AllowNull)) {} + + MDSignedOrMDField(int64_t Default, int64_t Min, int64_t Max, + bool AllowNull = true) + : ImplTy(MDSignedField(Default, Min, Max), MDField(AllowNull)) {} + + bool isMDSignedField() const { return WhatIs == IsTypeA; } + bool isMDField() const { return WhatIs == IsTypeB; } + int64_t getMDSignedValue() const { + assert(isMDSignedField() && "Wrong field type"); + return A.Val; + } + Metadata *getMDFieldValue() const { + assert(isMDField() && "Wrong field type"); + return B.Val; + } +}; + } // end anonymous namespace namespace llvm { @@ -3836,6 +3889,29 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDField &Result) { } template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, + MDSignedOrMDField &Result) { + // Try to parse a signed int. + if (Lex.getKind() == lltok::APSInt) { + MDSignedField Res = Result.A; + if (!ParseMDField(Loc, Name, Res)) { + Result.assign(Res); + return false; + } + return true; + } + + // Otherwise, try to parse as an MDField. + MDField Res = Result.B; + if (!ParseMDField(Loc, Name, Res)) { + Result.assign(Res); + return false; + } + + return true; +} + +template <> bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDStringField &Result) { LocTy ValueLoc = Lex.getLoc(); std::string S; @@ -3979,14 +4055,23 @@ bool LLParser::ParseGenericDINode(MDNode *&Result, bool IsDistinct) { /// ParseDISubrange: /// ::= !DISubrange(count: 30, lowerBound: 2) +/// ::= !DISubrange(count: !node, lowerBound: 2) bool LLParser::ParseDISubrange(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(count, MDSignedField, (-1, -1, INT64_MAX)); \ + REQUIRED(count, MDSignedOrMDField, (-1, -1, INT64_MAX, false)); \ OPTIONAL(lowerBound, MDSignedField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS - Result = GET_OR_DISTINCT(DISubrange, (Context, count.Val, lowerBound.Val)); + if (count.isMDSignedField()) + Result = GET_OR_DISTINCT( + DISubrange, (Context, count.getMDSignedValue(), lowerBound.Val)); + else if (count.isMDField()) + Result = GET_OR_DISTINCT( + DISubrange, (Context, count.getMDFieldValue(), lowerBound.Val)); + else + return true; + return false; } diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index 7d79956a811..5250ac5176d 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1174,14 +1174,25 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( break; } case bitc::METADATA_SUBRANGE: { - if (Record.size() != 3) - return error("Invalid record"); + Metadata *Val = nullptr; + // Operand 'count' is interpreted as: + // - Signed integer (version 0) + // - Metadata node (version 1) + switch (Record[0] >> 1) { + case 0: + Val = GET_OR_DISTINCT(DISubrange, + (Context, Record[1], unrotateSign(Record.back()))); + break; + case 1: + Val = GET_OR_DISTINCT(DISubrange, (Context, getMDOrNull(Record[1]), + unrotateSign(Record.back()))); + break; + default: + return error("Invalid record: Unsupported version of DISubrange"); + } - IsDistinct = Record[0]; - MetadataList.assignValue( - GET_OR_DISTINCT(DISubrange, - (Context, Record[1], unrotateSign(Record[2]))), - NextMetadataNo); + MetadataList.assignValue(Val, NextMetadataNo); + IsDistinct = Record[0] & 1; NextMetadataNo++; break; } diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index f3f33c4474b..3876b5ffe35 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1442,8 +1442,9 @@ static uint64_t rotateSign(int64_t I) { void ModuleBitcodeWriter::writeDISubrange(const DISubrange *N, SmallVectorImpl<uint64_t> &Record, unsigned Abbrev) { - Record.push_back(N->isDistinct()); - Record.push_back(N->getCount()); + const uint64_t Version = 1 << 1; + Record.push_back((uint64_t)N->isDistinct() | Version); + Record.push_back(VE.getMetadataOrNullID(N->getRawCountNode())); Record.push_back(rotateSign(N->getLowerBound())); Stream.EmitRecord(bitc::METADATA_SUBRANGE, Record, Abbrev); diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 11c28ba6d9a..bee4d119300 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -1325,7 +1325,9 @@ TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) { const DISubrange *Subrange = cast<DISubrange>(Element); assert(Subrange->getLowerBound() == 0 && "codeview doesn't support subranges with lower bounds"); - int64_t Count = Subrange->getCount(); + int64_t Count = -1; + if (auto *CI = Subrange->getCount().dyn_cast<ConstantInt*>()) + Count = CI->getSExtValue(); // Forward declarations of arrays without a size and VLAs use a count of -1. // Emit a count of zero in these cases to match what MSVC does for arrays diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 61868a3bc06..907ede0a633 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1328,7 +1328,9 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR, // DW_AT_lower_bound and DW_AT_count attributes. int64_t LowerBound = SR->getLowerBound(); int64_t DefaultLowerBound = getDefaultLowerBound(); - int64_t Count = SR->getCount(); + int64_t Count = -1; + if (auto *CI = SR->getCount().dyn_cast<ConstantInt*>()) + Count = CI->getSExtValue(); if (DefaultLowerBound == -1 || LowerBound != DefaultLowerBound) addUInt(DW_Subrange, dwarf::DW_AT_lower_bound, None, LowerBound); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 7c647605894..638b0244148 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1621,10 +1621,15 @@ static void writeDILocation(raw_ostream &Out, const DILocation *DL, } static void writeDISubrange(raw_ostream &Out, const DISubrange *N, - TypePrinting *, SlotTracker *, const Module *) { + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { Out << "!DISubrange("; - MDFieldPrinter Printer(Out); - Printer.printInt("count", N->getCount(), /* ShouldSkipZero */ false); + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + if (auto *CE = N->getCount().dyn_cast<ConstantInt*>()) + Printer.printInt("count", CE->getSExtValue(), /* ShouldSkipZero */ false); + else + Printer.printMetadata("count", N->getCount().dyn_cast<DIVariable*>(), + /*ShouldSkipNull */ false); Printer.printInt("lowerBound", N->getLowerBound()); Out << ")"; } diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index f8ae23d4395..5ef3cdd88fd 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -582,6 +582,10 @@ DISubrange *DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Count) { return DISubrange::get(VMContext, Count, Lo); } +DISubrange *DIBuilder::getOrCreateSubrange(int64_t Lo, Metadata *CountNode) { + return DISubrange::get(VMContext, CountNode, Lo); +} + static void checkGlobalVariableScope(DIScope *Context) { #ifndef NDEBUG if (auto *CT = diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index 75ddd47b259..b6eda6a2921 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -249,8 +249,17 @@ void GenericDINode::recalculateHash() { DISubrange *DISubrange::getImpl(LLVMContext &Context, int64_t Count, int64_t Lo, StorageType Storage, bool ShouldCreate) { - DEFINE_GETIMPL_LOOKUP(DISubrange, (Count, Lo)); - DEFINE_GETIMPL_STORE_NO_OPS(DISubrange, (Count, Lo)); + auto *CountNode = ConstantAsMetadata::get( + ConstantInt::getSigned(Type::getInt64Ty(Context), Count)); + return getImpl(Context, CountNode, Lo, Storage, ShouldCreate); +} + +DISubrange *DISubrange::getImpl(LLVMContext &Context, Metadata *CountNode, + int64_t Lo, StorageType Storage, + bool ShouldCreate) { + DEFINE_GETIMPL_LOOKUP(DISubrange, (CountNode, Lo)); + Metadata *Ops[] = { CountNode }; + DEFINE_GETIMPL_STORE(DISubrange, (CountNode, Lo), Ops); } DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, int64_t Value, diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index f41acfa8ea9..e981a806602 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -321,19 +321,34 @@ template <> struct MDNodeKeyImpl<GenericDINode> : MDNodeOpsKey { }; template <> struct MDNodeKeyImpl<DISubrange> { - int64_t Count; + Metadata *CountNode; int64_t LowerBound; - MDNodeKeyImpl(int64_t Count, int64_t LowerBound) - : Count(Count), LowerBound(LowerBound) {} + MDNodeKeyImpl(Metadata *CountNode, int64_t LowerBound) + : CountNode(CountNode), LowerBound(LowerBound) {} MDNodeKeyImpl(const DISubrange *N) - : Count(N->getCount()), LowerBound(N->getLowerBound()) {} + : CountNode(N->getRawCountNode()), + LowerBound(N->getLowerBound()) {} bool isKeyOf(const DISubrange *RHS) const { - return Count == RHS->getCount() && LowerBound == RHS->getLowerBound(); + if (LowerBound != RHS->getLowerBound()) + return false; + + if (auto *RHSCount = RHS->getCount().dyn_cast<ConstantInt*>()) + if (auto *MD = dyn_cast<ConstantAsMetadata>(CountNode)) + if (RHSCount->getSExtValue() == + cast<ConstantInt>(MD->getValue())->getSExtValue()) + return true; + + return CountNode == RHS->getRawCountNode(); } - unsigned getHashValue() const { return hash_combine(Count, LowerBound); } + unsigned getHashValue() const { + if (auto *MD = dyn_cast<ConstantAsMetadata>(CountNode)) + return hash_combine(cast<ConstantInt>(MD->getValue())->getSExtValue(), + LowerBound); + return hash_combine(CountNode, LowerBound); + } }; template <> struct MDNodeKeyImpl<DIEnumerator> { diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 4dd5aebfc59..92389b60545 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -868,7 +868,12 @@ void Verifier::visitDIScope(const DIScope &N) { void Verifier::visitDISubrange(const DISubrange &N) { AssertDI(N.getTag() == dwarf::DW_TAG_subrange_type, "invalid tag", &N); - AssertDI(N.getCount() >= -1, "invalid subrange count", &N); + auto Count = N.getCount(); + AssertDI(Count, "Count must either be a signed constant or a DIVariable", + &N); + AssertDI(!Count.is<ConstantInt*>() || + Count.get<ConstantInt*>()->getSExtValue() >= -1, + "invalid subrange count", &N); } void Verifier::visitDIEnumerator(const DIEnumerator &N) { |

