Index: include/llvm/IR/BasicBlock.h =================================================================== --- include/llvm/IR/BasicBlock.h +++ include/llvm/IR/BasicBlock.h @@ -40,6 +40,7 @@ class PHINode; class TerminatorInst; class ValueSymbolTable; +class DILabel; /// \brief LLVM Basic Block Representation /// @@ -62,6 +63,15 @@ using InstListType = SymbolTableList; private: + enum { + LastRefCountBit = 3, + /// This is a bit stored in the SubClassData field which indicates whether + /// this basic block has metadata attached to it or not. + HasMetadataBit, + }; + static const unsigned RefCountBits = LastRefCountBit + 1; + static const unsigned RefCountMask = (1 << RefCountBits) - 1; + friend class BlockAddress; friend class SymbolTableListTraits; @@ -373,7 +383,9 @@ /// \brief Returns true if there are any uses of this basic block other than /// direct branches, switches, etc. to it. - bool hasAddressTaken() const { return getSubclassDataFromValue() != 0; } + bool hasAddressTaken() const { + return (getSubclassDataFromValue() & RefCountMask) != 0; + } /// \brief Update all phi nodes in this basic block's successors to refer to /// basic block \p New instead of to it. @@ -400,15 +412,61 @@ Optional getIrrLoopHeaderWeight() const; + //===--------------------------------------------------------------------===// + // Metadata manipulation. + //===--------------------------------------------------------------------===// + + /// Return true if this basic block has any metadata attached to it. + bool hasMetadata() const { return hasMetadataHashEntry(); } + + /// Get the metadata of given kind attached to this Basic Block. + /// If the metadata is not found then return null. + MDNode *getMetadata(unsigned KindID) const; + MDNode *getMetadata(StringRef Kind) const; + + /// Get all metadata attached to this BasicBlock. The first element of each + /// pair returned is the KindID, the second element is the metadata value. + /// This list is returned sorted by the KindID. + void + getAllMetadata(SmallVectorImpl> &MDs) const; + + /// Set the metadata of the specified kind to the specified node. This updates + /// or replaces metadata if already present, or removes it if Node is null. + void setMetadata(unsigned KindID, MDNode *Node); + void setMetadata(StringRef Kind, MDNode *Node); + + /// \brief Set the attached label. + /// + /// Calls \a setMetadata() with \a LLVMContext::MD_dbg. + void setLabel(DILabel *L); + + /// \brief Get the attached label. + /// + /// Calls \a getMetadata() with \a LLVMContext::MD_dbg and casts the result + /// to \a DILabel. + DILabel *getLabel() const; + private: + /// Return true if we have an entry in the on-the-side metadata hash. + bool hasMetadataHashEntry() const { + return (getSubclassDataFromValue() & HasMetadataBit) != 0; + } + + void setHasMetadataHashEntry(bool V) { + setValueSubclassData((getSubclassDataFromValue() & ~HasMetadataBit) | + (V ? HasMetadataBit : 0)); + } + /// \brief Increment the internal refcount of the number of BlockAddresses /// referencing this BasicBlock by \p Amt. /// /// This is almost always 0, sometimes one possibly, but almost never 2, and /// inconceivably 3 or more. void AdjustBlockAddressRefCount(int Amt) { - setValueSubclassData(getSubclassDataFromValue()+Amt); - assert((int)(signed char)getSubclassDataFromValue() >= 0 && + auto RefCount = getSubclassDataFromValue() & RefCountMask; + setValueSubclassData((getSubclassDataFromValue() & ~RefCountMask) + | (RefCount + Amt)); + assert((int)(signed char)(getSubclassDataFromValue() & RefCountMask) >= 0 && "Refcount wrap-around"); } Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -776,6 +776,9 @@ /// Add all of the metadata from a function. void processFunctionMetadata(const Function &F); + /// Add all of the metadata from a basic block. + void processBasicBlockMetadata(const BasicBlock &BB); + /// Add all of the metadata from an instruction. void processInstructionMetadata(const Instruction &I); }; @@ -977,11 +980,17 @@ void SlotTracker::processFunctionMetadata(const Function &F) { processGlobalObjectMetadata(F); for (auto &BB : F) { + processBasicBlockMetadata(BB); for (auto &I : BB) processInstructionMetadata(I); } } +void SlotTracker::processBasicBlockMetadata(const BasicBlock &BB) { + if (MDNode *N = BB.getLabel()) + CreateMetadataSlot(N); +} + void SlotTracker::processInstructionMetadata(const Instruction &I) { // Process metadata used directly by intrinsics. if (const CallInst *CI = dyn_cast(&I)) @@ -2917,6 +2926,11 @@ Out << ""; } + // Print Metadata info. + SmallVector, 4> InstMD; + BB->getAllMetadata(InstMD); + printMetadataAttachments(InstMD, " "); + if (!BB->getParent()) { Out.PadToColumn(50); Out << "; Error: Block without parent!"; Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -1319,6 +1319,9 @@ /// Collection of per-instruction metadata used in this context. DenseMap InstructionMetadata; + /// Collection of per-basicblock metadata used in this context. + DenseMap BasicBlockMetadata; + /// Collection of per-GlobalObject metadata used in this context. DenseMap GlobalObjectMetadata; Index: lib/IR/Metadata.cpp =================================================================== --- lib/IR/Metadata.cpp +++ lib/IR/Metadata.cpp @@ -1526,3 +1526,78 @@ for (MDNode *MD : MDs) GVs.push_back(cast(MD)); } + +MDNode *BasicBlock::getMetadata(unsigned KindID) const { + if (!hasMetadata()) + return nullptr; + auto &Info = getContext().pImpl->BasicBlockMetadata[this]; + assert(!Info.empty() && "bit out of sync with hash table"); + + return Info.lookup(KindID); +} + +MDNode *BasicBlock::getMetadata(StringRef Kind) const { + return getMetadata(getContext().getMDKindID(Kind)); +} + +void BasicBlock::setMetadata(unsigned KindID, MDNode *Node) { + if (!Node && !hasMetadata()) + return; + + // Handle the case when we're adding/updating metadata on an basic block. + if (Node) { + auto &Info = getContext().pImpl->BasicBlockMetadata[this]; + assert(!Info.empty() == hasMetadataHashEntry() && + "HasMetadata bit is wonked"); + if (Info.empty()) + setHasMetadataHashEntry(true); + Info.set(KindID, *Node); + return; + } + + // Otherwise, we're removing metadata from an basic block. + assert((hasMetadataHashEntry() == + (getContext().pImpl->BasicBlockMetadata.count(this) > 0)) && + "HasMetadata bit out of date!"); + if (!hasMetadataHashEntry()) + return; // Nothing to remove! + auto &Info = getContext().pImpl->BasicBlockMetadata[this]; + + // Handle removal of an existing value. + Info.erase(KindID); + + if (!Info.empty()) + return; + + getContext().pImpl->BasicBlockMetadata.erase(this); + setHasMetadataHashEntry(false); +} + +void BasicBlock::setMetadata(StringRef Kind, MDNode *Node) { + if (!Node && !hasMetadata()) + return; + setMetadata(getContext().getMDKindID(Kind), Node); +} + +void BasicBlock::getAllMetadata( + SmallVectorImpl> &Result) const { + Result.clear(); + + if (!hasMetadata()) + return; + + assert(hasMetadataHashEntry() && + getContext().pImpl->BasicBlockMetadata.count(this) && + "Shouldn't have called this"); + const auto &Info = getContext().pImpl->BasicBlockMetadata.find(this)->second; + assert(!Info.empty() && "Shouldn't have called this"); + Info.getAll(Result); +} + +void BasicBlock::setLabel(DILabel *L) { + setMetadata(LLVMContext::MD_dbg, L); +} + +DILabel *BasicBlock::getLabel() const { + return cast_or_null(getMetadata(LLVMContext::MD_dbg)); +}