Write and read metadata attachments.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82259 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index 9cb5758..3d89f3d 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -551,7 +551,74 @@
   }
   
   if (StartedMetadataBlock)
-    Stream.ExitBlock();    
+    Stream.ExitBlock();
+}
+
+static void WriteMetadataAttachment(const Function &F,
+				    const ValueEnumerator &VE,
+				    BitstreamWriter &Stream) {
+  bool StartedMetadataBlock = false;
+  SmallVector<uint64_t, 64> Record;
+  
+  // Write metadata attachments
+  // METADATA_ATTACHMENT - [m x [value, [n x [id, mdnode]]]
+  Metadata &TheMetadata = F.getContext().getMetadata();
+  for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
+    for (BasicBlock::const_iterator I = BB->begin(), E = BB->end();
+         I != E; ++I) {
+      const Metadata::MDMapTy *P = TheMetadata.getMDs(I);
+      if (!P) continue;
+      bool RecordedInstruction = false;
+      for (Metadata::MDMapTy::const_iterator PI = P->begin(), PE = P->end();
+	   PI != PE; ++PI) {
+	if (MDNode *ND = dyn_cast_or_null<MDNode>(PI->second)) {
+	  if (RecordedInstruction == false) {
+	    Record.push_back(VE.getInstructionID(I));
+	    RecordedInstruction = true;
+	  }
+	  Record.push_back(PI->first);
+	  Record.push_back(VE.getValueID(ND));
+	}
+      }
+      if (!StartedMetadataBlock)  {
+	Stream.EnterSubblock(bitc::METADATA_ATTACHMENT_ID, 3);
+	StartedMetadataBlock = true;
+      }
+      Stream.EmitRecord(bitc::METADATA_ATTACHMENT, Record, 0);
+      Record.clear();
+    }
+
+  if (StartedMetadataBlock) 
+    Stream.ExitBlock();
+}
+
+static void WriteModuleMetadataStore(const Module *M,
+				     const ValueEnumerator &VE,
+				     BitstreamWriter &Stream) {
+  
+  bool StartedMetadataBlock = false;
+  SmallVector<uint64_t, 64> Record;
+  
+  // Write metadata kinds
+  // METADATA_KIND - [n x [id, name]]
+  Metadata &TheMetadata = M->getContext().getMetadata();
+  const StringMap<unsigned> *Kinds = TheMetadata.getHandlerNames();
+  for (StringMap<unsigned>::const_iterator 
+	 I = Kinds->begin(), E = Kinds->end(); I != E; ++I) {
+    Record.push_back(I->second);
+    StringRef KName = I->first();
+    for (unsigned i = 0, e = KName.size(); i != e; ++i)
+      Record.push_back(KName[i]);
+    if (!StartedMetadataBlock)  {
+      Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3);
+      StartedMetadataBlock = true;
+    }
+    Stream.EmitRecord(bitc::METADATA_KIND, Record, 0);
+    Record.clear();
+  }
+
+  if (StartedMetadataBlock) 
+    Stream.ExitBlock();
 }
 
 static void WriteConstants(unsigned FirstVal, unsigned LastVal,
@@ -833,6 +900,7 @@
                              SmallVector<unsigned, 64> &Vals) {
   unsigned Code = 0;
   unsigned AbbrevToUse = 0;
+  VE.setInstructionID(&I);
   switch (I.getOpcode()) {
   default:
     if (Instruction::isCast(I.getOpcode())) {
@@ -1146,7 +1214,8 @@
   
   // Emit names for all the instructions etc.
   WriteValueSymbolTable(F.getValueSymbolTable(), VE, Stream);
-    
+
+  WriteMetadataAttachment(F, VE, Stream);
   VE.purgeFunction();
   Stream.ExitBlock();
 }
@@ -1390,6 +1459,9 @@
   for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
     if (!I->isDeclaration())
       WriteFunction(*I, VE, Stream);
+
+  // Emit metadata.
+  WriteModuleMetadataStore(M, VE, Stream);
   
   // Emit the type symbol table information.
   WriteTypeSymbolTable(M->getTypeSymbolTable(), VE, Stream);
diff --git a/lib/Bitcode/Writer/ValueEnumerator.cpp b/lib/Bitcode/Writer/ValueEnumerator.cpp
index 783022c..f4682a2 100644
--- a/lib/Bitcode/Writer/ValueEnumerator.cpp
+++ b/lib/Bitcode/Writer/ValueEnumerator.cpp
@@ -40,6 +40,8 @@
 
 /// ValueEnumerator - Enumerate module-level information.
 ValueEnumerator::ValueEnumerator(const Module *M) {
+  InstructionCount = 0;
+
   // Enumerate the global variables.
   for (Module::const_global_iterator I = M->global_begin(),
          E = M->global_end(); I != E; ++I)
@@ -83,7 +85,8 @@
     for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end();
          I != E; ++I)
       EnumerateType(I->getType());
-    
+
+    Metadata &TheMetadata = F->getContext().getMetadata();    
     for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
       for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E;++I){
         for (User::const_op_iterator OI = I->op_begin(), E = I->op_end(); 
@@ -94,6 +97,14 @@
           EnumerateAttributes(CI->getAttributes());
         else if (const InvokeInst *II = dyn_cast<InvokeInst>(I))
           EnumerateAttributes(II->getAttributes());
+
+	// Enumerate metadata attached with this instruction.
+	const Metadata::MDMapTy *MDs = TheMetadata.getMDs(I);
+	if (MDs)
+	  for (Metadata::MDMapTy::const_iterator MI = MDs->begin(), 
+		 ME = MDs->end(); MI != ME; ++MI)
+	    if (MDNode *MDN = dyn_cast_or_null<MDNode>(MI->second))
+	      EnumerateMetadata(MDN);
       }
   }
   
@@ -114,6 +125,16 @@
     TypeMap[Types[i].first] = i+1;
 }
 
