diff options
Diffstat (limited to 'llvm/lib/Bitcode/Reader')
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 95 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.h | 25 |
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]; |