summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Bitcode/Reader
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Bitcode/Reader')
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp95
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.h25
2 files changed, 73 insertions, 47 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 72f823c2e3e..cc618069361 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -438,43 +438,58 @@ void BitcodeReaderValueList::ResolveConstantForwardRefs() {
}
}
-void BitcodeReaderMDValueList::AssignValue(Value *V, unsigned Idx) {
+void BitcodeReaderMDValueList::AssignValue(Metadata *MD, unsigned Idx) {
if (Idx == size()) {
- push_back(V);
+ push_back(MD);
return;
}
if (Idx >= size())
resize(Idx+1);
- WeakVH &OldV = MDValuePtrs[Idx];
- if (!OldV) {
- OldV = V;
+ TrackingMDRef &OldMD = MDValuePtrs[Idx];
+ if (!OldMD) {
+ OldMD.reset(MD);
return;
}
// If there was a forward reference to this value, replace it.
- MDNode *PrevVal = cast<MDNode>(OldV);
- OldV->replaceAllUsesWith(V);
- MDNode::deleteTemporary(PrevVal);
- // Deleting PrevVal sets Idx value in MDValuePtrs to null. Set new
- // value for Idx.
- MDValuePtrs[Idx] = V;
+ MDNodeFwdDecl *PrevMD = cast<MDNodeFwdDecl>(OldMD.get());
+ PrevMD->replaceAllUsesWith(MD);
+ MDNode::deleteTemporary(PrevMD);
+ --NumFwdRefs;
}
-Value *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) {
+Metadata *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) {
if (Idx >= size())
resize(Idx + 1);
- if (Value *V = MDValuePtrs[Idx]) {
- assert(V->getType()->isMetadataTy() && "Type mismatch in value table!");
- return V;
- }
+ if (Metadata *MD = MDValuePtrs[Idx])
+ return MD;
// Create and return a placeholder, which will later be RAUW'd.
- Value *V = MDNode::getTemporary(Context, None);
- MDValuePtrs[Idx] = V;
- return V;
+ AnyFwdRefs = true;
+ ++NumFwdRefs;
+ Metadata *MD = MDNode::getTemporary(Context, None);
+ MDValuePtrs[Idx].reset(MD);
+ return MD;
+}
+
+void BitcodeReaderMDValueList::tryToResolveCycles() {
+ if (!AnyFwdRefs)
+ // Nothing to do.
+ return;
+
+ if (NumFwdRefs)
+ // Still forward references... can't resolve cycles.
+ return;
+
+ // Resolve any cycles.
+ for (auto &MD : MDValuePtrs) {
+ assert(!(MD && isa<MDNodeFwdDecl>(MD)) && "Unexpected forward reference");
+ if (auto *G = dyn_cast_or_null<GenericMDNode>(MD))
+ G->resolveCycles();
+ }
}
Type *BitcodeReader::getTypeByID(unsigned ID) {
@@ -1066,6 +1081,7 @@ std::error_code BitcodeReader::ParseMetadata() {
case BitstreamEntry::Error:
return Error(BitcodeError::MalformedBlock);
case BitstreamEntry::EndBlock:
+ MDValueList.tryToResolveCycles();
return std::error_code();
case BitstreamEntry::Record:
// The interesting case.
@@ -1100,13 +1116,13 @@ std::error_code BitcodeReader::ParseMetadata() {
break;
}
case bitc::METADATA_FN_NODE: {
- // This is a function-local node.
+ // This is a LocalAsMetadata record, the only type of function-local
+ // metadata.
if (Record.size() % 2 == 1)
return Error(BitcodeError::InvalidRecord);
- // If this isn't a single-operand node that directly references
- // non-metadata, we're dropping it. This used to be legal, but there's
- // no upgrade path.
+ // If this isn't a LocalAsMetadata record, we're dropping it. This used
+ // to be legal, but there's no upgrade path.
auto dropRecord = [&] {
MDValueList.AssignValue(MDNode::get(Context, None), NextMDValueNo++);
};
@@ -1121,10 +1137,9 @@ std::error_code BitcodeReader::ParseMetadata() {
break;
}
- Value *Elts[] = {ValueList.getValueFwdRef(Record[1], Ty)};
- Value *V = MDNode::getWhenValsUnresolved(Context, Elts,
- /*IsFunctionLocal*/ true);
- MDValueList.AssignValue(V, NextMDValueNo++);
+ MDValueList.AssignValue(
+ LocalAsMetadata::get(ValueList.getValueFwdRef(Record[1], Ty)),
+ NextMDValueNo++);
break;
}
case bitc::METADATA_NODE: {
@@ -1132,28 +1147,30 @@ std::error_code BitcodeReader::ParseMetadata() {
return Error(BitcodeError::InvalidRecord);
unsigned Size = Record.size();
- SmallVector<Value*, 8> Elts;
+ SmallVector<Metadata *, 8> Elts;
for (unsigned i = 0; i != Size; i += 2) {
Type *Ty = getTypeByID(Record[i]);
if (!Ty)
return Error(BitcodeError::InvalidRecord);
if (Ty->isMetadataTy())
Elts.push_back(MDValueList.getValueFwdRef(Record[i+1]));
- else if (!Ty->isVoidTy())
- Elts.push_back(ValueList.getValueFwdRef(Record[i+1], Ty));
- else
+ else if (!Ty->isVoidTy()) {
+ auto *MD =
+ ValueAsMetadata::get(ValueList.getValueFwdRef(Record[i + 1], Ty));
+ assert(isa<ConstantAsMetadata>(MD) &&
+ "Expected non-function-local metadata");
+ Elts.push_back(MD);
+ } else
Elts.push_back(nullptr);
}
- Value *V = MDNode::getWhenValsUnresolved(Context, Elts,
- /*IsFunctionLocal*/ false);
- MDValueList.AssignValue(V, NextMDValueNo++);
+ MDValueList.AssignValue(MDNode::get(Context, Elts), NextMDValueNo++);
break;
}
case bitc::METADATA_STRING: {
std::string String(Record.begin(), Record.end());
llvm::UpgradeMDStringConstant(String);
- Value *V = MDString::get(Context, String);
- MDValueList.AssignValue(V, NextMDValueNo++);
+ Metadata *MD = MDString::get(Context, String);
+ MDValueList.AssignValue(MD, NextMDValueNo++);
break;
}
case bitc::METADATA_KIND: {
@@ -2359,12 +2376,12 @@ std::error_code BitcodeReader::ParseMetadataAttachment() {
MDKindMap.find(Kind);
if (I == MDKindMap.end())
return Error(BitcodeError::InvalidID);
- MDNode *Node = cast<MDNode>(MDValueList.getValueFwdRef(Record[i+1]));
- if (Node->isFunctionLocal())
+ Metadata *Node = MDValueList.getValueFwdRef(Record[i + 1]);
+ if (isa<LocalAsMetadata>(Node))
// Drop the attachment. This used to be legal, but there's no
// upgrade path.
break;
- Inst->setMetadata(I->second, Node);
+ Inst->setMetadata(I->second, cast<MDNode>(Node));
if (I->second == LLVMContext::MD_tbaa)
InstsWithTBAATag.push_back(Inst);
}
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.h b/llvm/lib/Bitcode/Reader/BitcodeReader.h
index 10f870b59b8..639ddb90350 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.h
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.h
@@ -19,7 +19,9 @@
#include "llvm/Bitcode/LLVMBitCodes.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/GVMaterializer.h"
+#include "llvm/IR/Metadata.h"
#include "llvm/IR/OperandTraits.h"
+#include "llvm/IR/TrackingMDRef.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/ValueHandle.h"
#include <deque>
@@ -95,22 +97,25 @@ public:
//===----------------------------------------------------------------------===//
class BitcodeReaderMDValueList {
- std::vector<WeakVH> MDValuePtrs;
+ unsigned NumFwdRefs;
+ bool AnyFwdRefs;
+ std::vector<TrackingMDRef> MDValuePtrs;
LLVMContext &Context;
public:
- BitcodeReaderMDValueList(LLVMContext& C) : Context(C) {}
+ BitcodeReaderMDValueList(LLVMContext &C)
+ : NumFwdRefs(0), AnyFwdRefs(false), Context(C) {}
// vector compatibility methods
unsigned size() const { return MDValuePtrs.size(); }
void resize(unsigned N) { MDValuePtrs.resize(N); }
- void push_back(Value *V) { MDValuePtrs.push_back(V); }
+ void push_back(Metadata *MD) { MDValuePtrs.emplace_back(MD); }
void clear() { MDValuePtrs.clear(); }
- Value *back() const { return MDValuePtrs.back(); }
+ Metadata *back() const { return MDValuePtrs.back(); }
void pop_back() { MDValuePtrs.pop_back(); }
bool empty() const { return MDValuePtrs.empty(); }
- Value *operator[](unsigned i) const {
+ Metadata *operator[](unsigned i) const {
assert(i < MDValuePtrs.size());
return MDValuePtrs[i];
}
@@ -120,8 +125,9 @@ public:
MDValuePtrs.resize(N);
}
- Value *getValueFwdRef(unsigned Idx);
- void AssignValue(Value *V, unsigned Idx);
+ Metadata *getValueFwdRef(unsigned Idx);
+ void AssignValue(Metadata *MD, unsigned Idx);
+ void tryToResolveCycles();
};
class BitcodeReader : public GVMaterializer {
@@ -248,9 +254,12 @@ private:
Type *getTypeByID(unsigned ID);
Value *getFnValueByID(unsigned ID, Type *Ty) {
if (Ty && Ty->isMetadataTy())
- return MDValueList.getValueFwdRef(ID);
+ return MetadataAsValue::get(Ty->getContext(), getFnMetadataByID(ID));
return ValueList.getValueFwdRef(ID, Ty);
}
+ Metadata *getFnMetadataByID(unsigned ID) {
+ return MDValueList.getValueFwdRef(ID);
+ }
BasicBlock *getBasicBlock(unsigned ID) const {
if (ID >= FunctionBBs.size()) return nullptr; // Invalid ID
return FunctionBBs[ID];
OpenPOWER on IntegriCloud