Update SLotTracker to handle MDNode slots.
authorDevang Patel <dpatel@apple.com>
Wed, 8 Jul 2009 21:44:25 +0000 (21:44 +0000)
committerDevang Patel <dpatel@apple.com>
Wed, 8 Jul 2009 21:44:25 +0000 (21:44 +0000)
Simplify MDNode printing.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75053 91177308-0d34-0410-b5e6-96231b3b80d8

lib/VMCore/AsmWriter.cpp
test/Feature/mdnode2.ll
unittests/VMCore/MetadataTest.cpp

index ec2991719829350c2bb7f5f40f7d2d24e0d98ab6..f13d39d12e0f03332d5d8a76193437ae0848bf07 100644 (file)
@@ -466,35 +466,44 @@ namespace {
 ///
 class SlotTracker {
 public:
-  /// ValueMap - A mapping of Values to slot numbers
+  /// ValueMap - A mapping of Values to slot numbers.
   typedef DenseMap<const Value*, unsigned> ValueMap;
   
 private:  
-  /// TheModule - The module for which we are holding slot numbers
+  /// TheModule - The module for which we are holding slot numbers.
   const Module* TheModule;
   
-  /// TheFunction - The function for which we are holding slot numbers
+  /// TheFunction - The function for which we are holding slot numbers.
   const Function* TheFunction;
   bool FunctionProcessed;
   
-  /// mMap - The TypePlanes map for the module level data
+  /// TheMDNode - The MDNode for which we are holding slot numbers.
+  const MDNode *TheMDNode;
+
+  /// mMap - The TypePlanes map for the module level data.
   ValueMap mMap;
   unsigned mNext;
   
-  /// fMap - The TypePlanes map for the function level data
+  /// fMap - The TypePlanes map for the function level data.
   ValueMap fMap;
   unsigned fNext;
   
+  /// mdnMap - Map for MDNodes.
+  ValueMap mdnMap;
+  unsigned mdnNext;
 public:
   /// Construct from a module
   explicit SlotTracker(const Module *M);
   /// Construct from a function, starting out in incorp state.
   explicit SlotTracker(const Function *F);
+  /// Construct from a mdnode.
+  explicit SlotTracker(const MDNode *N);
 
   /// Return the slot number of the specified value in it's type
   /// plane.  If something is not in the SlotTracker, return -1.
   int getLocalSlot(const Value *V);
   int getGlobalSlot(const GlobalValue *V);
+  int getMetadataSlot(const MDNode *N);
 
   /// If you'd like to deal with a function instead of just a module, use
   /// this method to get its data into the SlotTracker.
@@ -508,14 +517,22 @@ public:
   /// will reset the state of the machine back to just the module contents.
   void purgeFunction();
 
-  // Implementation Details
-private:
+  /// MDNode map iterators.
+  ValueMap::iterator mdnBegin() { return mdnMap.begin(); }
+  ValueMap::iterator mdnEnd() { return mdnMap.end(); }
+  unsigned mdnSize() { return mdnMap.size(); }
+
   /// This function does the actual initialization.
   inline void initialize();
 
+  // Implementation Details
+private:
   /// CreateModuleSlot - Insert the specified GlobalValue* into the slot table.
   void CreateModuleSlot(const GlobalValue *V);
-  
+
+  /// CreateMetadataSlot - Insert the specified MDNode* into the slot table.
+  void CreateMetadataSlot(const MDNode *N);
+
   /// CreateFunctionSlot - Insert the specified Value* into the slot table.
   void CreateFunctionSlot(const Value *V);
 
@@ -523,9 +540,12 @@ private:
   /// and function declarations, but not the contents of those functions.
   void processModule();
 
-  /// Add all of the functions arguments, basic blocks, and instructions
+  /// Add all of the functions arguments, basic blocks, and instructions.
   void processFunction();
 
+  /// Add all MDNode operands.
+  void processMDNode();
+
   SlotTracker(const SlotTracker &);  // DO NOT IMPLEMENT
   void operator=(const SlotTracker &);  // DO NOT IMPLEMENT
 };
@@ -564,14 +584,21 @@ static SlotTracker *createSlotTracker(const Value *V) {
 // Module level constructor. Causes the contents of the Module (sans functions)
 // to be added to the slot table.
 SlotTracker::SlotTracker(const Module *M)
-  : TheModule(M), TheFunction(0), FunctionProcessed(false), mNext(0), fNext(0) {
+  : TheModule(M), TheFunction(0), FunctionProcessed(false), TheMDNode(0),
+    mNext(0), fNext(0),  mdnNext(0) {
 }
 
 // Function level constructor. Causes the contents of the Module and the one
 // function provided to be added to the slot table.
 SlotTracker::SlotTracker(const Function *F)
   : TheModule(F ? F->getParent() : 0), TheFunction(F), FunctionProcessed(false),
-    mNext(0), fNext(0) {
+    TheMDNode(0), mNext(0), fNext(0) {
+}
+
+// Constructor to handle single MDNode.
+SlotTracker::SlotTracker(const MDNode *C)
+  : TheModule(0), TheFunction(0), FunctionProcessed(false), TheMDNode(C),
+    mNext(0), fNext(0),  mdnNext(0) {
 }
 
 inline void SlotTracker::initialize() {
@@ -582,6 +609,9 @@ inline void SlotTracker::initialize() {
   
   if (TheFunction && !FunctionProcessed)
     processFunction();
+
+  if (TheMDNode)
+    processMDNode();
 }
 
 // Iterate through all the global variables, functions, and global
@@ -591,9 +621,14 @@ void SlotTracker::processModule() {
   
   // Add all of the unnamed global variables to the value table.
   for (Module::const_global_iterator I = TheModule->global_begin(),
-       E = TheModule->global_end(); I != E; ++I)
+         E = TheModule->global_end(); I != E; ++I) {
     if (!I->hasName()) 
       CreateModuleSlot(I);
+    if (I->hasInitializer()) {
+      if (MDNode *N = dyn_cast<MDNode>(I->getInitializer())) 
+        CreateMetadataSlot(N);
+    }
+  }
   
   // Add all the unnamed functions to the table.
   for (Module::const_iterator I = TheModule->begin(), E = TheModule->end();
@@ -604,7 +639,6 @@ void SlotTracker::processModule() {
   ST_DEBUG("end processModule!\n");
 }
 
-
 // Process the arguments, basic blocks, and instructions  of a function.
 void SlotTracker::processFunction() {
   ST_DEBUG("begin processFunction!\n");
@@ -623,9 +657,14 @@ void SlotTracker::processFunction() {
        E = TheFunction->end(); BB != E; ++BB) {
     if (!BB->hasName())
       CreateFunctionSlot(BB);
-    for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I)
+    for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; 
+         ++I) {
       if (I->getType() != Type::VoidTy && !I->hasName())
         CreateFunctionSlot(I);
+      for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) 
+        if (MDNode *N = dyn_cast<MDNode>(I->getOperand(i))) 
+          CreateMetadataSlot(N);
+    }
   }
   
   FunctionProcessed = true;
@@ -633,6 +672,15 @@ void SlotTracker::processFunction() {
   ST_DEBUG("end processFunction!\n");
 }
 
+/// processMDNode - Process TheMDNode.
+void SlotTracker::processMDNode() {
+  ST_DEBUG("begin processMDNode!\n");
+  mdnNext = 0;
+  CreateMetadataSlot(TheMDNode);
+  TheMDNode = 0;
+  ST_DEBUG("end processMDNode!\n");
+}
+
 /// Clean up after incorporating a function. This is the only way to get out of
 /// the function incorporation state that affects get*Slot/Create*Slot. Function
 /// incorporation state is indicated by TheFunction != 0.
@@ -654,6 +702,16 @@ int SlotTracker::getGlobalSlot(const GlobalValue *V) {
   return MI == mMap.end() ? -1 : (int)MI->second;
 }
 
+/// getGlobalSlot - Get the slot number of a MDNode.
+int SlotTracker::getMetadataSlot(const MDNode *N) {
+  // Check for uninitialized state and do lazy initialization.
+  initialize();
+  
+  // Find the type plane in the module map
+  ValueMap::iterator MI = mdnMap.find(N);
+  return MI == mdnMap.end() ? -1 : (int)MI->second;
+}
+
 
 /// getLocalSlot - Get the slot number for a value that is local to a function.
 int SlotTracker::getLocalSlot(const Value *V) {
@@ -684,7 +742,6 @@ void SlotTracker::CreateModuleSlot(const GlobalValue *V) {
              (isa<GlobalAlias>(V) ? 'A' : 'o'))) << "]\n");
 }
 
-
 /// CreateSlot - Create a new slot for the specified value if it has no name.
 void SlotTracker::CreateFunctionSlot(const Value *V) {
   assert(V->getType() != Type::VoidTy && !V->hasName() &&
@@ -698,7 +755,25 @@ void SlotTracker::CreateFunctionSlot(const Value *V) {
            DestSlot << " [o]\n");
 }  
 
+/// CreateModuleSlot - Insert the specified MDNode* into the slot table.
+void SlotTracker::CreateMetadataSlot(const MDNode *N) {
+  assert(N && "Can't insert a null Value into SlotTracker!");
+  
+  ValueMap::iterator I = mdnMap.find(N);
+  if (I != mdnMap.end())
+    return;
+
+  unsigned DestSlot = mdnNext++;
+  mdnMap[N] = DestSlot;
 
+  for (MDNode::const_elem_iterator MDI = N->elem_begin(), 
+         MDE = N->elem_end(); MDI != MDE; ++MDI) {
+    const Value *TV = *MDI;
+    if (TV)
+      if (const MDNode *N2 = dyn_cast<MDNode>(TV)) 
+        CreateMetadataSlot(N2);
+  }
+}
 
 //===----------------------------------------------------------------------===//
 // AsmWriter Implementation
@@ -743,6 +818,39 @@ static const char *getPredicateText(unsigned predicate) {
   return pred;
 }
 
+static void WriteMDNodes(raw_ostream &Out, TypePrinting &TypePrinter,
+                         SlotTracker &Machine) {
+  SmallVector<const MDNode *, 16> Nodes;
+  Nodes.resize(Machine.mdnSize());
+  for (SlotTracker::ValueMap::iterator I = 
+         Machine.mdnBegin(), E = Machine.mdnEnd(); I != E; ++I) 
+    Nodes[I->second] = cast<MDNode>(I->first);
+
+  for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
+    Out << '!' << i << " = constant metadata ";
+    const MDNode *Node = Nodes[i];
+    Out << "!{";
+    for (MDNode::const_elem_iterator NI = Node->elem_begin(), 
+           NE = Node->elem_end(); NI != NE;) {
+      const Value *V = *NI;
+      if (!V)
+        Out << "null";
+      else if (const MDNode *N = dyn_cast<MDNode>(V)) {
+        Out << "metadata ";
+        Out << '!' << Machine.getMetadataSlot(N);
+      }
+      else {
+        TypePrinter.print((*NI)->getType(), Out);
+        Out << ' ';
+        WriteAsOperandInternal(Out, *NI, TypePrinter, &Machine);
+      }
+      if (++NI != NE)
+        Out << ", ";
+    }
+    Out << "}\n";
+  }
+}
+
 static void WriteConstantInt(raw_ostream &Out, const Constant *CV,
                              TypePrinting &TypePrinter, SlotTracker *Machine) {
   if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
@@ -948,6 +1056,11 @@ static void WriteConstantInt(raw_ostream &Out, const Constant *CV,
     return;
   }
 
+  if (const MDNode *Node = dyn_cast<MDNode>(CV)) {
+    Out << "!" << Machine->getMetadataSlot(Node);
+    return;
+  }
+
   if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
     Out << CE->getOpcodeName();
     if (CE->isCompare())
@@ -1105,7 +1218,6 @@ public:
 
   void writeOperand(const Value *Op, bool PrintType);
   void writeParamOperand(const Value *Operand, Attributes Attrs);
-  void printMDNode(const MDNode *Node, bool StandAlone);
 
   const Module* getModule() { return TheModule; }
 
@@ -1216,6 +1328,8 @@ void AssemblyWriter::printModule(const Module *M) {
   // Output all of the functions.
   for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
     printFunction(I);
+
+  WriteMDNodes(Out, TypePrinter, Machine);
 }
 
 static void PrintLinkage(GlobalValue::LinkageTypes LT, raw_ostream &Out) {
@@ -1252,28 +1366,6 @@ static void PrintVisibility(GlobalValue::VisibilityTypes Vis,
 }
 
 void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
-  if (GV->hasInitializer())
-    // If GV is initialized using Metadata then separate out metadata
-    // operands used by the initializer. Note, MDNodes are not cyclic.
-    if (MDNode *N = dyn_cast<MDNode>(GV->getInitializer())) {
-      SmallVector<const MDNode *, 4> WorkList;
-      // Collect MDNodes used by the initializer.
-      for (MDNode::const_elem_iterator I = N->elem_begin(), E = N->elem_end();
-          I != E; ++I) {
-       const Value *TV = *I;
-       if (TV)
-         if (const MDNode *NN = dyn_cast<MDNode>(TV))
-           WorkList.push_back(NN);
-      }
-
-      // Print MDNodes used by the initializer.
-      while (!WorkList.empty()) {
-       const MDNode *N = WorkList.back(); WorkList.pop_back();
-       printMDNode(N, true);
-       Out << '\n';
-      }
-    }
-
   if (GV->hasName()) {
     PrintLLVMName(Out, GV);
     Out << " = ";
@@ -1293,10 +1385,7 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
 
   if (GV->hasInitializer()) {
     Out << ' ';
-    if (MDNode *N = dyn_cast<MDNode>(GV->getInitializer()))
-      printMDNode(N, false);
-    else
-      writeOperand(GV->getInitializer(), false);
+    writeOperand(GV->getInitializer(), false);
   }
     
   if (GV->hasSection())
@@ -1308,47 +1397,6 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
   Out << '\n';
 }
 
-void AssemblyWriter::printMDNode(const MDNode *Node,
-                                bool StandAlone) {
-  std::map<const MDNode *, unsigned>::iterator MI = MDNodes.find(Node);
-  // If this node is already printed then just refer it using its Metadata
-  // id number.
-  if (MI != MDNodes.end()) {
-    if (!StandAlone)
-      Out << "!" << MI->second;
-    return;
-  }
-  
-  if (StandAlone) {
-    // Print standalone MDNode.
-    // !42 = !{ ... }
-    Out << "!" << MetadataIDNo << " = ";
-    Out << "constant metadata ";
-  }
-
-  Out << "!{";
-  for (MDNode::const_elem_iterator I = Node->elem_begin(), E = Node->elem_end();
-       I != E;) {
-    const Value *TV = *I;
-    if (!TV)
-      Out << "null";
-    else if (const MDNode *N = dyn_cast<MDNode>(TV)) {
-      TypePrinter.print(N->getType(), Out);
-      Out << ' ';
-      printMDNode(N, StandAlone);
-    }
-    else if (!*I)
-      Out << "null";
-    else 
-      writeOperand(*I, true);
-    if (++I != E)
-      Out << ", ";
-  }
-  Out << "}";
-
-  MDNodes[Node] = MetadataIDNo++;
-}
-
 void AssemblyWriter::printAlias(const GlobalAlias *GA) {
   // Don't crash when dumping partially built GA
   if (!GA->hasName())
@@ -1891,7 +1939,6 @@ void Value::print(raw_ostream &OS, AssemblyAnnotationWriter *AAW) const {
     OS << "printing a <null> value\n";
     return;
   }
-
   if (const Instruction *I = dyn_cast<Instruction>(this)) {
     const Function *F = I->getParent() ? I->getParent()->getParent() : 0;
     SlotTracker SlotTable(F);
@@ -1907,13 +1954,10 @@ void Value::print(raw_ostream &OS, AssemblyAnnotationWriter *AAW) const {
     AssemblyWriter W(OS, SlotTable, GV->getParent(), AAW);
     W.write(GV);
   } else if (const MDNode *N = dyn_cast<MDNode>(this)) {
+    SlotTracker SlotTable(N);
     TypePrinting TypePrinter;
-    TypePrinter.print(N->getType(), OS);
-    OS << ' ';
-    // FIXME: Do we need a slot tracker for metadata ?
-    SlotTracker SlotTable((const Function *)NULL);
-    AssemblyWriter W(OS, SlotTable, NULL, AAW);
-    W.printMDNode(N, false);
+    SlotTable.initialize();
+    WriteMDNodes(OS, TypePrinter, SlotTable);
   } else if (const Constant *C = dyn_cast<Constant>(this)) {
     TypePrinting TypePrinter;
     TypePrinter.print(C->getType(), OS);
index 9feac7e1315de3829276357691d09a748d8d24ee..1fb9c4a67d8dc505bb2429bfc1c0c968fb03a6f1 100644 (file)
@@ -1,7 +1,8 @@
+; Test standalone metadata
 ; RUN: llvm-as < %s | llvm-dis > %t.ll
-; RUN: grep "!0 = constant metadata !{i32 21, i32 22}" %t.ll
-; RUN: grep "!1 = constant metadata !{i32 23, i32 24}" %t.ll
-; RUN: grep "@llvm.blah = constant metadata !{i32 1000, i16 200, metadata !1, metadata !0}" %t.ll
+; RUN: grep "metadata !{i32 21, i32 22}" %t.ll
+; RUN: grep "metadata !{i32 23, i32 24}" %t.ll
+
 !0 = constant metadata !{i32 21, i32 22}
 !1 = constant metadata !{i32 23, i32 24}
 @llvm.blah = constant metadata !{i32 1000, i16 200, metadata !1, metadata !0}
index 2de3a924818551dbda2dbf07f641efcc4cedb6c6..0abd8aca4cdb8b08132c91b218dcd1dd2cf228f2 100644 (file)
@@ -94,10 +94,10 @@ TEST(MDNodeTest, Simple) {
   std::ostringstream oss1, oss2;
   n1->print(oss1);
   n2->print(oss2);
-  EXPECT_STREQ("metadata !{metadata !\"abc\", i8 0, metadata !\"123\"}",
+  EXPECT_STREQ("!0 = constant metadata !{metadata !\"abc\", i8 0, metadata !\"123\"}\n",
                oss1.str().c_str());
-  EXPECT_STREQ("metadata !{metadata !{metadata !\"abc\", i8 0, "
-                                     "metadata !\"123\"}}",
+  EXPECT_STREQ("!0 = constant metadata !{metadata !1}\n"
+               "!1 = constant metadata !{metadata !\"abc\", i8 0, metadata !\"123\"}\n",
                oss2.str().c_str());
 }
 
@@ -134,6 +134,6 @@ TEST(MDNodeTest, Delete) {
 
   std::ostringstream oss;
   wvh->print(oss);
-  EXPECT_STREQ("metadata !{null}", oss.str().c_str());
+  EXPECT_STREQ("!0 = constant metadata !{null}\n", oss.str().c_str());
 }
 }