From cceae7feda8e33194d1a6c5963bd4114bb8d2b36 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Tue, 31 May 2016 23:01:54 +0000 Subject: 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 --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 39 ++++++++++++++++++++------- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 42 ++++++++++++++++++++--------- llvm/lib/Bitcode/Writer/ValueEnumerator.cpp | 16 +++++++---- llvm/lib/Bitcode/Writer/ValueEnumerator.h | 4 +-- 4 files changed, 73 insertions(+), 28 deletions(-) (limited to 'llvm/lib/Bitcode') diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 2cd1297d902..55c0d064938 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/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/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index ec3ecb2287e..d65e924507c 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/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/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp index 6bf95b12d80..6051173eed6 100644 --- a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/llvm/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/llvm/lib/Bitcode/Writer/ValueEnumerator.h b/llvm/lib/Bitcode/Writer/ValueEnumerator.h index bff2de70b3e..34d33fc418b 100644 --- a/llvm/lib/Bitcode/Writer/ValueEnumerator.h +++ b/llvm/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); ///} -- cgit v1.2.3