[llvm] r289461 - Refactor BitcodeReader: move Metadata and ValueId handling in their own class/file
Robinson, Paul via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 12 14:14:23 PST 2016
Hi Mehdi, it looks like this made the Windows bots sad.
Can you take a look? Probably a missing 'using' or something.
Thanks,
--paulr
FAILED: C:\PROGRA~2\MICROS~3.0\VC\bin\amd64\cl.exe /nologo /TP -DGTEST_HAS_RTTI=0 -DUNICODE -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_HAS_EXCEPTIONS=0 -D_SCL_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS -D_UNICODE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Ilib\Bitcode\Reader -ID:\buildslave\clang-x64-ninja-win7\llvm\lib\Bitcode\Reader -Iinclude -ID:\buildslave\clang-x64-ninja-win7\llvm\include /DWIN32 /D_WINDOWS /W4 -wd4141 -wd4146 -wd4180 -wd4244 -wd4258 -wd4267 -wd4291 -wd4345 -wd4351 -wd4355 -wd4456 -wd4457 -wd4458 -wd4459 -wd4503 -wd4624 -wd4722 -wd4800 -wd4100 -wd4127 -wd4512 -wd4505 -wd4610 -wd4510 -wd4702 -wd4245 -wd4706 -wd4310 -wd4701 -wd4703 -wd4389 -wd4611 -wd4805 -wd4204 -wd4577 -wd4091 -wd4592 -wd4319 -wd4324 -w14062 -we4238 /Zc:inline /Zc:strictStrings /Oi /Zc:rvalueCast /MD /O2 /Ob2 -UNDEBUG /EHs-c- /GR- /showIncludes /Folib\Bitcode\Reader\CMakeFiles\LLVMBitReader.dir\MetadataLoader.cpp.obj /Fdlib\Bitcode\Reader\CMakeFiles\LLVMBitReader.dir\ /FS -c D:\buildslave\clang-x64-ninja-win7\llvm\lib\Bitcode\Reader\MetadataLoader.cpp
D:\buildslave\clang-x64-ninja-win7\llvm\lib\Bitcode\Reader\MetadataLoader.cpp(1284): error C2668: 'llvm::make_unique': ambiguous call to overloaded function
D:\buildslave\clang-x64-ninja-win7\llvm\include\llvm/ADT/STLExtras.h(680): note: could be 'std::unique_ptr<llvm::MetadataLoader::MetadataLoaderImpl,std::default_delete<_Ty>> llvm::make_unique<llvm::MetadataLoader::MetadataLoaderImpl,llvm::BitstreamCursor&,llvm::Module&,llvm::BitcodeReaderValueList&,std::function<llvm::Type *(unsigned int)>&>(llvm::BitstreamCursor &,llvm::Module &,llvm::BitcodeReaderValueList &,std::function<llvm::Type *(unsigned int)> &)'
with
[
_Ty=llvm::MetadataLoader::MetadataLoaderImpl
]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\memory(1628): note: or 'std::unique_ptr<llvm::MetadataLoader::MetadataLoaderImpl,std::default_delete<_Ty>> std::make_unique<llvm::MetadataLoader::MetadataLoaderImpl,llvm::BitstreamCursor&,llvm::Module&,llvm::BitcodeReaderValueList&,std::function<llvm::Type *(unsigned int)>&>(llvm::BitstreamCursor &,llvm::Module &,llvm::BitcodeReaderValueList &,std::function<llvm::Type *(unsigned int)> &)' [found using argument-dependent lookup]
with
[
_Ty=llvm::MetadataLoader::MetadataLoaderImpl
]
D:\buildslave\clang-x64-ninja-win7\llvm\lib\Bitcode\Reader\MetadataLoader.cpp(1284): note: while trying to match the argument list '(llvm::BitstreamCursor, llvm::Module, llvm::BitcodeReaderValueList, std::function<llvm::Type *(unsigned int)>)'
> -----Original Message-----
> From: llvm-commits [mailto:llvm-commits-bounces at lists.llvm.org] On Behalf
> Of Mehdi Amini via llvm-commits
> Sent: Monday, December 12, 2016 11:34 AM
> To: llvm-commits at lists.llvm.org
> Subject: [llvm] r289461 - Refactor BitcodeReader: move Metadata and
> ValueId handling in their own class/file
>
> Author: mehdi_amini
> Date: Mon Dec 12 13:34:26 2016
> New Revision: 289461
>
> URL: http://llvm.org/viewvc/llvm-project?rev=289461&view=rev
> Log:
> Refactor BitcodeReader: move Metadata and ValueId handling in their own
> class/file
>
> Summary:
> I'm planning on changing the way we load metadata to enable laziness.
> I'm getting lost in this gigantic files, and gigantic class that is the
> bitcode
> reader. This is a first toward splitting it in a few coarse components
> that
> are more easily understandable.
>
> Reviewers: pcc, tejohnson
>
> Subscribers: mgorny, llvm-commits, dexonsmith
>
> Differential Revision: https://reviews.llvm.org/D27646
>
> Added:
> llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp
> llvm/trunk/lib/Bitcode/Reader/MetadataLoader.h
> llvm/trunk/lib/Bitcode/Reader/ValueList.cpp
> llvm/trunk/lib/Bitcode/Reader/ValueList.h
> Modified:
> llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
> llvm/trunk/lib/Bitcode/Reader/CMakeLists.txt
>
> Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=289461&r1=2894
> 60&r2=289461&view=diff
> ==========================================================================
> ====
> --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
> +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Mon Dec 12 13:34:26
> 2016
> @@ -8,6 +8,9 @@
> //===--------------------------------------------------------------------
> --===//
>
> #include "llvm/Bitcode/BitcodeReader.h"
> +#include "MetadataLoader.h"
> +#include "ValueList.h"
> +
> #include "llvm/ADT/APFloat.h"
> #include "llvm/ADT/APInt.h"
> #include "llvm/ADT/ArrayRef.h"
> @@ -94,140 +97,6 @@ enum {
> SWITCH_INST_MAGIC = 0x4B5 // May 2012 => 1205 => Hex
> };
>
> -class BitcodeReaderValueList {
> - std::vector<WeakVH> ValuePtrs;
> -
> - /// As we resolve forward-referenced constants, we add information
> about them
> - /// to this vector. This allows us to resolve them in bulk instead of
> - /// resolving each reference at a time. See the code in
> - /// ResolveConstantForwardRefs for more information about this.
> - ///
> - /// The key of this vector is the placeholder constant, the value is
> the slot
> - /// number that holds the resolved value.
> - typedef std::vector<std::pair<Constant*, unsigned> >
> ResolveConstantsTy;
> - ResolveConstantsTy ResolveConstants;
> - LLVMContext &Context;
> -
> -public:
> - BitcodeReaderValueList(LLVMContext &C) : Context(C) {}
> - ~BitcodeReaderValueList() {
> - assert(ResolveConstants.empty() && "Constants not resolved?");
> - }
> -
> - // vector compatibility methods
> - unsigned size() const { return ValuePtrs.size(); }
> - void resize(unsigned N) { ValuePtrs.resize(N); }
> - void push_back(Value *V) { ValuePtrs.emplace_back(V); }
> -
> - void clear() {
> - assert(ResolveConstants.empty() && "Constants not resolved?");
> - ValuePtrs.clear();
> - }
> -
> - Value *operator[](unsigned i) const {
> - assert(i < ValuePtrs.size());
> - return ValuePtrs[i];
> - }
> -
> - Value *back() const { return ValuePtrs.back(); }
> - void pop_back() { ValuePtrs.pop_back(); }
> - bool empty() const { return ValuePtrs.empty(); }
> -
> - void shrinkTo(unsigned N) {
> - assert(N <= size() && "Invalid shrinkTo request!");
> - ValuePtrs.resize(N);
> - }
> -
> - Constant *getConstantFwdRef(unsigned Idx, Type *Ty);
> - Value *getValueFwdRef(unsigned Idx, Type *Ty);
> -
> - void assignValue(Value *V, unsigned Idx);
> -
> - /// Once all constants are read, this method bulk resolves any forward
> - /// references.
> - void resolveConstantForwardRefs();
> -};
> -
> -class BitcodeReaderMetadataList {
> - unsigned NumFwdRefs;
> - bool AnyFwdRefs;
> - unsigned MinFwdRef;
> - unsigned MaxFwdRef;
> -
> - /// Array of metadata references.
> - ///
> - /// Don't use std::vector here. Some versions of libc++ copy (instead
> of
> - /// move) on resize, and TrackingMDRef is very expensive to copy.
> - SmallVector<TrackingMDRef, 1> MetadataPtrs;
> -
> - /// Structures for resolving old type refs.
> - struct {
> - SmallDenseMap<MDString *, TempMDTuple, 1> Unknown;
> - SmallDenseMap<MDString *, DICompositeType *, 1> Final;
> - SmallDenseMap<MDString *, DICompositeType *, 1> FwdDecls;
> - SmallVector<std::pair<TrackingMDRef, TempMDTuple>, 1> Arrays;
> - } OldTypeRefs;
> -
> - LLVMContext &Context;
> -
> -public:
> - BitcodeReaderMetadataList(LLVMContext &C)
> - : NumFwdRefs(0), AnyFwdRefs(false), Context(C) {}
> -
> - // vector compatibility methods
> - unsigned size() const { return MetadataPtrs.size(); }
> - void resize(unsigned N) { MetadataPtrs.resize(N); }
> - void push_back(Metadata *MD) { MetadataPtrs.emplace_back(MD); }
> - void clear() { MetadataPtrs.clear(); }
> - Metadata *back() const { return MetadataPtrs.back(); }
> - void pop_back() { MetadataPtrs.pop_back(); }
> - bool empty() const { return MetadataPtrs.empty(); }
> -
> - Metadata *operator[](unsigned i) const {
> - assert(i < MetadataPtrs.size());
> - return MetadataPtrs[i];
> - }
> -
> - Metadata *lookup(unsigned I) const {
> - if (I < MetadataPtrs.size())
> - return MetadataPtrs[I];
> - return nullptr;
> - }
> -
> - void shrinkTo(unsigned N) {
> - assert(N <= size() && "Invalid shrinkTo request!");
> - assert(!AnyFwdRefs && "Unexpected forward refs");
> - MetadataPtrs.resize(N);
> - }
> -
> - /// Return the given metadata, creating a replaceable forward reference
> if
> - /// necessary.
> - Metadata *getMetadataFwdRef(unsigned Idx);
> -
> - /// Return the the given metadata only if it is fully resolved.
> - ///
> - /// Gives the same result as \a lookup(), unless \a
> MDNode::isResolved()
> - /// would give \c false.
> - Metadata *getMetadataIfResolved(unsigned Idx);
> -
> - MDNode *getMDNodeFwdRefOrNull(unsigned Idx);
> - void assignValue(Metadata *MD, unsigned Idx);
> - void tryToResolveCycles();
> - bool hasFwdRefs() const { return AnyFwdRefs; }
> -
> - /// Upgrade a type that had an MDString reference.
> - void addTypeRef(MDString &UUID, DICompositeType &CT);
> -
> - /// Upgrade a type that had an MDString reference.
> - Metadata *upgradeTypeRef(Metadata *MaybeUUID);
> -
> - /// Upgrade a type ref array that may have MDString references.
> - Metadata *upgradeTypeRefArray(Metadata *MaybeTuple);
> -
> -private:
> - Metadata *resolveTypeRefArray(Metadata *MaybeTuple);
> -};
> -
> Error error(const Twine &Message) {
> return make_error<StringError>(
> Message, make_error_code(BitcodeError::CorruptedBitcode));
> @@ -526,7 +395,7 @@ class BitcodeReader : public BitcodeRead
>
> std::vector<Type*> TypeList;
> BitcodeReaderValueList ValueList;
> - BitcodeReaderMetadataList MetadataList;
> + Optional<MetadataLoader> MDLoader;
> std::vector<Comdat *> ComdatList;
> SmallVector<Instruction *, 64> InstructionList;
>
> @@ -536,8 +405,6 @@ class BitcodeReader : public BitcodeRead
> std::vector<std::pair<Function*, unsigned> > FunctionPrologues;
> std::vector<std::pair<Function*, unsigned> > FunctionPersonalityFns;
>
> - bool HasSeenOldLoopTags = false;
> -
> /// The set of attributes by index. Index zero in the file is for
> null, and
> /// is thus not represented here. As such all indices are off by one.
> std::vector<AttributeSet> MAttributes;
> @@ -560,9 +427,6 @@ class BitcodeReader : public BitcodeRead
> // Intrinsics which were remangled because of types rename
> UpdatedIntrinsicMap RemangledIntrinsics;
>
> - // Map the bitcode's custom MDKind ID to the Module's MDKind ID.
> - DenseMap<unsigned, unsigned> MDKindMap;
> -
> // Several operations happen after the module header has been read, but
> // before function bodies are processed. This keeps track of whether
> // we've done this yet.
> @@ -597,10 +461,6 @@ class BitcodeReader : public BitcodeRead
>
> bool StripDebugInfo = false;
>
> - /// Functions that need to be matched with subprograms when upgrading
> old
> - /// metadata.
> - SmallDenseMap<Function *, DISubprogram *, 16> FunctionsWithSPs;
> -
> std::vector<std::string> BundleTags;
>
> public:
> @@ -638,7 +498,7 @@ private:
> }
>
> Metadata *getFnMetadataByID(unsigned ID) {
> - return MetadataList.getMetadataFwdRef(ID);
> + return MDLoader->getMetadataFwdRef(ID);
> }
>
> BasicBlock *getBasicBlock(unsigned ID) const {
> @@ -742,14 +602,6 @@ private:
> Error parseFunctionBody(Function *F);
> Error globalCleanup();
> Error resolveGlobalAndIndirectSymbolInits();
> - Error parseMetadata(bool ModuleLevel = false);
> - Error parseMetadataStrings(ArrayRef<uint64_t> Record, StringRef Blob,
> - unsigned &NextMetadataNo);
> - Error parseMetadataKinds();
> - Error parseMetadataKindRecord(SmallVectorImpl<uint64_t> &Record);
> - Error parseGlobalObjectAttachment(GlobalObject &GO,
> - ArrayRef<uint64_t> Record);
> - Error parseMetadataAttachment(Function &F);
> Error parseUseLists();
> Error findFunctionInStream(
> Function *F,
> @@ -831,7 +683,7 @@ BitcodeReader::BitcodeReader(BitstreamCu
> StringRef ProducerIdentification,
> LLVMContext &Context)
> : BitcodeReaderBase(std::move(Stream)), Context(Context),
> - ValueList(Context), MetadataList(Context) {
> + ValueList(Context) {
> this->ProducerIdentification = ProducerIdentification;
> }
>
> @@ -1114,360 +966,6 @@ static void upgradeDLLImportExportLinkag
> }
> }
>
> -namespace llvm {
> -namespace {
> -
> -/// \brief A class for maintaining the slot number definition
> -/// as a placeholder for the actual definition for forward constants
> defs.
> -class ConstantPlaceHolder : public ConstantExpr {
> - void operator=(const ConstantPlaceHolder &) = delete;
> -
> -public:
> - // allocate space for exactly one operand
> - void *operator new(size_t s) { return User::operator new(s, 1); }
> - explicit ConstantPlaceHolder(Type *Ty, LLVMContext &Context)
> - : ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) {
> - Op<0>() = UndefValue::get(Type::getInt32Ty(Context));
> - }
> -
> - /// \brief Methods to support type inquiry through isa, cast, and
> dyn_cast.
> - static bool classof(const Value *V) {
> - return isa<ConstantExpr>(V) &&
> - cast<ConstantExpr>(V)->getOpcode() == Instruction::UserOp1;
> - }
> -
> - /// Provide fast operand accessors
> - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
> -};
> -
> -} // end anonymous namespace
> -
> -// FIXME: can we inherit this from ConstantExpr?
> -template <>
> -struct OperandTraits<ConstantPlaceHolder> :
> - public FixedNumOperandTraits<ConstantPlaceHolder, 1> {
> -};
> -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantPlaceHolder, Value)
> -
> -} // end namespace llvm
> -
> -void BitcodeReaderValueList::assignValue(Value *V, unsigned Idx) {
> - if (Idx == size()) {
> - push_back(V);
> - return;
> - }
> -
> - if (Idx >= size())
> - resize(Idx+1);
> -
> - WeakVH &OldV = ValuePtrs[Idx];
> - if (!OldV) {
> - OldV = V;
> - return;
> - }
> -
> - // Handle constants and non-constants (e.g. instrs) differently for
> - // efficiency.
> - if (Constant *PHC = dyn_cast<Constant>(&*OldV)) {
> - ResolveConstants.push_back(std::make_pair(PHC, Idx));
> - OldV = V;
> - } else {
> - // If there was a forward reference to this value, replace it.
> - Value *PrevVal = OldV;
> - OldV->replaceAllUsesWith(V);
> - delete PrevVal;
> - }
> -}
> -
> -Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx,
> - Type *Ty) {
> - if (Idx >= size())
> - resize(Idx + 1);
> -
> - if (Value *V = ValuePtrs[Idx]) {
> - if (Ty != V->getType())
> - report_fatal_error("Type mismatch in constant table!");
> - return cast<Constant>(V);
> - }
> -
> - // Create and return a placeholder, which will later be RAUW'd.
> - Constant *C = new ConstantPlaceHolder(Ty, Context);
> - ValuePtrs[Idx] = C;
> - return C;
> -}
> -
> -Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) {
> - // Bail out for a clearly invalid value. This would make us call
> resize(0)
> - if (Idx == std::numeric_limits<unsigned>::max())
> - return nullptr;
> -
> - if (Idx >= size())
> - resize(Idx + 1);
> -
> - if (Value *V = ValuePtrs[Idx]) {
> - // If the types don't match, it's invalid.
> - if (Ty && Ty != V->getType())
> - return nullptr;
> - return V;
> - }
> -
> - // No type specified, must be invalid reference.
> - if (!Ty) return nullptr;
> -
> - // Create and return a placeholder, which will later be RAUW'd.
> - Value *V = new Argument(Ty);
> - ValuePtrs[Idx] = V;
> - return V;
> -}
> -
> -/// Once all constants are read, this method bulk resolves any forward
> -/// references. The idea behind this is that we sometimes get constants
> (such
> -/// as large arrays) which reference *many* forward ref constants.
> Replacing
> -/// each of these causes a lot of thrashing when building/reuniquing the
> -/// constant. Instead of doing this, we look at all the uses and rewrite
> all
> -/// the place holders at once for any constant that uses a placeholder.
> -void BitcodeReaderValueList::resolveConstantForwardRefs() {
> - // Sort the values by-pointer so that they are efficient to look up
> with a
> - // binary search.
> - std::sort(ResolveConstants.begin(), ResolveConstants.end());
> -
> - SmallVector<Constant*, 64> NewOps;
> -
> - while (!ResolveConstants.empty()) {
> - Value *RealVal = operator[](ResolveConstants.back().second);
> - Constant *Placeholder = ResolveConstants.back().first;
> - ResolveConstants.pop_back();
> -
> - // Loop over all users of the placeholder, updating them to reference
> the
> - // new value. If they reference more than one placeholder, update
> them all
> - // at once.
> - while (!Placeholder->use_empty()) {
> - auto UI = Placeholder->user_begin();
> - User *U = *UI;
> -
> - // If the using object isn't uniqued, just update the operands.
> This
> - // handles instructions and initializers for global variables.
> - if (!isa<Constant>(U) || isa<GlobalValue>(U)) {
> - UI.getUse().set(RealVal);
> - continue;
> - }
> -
> - // Otherwise, we have a constant that uses the placeholder.
> Replace that
> - // constant with a new constant that has *all* placeholder uses
> updated.
> - Constant *UserC = cast<Constant>(U);
> - for (User::op_iterator I = UserC->op_begin(), E = UserC->op_end();
> - I != E; ++I) {
> - Value *NewOp;
> - if (!isa<ConstantPlaceHolder>(*I)) {
> - // Not a placeholder reference.
> - NewOp = *I;
> - } else if (*I == Placeholder) {
> - // Common case is that it just references this one placeholder.
> - NewOp = RealVal;
> - } else {
> - // Otherwise, look up the placeholder in ResolveConstants.
> - ResolveConstantsTy::iterator It =
> - std::lower_bound(ResolveConstants.begin(),
> ResolveConstants.end(),
> - std::pair<Constant*,
> unsigned>(cast<Constant>(*I),
> - 0));
> - assert(It != ResolveConstants.end() && It->first == *I);
> - NewOp = operator[](It->second);
> - }
> -
> - NewOps.push_back(cast<Constant>(NewOp));
> - }
> -
> - // Make the new constant.
> - Constant *NewC;
> - if (ConstantArray *UserCA = dyn_cast<ConstantArray>(UserC)) {
> - NewC = ConstantArray::get(UserCA->getType(), NewOps);
> - } else if (ConstantStruct *UserCS =
> dyn_cast<ConstantStruct>(UserC)) {
> - NewC = ConstantStruct::get(UserCS->getType(), NewOps);
> - } else if (isa<ConstantVector>(UserC)) {
> - NewC = ConstantVector::get(NewOps);
> - } else {
> - assert(isa<ConstantExpr>(UserC) && "Must be a ConstantExpr.");
> - NewC = cast<ConstantExpr>(UserC)->getWithOperands(NewOps);
> - }
> -
> - UserC->replaceAllUsesWith(NewC);
> - UserC->destroyConstant();
> - NewOps.clear();
> - }
> -
> - // Update all ValueHandles, they should be the only users at this
> point.
> - Placeholder->replaceAllUsesWith(RealVal);
> - delete Placeholder;
> - }
> -}
> -
> -void BitcodeReaderMetadataList::assignValue(Metadata *MD, unsigned Idx) {
> - if (Idx == size()) {
> - push_back(MD);
> - return;
> - }
> -
> - if (Idx >= size())
> - resize(Idx+1);
> -
> - TrackingMDRef &OldMD = MetadataPtrs[Idx];
> - if (!OldMD) {
> - OldMD.reset(MD);
> - return;
> - }
> -
> - // If there was a forward reference to this value, replace it.
> - TempMDTuple PrevMD(cast<MDTuple>(OldMD.get()));
> - PrevMD->replaceAllUsesWith(MD);
> - --NumFwdRefs;
> -}
> -
> -Metadata *BitcodeReaderMetadataList::getMetadataFwdRef(unsigned Idx) {
> - if (Idx >= size())
> - resize(Idx + 1);
> -
> - if (Metadata *MD = MetadataPtrs[Idx])
> - return MD;
> -
> - // Track forward refs to be resolved later.
> - if (AnyFwdRefs) {
> - MinFwdRef = std::min(MinFwdRef, Idx);
> - MaxFwdRef = std::max(MaxFwdRef, Idx);
> - } else {
> - AnyFwdRefs = true;
> - MinFwdRef = MaxFwdRef = Idx;
> - }
> - ++NumFwdRefs;
> -
> - // Create and return a placeholder, which will later be RAUW'd.
> - Metadata *MD = MDNode::getTemporary(Context, None).release();
> - MetadataPtrs[Idx].reset(MD);
> - return MD;
> -}
> -
> -Metadata *BitcodeReaderMetadataList::getMetadataIfResolved(unsigned Idx)
> {
> - Metadata *MD = lookup(Idx);
> - if (auto *N = dyn_cast_or_null<MDNode>(MD))
> - if (!N->isResolved())
> - return nullptr;
> - return MD;
> -}
> -
> -MDNode *BitcodeReaderMetadataList::getMDNodeFwdRefOrNull(unsigned Idx) {
> - return dyn_cast_or_null<MDNode>(getMetadataFwdRef(Idx));
> -}
> -
> -void BitcodeReaderMetadataList::tryToResolveCycles() {
> - if (NumFwdRefs)
> - // Still forward references... can't resolve cycles.
> - return;
> -
> - bool DidReplaceTypeRefs = false;
> -
> - // Give up on finding a full definition for any forward decls that
> remain.
> - for (const auto &Ref : OldTypeRefs.FwdDecls)
> - OldTypeRefs.Final.insert(Ref);
> - OldTypeRefs.FwdDecls.clear();
> -
> - // Upgrade from old type ref arrays. In strange cases, this could add
> to
> - // OldTypeRefs.Unknown.
> - for (const auto &Array : OldTypeRefs.Arrays) {
> - DidReplaceTypeRefs = true;
> - Array.second-
> >replaceAllUsesWith(resolveTypeRefArray(Array.first.get()));
> - }
> - OldTypeRefs.Arrays.clear();
> -
> - // Replace old string-based type refs with the resolved node, if
> possible.
> - // If we haven't seen the node, leave it to the verifier to complain
> about
> - // the invalid string reference.
> - for (const auto &Ref : OldTypeRefs.Unknown) {
> - DidReplaceTypeRefs = true;
> - if (DICompositeType *CT = OldTypeRefs.Final.lookup(Ref.first))
> - Ref.second->replaceAllUsesWith(CT);
> - else
> - Ref.second->replaceAllUsesWith(Ref.first);
> - }
> - OldTypeRefs.Unknown.clear();
> -
> - // Make sure all the upgraded types are resolved.
> - if (DidReplaceTypeRefs) {
> - AnyFwdRefs = true;
> - MinFwdRef = 0;
> - MaxFwdRef = MetadataPtrs.size() - 1;
> - }
> -
> - if (!AnyFwdRefs)
> - // Nothing to do.
> - return;
> -
> - // Resolve any cycles.
> - for (unsigned I = MinFwdRef, E = MaxFwdRef + 1; I != E; ++I) {
> - auto &MD = MetadataPtrs[I];
> - auto *N = dyn_cast_or_null<MDNode>(MD);
> - if (!N)
> - continue;
> -
> - assert(!N->isTemporary() && "Unexpected forward reference");
> - N->resolveCycles();
> - }
> -
> - // Make sure we return early again until there's another forward ref.
> - AnyFwdRefs = false;
> -}
> -
> -void BitcodeReaderMetadataList::addTypeRef(MDString &UUID,
> - DICompositeType &CT) {
> - assert(CT.getRawIdentifier() == &UUID && "Mismatched UUID");
> - if (CT.isForwardDecl())
> - OldTypeRefs.FwdDecls.insert(std::make_pair(&UUID, &CT));
> - else
> - OldTypeRefs.Final.insert(std::make_pair(&UUID, &CT));
> -}
> -
> -Metadata *BitcodeReaderMetadataList::upgradeTypeRef(Metadata *MaybeUUID)
> {
> - auto *UUID = dyn_cast_or_null<MDString>(MaybeUUID);
> - if (LLVM_LIKELY(!UUID))
> - return MaybeUUID;
> -
> - if (auto *CT = OldTypeRefs.Final.lookup(UUID))
> - return CT;
> -
> - auto &Ref = OldTypeRefs.Unknown[UUID];
> - if (!Ref)
> - Ref = MDNode::getTemporary(Context, None);
> - return Ref.get();
> -}
> -
> -Metadata *BitcodeReaderMetadataList::upgradeTypeRefArray(Metadata
> *MaybeTuple) {
> - auto *Tuple = dyn_cast_or_null<MDTuple>(MaybeTuple);
> - if (!Tuple || Tuple->isDistinct())
> - return MaybeTuple;
> -
> - // Look through the array immediately if possible.
> - if (!Tuple->isTemporary())
> - return resolveTypeRefArray(Tuple);
> -
> - // Create and return a placeholder to use for now. Eventually
> - // resolveTypeRefArrays() will be resolve this forward reference.
> - OldTypeRefs.Arrays.emplace_back(
> - std::piecewise_construct, std::forward_as_tuple(Tuple),
> - std::forward_as_tuple(MDTuple::getTemporary(Context, None)));
> - return OldTypeRefs.Arrays.back().second.get();
> -}
> -
> -Metadata *BitcodeReaderMetadataList::resolveTypeRefArray(Metadata
> *MaybeTuple) {
> - auto *Tuple = dyn_cast_or_null<MDTuple>(MaybeTuple);
> - if (!Tuple || Tuple->isDistinct())
> - return MaybeTuple;
> -
> - // Look through the DITypeRefArray, upgrading each DITypeRef.
> - SmallVector<Metadata *, 32> Ops;
> - Ops.reserve(Tuple->getNumOperands());
> - for (Metadata *MD : Tuple->operands())
> - Ops.push_back(upgradeTypeRef(MD));
> -
> - return MDTuple::get(Context, Ops);
> -}
>
> Type *BitcodeReader::getTypeByID(unsigned ID) {
> // The type table size is always specified correctly.
> @@ -2321,798 +1819,6 @@ Error BitcodeReader::parseValueSymbolTab
> }
> }
>
> -/// Parse a single METADATA_KIND record, inserting result in MDKindMap.
> -Error BitcodeReader::parseMetadataKindRecord(
> - SmallVectorImpl<uint64_t> &Record) {
> - if (Record.size() < 2)
> - return error("Invalid record");
> -
> - unsigned Kind = Record[0];
> - SmallString<8> Name(Record.begin() + 1, Record.end());
> -
> - unsigned NewKind = TheModule->getMDKindID(Name.str());
> - if (!MDKindMap.insert(std::make_pair(Kind, NewKind)).second)
> - return error("Conflicting METADATA_KIND records");
> - return Error::success();
> -}
> -
> -static int64_t unrotateSign(uint64_t U) { return U & 1 ? ~(U >> 1) : U >>
> 1; }
> -
> -Error BitcodeReader::parseMetadataStrings(ArrayRef<uint64_t> Record,
> - StringRef Blob,
> - unsigned &NextMetadataNo) {
> - // All the MDStrings in the block are emitted together in a single
> - // record. The strings are concatenated and stored in a blob along
> with
> - // their sizes.
> - if (Record.size() != 2)
> - return error("Invalid record: metadata strings layout");
> -
> - unsigned NumStrings = Record[0];
> - unsigned StringsOffset = Record[1];
> - if (!NumStrings)
> - return error("Invalid record: metadata strings with no strings");
> - if (StringsOffset > Blob.size())
> - return error("Invalid record: metadata strings corrupt offset");
> -
> - StringRef Lengths = Blob.slice(0, StringsOffset);
> - SimpleBitstreamCursor R(Lengths);
> -
> - StringRef Strings = Blob.drop_front(StringsOffset);
> - do {
> - if (R.AtEndOfStream())
> - return error("Invalid record: metadata strings bad length");
> -
> - unsigned Size = R.ReadVBR(6);
> - if (Strings.size() < Size)
> - return error("Invalid record: metadata strings truncated chars");
> -
> - MetadataList.assignValue(MDString::get(Context, Strings.slice(0,
> Size)),
> - NextMetadataNo++);
> - Strings = Strings.drop_front(Size);
> - } while (--NumStrings);
> -
> - return Error::success();
> -}
> -
> -namespace {
> -
> -class PlaceholderQueue {
> - // Placeholders would thrash around when moved, so store in a
> std::deque
> - // instead of some sort of vector.
> - std::deque<DistinctMDOperandPlaceholder> PHs;
> -
> -public:
> - DistinctMDOperandPlaceholder &getPlaceholderOp(unsigned ID);
> - void flush(BitcodeReaderMetadataList &MetadataList);
> -};
> -
> -} // end anonymous namespace
> -
> -DistinctMDOperandPlaceholder &PlaceholderQueue::getPlaceholderOp(unsigned
> ID) {
> - PHs.emplace_back(ID);
> - return PHs.back();
> -}
> -
> -void PlaceholderQueue::flush(BitcodeReaderMetadataList &MetadataList) {
> - while (!PHs.empty()) {
> - PHs.front().replaceUseWith(
> - MetadataList.getMetadataFwdRef(PHs.front().getID()));
> - PHs.pop_front();
> - }
> -}
> -
> -/// Parse a METADATA_BLOCK. If ModuleLevel is true then we are parsing
> -/// module level metadata.
> -Error BitcodeReader::parseMetadata(bool ModuleLevel) {
> - assert((ModuleLevel || DeferredMetadataInfo.empty()) &&
> - "Must read all module-level metadata before function-level");
> -
> - unsigned NextMetadataNo = MetadataList.size();
> -
> - if (!ModuleLevel && MetadataList.hasFwdRefs())
> - return error("Invalid metadata: fwd refs into function blocks");
> -
> - if (Stream.EnterSubBlock(bitc::METADATA_BLOCK_ID))
> - return error("Invalid record");
> -
> - std::vector<std::pair<DICompileUnit *, Metadata *>> CUSubprograms;
> - SmallVector<uint64_t, 64> Record;
> -
> - PlaceholderQueue Placeholders;
> - bool IsDistinct;
> - auto getMD = [&](unsigned ID) -> Metadata * {
> - if (!IsDistinct)
> - return MetadataList.getMetadataFwdRef(ID);
> - if (auto *MD = MetadataList.getMetadataIfResolved(ID))
> - return MD;
> - return &Placeholders.getPlaceholderOp(ID);
> - };
> - auto getMDOrNull = [&](unsigned ID) -> Metadata * {
> - if (ID)
> - return getMD(ID - 1);
> - return nullptr;
> - };
> - auto getMDOrNullWithoutPlaceholders = [&](unsigned ID) -> Metadata * {
> - if (ID)
> - return MetadataList.getMetadataFwdRef(ID - 1);
> - return nullptr;
> - };
> - auto getMDString = [&](unsigned ID) -> MDString *{
> - // This requires that the ID is not really a forward reference. In
> - // particular, the MDString must already have been resolved.
> - return cast_or_null<MDString>(getMDOrNull(ID));
> - };
> -
> - // Support for old type refs.
> - auto getDITypeRefOrNull = [&](unsigned ID) {
> - return MetadataList.upgradeTypeRef(getMDOrNull(ID));
> - };
> -
> -#define GET_OR_DISTINCT(CLASS, ARGS)
> \
> - (IsDistinct ? CLASS::getDistinct ARGS : CLASS::get ARGS)
> -
> - // Read all the records.
> - while (true) {
> - BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
> -
> - switch (Entry.Kind) {
> - case BitstreamEntry::SubBlock: // Handled for us already.
> - case BitstreamEntry::Error:
> - return error("Malformed block");
> - case BitstreamEntry::EndBlock:
> - // Upgrade old-style CU <-> SP pointers to point from SP to CU.
> - for (auto CU_SP : CUSubprograms)
> - if (auto *SPs = dyn_cast_or_null<MDTuple>(CU_SP.second))
> - for (auto &Op : SPs->operands())
> - if (auto *SP = dyn_cast_or_null<MDNode>(Op))
> - SP->replaceOperandWith(7, CU_SP.first);
> -
> - MetadataList.tryToResolveCycles();
> - Placeholders.flush(MetadataList);
> - return Error::success();
> - case BitstreamEntry::Record:
> - // The interesting case.
> - break;
> - }
> -
> - // Read a record.
> - Record.clear();
> - StringRef Blob;
> - unsigned Code = Stream.readRecord(Entry.ID, Record, &Blob);
> - IsDistinct = false;
> - switch (Code) {
> - default: // Default behavior: ignore.
> - break;
> - case bitc::METADATA_NAME: {
> - // Read name of the named metadata.
> - SmallString<8> Name(Record.begin(), Record.end());
> - Record.clear();
> - Code = Stream.ReadCode();
> -
> - unsigned NextBitCode = Stream.readRecord(Code, Record);
> - if (NextBitCode != bitc::METADATA_NAMED_NODE)
> - return error("METADATA_NAME not followed by
> METADATA_NAMED_NODE");
> -
> - // Read named metadata elements.
> - unsigned Size = Record.size();
> - NamedMDNode *NMD = TheModule->getOrInsertNamedMetadata(Name);
> - for (unsigned i = 0; i != Size; ++i) {
> - MDNode *MD = MetadataList.getMDNodeFwdRefOrNull(Record[i]);
> - if (!MD)
> - return error("Invalid record");
> - NMD->addOperand(MD);
> - }
> - break;
> - }
> - case bitc::METADATA_OLD_FN_NODE: {
> - // FIXME: Remove in 4.0.
> - // This is a LocalAsMetadata record, the only type of function-
> local
> - // metadata.
> - if (Record.size() % 2 == 1)
> - return error("Invalid record");
> -
> - // If this isn't a LocalAsMetadata record, we're dropping it. This
> used
> - // to be legal, but there's no upgrade path.
> - auto dropRecord = [&] {
> - MetadataList.assignValue(MDNode::get(Context, None),
> NextMetadataNo++);
> - };
> - if (Record.size() != 2) {
> - dropRecord();
> - break;
> - }
> -
> - Type *Ty = getTypeByID(Record[0]);
> - if (Ty->isMetadataTy() || Ty->isVoidTy()) {
> - dropRecord();
> - break;
> - }
> -
> - MetadataList.assignValue(
> - LocalAsMetadata::get(ValueList.getValueFwdRef(Record[1], Ty)),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_OLD_NODE: {
> - // FIXME: Remove in 4.0.
> - if (Record.size() % 2 == 1)
> - return error("Invalid record");
> -
> - unsigned Size = Record.size();
> - SmallVector<Metadata *, 8> Elts;
> - for (unsigned i = 0; i != Size; i += 2) {
> - Type *Ty = getTypeByID(Record[i]);
> - if (!Ty)
> - return error("Invalid record");
> - if (Ty->isMetadataTy())
> - Elts.push_back(getMD(Record[i + 1]));
> - 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);
> - }
> - MetadataList.assignValue(MDNode::get(Context, Elts),
> NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_VALUE: {
> - if (Record.size() != 2)
> - return error("Invalid record");
> -
> - Type *Ty = getTypeByID(Record[0]);
> - if (Ty->isMetadataTy() || Ty->isVoidTy())
> - return error("Invalid record");
> -
> - MetadataList.assignValue(
> - ValueAsMetadata::get(ValueList.getValueFwdRef(Record[1], Ty)),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_DISTINCT_NODE:
> - IsDistinct = true;
> - LLVM_FALLTHROUGH;
> - case bitc::METADATA_NODE: {
> - SmallVector<Metadata *, 8> Elts;
> - Elts.reserve(Record.size());
> - for (unsigned ID : Record)
> - Elts.push_back(getMDOrNull(ID));
> - MetadataList.assignValue(IsDistinct ? MDNode::getDistinct(Context,
> Elts)
> - : MDNode::get(Context, Elts),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_LOCATION: {
> - if (Record.size() != 5)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0];
> - unsigned Line = Record[1];
> - unsigned Column = Record[2];
> - Metadata *Scope = getMD(Record[3]);
> - Metadata *InlinedAt = getMDOrNull(Record[4]);
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DILocation,
> - (Context, Line, Column, Scope, InlinedAt)),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_GENERIC_DEBUG: {
> - if (Record.size() < 4)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0];
> - unsigned Tag = Record[1];
> - unsigned Version = Record[2];
> -
> - if (Tag >= 1u << 16 || Version != 0)
> - return error("Invalid record");
> -
> - auto *Header = getMDString(Record[3]);
> - SmallVector<Metadata *, 8> DwarfOps;
> - for (unsigned I = 4, E = Record.size(); I != E; ++I)
> - DwarfOps.push_back(getMDOrNull(Record[I]));
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(GenericDINode, (Context, Tag, Header,
> DwarfOps)),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_SUBRANGE: {
> - if (Record.size() != 3)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0];
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DISubrange,
> - (Context, Record[1], unrotateSign(Record[2]))),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_ENUMERATOR: {
> - if (Record.size() != 3)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0];
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DIEnumerator, (Context,
> unrotateSign(Record[1]),
> - getMDString(Record[2]))),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_BASIC_TYPE: {
> - if (Record.size() != 6)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0];
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DIBasicType,
> - (Context, Record[1], getMDString(Record[2]),
> - Record[3], Record[4], Record[5])),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_DERIVED_TYPE: {
> - if (Record.size() != 12)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0];
> - DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[10]);
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DIDerivedType,
> - (Context, Record[1], getMDString(Record[2]),
> - getMDOrNull(Record[3]), Record[4],
> - getDITypeRefOrNull(Record[5]),
> - getDITypeRefOrNull(Record[6]), Record[7],
> Record[8],
> - Record[9], Flags,
> getDITypeRefOrNull(Record[11]))),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_COMPOSITE_TYPE: {
> - if (Record.size() != 16)
> - return error("Invalid record");
> -
> - // If we have a UUID and this is not a forward declaration, lookup
> the
> - // mapping.
> - IsDistinct = Record[0] & 0x1;
> - bool IsNotUsedInTypeRef = Record[0] >= 2;
> - unsigned Tag = Record[1];
> - MDString *Name = getMDString(Record[2]);
> - Metadata *File = getMDOrNull(Record[3]);
> - unsigned Line = Record[4];
> - Metadata *Scope = getDITypeRefOrNull(Record[5]);
> - Metadata *BaseType = getDITypeRefOrNull(Record[6]);
> - uint64_t SizeInBits = Record[7];
> - if (Record[8] > (uint64_t)std::numeric_limits<uint32_t>::max())
> - return error("Alignment value is too large");
> - uint32_t AlignInBits = Record[8];
> - uint64_t OffsetInBits = Record[9];
> - DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[10]);
> - Metadata *Elements = getMDOrNull(Record[11]);
> - unsigned RuntimeLang = Record[12];
> - Metadata *VTableHolder = getDITypeRefOrNull(Record[13]);
> - Metadata *TemplateParams = getMDOrNull(Record[14]);
> - auto *Identifier = getMDString(Record[15]);
> - DICompositeType *CT = nullptr;
> - if (Identifier)
> - CT = DICompositeType::buildODRType(
> - Context, *Identifier, Tag, Name, File, Line, Scope, BaseType,
> - SizeInBits, AlignInBits, OffsetInBits, Flags, Elements,
> RuntimeLang,
> - VTableHolder, TemplateParams);
> -
> - // Create a node if we didn't get a lazy ODR type.
> - if (!CT)
> - CT = GET_OR_DISTINCT(DICompositeType,
> - (Context, Tag, Name, File, Line, Scope,
> BaseType,
> - SizeInBits, AlignInBits, OffsetInBits,
> Flags,
> - Elements, RuntimeLang, VTableHolder,
> - TemplateParams, Identifier));
> - if (!IsNotUsedInTypeRef && Identifier)
> - MetadataList.addTypeRef(*Identifier, *cast<DICompositeType>(CT));
> -
> - MetadataList.assignValue(CT, NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_SUBROUTINE_TYPE: {
> - if (Record.size() < 3 || Record.size() > 4)
> - return error("Invalid record");
> - bool IsOldTypeRefArray = Record[0] < 2;
> - unsigned CC = (Record.size() > 3) ? Record[3] : 0;
> -
> - IsDistinct = Record[0] & 0x1;
> - DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[1]);
> - Metadata *Types = getMDOrNull(Record[2]);
> - if (LLVM_UNLIKELY(IsOldTypeRefArray))
> - Types = MetadataList.upgradeTypeRefArray(Types);
> -
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DISubroutineType, (Context, Flags, CC, Types)),
> - NextMetadataNo++);
> - break;
> - }
> -
> - case bitc::METADATA_MODULE: {
> - if (Record.size() != 6)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0];
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DIModule,
> - (Context, getMDOrNull(Record[1]),
> - getMDString(Record[2]),
> getMDString(Record[3]),
> - getMDString(Record[4]),
> getMDString(Record[5]))),
> - NextMetadataNo++);
> - break;
> - }
> -
> - case bitc::METADATA_FILE: {
> - if (Record.size() != 3)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0];
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DIFile, (Context, getMDString(Record[1]),
> - getMDString(Record[2]))),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_COMPILE_UNIT: {
> - if (Record.size() < 14 || Record.size() > 17)
> - return error("Invalid record");
> -
> - // Ignore Record[0], which indicates whether this compile unit is
> - // distinct. It's always distinct.
> - IsDistinct = true;
> - auto *CU = DICompileUnit::getDistinct(
> - Context, Record[1], getMDOrNull(Record[2]),
> getMDString(Record[3]),
> - Record[4], getMDString(Record[5]), Record[6],
> getMDString(Record[7]),
> - Record[8], getMDOrNull(Record[9]), getMDOrNull(Record[10]),
> - getMDOrNull(Record[12]), getMDOrNull(Record[13]),
> - Record.size() <= 15 ? nullptr : getMDOrNull(Record[15]),
> - Record.size() <= 14 ? 0 : Record[14],
> - Record.size() <= 16 ? true : Record[16]);
> -
> - MetadataList.assignValue(CU, NextMetadataNo++);
> -
> - // Move the Upgrade the list of subprograms.
> - if (Metadata *SPs = getMDOrNullWithoutPlaceholders(Record[11]))
> - CUSubprograms.push_back({CU, SPs});
> - break;
> - }
> - case bitc::METADATA_SUBPROGRAM: {
> - if (Record.size() < 18 || Record.size() > 20)
> - return error("Invalid record");
> -
> - IsDistinct =
> - (Record[0] & 1) || Record[8]; // All definitions should be
> distinct.
> - // Version 1 has a Function as Record[15].
> - // Version 2 has removed Record[15].
> - // Version 3 has the Unit as Record[15].
> - // Version 4 added thisAdjustment.
> - bool HasUnit = Record[0] >= 2;
> - if (HasUnit && Record.size() < 19)
> - return error("Invalid record");
> - Metadata *CUorFn = getMDOrNull(Record[15]);
> - unsigned Offset = Record.size() >= 19 ? 1 : 0;
> - bool HasFn = Offset && !HasUnit;
> - bool HasThisAdj = Record.size() >= 20;
> - DISubprogram *SP = GET_OR_DISTINCT(
> - DISubprogram, (Context,
> - getDITypeRefOrNull(Record[1]), // scope
> - getMDString(Record[2]), // name
> - getMDString(Record[3]), // linkageName
> - getMDOrNull(Record[4]), // file
> - Record[5], // line
> - getMDOrNull(Record[6]), // type
> - Record[7], // isLocal
> - Record[8], // isDefinition
> - Record[9], // scopeLine
> - getDITypeRefOrNull(Record[10]), //
> containingType
> - Record[11], // virtuality
> - Record[12], // virtualIndex
> - HasThisAdj ? Record[19] : 0, //
> thisAdjustment
> - static_cast<DINode::DIFlags>(Record[13] // flags
> - ),
> - Record[14], // isOptimized
> - HasUnit ? CUorFn : nullptr, // unit
> - getMDOrNull(Record[15 + Offset]), //
> templateParams
> - getMDOrNull(Record[16 + Offset]), // declaration
> - getMDOrNull(Record[17 + Offset]) // variables
> - ));
> - MetadataList.assignValue(SP, NextMetadataNo++);
> -
> - // Upgrade sp->function mapping to function->sp mapping.
> - if (HasFn) {
> - if (auto *CMD = dyn_cast_or_null<ConstantAsMetadata>(CUorFn))
> - if (auto *F = dyn_cast<Function>(CMD->getValue())) {
> - if (F->isMaterializable())
> - // Defer until materialized; unmaterialized functions may
> not have
> - // metadata.
> - FunctionsWithSPs[F] = SP;
> - else if (!F->empty())
> - F->setSubprogram(SP);
> - }
> - }
> - break;
> - }
> - case bitc::METADATA_LEXICAL_BLOCK: {
> - if (Record.size() != 5)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0];
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DILexicalBlock,
> - (Context, getMDOrNull(Record[1]),
> - getMDOrNull(Record[2]), Record[3],
> Record[4])),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_LEXICAL_BLOCK_FILE: {
> - if (Record.size() != 4)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0];
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DILexicalBlockFile,
> - (Context, getMDOrNull(Record[1]),
> - getMDOrNull(Record[2]), Record[3])),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_NAMESPACE: {
> - if (Record.size() != 5)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0] & 1;
> - bool ExportSymbols = Record[0] & 2;
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DINamespace,
> - (Context, getMDOrNull(Record[1]),
> - getMDOrNull(Record[2]),
> getMDString(Record[3]),
> - Record[4], ExportSymbols)),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_MACRO: {
> - if (Record.size() != 5)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0];
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DIMacro,
> - (Context, Record[1], Record[2],
> - getMDString(Record[3]),
> getMDString(Record[4]))),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_MACRO_FILE: {
> - if (Record.size() != 5)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0];
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DIMacroFile,
> - (Context, Record[1], Record[2],
> - getMDOrNull(Record[3]),
> getMDOrNull(Record[4]))),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_TEMPLATE_TYPE: {
> - if (Record.size() != 3)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0];
> - MetadataList.assignValue(GET_OR_DISTINCT(DITemplateTypeParameter,
> - (Context,
> getMDString(Record[1]),
> -
> getDITypeRefOrNull(Record[2]))),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_TEMPLATE_VALUE: {
> - if (Record.size() != 5)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0];
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DITemplateValueParameter,
> - (Context, Record[1], getMDString(Record[2]),
> - getDITypeRefOrNull(Record[3]),
> - getMDOrNull(Record[4]))),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_GLOBAL_VAR: {
> - if (Record.size() < 11 || Record.size() > 12)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0];
> -
> - // Upgrade old metadata, which stored a global variable reference
> or a
> - // ConstantInt here.
> - Metadata *Expr = getMDOrNull(Record[9]);
> - uint32_t AlignInBits = 0;
> - if (Record.size() > 11) {
> - if (Record[11] > (uint64_t)std::numeric_limits<uint32_t>::max())
> - return error("Alignment value is too large");
> - AlignInBits = Record[11];
> - }
> - GlobalVariable *Attach = nullptr;
> - if (auto *CMD = dyn_cast_or_null<ConstantAsMetadata>(Expr)) {
> - if (auto *GV = dyn_cast<GlobalVariable>(CMD->getValue())) {
> - Attach = GV;
> - Expr = nullptr;
> - } else if (auto *CI = dyn_cast<ConstantInt>(CMD->getValue())) {
> - Expr = DIExpression::get(Context,
> - {dwarf::DW_OP_constu, CI-
> >getZExtValue(),
> - dwarf::DW_OP_stack_value});
> - } else {
> - Expr = nullptr;
> - }
> - }
> -
> - DIGlobalVariable *DGV = GET_OR_DISTINCT(
> - DIGlobalVariable,
> - (Context, getMDOrNull(Record[1]), getMDString(Record[2]),
> - getMDString(Record[3]), getMDOrNull(Record[4]), Record[5],
> - getDITypeRefOrNull(Record[6]), Record[7], Record[8], Expr,
> - getMDOrNull(Record[10]), AlignInBits));
> - MetadataList.assignValue(DGV, NextMetadataNo++);
> -
> - if (Attach)
> - Attach->addDebugInfo(DGV);
> -
> - break;
> - }
> - case bitc::METADATA_LOCAL_VAR: {
> - // 10th field is for the obseleted 'inlinedAt:' field.
> - if (Record.size() < 8 || Record.size() > 10)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0] & 1;
> - bool HasAlignment = Record[0] & 2;
> - // 2nd field used to be an artificial tag, either
> DW_TAG_auto_variable or
> - // DW_TAG_arg_variable, if we have alignment flag encoded it means,
> that
> - // this is newer version of record which doesn't have artifical
> tag.
> - bool HasTag = !HasAlignment && Record.size() > 8;
> - DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[7 +
> HasTag]);
> - uint32_t AlignInBits = 0;
> - if (HasAlignment) {
> - if (Record[8 + HasTag] >
> - (uint64_t)std::numeric_limits<uint32_t>::max())
> - return error("Alignment value is too large");
> - AlignInBits = Record[8 + HasTag];
> - }
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DILocalVariable,
> - (Context, getMDOrNull(Record[1 + HasTag]),
> - getMDString(Record[2 + HasTag]),
> - getMDOrNull(Record[3 + HasTag]), Record[4 +
> HasTag],
> - getDITypeRefOrNull(Record[5 + HasTag]),
> - Record[6 + HasTag], Flags, AlignInBits)),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_EXPRESSION: {
> - if (Record.size() < 1)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0] & 1;
> - bool HasOpFragment = Record[0] & 2;
> - auto Elts = MutableArrayRef<uint64_t>(Record).slice(1);
> - if (!HasOpFragment)
> - if (unsigned N = Elts.size())
> - if (N >= 3 && Elts[N - 3] == dwarf::DW_OP_bit_piece)
> - Elts[N-3] = dwarf::DW_OP_LLVM_fragment;
> -
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DIExpression,
> - (Context, makeArrayRef(Record).slice(1))),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_OBJC_PROPERTY: {
> - if (Record.size() != 8)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0];
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DIObjCProperty,
> - (Context, getMDString(Record[1]),
> - getMDOrNull(Record[2]), Record[3],
> - getMDString(Record[4]),
> getMDString(Record[5]),
> - Record[6], getDITypeRefOrNull(Record[7]))),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_IMPORTED_ENTITY: {
> - if (Record.size() != 6)
> - return error("Invalid record");
> -
> - IsDistinct = Record[0];
> - MetadataList.assignValue(
> - GET_OR_DISTINCT(DIImportedEntity,
> - (Context, Record[1], getMDOrNull(Record[2]),
> - getDITypeRefOrNull(Record[3]), Record[4],
> - getMDString(Record[5]))),
> - NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_STRING_OLD: {
> - std::string String(Record.begin(), Record.end());
> -
> - // Test for upgrading !llvm.loop.
> - HasSeenOldLoopTags |= mayBeOldLoopAttachmentTag(String);
> -
> - Metadata *MD = MDString::get(Context, String);
> - MetadataList.assignValue(MD, NextMetadataNo++);
> - break;
> - }
> - case bitc::METADATA_STRINGS:
> - if (Error Err = parseMetadataStrings(Record, Blob, NextMetadataNo))
> - return Err;
> - break;
> - case bitc::METADATA_GLOBAL_DECL_ATTACHMENT: {
> - if (Record.size() % 2 == 0)
> - return error("Invalid record");
> - unsigned ValueID = Record[0];
> - if (ValueID >= ValueList.size())
> - return error("Invalid record");
> - if (auto *GO = dyn_cast<GlobalObject>(ValueList[ValueID]))
> - if (Error Err = parseGlobalObjectAttachment(
> - *GO, ArrayRef<uint64_t>(Record).slice(1)))
> - return Err;
> - break;
> - }
> - case bitc::METADATA_KIND: {
> - // Support older bitcode files that had METADATA_KIND records in a
> - // block with METADATA_BLOCK_ID.
> - if (Error Err = parseMetadataKindRecord(Record))
> - return Err;
> - break;
> - }
> - }
> - }
> -
> -#undef GET_OR_DISTINCT
> -}
> -
> -/// Parse the metadata kinds out of the METADATA_KIND_BLOCK.
> -Error BitcodeReader::parseMetadataKinds() {
> - if (Stream.EnterSubBlock(bitc::METADATA_KIND_BLOCK_ID))
> - return error("Invalid record");
> -
> - SmallVector<uint64_t, 64> Record;
> -
> - // Read all the records.
> - while (true) {
> - BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
> -
> - switch (Entry.Kind) {
> - case BitstreamEntry::SubBlock: // Handled for us already.
> - case BitstreamEntry::Error:
> - return error("Malformed block");
> - case BitstreamEntry::EndBlock:
> - return Error::success();
> - case BitstreamEntry::Record:
> - // The interesting case.
> - break;
> - }
> -
> - // Read a record.
> - Record.clear();
> - unsigned Code = Stream.readRecord(Entry.ID, Record);
> - switch (Code) {
> - default: // Default behavior: ignore.
> - break;
> - case bitc::METADATA_KIND: {
> - if (Error Err = parseMetadataKindRecord(Record))
> - return Err;
> - break;
> - }
> - }
> - }
> -}
> -
> /// Decode a signed value stored with the sign bit in the LSB for dense
> VBR
> /// encoding.
> uint64_t BitcodeReader::decodeSignRotatedValue(uint64_t V) {
> @@ -3777,7 +2483,7 @@ Error BitcodeReader::materializeMetadata
> for (uint64_t BitPos : DeferredMetadataInfo) {
> // Move the bit stream to the saved position.
> Stream.JumpToBit(BitPos);
> - if (Error Err = parseMetadata(true))
> + if (Error Err = MDLoader->parseModuleMetadata())
> return Err;
> }
> DeferredMetadataInfo.clear();
> @@ -3961,11 +2667,11 @@ Error BitcodeReader::parseModule(uint64_
> break;
> }
> assert(DeferredMetadataInfo.empty() && "Unexpected deferred
> metadata");
> - if (Error Err = parseMetadata(true))
> + if (Error Err = MDLoader->parseModuleMetadata())
> return Err;
> break;
> case bitc::METADATA_KIND_BLOCK_ID:
> - if (Error Err = parseMetadataKinds())
> + if (Error Err = MDLoader->parseMetadataKinds())
> return Err;
> break;
> case bitc::FUNCTION_BLOCK_ID:
> @@ -4367,92 +3073,11 @@ Error BitcodeReader::parseModule(uint64_
>
> Error BitcodeReader::parseBitcodeInto(Module *M, bool
> ShouldLazyLoadMetadata) {
> TheModule = M;
> + MDLoader = MetadataLoader(Stream, *M, ValueList,
> + [&](unsigned ID) { return getTypeByID(ID);
> });
> return parseModule(0, ShouldLazyLoadMetadata);
> }
>
> -Error BitcodeReader::parseGlobalObjectAttachment(GlobalObject &GO,
> - ArrayRef<uint64_t>
> Record) {
> - assert(Record.size() % 2 == 0);
> - for (unsigned I = 0, E = Record.size(); I != E; I += 2) {
> - auto K = MDKindMap.find(Record[I]);
> - if (K == MDKindMap.end())
> - return error("Invalid ID");
> - MDNode *MD = MetadataList.getMDNodeFwdRefOrNull(Record[I + 1]);
> - if (!MD)
> - return error("Invalid metadata attachment");
> - GO.addMetadata(K->second, *MD);
> - }
> - return Error::success();
> -}
> -
> -/// Parse metadata attachments.
> -Error BitcodeReader::parseMetadataAttachment(Function &F) {
> - if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
> - return error("Invalid record");
> -
> - SmallVector<uint64_t, 64> Record;
> -
> - while (true) {
> - BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
> -
> - switch (Entry.Kind) {
> - case BitstreamEntry::SubBlock: // Handled for us already.
> - case BitstreamEntry::Error:
> - return error("Malformed block");
> - case BitstreamEntry::EndBlock:
> - return Error::success();
> - case BitstreamEntry::Record:
> - // The interesting case.
> - break;
> - }
> -
> - // Read a metadata attachment record.
> - Record.clear();
> - switch (Stream.readRecord(Entry.ID, Record)) {
> - default: // Default behavior: ignore.
> - break;
> - case bitc::METADATA_ATTACHMENT: {
> - unsigned RecordLength = Record.size();
> - if (Record.empty())
> - return error("Invalid record");
> - if (RecordLength % 2 == 0) {
> - // A function attachment.
> - if (Error Err = parseGlobalObjectAttachment(F, Record))
> - return Err;
> - continue;
> - }
> -
> - // An instruction attachment.
> - Instruction *Inst = InstructionList[Record[0]];
> - for (unsigned i = 1; i != RecordLength; i = i+2) {
> - unsigned Kind = Record[i];
> - DenseMap<unsigned, unsigned>::iterator I =
> - MDKindMap.find(Kind);
> - if (I == MDKindMap.end())
> - return error("Invalid ID");
> - Metadata *Node = MetadataList.getMetadataFwdRef(Record[i + 1]);
> - if (isa<LocalAsMetadata>(Node))
> - // Drop the attachment. This used to be legal, but there's no
> - // upgrade path.
> - break;
> - MDNode *MD = dyn_cast_or_null<MDNode>(Node);
> - if (!MD)
> - return error("Invalid metadata attachment");
> -
> - if (HasSeenOldLoopTags && I->second == LLVMContext::MD_loop)
> - MD = upgradeInstructionLoopAttachment(*MD);
> -
> - if (I->second == LLVMContext::MD_tbaa) {
> - assert(!MD->isTemporary() && "should load MDs before
> attachments");
> - MD = UpgradeTBAANode(*MD);
> - }
> - Inst->setMetadata(I->second, MD);
> - }
> - break;
> - }
> - }
> - }
> -}
>
> Error BitcodeReader::typeCheckLoadStoreInst(Type *ValType, Type *PtrType)
> {
> if (!isa<PointerType>(PtrType))
> @@ -4473,12 +3098,12 @@ Error BitcodeReader::parseFunctionBody(F
> return error("Invalid record");
>
> // Unexpected unresolved metadata when parsing function.
> - if (MetadataList.hasFwdRefs())
> + if (MDLoader->hasFwdRefs())
> return error("Invalid function metadata: incoming forward
> references");
>
> InstructionList.clear();
> unsigned ModuleValueListSize = ValueList.size();
> - unsigned ModuleMetadataListSize = MetadataList.size();
> + unsigned ModuleMDLoaderSize = MDLoader->size();
>
> // Add all the function arguments to the value table.
> for (Argument &I : F->args())
> @@ -4528,11 +3153,13 @@ Error BitcodeReader::parseFunctionBody(F
> return Err;
> break;
> case bitc::METADATA_ATTACHMENT_ID:
> - if (Error Err = parseMetadataAttachment(*F))
> + if (Error Err = MDLoader->parseMetadataAttachment(*F,
> InstructionList))
> return Err;
> break;
> case bitc::METADATA_BLOCK_ID:
> - if (Error Err = parseMetadata())
> + assert(DeferredMetadataInfo.empty() &&
> + "Must read all module-level metadata before function-
> level");
> + if (Error Err = MDLoader->parseFunctionMetadata())
> return Err;
> break;
> case bitc::USELIST_BLOCK_ID:
> @@ -4610,12 +3237,12 @@ Error BitcodeReader::parseFunctionBody(F
>
> MDNode *Scope = nullptr, *IA = nullptr;
> if (ScopeID) {
> - Scope = MetadataList.getMDNodeFwdRefOrNull(ScopeID - 1);
> + Scope = MDLoader->getMDNodeFwdRefOrNull(ScopeID - 1);
> if (!Scope)
> return error("Invalid record");
> }
> if (IAID) {
> - IA = MetadataList.getMDNodeFwdRefOrNull(IAID - 1);
> + IA = MDLoader->getMDNodeFwdRefOrNull(IAID - 1);
> if (!IA)
> return error("Invalid record");
> }
> @@ -5740,12 +4367,12 @@ OutOfRecordLoop:
> }
>
> // Unexpected unresolved metadata about to be dropped.
> - if (MetadataList.hasFwdRefs())
> + if (MDLoader->hasFwdRefs())
> return error("Invalid function metadata: outgoing forward refs");
>
> // Trim the value list down to the size it was before we parsed this
> function.
> ValueList.shrinkTo(ModuleValueListSize);
> - MetadataList.shrinkTo(ModuleMetadataListSize);
> + MDLoader->shrinkTo(ModuleMDLoaderSize);
> std::vector<BasicBlock*>().swap(FunctionBBs);
> return Error::success();
> }
> @@ -5819,7 +4446,7 @@ Error BitcodeReader::materialize(GlobalV
> CallSite(*UI++).setCalledFunction(I.second);
>
> // Finish fn->subprogram upgrade for materialized functions.
> - if (DISubprogram *SP = FunctionsWithSPs.lookup(F))
> + if (DISubprogram *SP = MDLoader->lookupSubprogramForFunction(F))
> F->setSubprogram(SP);
>
> // Bring in any functions that this function forward-referenced via
>
> Modified: llvm/trunk/lib/Bitcode/Reader/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-
> project/llvm/trunk/lib/Bitcode/Reader/CMakeLists.txt?rev=289461&r1=289460&
> r2=289461&view=diff
> ==========================================================================
> ====
> --- llvm/trunk/lib/Bitcode/Reader/CMakeLists.txt (original)
> +++ llvm/trunk/lib/Bitcode/Reader/CMakeLists.txt Mon Dec 12 13:34:26 2016
> @@ -2,6 +2,8 @@ add_llvm_library(LLVMBitReader
> BitReader.cpp
> BitcodeReader.cpp
> BitstreamReader.cpp
> + MetadataLoader.cpp
> + ValueList.cpp
>
> ADDITIONAL_HEADER_DIRS
> ${LLVM_MAIN_INCLUDE_DIR}/llvm/Bitcode
>
> Added: llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp?rev=289461&view=a
> uto
> ==========================================================================
> ====
> --- llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp (added)
> +++ llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp Mon Dec 12 13:34:26
> 2016
> @@ -0,0 +1,1316 @@
> +//===- MetadataLoader.cpp - Internal BitcodeReader implementation -------
> --===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===--------------------------------------------------------------------
> --===//
> +
> +#include "MetadataLoader.h"
> +#include "ValueList.h"
> +
> +#include "llvm/ADT/APFloat.h"
> +#include "llvm/ADT/APInt.h"
> +#include "llvm/ADT/ArrayRef.h"
> +#include "llvm/ADT/DenseMap.h"
> +#include "llvm/ADT/None.h"
> +#include "llvm/ADT/STLExtras.h"
> +#include "llvm/ADT/SmallString.h"
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/ADT/StringRef.h"
> +#include "llvm/ADT/Triple.h"
> +#include "llvm/ADT/Twine.h"
> +#include "llvm/Bitcode/BitcodeReader.h"
> +#include "llvm/Bitcode/BitstreamReader.h"
> +#include "llvm/Bitcode/LLVMBitCodes.h"
> +#include "llvm/IR/Argument.h"
> +#include "llvm/IR/Attributes.h"
> +#include "llvm/IR/AutoUpgrade.h"
> +#include "llvm/IR/BasicBlock.h"
> +#include "llvm/IR/CallSite.h"
> +#include "llvm/IR/CallingConv.h"
> +#include "llvm/IR/Comdat.h"
> +#include "llvm/IR/Constant.h"
> +#include "llvm/IR/Constants.h"
> +#include "llvm/IR/DebugInfo.h"
> +#include "llvm/IR/DebugInfoMetadata.h"
> +#include "llvm/IR/DebugLoc.h"
> +#include "llvm/IR/DerivedTypes.h"
> +#include "llvm/IR/DiagnosticInfo.h"
> +#include "llvm/IR/DiagnosticPrinter.h"
> +#include "llvm/IR/Function.h"
> +#include "llvm/IR/GVMaterializer.h"
> +#include "llvm/IR/GlobalAlias.h"
> +#include "llvm/IR/GlobalIFunc.h"
> +#include "llvm/IR/GlobalIndirectSymbol.h"
> +#include "llvm/IR/GlobalObject.h"
> +#include "llvm/IR/GlobalValue.h"
> +#include "llvm/IR/GlobalVariable.h"
> +#include "llvm/IR/InlineAsm.h"
> +#include "llvm/IR/InstrTypes.h"
> +#include "llvm/IR/Instruction.h"
> +#include "llvm/IR/Instructions.h"
> +#include "llvm/IR/Intrinsics.h"
> +#include "llvm/IR/LLVMContext.h"
> +#include "llvm/IR/Module.h"
> +#include "llvm/IR/ModuleSummaryIndex.h"
> +#include "llvm/IR/OperandTraits.h"
> +#include "llvm/IR/Operator.h"
> +#include "llvm/IR/TrackingMDRef.h"
> +#include "llvm/IR/Type.h"
> +#include "llvm/IR/ValueHandle.h"
> +#include "llvm/Support/AtomicOrdering.h"
> +#include "llvm/Support/Casting.h"
> +#include "llvm/Support/CommandLine.h"
> +#include "llvm/Support/Compiler.h"
> +#include "llvm/Support/Debug.h"
> +#include "llvm/Support/Error.h"
> +#include "llvm/Support/ErrorHandling.h"
> +#include "llvm/Support/ManagedStatic.h"
> +#include "llvm/Support/MemoryBuffer.h"
> +#include "llvm/Support/raw_ostream.h"
> +#include <algorithm>
> +#include <cassert>
> +#include <cstddef>
> +#include <cstdint>
> +#include <deque>
> +#include <limits>
> +#include <map>
> +#include <memory>
> +#include <string>
> +#include <system_error>
> +#include <tuple>
> +#include <utility>
> +#include <vector>
> +
> +using namespace llvm;
> +
> +namespace {
> +
> +static int64_t unrotateSign(uint64_t U) { return U & 1 ? ~(U >> 1) : U >>
> 1; }
> +
> +class BitcodeReaderMetadataList {
> + unsigned NumFwdRefs;
> + bool AnyFwdRefs;
> + unsigned MinFwdRef;
> + unsigned MaxFwdRef;
> +
> + /// Array of metadata references.
> + ///
> + /// Don't use std::vector here. Some versions of libc++ copy (instead
> of
> + /// move) on resize, and TrackingMDRef is very expensive to copy.
> + SmallVector<TrackingMDRef, 1> MetadataPtrs;
> +
> + /// Structures for resolving old type refs.
> + struct {
> + SmallDenseMap<MDString *, TempMDTuple, 1> Unknown;
> + SmallDenseMap<MDString *, DICompositeType *, 1> Final;
> + SmallDenseMap<MDString *, DICompositeType *, 1> FwdDecls;
> + SmallVector<std::pair<TrackingMDRef, TempMDTuple>, 1> Arrays;
> + } OldTypeRefs;
> +
> + LLVMContext &Context;
> +
> +public:
> + BitcodeReaderMetadataList(LLVMContext &C)
> + : NumFwdRefs(0), AnyFwdRefs(false), Context(C) {}
> +
> + // vector compatibility methods
> + unsigned size() const { return MetadataPtrs.size(); }
> + void resize(unsigned N) { MetadataPtrs.resize(N); }
> + void push_back(Metadata *MD) { MetadataPtrs.emplace_back(MD); }
> + void clear() { MetadataPtrs.clear(); }
> + Metadata *back() const { return MetadataPtrs.back(); }
> + void pop_back() { MetadataPtrs.pop_back(); }
> + bool empty() const { return MetadataPtrs.empty(); }
> +
> + Metadata *operator[](unsigned i) const {
> + assert(i < MetadataPtrs.size());
> + return MetadataPtrs[i];
> + }
> +
> + Metadata *lookup(unsigned I) const {
> + if (I < MetadataPtrs.size())
> + return MetadataPtrs[I];
> + return nullptr;
> + }
> +
> + void shrinkTo(unsigned N) {
> + assert(N <= size() && "Invalid shrinkTo request!");
> + assert(!AnyFwdRefs && "Unexpected forward refs");
> + MetadataPtrs.resize(N);
> + }
> +
> + /// Return the given metadata, creating a replaceable forward reference
> if
> + /// necessary.
> + Metadata *getMetadataFwdRef(unsigned Idx);
> +
> + /// Return the the given metadata only if it is fully resolved.
> + ///
> + /// Gives the same result as \a lookup(), unless \a
> MDNode::isResolved()
> + /// would give \c false.
> + Metadata *getMetadataIfResolved(unsigned Idx);
> +
> + MDNode *getMDNodeFwdRefOrNull(unsigned Idx);
> + void assignValue(Metadata *MD, unsigned Idx);
> + void tryToResolveCycles();
> + bool hasFwdRefs() const { return AnyFwdRefs; }
> +
> + /// Upgrade a type that had an MDString reference.
> + void addTypeRef(MDString &UUID, DICompositeType &CT);
> +
> + /// Upgrade a type that had an MDString reference.
> + Metadata *upgradeTypeRef(Metadata *MaybeUUID);
> +
> + /// Upgrade a type ref array that may have MDString references.
> + Metadata *upgradeTypeRefArray(Metadata *MaybeTuple);
> +
> +private:
> + Metadata *resolveTypeRefArray(Metadata *MaybeTuple);
> +};
> +
> +void BitcodeReaderMetadataList::assignValue(Metadata *MD, unsigned Idx) {
> + if (Idx == size()) {
> + push_back(MD);
> + return;
> + }
> +
> + if (Idx >= size())
> + resize(Idx + 1);
> +
> + TrackingMDRef &OldMD = MetadataPtrs[Idx];
> + if (!OldMD) {
> + OldMD.reset(MD);
> + return;
> + }
> +
> + // If there was a forward reference to this value, replace it.
> + TempMDTuple PrevMD(cast<MDTuple>(OldMD.get()));
> + PrevMD->replaceAllUsesWith(MD);
> + --NumFwdRefs;
> +}
> +
> +Metadata *BitcodeReaderMetadataList::getMetadataFwdRef(unsigned Idx) {
> + if (Idx >= size())
> + resize(Idx + 1);
> +
> + if (Metadata *MD = MetadataPtrs[Idx])
> + return MD;
> +
> + // Track forward refs to be resolved later.
> + if (AnyFwdRefs) {
> + MinFwdRef = std::min(MinFwdRef, Idx);
> + MaxFwdRef = std::max(MaxFwdRef, Idx);
> + } else {
> + AnyFwdRefs = true;
> + MinFwdRef = MaxFwdRef = Idx;
> + }
> + ++NumFwdRefs;
> +
> + // Create and return a placeholder, which will later be RAUW'd.
> + Metadata *MD = MDNode::getTemporary(Context, None).release();
> + MetadataPtrs[Idx].reset(MD);
> + return MD;
> +}
> +
> +Metadata *BitcodeReaderMetadataList::getMetadataIfResolved(unsigned Idx)
> {
> + Metadata *MD = lookup(Idx);
> + if (auto *N = dyn_cast_or_null<MDNode>(MD))
> + if (!N->isResolved())
> + return nullptr;
> + return MD;
> +}
> +
> +MDNode *BitcodeReaderMetadataList::getMDNodeFwdRefOrNull(unsigned Idx) {
> + return dyn_cast_or_null<MDNode>(getMetadataFwdRef(Idx));
> +}
> +
> +void BitcodeReaderMetadataList::tryToResolveCycles() {
> + if (NumFwdRefs)
> + // Still forward references... can't resolve cycles.
> + return;
> +
> + bool DidReplaceTypeRefs = false;
> +
> + // Give up on finding a full definition for any forward decls that
> remain.
> + for (const auto &Ref : OldTypeRefs.FwdDecls)
> + OldTypeRefs.Final.insert(Ref);
> + OldTypeRefs.FwdDecls.clear();
> +
> + // Upgrade from old type ref arrays. In strange cases, this could add
> to
> + // OldTypeRefs.Unknown.
> + for (const auto &Array : OldTypeRefs.Arrays) {
> + DidReplaceTypeRefs = true;
> + Array.second-
> >replaceAllUsesWith(resolveTypeRefArray(Array.first.get()));
> + }
> + OldTypeRefs.Arrays.clear();
> +
> + // Replace old string-based type refs with the resolved node, if
> possible.
> + // If we haven't seen the node, leave it to the verifier to complain
> about
> + // the invalid string reference.
> + for (const auto &Ref : OldTypeRefs.Unknown) {
> + DidReplaceTypeRefs = true;
> + if (DICompositeType *CT = OldTypeRefs.Final.lookup(Ref.first))
> + Ref.second->replaceAllUsesWith(CT);
> + else
> + Ref.second->replaceAllUsesWith(Ref.first);
> + }
> + OldTypeRefs.Unknown.clear();
> +
> + // Make sure all the upgraded types are resolved.
> + if (DidReplaceTypeRefs) {
> + AnyFwdRefs = true;
> + MinFwdRef = 0;
> + MaxFwdRef = MetadataPtrs.size() - 1;
> + }
> +
> + if (!AnyFwdRefs)
> + // Nothing to do.
> + return;
> +
> + // Resolve any cycles.
> + for (unsigned I = MinFwdRef, E = MaxFwdRef + 1; I != E; ++I) {
> + auto &MD = MetadataPtrs[I];
> + auto *N = dyn_cast_or_null<MDNode>(MD);
> + if (!N)
> + continue;
> +
> + assert(!N->isTemporary() && "Unexpected forward reference");
> + N->resolveCycles();
> + }
> +
> + // Make sure we return early again until there's another forward ref.
> + AnyFwdRefs = false;
> +}
> +
> +void BitcodeReaderMetadataList::addTypeRef(MDString &UUID,
> + DICompositeType &CT) {
> + assert(CT.getRawIdentifier() == &UUID && "Mismatched UUID");
> + if (CT.isForwardDecl())
> + OldTypeRefs.FwdDecls.insert(std::make_pair(&UUID, &CT));
> + else
> + OldTypeRefs.Final.insert(std::make_pair(&UUID, &CT));
> +}
> +
> +Metadata *BitcodeReaderMetadataList::upgradeTypeRef(Metadata *MaybeUUID)
> {
> + auto *UUID = dyn_cast_or_null<MDString>(MaybeUUID);
> + if (LLVM_LIKELY(!UUID))
> + return MaybeUUID;
> +
> + if (auto *CT = OldTypeRefs.Final.lookup(UUID))
> + return CT;
> +
> + auto &Ref = OldTypeRefs.Unknown[UUID];
> + if (!Ref)
> + Ref = MDNode::getTemporary(Context, None);
> + return Ref.get();
> +}
> +
> +Metadata *BitcodeReaderMetadataList::upgradeTypeRefArray(Metadata
> *MaybeTuple) {
> + auto *Tuple = dyn_cast_or_null<MDTuple>(MaybeTuple);
> + if (!Tuple || Tuple->isDistinct())
> + return MaybeTuple;
> +
> + // Look through the array immediately if possible.
> + if (!Tuple->isTemporary())
> + return resolveTypeRefArray(Tuple);
> +
> + // Create and return a placeholder to use for now. Eventually
> + // resolveTypeRefArrays() will be resolve this forward reference.
> + OldTypeRefs.Arrays.emplace_back(
> + std::piecewise_construct, std::forward_as_tuple(Tuple),
> + std::forward_as_tuple(MDTuple::getTemporary(Context, None)));
> + return OldTypeRefs.Arrays.back().second.get();
> +}
> +
> +Metadata *BitcodeReaderMetadataList::resolveTypeRefArray(Metadata
> *MaybeTuple) {
> + auto *Tuple = dyn_cast_or_null<MDTuple>(MaybeTuple);
> + if (!Tuple || Tuple->isDistinct())
> + return MaybeTuple;
> +
> + // Look through the DITypeRefArray, upgrading each DITypeRef.
> + SmallVector<Metadata *, 32> Ops;
> + Ops.reserve(Tuple->getNumOperands());
> + for (Metadata *MD : Tuple->operands())
> + Ops.push_back(upgradeTypeRef(MD));
> +
> + return MDTuple::get(Context, Ops);
> +}
> +
> +namespace {
> +
> +class PlaceholderQueue {
> + // Placeholders would thrash around when moved, so store in a
> std::deque
> + // instead of some sort of vector.
> + std::deque<DistinctMDOperandPlaceholder> PHs;
> +
> +public:
> + DistinctMDOperandPlaceholder &getPlaceholderOp(unsigned ID);
> + void flush(BitcodeReaderMetadataList &MetadataList);
> +};
> +
> +} // end anonymous namespace
> +
> +DistinctMDOperandPlaceholder &PlaceholderQueue::getPlaceholderOp(unsigned
> ID) {
> + PHs.emplace_back(ID);
> + return PHs.back();
> +}
> +
> +void PlaceholderQueue::flush(BitcodeReaderMetadataList &MetadataList) {
> + while (!PHs.empty()) {
> + PHs.front().replaceUseWith(
> + MetadataList.getMetadataFwdRef(PHs.front().getID()));
> + PHs.pop_front();
> + }
> +}
> +
> +} // anonynous namespace
> +
> +class MetadataLoader::MetadataLoaderImpl {
> + BitcodeReaderMetadataList MetadataList;
> + BitcodeReaderValueList &ValueList;
> + BitstreamCursor &Stream;
> + LLVMContext &Context;
> + Module &TheModule;
> + std::function<Type *(unsigned)> getTypeByID;
> +
> + /// Functions that need to be matched with subprograms when upgrading
> old
> + /// metadata.
> + SmallDenseMap<Function *, DISubprogram *, 16> FunctionsWithSPs;
> +
> + // Map the bitcode's custom MDKind ID to the Module's MDKind ID.
> + DenseMap<unsigned, unsigned> MDKindMap;
> +
> + bool HasSeenOldLoopTags = false;
> +
> + Error parseMetadataStrings(ArrayRef<uint64_t> Record, StringRef Blob,
> + unsigned &NextMetadataNo);
> + Error parseGlobalObjectAttachment(GlobalObject &GO,
> + ArrayRef<uint64_t> Record);
> + Error parseMetadataKindRecord(SmallVectorImpl<uint64_t> &Record);
> +
> +public:
> + MetadataLoaderImpl(BitstreamCursor &Stream, Module &TheModule,
> + BitcodeReaderValueList &ValueList,
> + std::function<Type *(unsigned)> getTypeByID)
> + : MetadataList(TheModule.getContext()), ValueList(ValueList),
> + Stream(Stream), Context(TheModule.getContext()),
> TheModule(TheModule),
> + getTypeByID(getTypeByID) {}
> +
> + Error parseMetadata(bool ModuleLevel);
> +
> + bool hasFwdRefs() const { return MetadataList.hasFwdRefs(); }
> + Metadata *getMetadataFwdRef(unsigned Idx) {
> + return MetadataList.getMetadataFwdRef(Idx);
> + }
> +
> + MDNode *getMDNodeFwdRefOrNull(unsigned Idx) {
> + return MetadataList.getMDNodeFwdRefOrNull(Idx);
> + }
> +
> + DISubprogram *lookupSubprogramForFunction(Function *F) {
> + return FunctionsWithSPs.lookup(F);
> + }
> +
> + bool hasSeenOldLoopTags() { return HasSeenOldLoopTags; }
> +
> + Error parseMetadataAttachment(
> + Function &F, const SmallVectorImpl<Instruction *>
> &InstructionList);
> +
> + Error parseMetadataKinds();
> +
> + unsigned size() const { return MetadataList.size(); }
> + void shrinkTo(unsigned N) { MetadataList.shrinkTo(N); }
> +};
> +
> +Error error(const Twine &Message) {
> + return make_error<StringError>(
> + Message, make_error_code(BitcodeError::CorruptedBitcode));
> +}
> +
> +/// Parse a METADATA_BLOCK. If ModuleLevel is true then we are parsing
> +/// module level metadata.
> +Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel)
> {
> + if (!ModuleLevel && MetadataList.hasFwdRefs())
> + return error("Invalid metadata: fwd refs into function blocks");
> +
> + if (Stream.EnterSubBlock(bitc::METADATA_BLOCK_ID))
> + return error("Invalid record");
> +
> + unsigned NextMetadataNo = MetadataList.size();
> + std::vector<std::pair<DICompileUnit *, Metadata *>> CUSubprograms;
> + SmallVector<uint64_t, 64> Record;
> +
> + PlaceholderQueue Placeholders;
> + bool IsDistinct;
> + auto getMD = [&](unsigned ID) -> Metadata * {
> + if (!IsDistinct)
> + return MetadataList.getMetadataFwdRef(ID);
> + if (auto *MD = MetadataList.getMetadataIfResolved(ID))
> + return MD;
> + return &Placeholders.getPlaceholderOp(ID);
> + };
> + auto getMDOrNull = [&](unsigned ID) -> Metadata * {
> + if (ID)
> + return getMD(ID - 1);
> + return nullptr;
> + };
> + auto getMDOrNullWithoutPlaceholders = [&](unsigned ID) -> Metadata * {
> + if (ID)
> + return MetadataList.getMetadataFwdRef(ID - 1);
> + return nullptr;
> + };
> + auto getMDString = [&](unsigned ID) -> MDString * {
> + // This requires that the ID is not really a forward reference. In
> + // particular, the MDString must already have been resolved.
> + return cast_or_null<MDString>(getMDOrNull(ID));
> + };
> +
> + // Support for old type refs.
> + auto getDITypeRefOrNull = [&](unsigned ID) {
> + return MetadataList.upgradeTypeRef(getMDOrNull(ID));
> + };
> +
> +#define GET_OR_DISTINCT(CLASS, ARGS)
> \
> + (IsDistinct ? CLASS::getDistinct ARGS : CLASS::get ARGS)
> +
> + // Read all the records.
> + while (true) {
> + BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
> +
> + switch (Entry.Kind) {
> + case BitstreamEntry::SubBlock: // Handled for us already.
> + case BitstreamEntry::Error:
> + return error("Malformed block");
> + case BitstreamEntry::EndBlock:
> + // Upgrade old-style CU <-> SP pointers to point from SP to CU.
> + for (auto CU_SP : CUSubprograms)
> + if (auto *SPs = dyn_cast_or_null<MDTuple>(CU_SP.second))
> + for (auto &Op : SPs->operands())
> + if (auto *SP = dyn_cast_or_null<MDNode>(Op))
> + SP->replaceOperandWith(7, CU_SP.first);
> +
> + MetadataList.tryToResolveCycles();
> + Placeholders.flush(MetadataList);
> + return Error::success();
> + case BitstreamEntry::Record:
> + // The interesting case.
> + break;
> + }
> +
> + // Read a record.
> + Record.clear();
> + StringRef Blob;
> + unsigned Code = Stream.readRecord(Entry.ID, Record, &Blob);
> + IsDistinct = false;
> + switch (Code) {
> + default: // Default behavior: ignore.
> + break;
> + case bitc::METADATA_NAME: {
> + // Read name of the named metadata.
> + SmallString<8> Name(Record.begin(), Record.end());
> + Record.clear();
> + Code = Stream.ReadCode();
> +
> + unsigned NextBitCode = Stream.readRecord(Code, Record);
> + if (NextBitCode != bitc::METADATA_NAMED_NODE)
> + return error("METADATA_NAME not followed by
> METADATA_NAMED_NODE");
> +
> + // Read named metadata elements.
> + unsigned Size = Record.size();
> + NamedMDNode *NMD = TheModule.getOrInsertNamedMetadata(Name);
> + for (unsigned i = 0; i != Size; ++i) {
> + MDNode *MD = MetadataList.getMDNodeFwdRefOrNull(Record[i]);
> + if (!MD)
> + return error("Invalid record");
> + NMD->addOperand(MD);
> + }
> + break;
> + }
> + case bitc::METADATA_OLD_FN_NODE: {
> + // FIXME: Remove in 4.0.
> + // This is a LocalAsMetadata record, the only type of function-
> local
> + // metadata.
> + if (Record.size() % 2 == 1)
> + return error("Invalid record");
> +
> + // If this isn't a LocalAsMetadata record, we're dropping it. This
> used
> + // to be legal, but there's no upgrade path.
> + auto dropRecord = [&] {
> + MetadataList.assignValue(MDNode::get(Context, None),
> NextMetadataNo++);
> + };
> + if (Record.size() != 2) {
> + dropRecord();
> + break;
> + }
> +
> + Type *Ty = getTypeByID(Record[0]);
> + if (Ty->isMetadataTy() || Ty->isVoidTy()) {
> + dropRecord();
> + break;
> + }
> +
> + MetadataList.assignValue(
> + LocalAsMetadata::get(ValueList.getValueFwdRef(Record[1], Ty)),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_OLD_NODE: {
> + // FIXME: Remove in 4.0.
> + if (Record.size() % 2 == 1)
> + return error("Invalid record");
> +
> + unsigned Size = Record.size();
> + SmallVector<Metadata *, 8> Elts;
> + for (unsigned i = 0; i != Size; i += 2) {
> + Type *Ty = getTypeByID(Record[i]);
> + if (!Ty)
> + return error("Invalid record");
> + if (Ty->isMetadataTy())
> + Elts.push_back(getMD(Record[i + 1]));
> + 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);
> + }
> + MetadataList.assignValue(MDNode::get(Context, Elts),
> NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_VALUE: {
> + if (Record.size() != 2)
> + return error("Invalid record");
> +
> + Type *Ty = getTypeByID(Record[0]);
> + if (Ty->isMetadataTy() || Ty->isVoidTy())
> + return error("Invalid record");
> +
> + MetadataList.assignValue(
> + ValueAsMetadata::get(ValueList.getValueFwdRef(Record[1], Ty)),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_DISTINCT_NODE:
> + IsDistinct = true;
> + LLVM_FALLTHROUGH;
> + case bitc::METADATA_NODE: {
> + SmallVector<Metadata *, 8> Elts;
> + Elts.reserve(Record.size());
> + for (unsigned ID : Record)
> + Elts.push_back(getMDOrNull(ID));
> + MetadataList.assignValue(IsDistinct ? MDNode::getDistinct(Context,
> Elts)
> + : MDNode::get(Context, Elts),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_LOCATION: {
> + if (Record.size() != 5)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0];
> + unsigned Line = Record[1];
> + unsigned Column = Record[2];
> + Metadata *Scope = getMD(Record[3]);
> + Metadata *InlinedAt = getMDOrNull(Record[4]);
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DILocation,
> + (Context, Line, Column, Scope, InlinedAt)),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_GENERIC_DEBUG: {
> + if (Record.size() < 4)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0];
> + unsigned Tag = Record[1];
> + unsigned Version = Record[2];
> +
> + if (Tag >= 1u << 16 || Version != 0)
> + return error("Invalid record");
> +
> + auto *Header = getMDString(Record[3]);
> + SmallVector<Metadata *, 8> DwarfOps;
> + for (unsigned I = 4, E = Record.size(); I != E; ++I)
> + DwarfOps.push_back(getMDOrNull(Record[I]));
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(GenericDINode, (Context, Tag, Header,
> DwarfOps)),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_SUBRANGE: {
> + if (Record.size() != 3)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0];
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DISubrange,
> + (Context, Record[1], unrotateSign(Record[2]))),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_ENUMERATOR: {
> + if (Record.size() != 3)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0];
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DIEnumerator, (Context,
> unrotateSign(Record[1]),
> + getMDString(Record[2]))),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_BASIC_TYPE: {
> + if (Record.size() != 6)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0];
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DIBasicType,
> + (Context, Record[1], getMDString(Record[2]),
> + Record[3], Record[4], Record[5])),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_DERIVED_TYPE: {
> + if (Record.size() != 12)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0];
> + DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[10]);
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DIDerivedType,
> + (Context, Record[1], getMDString(Record[2]),
> + getMDOrNull(Record[3]), Record[4],
> + getDITypeRefOrNull(Record[5]),
> + getDITypeRefOrNull(Record[6]), Record[7],
> Record[8],
> + Record[9], Flags,
> getDITypeRefOrNull(Record[11]))),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_COMPOSITE_TYPE: {
> + if (Record.size() != 16)
> + return error("Invalid record");
> +
> + // If we have a UUID and this is not a forward declaration, lookup
> the
> + // mapping.
> + IsDistinct = Record[0] & 0x1;
> + bool IsNotUsedInTypeRef = Record[0] >= 2;
> + unsigned Tag = Record[1];
> + MDString *Name = getMDString(Record[2]);
> + Metadata *File = getMDOrNull(Record[3]);
> + unsigned Line = Record[4];
> + Metadata *Scope = getDITypeRefOrNull(Record[5]);
> + Metadata *BaseType = getDITypeRefOrNull(Record[6]);
> + uint64_t SizeInBits = Record[7];
> + if (Record[8] > (uint64_t)std::numeric_limits<uint32_t>::max())
> + return error("Alignment value is too large");
> + uint32_t AlignInBits = Record[8];
> + uint64_t OffsetInBits = Record[9];
> + DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[10]);
> + Metadata *Elements = getMDOrNull(Record[11]);
> + unsigned RuntimeLang = Record[12];
> + Metadata *VTableHolder = getDITypeRefOrNull(Record[13]);
> + Metadata *TemplateParams = getMDOrNull(Record[14]);
> + auto *Identifier = getMDString(Record[15]);
> + DICompositeType *CT = nullptr;
> + if (Identifier)
> + CT = DICompositeType::buildODRType(
> + Context, *Identifier, Tag, Name, File, Line, Scope, BaseType,
> + SizeInBits, AlignInBits, OffsetInBits, Flags, Elements,
> RuntimeLang,
> + VTableHolder, TemplateParams);
> +
> + // Create a node if we didn't get a lazy ODR type.
> + if (!CT)
> + CT = GET_OR_DISTINCT(DICompositeType,
> + (Context, Tag, Name, File, Line, Scope,
> BaseType,
> + SizeInBits, AlignInBits, OffsetInBits,
> Flags,
> + Elements, RuntimeLang, VTableHolder,
> + TemplateParams, Identifier));
> + if (!IsNotUsedInTypeRef && Identifier)
> + MetadataList.addTypeRef(*Identifier, *cast<DICompositeType>(CT));
> +
> + MetadataList.assignValue(CT, NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_SUBROUTINE_TYPE: {
> + if (Record.size() < 3 || Record.size() > 4)
> + return error("Invalid record");
> + bool IsOldTypeRefArray = Record[0] < 2;
> + unsigned CC = (Record.size() > 3) ? Record[3] : 0;
> +
> + IsDistinct = Record[0] & 0x1;
> + DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[1]);
> + Metadata *Types = getMDOrNull(Record[2]);
> + if (LLVM_UNLIKELY(IsOldTypeRefArray))
> + Types = MetadataList.upgradeTypeRefArray(Types);
> +
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DISubroutineType, (Context, Flags, CC, Types)),
> + NextMetadataNo++);
> + break;
> + }
> +
> + case bitc::METADATA_MODULE: {
> + if (Record.size() != 6)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0];
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DIModule,
> + (Context, getMDOrNull(Record[1]),
> + getMDString(Record[2]),
> getMDString(Record[3]),
> + getMDString(Record[4]),
> getMDString(Record[5]))),
> + NextMetadataNo++);
> + break;
> + }
> +
> + case bitc::METADATA_FILE: {
> + if (Record.size() != 3)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0];
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DIFile, (Context, getMDString(Record[1]),
> + getMDString(Record[2]))),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_COMPILE_UNIT: {
> + if (Record.size() < 14 || Record.size() > 17)
> + return error("Invalid record");
> +
> + // Ignore Record[0], which indicates whether this compile unit is
> + // distinct. It's always distinct.
> + IsDistinct = true;
> + auto *CU = DICompileUnit::getDistinct(
> + Context, Record[1], getMDOrNull(Record[2]),
> getMDString(Record[3]),
> + Record[4], getMDString(Record[5]), Record[6],
> getMDString(Record[7]),
> + Record[8], getMDOrNull(Record[9]), getMDOrNull(Record[10]),
> + getMDOrNull(Record[12]), getMDOrNull(Record[13]),
> + Record.size() <= 15 ? nullptr : getMDOrNull(Record[15]),
> + Record.size() <= 14 ? 0 : Record[14],
> + Record.size() <= 16 ? true : Record[16]);
> +
> + MetadataList.assignValue(CU, NextMetadataNo++);
> +
> + // Move the Upgrade the list of subprograms.
> + if (Metadata *SPs = getMDOrNullWithoutPlaceholders(Record[11]))
> + CUSubprograms.push_back({CU, SPs});
> + break;
> + }
> + case bitc::METADATA_SUBPROGRAM: {
> + if (Record.size() < 18 || Record.size() > 20)
> + return error("Invalid record");
> +
> + IsDistinct =
> + (Record[0] & 1) || Record[8]; // All definitions should be
> distinct.
> + // Version 1 has a Function as Record[15].
> + // Version 2 has removed Record[15].
> + // Version 3 has the Unit as Record[15].
> + // Version 4 added thisAdjustment.
> + bool HasUnit = Record[0] >= 2;
> + if (HasUnit && Record.size() < 19)
> + return error("Invalid record");
> + Metadata *CUorFn = getMDOrNull(Record[15]);
> + unsigned Offset = Record.size() >= 19 ? 1 : 0;
> + bool HasFn = Offset && !HasUnit;
> + bool HasThisAdj = Record.size() >= 20;
> + DISubprogram *SP = GET_OR_DISTINCT(
> + DISubprogram, (Context,
> + getDITypeRefOrNull(Record[1]), // scope
> + getMDString(Record[2]), // name
> + getMDString(Record[3]), // linkageName
> + getMDOrNull(Record[4]), // file
> + Record[5], // line
> + getMDOrNull(Record[6]), // type
> + Record[7], // isLocal
> + Record[8], // isDefinition
> + Record[9], // scopeLine
> + getDITypeRefOrNull(Record[10]), //
> containingType
> + Record[11], // virtuality
> + Record[12], // virtualIndex
> + HasThisAdj ? Record[19] : 0, //
> thisAdjustment
> + static_cast<DINode::DIFlags>(Record[13] // flags
> + ),
> + Record[14], // isOptimized
> + HasUnit ? CUorFn : nullptr, // unit
> + getMDOrNull(Record[15 + Offset]), //
> templateParams
> + getMDOrNull(Record[16 + Offset]), // declaration
> + getMDOrNull(Record[17 + Offset]) // variables
> + ));
> + MetadataList.assignValue(SP, NextMetadataNo++);
> +
> + // Upgrade sp->function mapping to function->sp mapping.
> + if (HasFn) {
> + if (auto *CMD = dyn_cast_or_null<ConstantAsMetadata>(CUorFn))
> + if (auto *F = dyn_cast<Function>(CMD->getValue())) {
> + if (F->isMaterializable())
> + // Defer until materialized; unmaterialized functions may
> not have
> + // metadata.
> + FunctionsWithSPs[F] = SP;
> + else if (!F->empty())
> + F->setSubprogram(SP);
> + }
> + }
> + break;
> + }
> + case bitc::METADATA_LEXICAL_BLOCK: {
> + if (Record.size() != 5)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0];
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DILexicalBlock,
> + (Context, getMDOrNull(Record[1]),
> + getMDOrNull(Record[2]), Record[3],
> Record[4])),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_LEXICAL_BLOCK_FILE: {
> + if (Record.size() != 4)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0];
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DILexicalBlockFile,
> + (Context, getMDOrNull(Record[1]),
> + getMDOrNull(Record[2]), Record[3])),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_NAMESPACE: {
> + if (Record.size() != 5)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0] & 1;
> + bool ExportSymbols = Record[0] & 2;
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DINamespace,
> + (Context, getMDOrNull(Record[1]),
> + getMDOrNull(Record[2]),
> getMDString(Record[3]),
> + Record[4], ExportSymbols)),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_MACRO: {
> + if (Record.size() != 5)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0];
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DIMacro,
> + (Context, Record[1], Record[2],
> + getMDString(Record[3]),
> getMDString(Record[4]))),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_MACRO_FILE: {
> + if (Record.size() != 5)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0];
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DIMacroFile,
> + (Context, Record[1], Record[2],
> + getMDOrNull(Record[3]),
> getMDOrNull(Record[4]))),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_TEMPLATE_TYPE: {
> + if (Record.size() != 3)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0];
> + MetadataList.assignValue(GET_OR_DISTINCT(DITemplateTypeParameter,
> + (Context,
> getMDString(Record[1]),
> +
> getDITypeRefOrNull(Record[2]))),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_TEMPLATE_VALUE: {
> + if (Record.size() != 5)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0];
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DITemplateValueParameter,
> + (Context, Record[1], getMDString(Record[2]),
> + getDITypeRefOrNull(Record[3]),
> + getMDOrNull(Record[4]))),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_GLOBAL_VAR: {
> + if (Record.size() < 11 || Record.size() > 12)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0];
> +
> + // Upgrade old metadata, which stored a global variable reference
> or a
> + // ConstantInt here.
> + Metadata *Expr = getMDOrNull(Record[9]);
> + uint32_t AlignInBits = 0;
> + if (Record.size() > 11) {
> + if (Record[11] > (uint64_t)std::numeric_limits<uint32_t>::max())
> + return error("Alignment value is too large");
> + AlignInBits = Record[11];
> + }
> + GlobalVariable *Attach = nullptr;
> + if (auto *CMD = dyn_cast_or_null<ConstantAsMetadata>(Expr)) {
> + if (auto *GV = dyn_cast<GlobalVariable>(CMD->getValue())) {
> + Attach = GV;
> + Expr = nullptr;
> + } else if (auto *CI = dyn_cast<ConstantInt>(CMD->getValue())) {
> + Expr = DIExpression::get(Context,
> + {dwarf::DW_OP_constu, CI-
> >getZExtValue(),
> + dwarf::DW_OP_stack_value});
> + } else {
> + Expr = nullptr;
> + }
> + }
> +
> + DIGlobalVariable *DGV = GET_OR_DISTINCT(
> + DIGlobalVariable,
> + (Context, getMDOrNull(Record[1]), getMDString(Record[2]),
> + getMDString(Record[3]), getMDOrNull(Record[4]), Record[5],
> + getDITypeRefOrNull(Record[6]), Record[7], Record[8], Expr,
> + getMDOrNull(Record[10]), AlignInBits));
> + MetadataList.assignValue(DGV, NextMetadataNo++);
> +
> + if (Attach)
> + Attach->addDebugInfo(DGV);
> +
> + break;
> + }
> + case bitc::METADATA_LOCAL_VAR: {
> + // 10th field is for the obseleted 'inlinedAt:' field.
> + if (Record.size() < 8 || Record.size() > 10)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0] & 1;
> + bool HasAlignment = Record[0] & 2;
> + // 2nd field used to be an artificial tag, either
> DW_TAG_auto_variable or
> + // DW_TAG_arg_variable, if we have alignment flag encoded it means,
> that
> + // this is newer version of record which doesn't have artifical
> tag.
> + bool HasTag = !HasAlignment && Record.size() > 8;
> + DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[7 +
> HasTag]);
> + uint32_t AlignInBits = 0;
> + if (HasAlignment) {
> + if (Record[8 + HasTag] >
> (uint64_t)std::numeric_limits<uint32_t>::max())
> + return error("Alignment value is too large");
> + AlignInBits = Record[8 + HasTag];
> + }
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DILocalVariable,
> + (Context, getMDOrNull(Record[1 + HasTag]),
> + getMDString(Record[2 + HasTag]),
> + getMDOrNull(Record[3 + HasTag]), Record[4 +
> HasTag],
> + getDITypeRefOrNull(Record[5 + HasTag]),
> + Record[6 + HasTag], Flags, AlignInBits)),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_EXPRESSION: {
> + if (Record.size() < 1)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0] & 1;
> + bool HasOpFragment = Record[0] & 2;
> + auto Elts = MutableArrayRef<uint64_t>(Record).slice(1);
> + if (!HasOpFragment)
> + if (unsigned N = Elts.size())
> + if (N >= 3 && Elts[N - 3] == dwarf::DW_OP_bit_piece)
> + Elts[N - 3] = dwarf::DW_OP_LLVM_fragment;
> +
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DIExpression,
> + (Context, makeArrayRef(Record).slice(1))),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_OBJC_PROPERTY: {
> + if (Record.size() != 8)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0];
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DIObjCProperty,
> + (Context, getMDString(Record[1]),
> + getMDOrNull(Record[2]), Record[3],
> + getMDString(Record[4]),
> getMDString(Record[5]),
> + Record[6], getDITypeRefOrNull(Record[7]))),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_IMPORTED_ENTITY: {
> + if (Record.size() != 6)
> + return error("Invalid record");
> +
> + IsDistinct = Record[0];
> + MetadataList.assignValue(
> + GET_OR_DISTINCT(DIImportedEntity,
> + (Context, Record[1], getMDOrNull(Record[2]),
> + getDITypeRefOrNull(Record[3]), Record[4],
> + getMDString(Record[5]))),
> + NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_STRING_OLD: {
> + std::string String(Record.begin(), Record.end());
> +
> + // Test for upgrading !llvm.loop.
> + HasSeenOldLoopTags |= mayBeOldLoopAttachmentTag(String);
> +
> + Metadata *MD = MDString::get(Context, String);
> + MetadataList.assignValue(MD, NextMetadataNo++);
> + break;
> + }
> + case bitc::METADATA_STRINGS:
> + if (Error Err = parseMetadataStrings(Record, Blob, NextMetadataNo))
> + return Err;
> + break;
> + case bitc::METADATA_GLOBAL_DECL_ATTACHMENT: {
> + if (Record.size() % 2 == 0)
> + return error("Invalid record");
> + unsigned ValueID = Record[0];
> + if (ValueID >= ValueList.size())
> + return error("Invalid record");
> + if (auto *GO = dyn_cast<GlobalObject>(ValueList[ValueID]))
> + if (Error Err = parseGlobalObjectAttachment(
> + *GO, ArrayRef<uint64_t>(Record).slice(1)))
> + return Err;
> + break;
> + }
> + case bitc::METADATA_KIND: {
> + // Support older bitcode files that had METADATA_KIND records in a
> + // block with METADATA_BLOCK_ID.
> + if (Error Err = parseMetadataKindRecord(Record))
> + return Err;
> + break;
> + }
> + }
> + }
> +#undef GET_OR_DISTINCT
> +}
> +
> +Error MetadataLoader::MetadataLoaderImpl::parseMetadataStrings(
> + ArrayRef<uint64_t> Record, StringRef Blob, unsigned &NextMetadataNo)
> {
> + // All the MDStrings in the block are emitted together in a single
> + // record. The strings are concatenated and stored in a blob along
> with
> + // their sizes.
> + if (Record.size() != 2)
> + return error("Invalid record: metadata strings layout");
> +
> + unsigned NumStrings = Record[0];
> + unsigned StringsOffset = Record[1];
> + if (!NumStrings)
> + return error("Invalid record: metadata strings with no strings");
> + if (StringsOffset > Blob.size())
> + return error("Invalid record: metadata strings corrupt offset");
> +
> + StringRef Lengths = Blob.slice(0, StringsOffset);
> + SimpleBitstreamCursor R(Lengths);
> +
> + StringRef Strings = Blob.drop_front(StringsOffset);
> + do {
> + if (R.AtEndOfStream())
> + return error("Invalid record: metadata strings bad length");
> +
> + unsigned Size = R.ReadVBR(6);
> + if (Strings.size() < Size)
> + return error("Invalid record: metadata strings truncated chars");
> +
> + MetadataList.assignValue(MDString::get(Context, Strings.slice(0,
> Size)),
> + NextMetadataNo++);
> + Strings = Strings.drop_front(Size);
> + } while (--NumStrings);
> +
> + return Error::success();
> +}
> +
> +Error MetadataLoader::MetadataLoaderImpl::parseGlobalObjectAttachment(
> + GlobalObject &GO, ArrayRef<uint64_t> Record) {
> + assert(Record.size() % 2 == 0);
> + for (unsigned I = 0, E = Record.size(); I != E; I += 2) {
> + auto K = MDKindMap.find(Record[I]);
> + if (K == MDKindMap.end())
> + return error("Invalid ID");
> + MDNode *MD = MetadataList.getMDNodeFwdRefOrNull(Record[I + 1]);
> + if (!MD)
> + return error("Invalid metadata attachment");
> + GO.addMetadata(K->second, *MD);
> + }
> + return Error::success();
> +}
> +
> +/// Parse metadata attachments.
> +Error MetadataLoader::MetadataLoaderImpl::parseMetadataAttachment(
> + Function &F, const SmallVectorImpl<Instruction *> &InstructionList) {
> + if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
> + return error("Invalid record");
> +
> + SmallVector<uint64_t, 64> Record;
> +
> + while (true) {
> + BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
> +
> + switch (Entry.Kind) {
> + case BitstreamEntry::SubBlock: // Handled for us already.
> + case BitstreamEntry::Error:
> + return error("Malformed block");
> + case BitstreamEntry::EndBlock:
> + return Error::success();
> + case BitstreamEntry::Record:
> + // The interesting case.
> + break;
> + }
> +
> + // Read a metadata attachment record.
> + Record.clear();
> + switch (Stream.readRecord(Entry.ID, Record)) {
> + default: // Default behavior: ignore.
> + break;
> + case bitc::METADATA_ATTACHMENT: {
> + unsigned RecordLength = Record.size();
> + if (Record.empty())
> + return error("Invalid record");
> + if (RecordLength % 2 == 0) {
> + // A function attachment.
> + if (Error Err = parseGlobalObjectAttachment(F, Record))
> + return Err;
> + continue;
> + }
> +
> + // An instruction attachment.
> + Instruction *Inst = InstructionList[Record[0]];
> + for (unsigned i = 1; i != RecordLength; i = i + 2) {
> + unsigned Kind = Record[i];
> + DenseMap<unsigned, unsigned>::iterator I = MDKindMap.find(Kind);
> + if (I == MDKindMap.end())
> + return error("Invalid ID");
> + Metadata *Node = MetadataList.getMetadataFwdRef(Record[i + 1]);
> + if (isa<LocalAsMetadata>(Node))
> + // Drop the attachment. This used to be legal, but there's no
> + // upgrade path.
> + break;
> + MDNode *MD = dyn_cast_or_null<MDNode>(Node);
> + if (!MD)
> + return error("Invalid metadata attachment");
> +
> + if (HasSeenOldLoopTags && I->second == LLVMContext::MD_loop)
> + MD = upgradeInstructionLoopAttachment(*MD);
> +
> + if (I->second == LLVMContext::MD_tbaa) {
> + assert(!MD->isTemporary() && "should load MDs before
> attachments");
> + MD = UpgradeTBAANode(*MD);
> + }
> + Inst->setMetadata(I->second, MD);
> + }
> + break;
> + }
> + }
> + }
> +}
> +
> +/// Parse a single METADATA_KIND record, inserting result in MDKindMap.
> +Error MetadataLoader::MetadataLoaderImpl::parseMetadataKindRecord(
> + SmallVectorImpl<uint64_t> &Record) {
> + if (Record.size() < 2)
> + return error("Invalid record");
> +
> + unsigned Kind = Record[0];
> + SmallString<8> Name(Record.begin() + 1, Record.end());
> +
> + unsigned NewKind = TheModule.getMDKindID(Name.str());
> + if (!MDKindMap.insert(std::make_pair(Kind, NewKind)).second)
> + return error("Conflicting METADATA_KIND records");
> + return Error::success();
> +}
> +
> +/// Parse the metadata kinds out of the METADATA_KIND_BLOCK.
> +Error MetadataLoader::MetadataLoaderImpl::parseMetadataKinds() {
> + if (Stream.EnterSubBlock(bitc::METADATA_KIND_BLOCK_ID))
> + return error("Invalid record");
> +
> + SmallVector<uint64_t, 64> Record;
> +
> + // Read all the records.
> + while (true) {
> + BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
> +
> + switch (Entry.Kind) {
> + case BitstreamEntry::SubBlock: // Handled for us already.
> + case BitstreamEntry::Error:
> + return error("Malformed block");
> + case BitstreamEntry::EndBlock:
> + return Error::success();
> + case BitstreamEntry::Record:
> + // The interesting case.
> + break;
> + }
> +
> + // Read a record.
> + Record.clear();
> + unsigned Code = Stream.readRecord(Entry.ID, Record);
> + switch (Code) {
> + default: // Default behavior: ignore.
> + break;
> + case bitc::METADATA_KIND: {
> + if (Error Err = parseMetadataKindRecord(Record))
> + return Err;
> + break;
> + }
> + }
> + }
> +}
> +
> +MetadataLoader &MetadataLoader::operator=(MetadataLoader &&RHS) {
> + Pimpl = std::move(RHS.Pimpl);
> + return *this;
> +}
> +MetadataLoader::MetadataLoader(MetadataLoader &&RHS)
> + : Pimpl(std::move(RHS.Pimpl)) {}
> +
> +MetadataLoader::~MetadataLoader() = default;
> +MetadataLoader::MetadataLoader(BitstreamCursor &Stream, Module
> &TheModule,
> + BitcodeReaderValueList &ValueList,
> + std::function<Type *(unsigned)>
> getTypeByID)
> + : Pimpl(make_unique<MetadataLoaderImpl>(Stream, TheModule, ValueList,
> + getTypeByID)) {}
> +
> +Error MetadataLoader::parseMetadata(bool ModuleLevel) {
> + return Pimpl->parseMetadata(ModuleLevel);
> +}
> +
> +bool MetadataLoader::hasFwdRefs() const { return Pimpl->hasFwdRefs(); }
> +
> +/// Return the given metadata, creating a replaceable forward reference
> if
> +/// necessary.
> +Metadata *MetadataLoader::getMetadataFwdRef(unsigned Idx) {
> + return Pimpl->getMetadataFwdRef(Idx);
> +}
> +
> +MDNode *MetadataLoader::getMDNodeFwdRefOrNull(unsigned Idx) {
> + return Pimpl->getMDNodeFwdRefOrNull(Idx);
> +}
> +
> +DISubprogram *MetadataLoader::lookupSubprogramForFunction(Function *F) {
> + return Pimpl->lookupSubprogramForFunction(F);
> +}
> +
> +Error MetadataLoader::parseMetadataAttachment(
> + Function &F, const SmallVectorImpl<Instruction *> &InstructionList) {
> + return Pimpl->parseMetadataAttachment(F, InstructionList);
> +}
> +
> +Error MetadataLoader::parseMetadataKinds() {
> + return Pimpl->parseMetadataKinds();
> +}
> +
> +unsigned MetadataLoader::size() const { return Pimpl->size(); }
> +void MetadataLoader::shrinkTo(unsigned N) { return Pimpl->shrinkTo(N); }
>
> Added: llvm/trunk/lib/Bitcode/Reader/MetadataLoader.h
> URL: http://llvm.org/viewvc/llvm-
> project/llvm/trunk/lib/Bitcode/Reader/MetadataLoader.h?rev=289461&view=aut
> o
> ==========================================================================
> ====
> --- llvm/trunk/lib/Bitcode/Reader/MetadataLoader.h (added)
> +++ llvm/trunk/lib/Bitcode/Reader/MetadataLoader.h Mon Dec 12 13:34:26
> 2016
> @@ -0,0 +1,79 @@
> +//===-- Bitcode/Reader/MetadataLoader.h - Load Metadatas -------*- C++ -
> *-====//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===--------------------------------------------------------------------
> --===//
> +//
> +// This class handles loading Metadatas.
> +//
> +//===--------------------------------------------------------------------
> --===//
> +
> +#ifndef LLVM_LIB_BITCODE_READER_METADATALOADER_H
> +#define LLVM_LIB_BITCODE_READER_METADATALOADER_H
> +
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/Support/Error.h"
> +
> +#include <functional>
> +#include <memory>
> +
> +namespace llvm {
> +class BitcodeReaderValueList;
> +class BitstreamCursor;
> +class DISubprogram;
> +class Error;
> +class Function;
> +class Instruction;
> +class Metadata;
> +class MDNode;
> +class Module;
> +class Type;
> +
> +/// Helper class that handles loading Metadatas and keeping them
> available.
> +class MetadataLoader {
> + class MetadataLoaderImpl;
> + std::unique_ptr<MetadataLoaderImpl> Pimpl;
> + Error parseMetadata(bool ModuleLevel);
> +
> +public:
> + ~MetadataLoader();
> + MetadataLoader(BitstreamCursor &Stream, Module &TheModule,
> + BitcodeReaderValueList &ValueList,
> + std::function<Type *(unsigned)> getTypeByID);
> + MetadataLoader &operator=(MetadataLoader &&);
> + MetadataLoader(MetadataLoader &&);
> +
> + // Parse a module metadata block
> + Error parseModuleMetadata() { return parseMetadata(true); }
> +
> + // Parse a function metadata block
> + Error parseFunctionMetadata() { return parseMetadata(false); }
> +
> + // Return true there are remaining unresolved forward references.
> + bool hasFwdRefs() const;
> +
> + /// Return the given metadata, creating a replaceable forward reference
> if
> + /// necessary.
> + Metadata *getMetadataFwdRef(unsigned Idx);
> +
> + MDNode *getMDNodeFwdRefOrNull(unsigned Idx);
> +
> + /// Return the DISubprogra metadata for a Function if any, null
> otherwise.
> + DISubprogram *lookupSubprogramForFunction(Function *F);
> +
> + /// Parse a `METADATA_ATTACHMENT` block for a function.
> + Error parseMetadataAttachment(
> + Function &F, const SmallVectorImpl<Instruction *>
> &InstructionList);
> +
> + /// Parse a `METADATA_KIND` block for the current module.
> + Error parseMetadataKinds();
> +
> + unsigned size() const;
> + void shrinkTo(unsigned N);
> +};
> +}
> +
> +#endif // LLVM_LIB_BITCODE_READER_METADATALOADER_H
>
> Added: llvm/trunk/lib/Bitcode/Reader/ValueList.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/llvm/trunk/lib/Bitcode/Reader/ValueList.cpp?rev=289461&view=auto
> ==========================================================================
> ====
> --- llvm/trunk/lib/Bitcode/Reader/ValueList.cpp (added)
> +++ llvm/trunk/lib/Bitcode/Reader/ValueList.cpp Mon Dec 12 13:34:26 2016
> @@ -0,0 +1,199 @@
> +//===----- ValueList.cpp - Internal BitcodeReader implementation --------
> --===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===--------------------------------------------------------------------
> --===//
> +
> +#include "ValueList.h"
> +#include "llvm/IR/Constants.h"
> +#include "llvm/IR/Instructions.h"
> +
> +using namespace llvm;
> +
> +namespace llvm {
> +namespace {
> +
> +/// \brief A class for maintaining the slot number definition
> +/// as a placeholder for the actual definition for forward constants
> defs.
> +class ConstantPlaceHolder : public ConstantExpr {
> + void operator=(const ConstantPlaceHolder &) = delete;
> +
> +public:
> + // allocate space for exactly one operand
> + void *operator new(size_t s) { return User::operator new(s, 1); }
> + explicit ConstantPlaceHolder(Type *Ty, LLVMContext &Context)
> + : ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) {
> + Op<0>() = UndefValue::get(Type::getInt32Ty(Context));
> + }
> +
> + /// \brief Methods to support type inquiry through isa, cast, and
> dyn_cast.
> + static bool classof(const Value *V) {
> + return isa<ConstantExpr>(V) &&
> + cast<ConstantExpr>(V)->getOpcode() == Instruction::UserOp1;
> + }
> +
> + /// Provide fast operand accessors
> + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
> +};
> +
> +} // end anonymous namespace
> +
> +// FIXME: can we inherit this from ConstantExpr?
> +template <>
> +struct OperandTraits<ConstantPlaceHolder>
> + : public FixedNumOperandTraits<ConstantPlaceHolder, 1> {};
> +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantPlaceHolder, Value)
> +
> +} // end namespace llvm
> +
> +void BitcodeReaderValueList::assignValue(Value *V, unsigned Idx) {
> + if (Idx == size()) {
> + push_back(V);
> + return;
> + }
> +
> + if (Idx >= size())
> + resize(Idx + 1);
> +
> + WeakVH &OldV = ValuePtrs[Idx];
> + if (!OldV) {
> + OldV = V;
> + return;
> + }
> +
> + // Handle constants and non-constants (e.g. instrs) differently for
> + // efficiency.
> + if (Constant *PHC = dyn_cast<Constant>(&*OldV)) {
> + ResolveConstants.push_back(std::make_pair(PHC, Idx));
> + OldV = V;
> + } else {
> + // If there was a forward reference to this value, replace it.
> + Value *PrevVal = OldV;
> + OldV->replaceAllUsesWith(V);
> + delete PrevVal;
> + }
> +}
> +
> +Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx, Type
> *Ty) {
> + if (Idx >= size())
> + resize(Idx + 1);
> +
> + if (Value *V = ValuePtrs[Idx]) {
> + if (Ty != V->getType())
> + report_fatal_error("Type mismatch in constant table!");
> + return cast<Constant>(V);
> + }
> +
> + // Create and return a placeholder, which will later be RAUW'd.
> + Constant *C = new ConstantPlaceHolder(Ty, Context);
> + ValuePtrs[Idx] = C;
> + return C;
> +}
> +
> +Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) {
> + // Bail out for a clearly invalid value. This would make us call
> resize(0)
> + if (Idx == std::numeric_limits<unsigned>::max())
> + return nullptr;
> +
> + if (Idx >= size())
> + resize(Idx + 1);
> +
> + if (Value *V = ValuePtrs[Idx]) {
> + // If the types don't match, it's invalid.
> + if (Ty && Ty != V->getType())
> + return nullptr;
> + return V;
> + }
> +
> + // No type specified, must be invalid reference.
> + if (!Ty)
> + return nullptr;
> +
> + // Create and return a placeholder, which will later be RAUW'd.
> + Value *V = new Argument(Ty);
> + ValuePtrs[Idx] = V;
> + return V;
> +}
> +
> +/// Once all constants are read, this method bulk resolves any forward
> +/// references. The idea behind this is that we sometimes get constants
> (such
> +/// as large arrays) which reference *many* forward ref constants.
> Replacing
> +/// each of these causes a lot of thrashing when building/reuniquing the
> +/// constant. Instead of doing this, we look at all the uses and rewrite
> all
> +/// the place holders at once for any constant that uses a placeholder.
> +void BitcodeReaderValueList::resolveConstantForwardRefs() {
> + // Sort the values by-pointer so that they are efficient to look up
> with a
> + // binary search.
> + std::sort(ResolveConstants.begin(), ResolveConstants.end());
> +
> + SmallVector<Constant *, 64> NewOps;
> +
> + while (!ResolveConstants.empty()) {
> + Value *RealVal = operator[](ResolveConstants.back().second);
> + Constant *Placeholder = ResolveConstants.back().first;
> + ResolveConstants.pop_back();
> +
> + // Loop over all users of the placeholder, updating them to reference
> the
> + // new value. If they reference more than one placeholder, update
> them all
> + // at once.
> + while (!Placeholder->use_empty()) {
> + auto UI = Placeholder->user_begin();
> + User *U = *UI;
> +
> + // If the using object isn't uniqued, just update the operands.
> This
> + // handles instructions and initializers for global variables.
> + if (!isa<Constant>(U) || isa<GlobalValue>(U)) {
> + UI.getUse().set(RealVal);
> + continue;
> + }
> +
> + // Otherwise, we have a constant that uses the placeholder.
> Replace that
> + // constant with a new constant that has *all* placeholder uses
> updated.
> + Constant *UserC = cast<Constant>(U);
> + for (User::op_iterator I = UserC->op_begin(), E = UserC->op_end();
> I != E;
> + ++I) {
> + Value *NewOp;
> + if (!isa<ConstantPlaceHolder>(*I)) {
> + // Not a placeholder reference.
> + NewOp = *I;
> + } else if (*I == Placeholder) {
> + // Common case is that it just references this one placeholder.
> + NewOp = RealVal;
> + } else {
> + // Otherwise, look up the placeholder in ResolveConstants.
> + ResolveConstantsTy::iterator It = std::lower_bound(
> + ResolveConstants.begin(), ResolveConstants.end(),
> + std::pair<Constant *, unsigned>(cast<Constant>(*I), 0));
> + assert(It != ResolveConstants.end() && It->first == *I);
> + NewOp = operator[](It->second);
> + }
> +
> + NewOps.push_back(cast<Constant>(NewOp));
> + }
> +
> + // Make the new constant.
> + Constant *NewC;
> + if (ConstantArray *UserCA = dyn_cast<ConstantArray>(UserC)) {
> + NewC = ConstantArray::get(UserCA->getType(), NewOps);
> + } else if (ConstantStruct *UserCS =
> dyn_cast<ConstantStruct>(UserC)) {
> + NewC = ConstantStruct::get(UserCS->getType(), NewOps);
> + } else if (isa<ConstantVector>(UserC)) {
> + NewC = ConstantVector::get(NewOps);
> + } else {
> + assert(isa<ConstantExpr>(UserC) && "Must be a ConstantExpr.");
> + NewC = cast<ConstantExpr>(UserC)->getWithOperands(NewOps);
> + }
> +
> + UserC->replaceAllUsesWith(NewC);
> + UserC->destroyConstant();
> + NewOps.clear();
> + }
> +
> + // Update all ValueHandles, they should be the only users at this
> point.
> + Placeholder->replaceAllUsesWith(RealVal);
> + delete Placeholder;
> + }
> +}
>
> Added: llvm/trunk/lib/Bitcode/Reader/ValueList.h
> URL: http://llvm.org/viewvc/llvm-
> project/llvm/trunk/lib/Bitcode/Reader/ValueList.h?rev=289461&view=auto
> ==========================================================================
> ====
> --- llvm/trunk/lib/Bitcode/Reader/ValueList.h (added)
> +++ llvm/trunk/lib/Bitcode/Reader/ValueList.h Mon Dec 12 13:34:26 2016
> @@ -0,0 +1,76 @@
> +//===-- Bitcode/Reader/ValueEnumerator.h - Number values --------*- C++ -
> *-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===--------------------------------------------------------------------
> --===//
> +//
> +// This class gives values and types Unique ID's.
> +//
> +//===--------------------------------------------------------------------
> --===//
> +
> +#include "llvm/IR/LLVMContext.h"
> +#include "llvm/IR/ValueHandle.h"
> +
> +#include <vector>
> +
> +namespace llvm {
> +class Constant;
> +
> +class BitcodeReaderValueList {
> + std::vector<WeakVH> ValuePtrs;
> +
> + /// As we resolve forward-referenced constants, we add information
> about them
> + /// to this vector. This allows us to resolve them in bulk instead of
> + /// resolving each reference at a time. See the code in
> + /// ResolveConstantForwardRefs for more information about this.
> + ///
> + /// The key of this vector is the placeholder constant, the value is
> the slot
> + /// number that holds the resolved value.
> + typedef std::vector<std::pair<Constant *, unsigned>>
> ResolveConstantsTy;
> + ResolveConstantsTy ResolveConstants;
> + LLVMContext &Context;
> +
> +public:
> + BitcodeReaderValueList(LLVMContext &C) : Context(C) {}
> + ~BitcodeReaderValueList() {
> + assert(ResolveConstants.empty() && "Constants not resolved?");
> + }
> +
> + // vector compatibility methods
> + unsigned size() const { return ValuePtrs.size(); }
> + void resize(unsigned N) { ValuePtrs.resize(N); }
> + void push_back(Value *V) { ValuePtrs.emplace_back(V); }
> +
> + void clear() {
> + assert(ResolveConstants.empty() && "Constants not resolved?");
> + ValuePtrs.clear();
> + }
> +
> + Value *operator[](unsigned i) const {
> + assert(i < ValuePtrs.size());
> + return ValuePtrs[i];
> + }
> +
> + Value *back() const { return ValuePtrs.back(); }
> + void pop_back() { ValuePtrs.pop_back(); }
> + bool empty() const { return ValuePtrs.empty(); }
> +
> + void shrinkTo(unsigned N) {
> + assert(N <= size() && "Invalid shrinkTo request!");
> + ValuePtrs.resize(N);
> + }
> +
> + Constant *getConstantFwdRef(unsigned Idx, Type *Ty);
> + Value *getValueFwdRef(unsigned Idx, Type *Ty);
> +
> + void assignValue(Value *V, unsigned Idx);
> +
> + /// Once all constants are read, this method bulk resolves any forward
> + /// references.
> + void resolveConstantForwardRefs();
> +};
> +
> +} // namespace llvm
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list