From fa4e4af5c94d328f426254c55f30e8eed11e8ce3 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Tue, 31 May 2016 23:01:54 +0000 Subject: [PATCH] Add support for metadata attachments for global variables. This patch adds an IR, assembly and bitcode representation for metadata attachments for globals. Future patches will port existing features to use these new attachments. Differential Revision: http://reviews.llvm.org/D20074 llvm-svn: 271348 --- docs/BitCodeFormat.rst | 10 +++++ docs/LangRef.rst | 5 ++- include/llvm/Bitcode/LLVMBitCodes.h | 3 ++ include/llvm/IR/Function.h | 45 +-------------------- include/llvm/IR/GlobalObject.h | 54 +++++++++++++++++++++++++- include/llvm/IR/GlobalVariable.h | 4 ++ lib/AsmParser/LLParser.cpp | 24 ++++++++---- lib/AsmParser/LLParser.h | 1 + lib/Bitcode/Reader/BitcodeReader.cpp | 39 ++++++++++++++----- lib/Bitcode/Writer/BitcodeWriter.cpp | 42 ++++++++++++++------ lib/Bitcode/Writer/ValueEnumerator.cpp | 16 +++++--- lib/Bitcode/Writer/ValueEnumerator.h | 4 +- lib/IR/AsmWriter.cpp | 15 ++++++- lib/IR/Function.cpp | 6 ++- lib/IR/Globals.cpp | 10 +++-- lib/IR/LLVMContextImpl.h | 4 +- lib/IR/Metadata.cpp | 26 ++++++------- test/Assembler/metadata.ll | 19 ++++++--- 18 files changed, 217 insertions(+), 110 deletions(-) diff --git a/docs/BitCodeFormat.rst b/docs/BitCodeFormat.rst index edab66ead64..ac051c49bc8 100644 --- a/docs/BitCodeFormat.rst +++ b/docs/BitCodeFormat.rst @@ -856,6 +856,16 @@ be one ``GCNAME`` record for each garbage collector name referenced in function ``gc`` attributes within the module. These records can be referenced by 1-based index in the *gc* fields of ``FUNCTION`` records. +MODULE_CODE_GLOBALVAR_ATTACHMENT Record +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``[GLOBALVAR_ATTACHMENT, valueid, n x [id, mdnode]]`` + +The ``GLOBALVAR_ATTACHMENT`` record (code 19) describes the metadata +attachments for a global variable. The ``valueid`` is the value index for +the global variable, and the remaining fields are pairs of metadata name +indices and metadata node indices. + .. _PARAMATTR_BLOCK: PARAMATTR_BLOCK Contents diff --git a/docs/LangRef.rst b/docs/LangRef.rst index 4882ac106b8..2a1c7a00049 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -619,7 +619,8 @@ assume that the globals are densely packed in their section and try to iterate over them as an array, alignment padding would break this iteration. The maximum alignment is ``1 << 29``. -Globals can also have a :ref:`DLL storage class `. +Globals can also have a :ref:`DLL storage class ` and +an optional list of attached :ref:`metadata `, Variables and aliases can have a :ref:`Thread Local Storage Model `. @@ -630,7 +631,7 @@ Syntax:: [unnamed_addr] [AddrSpace] [ExternallyInitialized] [] [, section "name"] [, comdat [($name)]] - [, align ] + [, align ] (, !name !N)* For example, the following defines a global in a numbered address space with an initializer, section, and alignment: diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index c1d5fb5f469..a134e8ca3bc 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -113,6 +113,9 @@ enum ModuleCodes { // IFUNC: [ifunc value type, addrspace, resolver val#, linkage, visibility] MODULE_CODE_IFUNC = 18, + + // GLOBALVAR_ATTACHMENT: [valueid, n x [id, mdnode]] + MODULE_CODE_GLOBALVAR_ATTACHMENT = 19, }; /// PARAMATTR blocks have code for defining a parameter attribute set. diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index 6aeddab4311..dd21f2d723c 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -72,13 +72,8 @@ private: /// Bits from GlobalObject::GlobalObjectSubclassData. enum { /// Whether this function is materializable. - IsMaterializableBit = 1 << 0, - HasMetadataHashEntryBit = 1 << 1 + IsMaterializableBit = 0, }; - void setGlobalObjectBit(unsigned Mask, bool Value) { - setGlobalObjectSubClassData((~Mask & getGlobalObjectSubClassData()) | - (Value ? Mask : 0u)); - } friend class SymbolTableListTraits; @@ -614,35 +609,6 @@ public: /// setjmp or other function that gcc recognizes as "returning twice". bool callsFunctionThatReturnsTwice() const; - /// \brief Check if this has any metadata. - bool hasMetadata() const { return hasMetadataHashEntry(); } - - /// \brief Get the current metadata attachment, if any. - /// - /// Returns \c nullptr if such an attachment is missing. - /// @{ - MDNode *getMetadata(unsigned KindID) const; - MDNode *getMetadata(StringRef Kind) const; - /// @} - - /// \brief Set a particular kind of metadata attachment. - /// - /// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or - /// replacing it if it already exists. - /// @{ - void setMetadata(unsigned KindID, MDNode *MD); - void setMetadata(StringRef Kind, MDNode *MD); - /// @} - - /// \brief Get all current metadata attachments. - void - getAllMetadata(SmallVectorImpl> &MDs) const; - - /// \brief Drop metadata not in the given list. - /// - /// Drop all metadata from \c this not included in \c KnownIDs. - void dropUnknownMetadata(ArrayRef KnownIDs); - /// \brief Set the attached subprogram. /// /// Calls \a setMetadata() with \a LLVMContext::MD_dbg. @@ -664,15 +630,6 @@ private: Value::setValueSubclassData(D); } void setValueSubclassDataBit(unsigned Bit, bool On); - - bool hasMetadataHashEntry() const { - return getGlobalObjectSubClassData() & HasMetadataHashEntryBit; - } - void setHasMetadataHashEntry(bool HasEntry) { - setGlobalObjectBit(HasMetadataHashEntryBit, HasEntry); - } - - void clearMetadata(); }; template <> diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h index 2171d6e71cb..038fda9218c 100644 --- a/include/llvm/IR/GlobalObject.h +++ b/include/llvm/IR/GlobalObject.h @@ -20,6 +20,7 @@ namespace llvm { class Comdat; +class MDNode; class Module; class GlobalObject : public GlobalValue { @@ -36,12 +37,19 @@ protected: std::string Section; // Section to emit this into, empty means default Comdat *ObjComdat; - static const unsigned AlignmentBits = 5; + enum { + LastAlignmentBit = 4, + HasMetadataHashEntryBit, + + GlobalObjectBits, + }; static const unsigned GlobalObjectSubClassDataBits = - GlobalValueSubClassDataBits - AlignmentBits; + GlobalValueSubClassDataBits - GlobalObjectBits; private: + static const unsigned AlignmentBits = LastAlignmentBit + 1; static const unsigned AlignmentMask = (1 << AlignmentBits) - 1; + static const unsigned GlobalObjectMask = (1 << GlobalObjectBits) - 1; public: unsigned getAlignment() const { @@ -63,6 +71,35 @@ public: Comdat *getComdat() { return ObjComdat; } void setComdat(Comdat *C) { ObjComdat = C; } + /// Check if this has any metadata. + bool hasMetadata() const { return hasMetadataHashEntry(); } + + /// Get the current metadata attachment, if any. + /// + /// Returns \c nullptr if such an attachment is missing. + /// @{ + MDNode *getMetadata(unsigned KindID) const; + MDNode *getMetadata(StringRef Kind) const; + /// @} + + /// Set a particular kind of metadata attachment. + /// + /// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or + /// replacing it if it already exists. + /// @{ + void setMetadata(unsigned KindID, MDNode *MD); + void setMetadata(StringRef Kind, MDNode *MD); + /// @} + + /// Get all current metadata attachments. + void + getAllMetadata(SmallVectorImpl> &MDs) const; + + /// Drop metadata not in the given list. + /// + /// Drop all metadata from \c this not included in \c KnownIDs. + void dropUnknownMetadata(ArrayRef KnownIDs); + void copyAttributesFrom(const GlobalValue *Src) override; // Methods for support type inquiry through isa, cast, and dyn_cast: @@ -70,6 +107,19 @@ public: return V->getValueID() == Value::FunctionVal || V->getValueID() == Value::GlobalVariableVal; } + +protected: + void clearMetadata(); + +private: + bool hasMetadataHashEntry() const { + return getGlobalValueSubClassData() & (1 << HasMetadataHashEntryBit); + } + void setHasMetadataHashEntry(bool HasEntry) { + unsigned Mask = 1 << HasMetadataHashEntryBit; + setGlobalValueSubClassData((~Mask & getGlobalValueSubClassData()) | + (HasEntry ? Mask : 0u)); + } }; } // End llvm namespace diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index fd08fe005ea..7bc528775dd 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -159,6 +159,10 @@ public: /// void eraseFromParent() override; + /// Drop all references in preparation to destroy the GlobalVariable. This + /// drops not only the reference to the initializer but also to any metadata. + void dropAllReferences(); + // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Value *V) { return V->getValueID() == Value::GlobalVariableVal; diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 3f9ea5766bd..09d012d5375 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -891,6 +891,9 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, unsigned Alignment; if (ParseOptionalAlignment(Alignment)) return true; GV->setAlignment(Alignment); + } else if (Lex.getKind() == lltok::MetadataVar) { + if (ParseGlobalObjectMetadataAttachment(*GV)) + return true; } else { Comdat *C; if (parseOptionalComdat(Name, C)) @@ -1708,17 +1711,24 @@ bool LLParser::ParseInstructionMetadata(Instruction &Inst) { return false; } +/// ParseGlobalObjectMetadataAttachment +/// ::= !dbg !57 +bool LLParser::ParseGlobalObjectMetadataAttachment(GlobalObject &GO) { + unsigned MDK; + MDNode *N; + if (ParseMetadataAttachment(MDK, N)) + return true; + + GO.setMetadata(MDK, N); + return false; +} + /// ParseOptionalFunctionMetadata /// ::= (!dbg !57)* bool LLParser::ParseOptionalFunctionMetadata(Function &F) { - while (Lex.getKind() == lltok::MetadataVar) { - unsigned MDK; - MDNode *N; - if (ParseMetadataAttachment(MDK, N)) + while (Lex.getKind() == lltok::MetadataVar) + if (ParseGlobalObjectMetadataAttachment(F)) return true; - - F.setMetadata(MDK, N); - } return false; } diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index cffea25485a..7c32f2c7fac 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -424,6 +424,7 @@ namespace llvm { bool ParseMDNodeVector(SmallVectorImpl &MDs); bool ParseMetadataAttachment(unsigned &Kind, MDNode *&MD); bool ParseInstructionMetadata(Instruction &Inst); + bool ParseGlobalObjectMetadataAttachment(GlobalObject &GO); bool ParseOptionalFunctionMetadata(Function &F); template diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 2cd1297d902..55c0d064938 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -443,6 +443,9 @@ private: unsigned &NextMetadataNo); std::error_code parseMetadataKinds(); std::error_code parseMetadataKindRecord(SmallVectorImpl &Record); + std::error_code + parseGlobalObjectAttachment(GlobalObject &GO, + ArrayRef Record); std::error_code parseMetadataAttachment(Function &F); ErrorOr parseModuleTriple(); std::error_code parseUseLists(); @@ -3820,6 +3823,16 @@ std::error_code BitcodeReader::parseModule(uint64_t ResumeBit, } break; } + case bitc::MODULE_CODE_GLOBALVAR_ATTACHMENT: { + if (Record.size() % 2 == 0) + return error("Invalid record"); + unsigned ValueID = Record[0]; + if (ValueID >= ValueList.size()) + return error("Invalid record"); + if (auto *GV = dyn_cast(ValueList[ValueID])) + parseGlobalObjectAttachment(*GV, ArrayRef(Record).slice(1)); + break; + } // FUNCTION: [type, callingconv, isproto, linkage, paramattr, // alignment, section, visibility, gc, unnamed_addr, // prologuedata, dllstorageclass, comdat, prefixdata] @@ -4144,6 +4157,21 @@ ErrorOr BitcodeReader::parseIdentificationBlock() { } } +std::error_code BitcodeReader::parseGlobalObjectAttachment( + GlobalObject &GO, ArrayRef 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.setMetadata(K->second, MD); + } + return std::error_code(); +} + /// Parse metadata attachments. std::error_code BitcodeReader::parseMetadataAttachment(Function &F) { if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID)) @@ -4175,15 +4203,8 @@ std::error_code BitcodeReader::parseMetadataAttachment(Function &F) { return error("Invalid record"); if (RecordLength % 2 == 0) { // A function attachment. - for (unsigned I = 0; I != RecordLength; 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"); - F.setMetadata(K->second, MD); - } + if (std::error_code EC = parseGlobalObjectAttachment(F, Record)) + return EC; continue; } diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index ec3ecb2287e..d65e924507c 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -223,7 +223,10 @@ private: SmallVectorImpl &Record); void writeModuleMetadata(); void writeFunctionMetadata(const Function &F); - void writeMetadataAttachment(const Function &F); + void writeFunctionMetadataAttachment(const Function &F); + void writeGlobalVariableMetadataAttachment(const GlobalVariable &GV); + void pushGlobalMetadataAttachment(SmallVectorImpl &Record, + const GlobalObject &GO); void writeModuleMetadataStore(); void writeOperandBundleTags(); void writeConstants(unsigned FirstVal, unsigned LastVal, bool isGlobal); @@ -1831,24 +1834,31 @@ void ModuleBitcodeWriter::writeFunctionMetadata(const Function &F) { Stream.ExitBlock(); } -void ModuleBitcodeWriter::writeMetadataAttachment(const Function &F) { +void ModuleBitcodeWriter::pushGlobalMetadataAttachment( + SmallVectorImpl &Record, const GlobalObject &GO) { + // [n x [id, mdnode]] + SmallVector, 4> MDs; + GO.getAllMetadata(MDs); + for (const auto &I : MDs) { + Record.push_back(I.first); + Record.push_back(VE.getMetadataID(I.second)); + } +} + +void ModuleBitcodeWriter::writeFunctionMetadataAttachment(const Function &F) { Stream.EnterSubblock(bitc::METADATA_ATTACHMENT_ID, 3); SmallVector Record; - // Write metadata attachments - // METADATA_ATTACHMENT - [m x [value, [n x [id, mdnode]]] - SmallVector, 4> MDs; - F.getAllMetadata(MDs); - if (!MDs.empty()) { - for (const auto &I : MDs) { - Record.push_back(I.first); - Record.push_back(VE.getMetadataID(I.second)); - } + if (F.hasMetadata()) { + pushGlobalMetadataAttachment(Record, F); Stream.EmitRecord(bitc::METADATA_ATTACHMENT, Record, 0); Record.clear(); } + // Write metadata attachments + // METADATA_ATTACHMENT - [m x [value, [n x [id, mdnode]]] + SmallVector, 4> MDs; for (const BasicBlock &BB : F) for (const Instruction &I : BB) { MDs.clear(); @@ -2894,7 +2904,7 @@ void ModuleBitcodeWriter::writeFunction( writeValueSymbolTable(F.getValueSymbolTable()); if (NeedsMetadataAttachment) - writeMetadataAttachment(F); + writeFunctionMetadataAttachment(F); if (VE.shouldPreserveUseListOrder()) writeUseListBlock(&F); VE.purgeFunction(); @@ -3597,6 +3607,14 @@ void ModuleBitcodeWriter::writeModule() { writeValueSymbolTable(M.getValueSymbolTable(), /* IsModuleLevel */ true, &FunctionToBitcodeIndex); + for (const GlobalVariable &GV : M.globals()) + if (GV.hasMetadata()) { + SmallVector Record; + Record.push_back(VE.getValueID(&GV)); + pushGlobalMetadataAttachment(Record, GV); + Stream.EmitRecord(bitc::MODULE_CODE_GLOBALVAR_ATTACHMENT, Record); + } + if (GenerateHash) { writeModuleHash(BlockStartPos); } diff --git a/lib/Bitcode/Writer/ValueEnumerator.cpp b/lib/Bitcode/Writer/ValueEnumerator.cpp index 6bf95b12d80..6051173eed6 100644 --- a/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -344,6 +344,11 @@ ValueEnumerator::ValueEnumerator(const Module &M, EnumerateNamedMetadata(M); SmallVector, 8> MDs; + for (const GlobalVariable &GV : M.globals()) { + GV.getAllMetadata(MDs); + for (const auto &I : MDs) + EnumerateMetadata(&GV, I.second); + } // Enumerate types used by function bodies and argument lists. for (const Function &F : M) { @@ -523,17 +528,18 @@ void ValueEnumerator::EnumerateNamedMDNode(const NamedMDNode *MD) { EnumerateMetadata(nullptr, MD->getOperand(i)); } -unsigned ValueEnumerator::getMetadataFunctionID(const Function *F) const { - return F ? getValueID(F) + 1 : 0; +unsigned ValueEnumerator::getMetadataGlobalID(const GlobalObject *GO) const { + return GO ? getValueID(GO) + 1 : 0; } -void ValueEnumerator::EnumerateMetadata(const Function *F, const Metadata *MD) { - EnumerateMetadata(getMetadataFunctionID(F), MD); +void ValueEnumerator::EnumerateMetadata(const GlobalObject *GO, + const Metadata *MD) { + EnumerateMetadata(getMetadataGlobalID(GO), MD); } void ValueEnumerator::EnumerateFunctionLocalMetadata( const Function &F, const LocalAsMetadata *Local) { - EnumerateFunctionLocalMetadata(getMetadataFunctionID(&F), Local); + EnumerateFunctionLocalMetadata(getMetadataGlobalID(&F), Local); } void ValueEnumerator::dropFunctionFromMetadata( diff --git a/lib/Bitcode/Writer/ValueEnumerator.h b/lib/Bitcode/Writer/ValueEnumerator.h index bff2de70b3e..34d33fc418b 100644 --- a/lib/Bitcode/Writer/ValueEnumerator.h +++ b/lib/Bitcode/Writer/ValueEnumerator.h @@ -255,7 +255,7 @@ private: /// it's an \a MDNode. const MDNode *enumerateMetadataImpl(unsigned F, const Metadata *MD); - unsigned getMetadataFunctionID(const Function *F) const; + unsigned getMetadataGlobalID(const GlobalObject *GO) const; /// Enumerate reachable metadata in (almost) post-order. /// @@ -272,7 +272,7 @@ private: /// \a organizeMetadata() will later partition distinct nodes ahead of /// uniqued ones. ///{ - void EnumerateMetadata(const Function *F, const Metadata *MD); + void EnumerateMetadata(const GlobalObject *GO, const Metadata *MD); void EnumerateMetadata(unsigned F, const Metadata *MD); ///} diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index ec975c77c96..c5002dc8c2f 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -681,6 +681,9 @@ private: /// Add all of the functions arguments, basic blocks, and instructions. void processFunction(); + /// Add the metadata directly attached to a GlobalObject. + void processGlobalObjectMetadata(const GlobalObject &GO); + /// Add all of the metadata from a function. void processFunctionMetadata(const Function &F); @@ -799,6 +802,7 @@ void SlotTracker::processModule() { for (const GlobalVariable &Var : TheModule->globals()) { if (!Var.hasName()) CreateModuleSlot(&Var); + processGlobalObjectMetadata(Var); } for (const GlobalAlias &A : TheModule->aliases()) { @@ -882,12 +886,15 @@ void SlotTracker::processFunction() { ST_DEBUG("end processFunction!\n"); } -void SlotTracker::processFunctionMetadata(const Function &F) { +void SlotTracker::processGlobalObjectMetadata(const GlobalObject &GO) { SmallVector, 4> MDs; - F.getAllMetadata(MDs); + GO.getAllMetadata(MDs); for (auto &MD : MDs) CreateMetadataSlot(MD.second); +} +void SlotTracker::processFunctionMetadata(const Function &F) { + processGlobalObjectMetadata(F); for (auto &BB : F) { for (auto &I : BB) processInstructionMetadata(I); @@ -2473,6 +2480,10 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { if (GV->getAlignment()) Out << ", align " << GV->getAlignment(); + SmallVector, 4> MDs; + GV->getAllMetadata(MDs); + printMetadataAttachments(MDs, ", "); + printInfoComment(*GV); } diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp index c8741964564..815922593e5 100644 --- a/lib/IR/Function.cpp +++ b/lib/IR/Function.cpp @@ -218,11 +218,13 @@ bool Argument::hasAttribute(Attribute::AttrKind Kind) const { //===----------------------------------------------------------------------===// bool Function::isMaterializable() const { - return getGlobalObjectSubClassData() & IsMaterializableBit; + return getGlobalObjectSubClassData() & (1 << IsMaterializableBit); } void Function::setIsMaterializable(bool V) { - setGlobalObjectBit(IsMaterializableBit, V); + unsigned Mask = 1 << IsMaterializableBit; + setGlobalObjectSubClassData((~Mask & getGlobalObjectSubClassData()) | + (V ? Mask : 0u)); } LLVMContext &Function::getContext() const { diff --git a/lib/IR/Globals.cpp b/lib/IR/Globals.cpp index 3bf3cc25455..d151b9c5dc2 100644 --- a/lib/IR/Globals.cpp +++ b/lib/IR/Globals.cpp @@ -81,13 +81,13 @@ void GlobalObject::setAlignment(unsigned Align) { unsigned GlobalObject::getGlobalObjectSubClassData() const { unsigned ValueData = getGlobalValueSubClassData(); - return ValueData >> AlignmentBits; + return ValueData >> GlobalObjectBits; } void GlobalObject::setGlobalObjectSubClassData(unsigned Val) { unsigned OldData = getGlobalValueSubClassData(); - setGlobalValueSubClassData((OldData & AlignmentMask) | - (Val << AlignmentBits)); + setGlobalValueSubClassData((OldData & GlobalObjectMask) | + (Val << GlobalObjectBits)); assert(getGlobalObjectSubClassData() == Val && "representation error"); } @@ -301,6 +301,10 @@ void GlobalVariable::copyAttributesFrom(const GlobalValue *Src) { } } +void GlobalVariable::dropAllReferences() { + User::dropAllReferences(); + clearMetadata(); +} //===----------------------------------------------------------------------===// // GlobalIndirectSymbol Implementation diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index 7d7be4492c7..02af08ac4f9 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -1107,8 +1107,8 @@ public: /// Collection of per-instruction metadata used in this context. DenseMap InstructionMetadata; - /// Collection of per-function metadata used in this context. - DenseMap FunctionMetadata; + /// Collection of per-GlobalObject metadata used in this context. + DenseMap GlobalObjectMetadata; /// DiscriminatorTable - This table maps file:line locations to an /// integer representing the next DWARF path discriminator to assign to diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index 9435cd2ec35..a77565cf087 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -1281,24 +1281,24 @@ void Instruction::clearMetadataHashEntries() { setHasMetadataHashEntry(false); } -MDNode *Function::getMetadata(unsigned KindID) const { +MDNode *GlobalObject::getMetadata(unsigned KindID) const { if (!hasMetadata()) return nullptr; - return getContext().pImpl->FunctionMetadata[this].lookup(KindID); + return getContext().pImpl->GlobalObjectMetadata[this].lookup(KindID); } -MDNode *Function::getMetadata(StringRef Kind) const { +MDNode *GlobalObject::getMetadata(StringRef Kind) const { if (!hasMetadata()) return nullptr; return getMetadata(getContext().getMDKindID(Kind)); } -void Function::setMetadata(unsigned KindID, MDNode *MD) { +void GlobalObject::setMetadata(unsigned KindID, MDNode *MD) { if (MD) { if (!hasMetadata()) setHasMetadataHashEntry(true); - getContext().pImpl->FunctionMetadata[this].set(KindID, *MD); + getContext().pImpl->GlobalObjectMetadata[this].set(KindID, *MD); return; } @@ -1306,29 +1306,29 @@ void Function::setMetadata(unsigned KindID, MDNode *MD) { if (!hasMetadata()) return; - auto &Store = getContext().pImpl->FunctionMetadata[this]; + auto &Store = getContext().pImpl->GlobalObjectMetadata[this]; Store.erase(KindID); if (Store.empty()) clearMetadata(); } -void Function::setMetadata(StringRef Kind, MDNode *MD) { +void GlobalObject::setMetadata(StringRef Kind, MDNode *MD) { if (!MD && !hasMetadata()) return; setMetadata(getContext().getMDKindID(Kind), MD); } -void Function::getAllMetadata( +void GlobalObject::getAllMetadata( SmallVectorImpl> &MDs) const { MDs.clear(); if (!hasMetadata()) return; - getContext().pImpl->FunctionMetadata[this].getAll(MDs); + getContext().pImpl->GlobalObjectMetadata[this].getAll(MDs); } -void Function::dropUnknownMetadata(ArrayRef KnownIDs) { +void GlobalObject::dropUnknownMetadata(ArrayRef KnownIDs) { if (!hasMetadata()) return; if (KnownIDs.empty()) { @@ -1339,7 +1339,7 @@ void Function::dropUnknownMetadata(ArrayRef KnownIDs) { SmallSet KnownSet; KnownSet.insert(KnownIDs.begin(), KnownIDs.end()); - auto &Store = getContext().pImpl->FunctionMetadata[this]; + auto &Store = getContext().pImpl->GlobalObjectMetadata[this]; assert(!Store.empty()); Store.remove_if([&KnownSet](const std::pair &I) { @@ -1350,10 +1350,10 @@ void Function::dropUnknownMetadata(ArrayRef KnownIDs) { clearMetadata(); } -void Function::clearMetadata() { +void GlobalObject::clearMetadata() { if (!hasMetadata()) return; - getContext().pImpl->FunctionMetadata.erase(this); + getContext().pImpl->GlobalObjectMetadata.erase(this); setHasMetadataHashEntry(false); } diff --git a/test/Assembler/metadata.ll b/test/Assembler/metadata.ll index ba7065d16f4..2fe26be47de 100644 --- a/test/Assembler/metadata.ll +++ b/test/Assembler/metadata.ll @@ -1,8 +1,11 @@ ; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s ; RUN: verify-uselistorder %s +; CHECK: @global = global i32 0, !foo [[M2:![0-9]+]], !baz [[M3:![0-9]+]] +@global = global i32 0, !foo !2, !baz !3 + ; CHECK-LABEL: @test -; CHECK: ret void, !bar !4, !foo !3 +; CHECK: ret void, !foo [[M0:![0-9]+]], !bar [[M1:![0-9]+]] define void @test() !dbg !1 { add i32 2, 1, !bar !0 add i32 1, 2, !foo !1 @@ -11,24 +14,30 @@ define void @test() !dbg !1 { ret void, !foo !0, !bar !1 } -; CHECK-LABEL: define void @test2() !foo !5 !baz !6 +; CHECK: define void @test2() !foo [[M2]] !baz [[M3]] define void @test2() !foo !2 !baz !3 { unreachable } -; CHECK-LABEL: define void @test3() !bar !6 -; CHECK: unreachable, !bar !7 +; CHECK: define void @test3() !bar [[M3]] +; CHECK: unreachable, !bar [[M4:![0-9]+]] define void @test3() !bar !3 { unreachable, !bar !4 } ; CHECK-LABEL: define void @test_attachment_name() { -; CHECK: unreachable, !\342abc !7 +; CHECK: unreachable, !\342abc [[M4]] define void @test_attachment_name() { ;; Escape the first character when printing text IR, since it's a digit unreachable, !\34\32abc !4 } +; CHECK: [[M2]] = distinct !{} +; CHECK: [[M3]] = distinct !{} +; CHECK: [[M0]] = !DILocation +; CHECK: [[M1]] = distinct !DISubprogram +; CHECK: [[M4]] = distinct !{} + !llvm.module.flags = !{!7} !llvm.dbg.cu = !{!5} !0 = !DILocation(line: 662302, column: 26, scope: !1)