summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDevang Patel <dpatel@apple.com>2009-07-08 21:44:25 +0000
committerDevang Patel <dpatel@apple.com>2009-07-08 21:44:25 +0000
commit320671d2654a543bbeed5b62efe165430146d55e (patch)
tree473d1f100dcbf73e6cfa02806e2aeee8e9a50cc3
parentf2d754bb382cba0bad2774144ddac84be5354d16 (diff)
downloadllvm-320671d2654a543bbeed5b62efe165430146d55e.tar.gz
llvm-320671d2654a543bbeed5b62efe165430146d55e.tar.bz2
llvm-320671d2654a543bbeed5b62efe165430146d55e.tar.xz
Update SLotTracker to handle MDNode slots.
Simplify MDNode printing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75053 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/VMCore/AsmWriter.cpp224
-rw-r--r--test/Feature/mdnode2.ll7
-rw-r--r--unittests/VMCore/MetadataTest.cpp8
3 files changed, 142 insertions, 97 deletions
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp
index ec29917198..f13d39d12e 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 9feac7e131..1fb9c4a67d 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 2de3a92481..0abd8aca4c 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());
}
}