+static uint64_t GetOptimizationFlags(const Value *V) {
+ uint64_t Flags = 0;
+
+ if (const OverflowingBinaryOperator *OBO =
+ dyn_cast<OverflowingBinaryOperator>(V)) {
+ if (OBO->hasNoSignedWrap())
+ Flags |= 1 << bitc::OBO_NO_SIGNED_WRAP;
+ if (OBO->hasNoUnsignedWrap())
+ Flags |= 1 << bitc::OBO_NO_UNSIGNED_WRAP;
+ } else if (const SDivOperator *Div = dyn_cast<SDivOperator>(V)) {
+ if (Div->isExact())
+ Flags |= 1 << bitc::SDIV_EXACT;
+ }
+
+ return Flags;
+}
+
+static void WriteMDNode(const MDNode *N,
+ const ValueEnumerator &VE,
+ BitstreamWriter &Stream,
+ SmallVector<uint64_t, 64> &Record) {
+ for (unsigned i = 0, e = N->getNumElements(); i != e; ++i) {
+ if (N->getElement(i)) {
+ Record.push_back(VE.getTypeID(N->getElement(i)->getType()));
+ Record.push_back(VE.getValueID(N->getElement(i)));
+ } else {
+ Record.push_back(VE.getTypeID(Type::getVoidTy(N->getContext())));
+ Record.push_back(0);
+ }
+ }
+ Stream.EmitRecord(bitc::METADATA_NODE, Record, 0);
+ Record.clear();
+}
+
+static void WriteModuleMetadata(const ValueEnumerator &VE,
+ BitstreamWriter &Stream) {
+ const ValueEnumerator::ValueList &Vals = VE.getMDValues();
+ bool StartedMetadataBlock = false;
+ unsigned MDSAbbrev = 0;
+ SmallVector<uint64_t, 64> Record;
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
+
+ if (const MDNode *N = dyn_cast<MDNode>(Vals[i].first)) {
+ if (!StartedMetadataBlock) {
+ Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3);
+ StartedMetadataBlock = true;
+ }
+ WriteMDNode(N, VE, Stream, Record);
+ } else if (const MDString *MDS = dyn_cast<MDString>(Vals[i].first)) {
+ if (!StartedMetadataBlock) {
+ Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3);
+
+ // Abbrev for METADATA_STRING.
+ BitCodeAbbrev *Abbv = new BitCodeAbbrev();
+ Abbv->Add(BitCodeAbbrevOp(bitc::METADATA_STRING));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));
+ MDSAbbrev = Stream.EmitAbbrev(Abbv);
+ StartedMetadataBlock = true;
+ }
+
+ // Code: [strchar x N]
+ const char *StrBegin = MDS->begin();
+ for (unsigned i = 0, e = MDS->length(); i != e; ++i)
+ Record.push_back(StrBegin[i]);
+
+ // Emit the finished record.
+ Stream.EmitRecord(bitc::METADATA_STRING, Record, MDSAbbrev);
+ Record.clear();
+ } else if (const NamedMDNode *NMD = dyn_cast<NamedMDNode>(Vals[i].first)) {
+ if (!StartedMetadataBlock) {
+ Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3);
+ StartedMetadataBlock = true;
+ }
+
+ // Write name.
+ std::string Str = NMD->getNameStr();
+ const char *StrBegin = Str.c_str();
+ for (unsigned i = 0, e = Str.length(); i != e; ++i)
+ Record.push_back(StrBegin[i]);
+ Stream.EmitRecord(bitc::METADATA_NAME, Record, 0/*TODO*/);
+ Record.clear();
+
+ // Write named metadata elements.
+ for (unsigned i = 0, e = NMD->getNumElements(); i != e; ++i) {
+ if (NMD->getElement(i))
+ Record.push_back(VE.getValueID(NMD->getElement(i)));
+ else
+ Record.push_back(0);
+ }
+ Stream.EmitRecord(bitc::METADATA_NAMED_NODE, Record, 0);
+ Record.clear();
+ }
+ }
+
+ if (StartedMetadataBlock)
+ Stream.ExitBlock();
+}