summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/AsmParser/LLParser.cpp89
-rw-r--r--llvm/lib/Bitcode/Reader/MetadataLoader.cpp25
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp5
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp4
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp4
-rw-r--r--llvm/lib/IR/AsmWriter.cpp11
-rw-r--r--llvm/lib/IR/DIBuilder.cpp4
-rw-r--r--llvm/lib/IR/DebugInfoMetadata.cpp13
-rw-r--r--llvm/lib/IR/LLVMContextImpl.h27
-rw-r--r--llvm/lib/IR/Verifier.cpp7
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) {
OpenPOWER on IntegriCloud