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<Metadata *, 8> 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);
return Flags;
}
-static void WriteValueAsMetadataImpl(const ValueAsMetadata *MD,
- const ValueEnumerator &VE,
- BitstreamWriter &Stream,
- SmallVectorImpl<uint64_t> &Record,
- unsigned Code) {
+static void WriteValueAsMetadata(const ValueAsMetadata *MD,
+ const ValueEnumerator &VE,
+ BitstreamWriter &Stream,
+ SmallVectorImpl<uint64_t> &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<uint64_t> &Record) {
- WriteValueAsMetadataImpl(MD, VE, Stream, Record, bitc::METADATA_OLD_FN_NODE);
-}
-
-static void WriteConstantAsMetadata(const ConstantAsMetadata *MD,
- const ValueEnumerator &VE,
- BitstreamWriter &Stream,
- SmallVectorImpl<uint64_t> &Record) {
- WriteValueAsMetadataImpl(MD, VE, Stream, Record, bitc::METADATA_OLD_NODE);
-}
-
static void WriteMDNode(const MDNode *N,
const ValueEnumerator &VE,
BitstreamWriter &Stream,
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<ConstantAsMetadata>(MD)) {
- Record.push_back(VE.getTypeID(V->getValue()->getType()));
- Record.push_back(VE.getValueID(V->getValue()));
- continue;
- }
assert(!isa<LocalAsMetadata>(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();
}
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<MDString>(MDs[i])) {
if (!StartedMetadataBlock) {
Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3);
Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3);
StartedMetadataBlock = true;
}
- WriteLocalAsMetadata(MDs[i], VE, Stream, Record);
+ WriteValueAsMetadata(MDs[i], VE, Stream, Record);
}
if (StartedMetadataBlock)
--- /dev/null
+; 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 !{}