From e39dba9f078041e4bca7e821dfb252c1cc4a3fee Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Thu, 11 Dec 2014 23:02:24 +0000 Subject: [PATCH] Bitcode: Add METADATA_NODE and METADATA_VALUE This reflects the typelessness of `Metadata` in the bitcode format, removing types from all metadata operands. `METADATA_VALUE` represents a `ValueAsMetadata`, and always has two fields: the type and the value. `METADATA_NODE` represents an `MDNode`, and unlike `METADATA_OLD_NODE`, doesn't store types. It stores operands at their ID+1 so that `0` can reference `nullptr` operands. Part of PR21532. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224073 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/LLVMBitCodes.h | 4 +-- lib/Bitcode/Reader/BitcodeReader.cpp | 21 ++++++++++++ lib/Bitcode/Writer/BitcodeWriter.cpp | 40 +++++----------------- lib/Bitcode/Writer/ValueEnumerator.cpp | 8 +---- test/Bitcode/metadata.3.5.ll | 26 ++++++++++++++ test/Bitcode/metadata.3.5.ll.bc | Bin 0 -> 432 bytes tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp | 2 ++ 7 files changed, 61 insertions(+), 40 deletions(-) create mode 100644 test/Bitcode/metadata.3.5.ll create mode 100644 test/Bitcode/metadata.3.5.ll.bc diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index 8e60d8bdfb6..a717cdde9ee 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -137,8 +137,8 @@ namespace bitc { enum MetadataCodes { METADATA_STRING = 1, // MDSTRING: [values] - // 2 is unused. - // 3 is unused. + METADATA_VALUE = 2, // VALUE: [type num, value num] + METADATA_NODE = 3, // NODE: [n x md num] METADATA_NAME = 4, // STRING: [values] // 5 is unused. METADATA_KIND = 6, // [n x [id, name]] diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index a92b9c83dfc..4265bf7edf1 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1166,6 +1166,27 @@ std::error_code BitcodeReader::ParseMetadata() { MDValueList.AssignValue(MDNode::get(Context, Elts), NextMDValueNo++); break; } + case bitc::METADATA_VALUE: { + if (Record.size() != 2) + return Error(BitcodeError::InvalidRecord); + + Type *Ty = getTypeByID(Record[0]); + if (Ty->isMetadataTy() || Ty->isVoidTy()) + return Error(BitcodeError::InvalidRecord); + + MDValueList.AssignValue( + ValueAsMetadata::get(ValueList.getValueFwdRef(Record[1], Ty)), + NextMDValueNo++); + break; + } + case bitc::METADATA_NODE: { + SmallVector Elts; + Elts.reserve(Record.size()); + for (unsigned ID : Record) + Elts.push_back(ID ? MDValueList.getValueFwdRef(ID - 1) : nullptr); + MDValueList.AssignValue(MDNode::get(Context, Elts), NextMDValueNo++); + break; + } case bitc::METADATA_STRING: { std::string String(Record.begin(), Record.end()); llvm::UpgradeMDStringConstant(String); diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index f7c29d44d4e..90ac1f19b7d 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -737,33 +737,18 @@ static uint64_t GetOptimizationFlags(const Value *V) { return Flags; } -static void WriteValueAsMetadataImpl(const ValueAsMetadata *MD, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Code) { +static void WriteValueAsMetadata(const ValueAsMetadata *MD, + const ValueEnumerator &VE, + BitstreamWriter &Stream, + SmallVectorImpl &Record) { // Mimic an MDNode with a value as one operand. Value *V = MD->getValue(); Record.push_back(VE.getTypeID(V->getType())); Record.push_back(VE.getValueID(V)); - Stream.EmitRecord(Code, Record, 0); + Stream.EmitRecord(bitc::METADATA_VALUE, Record, 0); Record.clear(); } -static void WriteLocalAsMetadata(const LocalAsMetadata *MD, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record) { - WriteValueAsMetadataImpl(MD, VE, Stream, Record, bitc::METADATA_OLD_FN_NODE); -} - -static void WriteConstantAsMetadata(const ConstantAsMetadata *MD, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record) { - WriteValueAsMetadataImpl(MD, VE, Stream, Record, bitc::METADATA_OLD_NODE); -} - static void WriteMDNode(const MDNode *N, const ValueEnumerator &VE, BitstreamWriter &Stream, @@ -771,20 +756,13 @@ static void WriteMDNode(const MDNode *N, for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { Metadata *MD = N->getOperand(i); if (!MD) { - Record.push_back(VE.getTypeID(Type::getVoidTy(N->getContext()))); Record.push_back(0); continue; } - if (auto *V = dyn_cast(MD)) { - Record.push_back(VE.getTypeID(V->getValue()->getType())); - Record.push_back(VE.getValueID(V->getValue())); - continue; - } assert(!isa(MD) && "Unexpected function-local metadata"); - Record.push_back(VE.getTypeID(Type::getMetadataTy(N->getContext()))); - Record.push_back(VE.getMetadataID(MD)); + Record.push_back(VE.getMetadataID(MD) + 1); } - Stream.EmitRecord(bitc::METADATA_OLD_NODE, Record, 0); + Stream.EmitRecord(bitc::METADATA_NODE, Record); Record.clear(); } @@ -807,7 +785,7 @@ static void WriteModuleMetadata(const Module *M, Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); StartedMetadataBlock = true; } - WriteConstantAsMetadata(MDC, VE, Stream, Record); + WriteValueAsMetadata(MDC, VE, Stream, Record); } else if (const MDString *MDS = dyn_cast(MDs[i])) { if (!StartedMetadataBlock) { Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); @@ -870,7 +848,7 @@ static void WriteFunctionLocalMetadata(const Function &F, Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); StartedMetadataBlock = true; } - WriteLocalAsMetadata(MDs[i], VE, Stream, Record); + WriteValueAsMetadata(MDs[i], VE, Stream, Record); } if (StartedMetadataBlock) diff --git a/lib/Bitcode/Writer/ValueEnumerator.cpp b/lib/Bitcode/Writer/ValueEnumerator.cpp index cae20a86af9..c90dfbd776a 100644 --- a/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -521,15 +521,9 @@ void ValueEnumerator::EnumerateNamedMDNode(const NamedMDNode *MD) { void ValueEnumerator::EnumerateMDNodeOperands(const MDNode *N) { for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { Metadata *MD = N->getOperand(i); - if (!MD) { - EnumerateType(Type::getVoidTy(N->getContext())); + if (!MD) continue; - } assert(!isa(MD) && "MDNodes cannot be function-local"); - if (auto *C = dyn_cast(MD)) { - EnumerateValue(C->getValue()); - continue; - } EnumerateMetadata(MD); } } diff --git a/test/Bitcode/metadata.3.5.ll b/test/Bitcode/metadata.3.5.ll new file mode 100644 index 00000000000..028c89cf358 --- /dev/null +++ b/test/Bitcode/metadata.3.5.ll @@ -0,0 +1,26 @@ +; RUN: llvm-dis < %s.bc | FileCheck %s + +; Check that metadata encoded in 3.5 is correctly understood going forward. +; +; Bitcode assembled by llvm-as v3.5.0. + +define void @foo(i32 %v) { +; CHECK: entry: +entry: +; CHECK-NEXT: call void @llvm.bar(metadata !0) + call void @llvm.bar(metadata !0) + +; CHECK-NEXT: ret void, !baz !1 + ret void, !baz !1 +} + +declare void @llvm.bar(metadata) + +@global = global i32 0 + +; CHECK: !0 = metadata !{metadata !1, metadata !2, i32* @global, null} +; CHECK: !1 = metadata !{metadata !2, null} +; CHECK: !2 = metadata !{} +!0 = metadata !{metadata !1, metadata !2, i32* @global, null} +!1 = metadata !{metadata !2, null} +!2 = metadata !{} diff --git a/test/Bitcode/metadata.3.5.ll.bc b/test/Bitcode/metadata.3.5.ll.bc new file mode 100644 index 0000000000000000000000000000000000000000..1857465755daad052b16f926358add32e72c5d22 GIT binary patch literal 432 zcmZ>AK5$Qwhk+rJfq{X$Nr8b0NDBcmd!zD1#}h1`Yyw7>lNeigR9QJBhD6gObNYphhcx6%Pev z6$b{l0~6YS`XNB#l8gh49jU+yWE#oM;E@#cnb52zyhS5Cn#yO zFbFg#x+roS5P*nF0>zCv8f1<D)WBX@!CpM0kmnf#|62jRFAaRg zJWg_l4$7WeD3fNu3Rc!EeTLcggtKiAv+bFRo{|FgY7X{FkM@EB_NoHrvWoTsg?7m! zihK_j@B^)2C{$oz0J)DXL84ojp_`Sb_3;dbO**2F*&SFCfpVZQ5oS5q!N|zq-1yLe fff>kW4-hyjlISK70%S89GJxYEy6pi6kP8O@0P|xf literal 0 HcmV?d00001 diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp index a18665964bc..69880a425a1 100644 --- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -266,6 +266,8 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, case bitc::METADATA_STRING: return "METADATA_STRING"; case bitc::METADATA_NAME: return "METADATA_NAME"; case bitc::METADATA_KIND: return "METADATA_KIND"; + case bitc::METADATA_NODE: return "METADATA_NODE"; + case bitc::METADATA_VALUE: return "METADATA_VALUE"; case bitc::METADATA_OLD_NODE: return "METADATA_OLD_NODE"; case bitc::METADATA_OLD_FN_NODE: return "METADATA_OLD_FN_NODE"; case bitc::METADATA_NAMED_NODE: return "METADATA_NAMED_NODE"; -- 2.40.0