+unsigned ValueEnumerator::getInstructionID(const Instruction *Inst) const {
+  InstructionMapType::const_iterator I = InstructionMap.find(Inst);
+  assert (I != InstructionMap.end() && "Instruction is not mapped!");
+    return I->second;
+}  
+
+void ValueEnumerator::setInstructionID(const Instruction *I) {
+  InstructionMap[I] = InstructionCount++;
+}
+
 unsigned ValueEnumerator::getValueID(const Value *V) const {
   if (isa<MetadataBase>(V)) {
     ValueMapType::const_iterator I = MDValueMap.find(V);
diff --git a/lib/Bitcode/Writer/ValueEnumerator.h b/lib/Bitcode/Writer/ValueEnumerator.h
index b5106f0..da63dde 100644
--- a/lib/Bitcode/Writer/ValueEnumerator.h
+++ b/lib/Bitcode/Writer/ValueEnumerator.h
@@ -22,6 +22,7 @@
 
 class Type;
 class Value;
+class Instruction;
 class BasicBlock;
 class Function;
 class Module;
@@ -47,11 +48,15 @@
   ValueList Values;
   ValueList MDValues;
   ValueMapType MDValueMap;
-
+  
   typedef DenseMap<void*, unsigned> AttributeMapType;
   AttributeMapType AttributeMap;
   std::vector<AttrListPtr> Attributes;
   
+  typedef DenseMap<const Instruction*, unsigned> InstructionMapType;
+  InstructionMapType InstructionMap;
+  unsigned InstructionCount;
+
   /// BasicBlocks - This contains all the basic blocks for the currently
   /// incorporated function.  Their reverse mapping is stored in ValueMap.
   std::vector<const BasicBlock*> BasicBlocks;
@@ -74,7 +79,10 @@
     assert(I != TypeMap.end() && "Type not in ValueEnumerator!");
     return I->second-1;
   }
-  
+
+  unsigned getInstructionID(const Instruction *I) const;
+  void setInstructionID(const Instruction *I);
+
   unsigned getAttributeID(const AttrListPtr &PAL) const {
     if (PAL.isEmpty()) return 0;  // Null maps to zero.
     AttributeMapType::const_iterator I = AttributeMap.find(PAL.getRawPointer());