diff options
-rw-r--r-- | lib/VMCore/AsmWriter.cpp | 224 | ||||
-rw-r--r-- | test/Feature/mdnode2.ll | 7 | ||||
-rw-r--r-- | unittests/VMCore/MetadataTest.cpp | 8 |
3 files changed, 142 insertions, 97 deletions
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index ec29917..f13d39d 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -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); diff --git a/test/Feature/mdnode2.ll b/test/Feature/mdnode2.ll index 9feac7e..1fb9c4a 100644 --- a/test/Feature/mdnode2.ll +++ b/test/Feature/mdnode2.ll @@ -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} diff --git a/unittests/VMCore/MetadataTest.cpp b/unittests/VMCore/MetadataTest.cpp index 2de3a92..0abd8ac 100644 --- a/unittests/VMCore/MetadataTest.cpp +++ b/unittests/VMCore/MetadataTest.cpp @@ -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()); } } |