From 923078c65d5a37a4f135705300c9feea49487de5 Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Wed, 1 Jul 2009 19:21:12 +0000 Subject: [PATCH] Support stand alone metadata syntax. !0 = constant metadata !{i32 21, i32 22} @llvm.blah = constant metadata !{i32 1000, i16 200, metadata !0} git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74630 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AsmParser/LLParser.cpp | 40 +++++++++++++++++ lib/AsmParser/LLParser.h | 4 +- lib/VMCore/AsmWriter.cpp | 90 +++++++++++++++++++++++++++++--------- test/Feature/mdnode2.ll | 7 +++ 4 files changed, 119 insertions(+), 22 deletions(-) create mode 100644 test/Feature/mdnode2.ll diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 83ed401ef4b..4ab0f26f75d 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -109,6 +109,7 @@ bool LLParser::ParseTopLevelEntities() { case lltok::StringConstant: // FIXME: REMOVE IN LLVM 3.0 case lltok::LocalVar: if (ParseNamedType()) return true; break; case lltok::GlobalVar: if (ParseNamedGlobal()) return true; break; + case lltok::Metadata: if (ParseStandaloneMetadata()) return true; break; // The Global variable production with no name can have many different // optional leading prefixes, the production is: @@ -355,6 +356,34 @@ bool LLParser::ParseNamedGlobal() { return ParseAlias(Name, NameLoc, Visibility); } +/// ParseStandaloneMetadata: +/// !42 = !{...} +bool LLParser::ParseStandaloneMetadata() { + assert(Lex.getKind() == lltok::Metadata); + Lex.Lex(); + unsigned MetadataID = 0; + if (ParseUInt32(MetadataID)) + return true; + if (MetadataCache.find(MetadataID) != MetadataCache.end()) + return TokError("Metadata id is already used"); + if (ParseToken(lltok::equal, "expected '=' here")) + return true; + + LocTy TyLoc; + bool IsConstant; + PATypeHolder Ty(Type::VoidTy); + if (ParseGlobalType(IsConstant) || + ParseType(Ty, TyLoc)) + return true; + + Constant *Init = 0; + if (ParseGlobalValue(Ty, Init)) + return true; + + MetadataCache[MetadataID] = Init; + return false; +} + /// ParseAlias: /// ::= GlobalVar '=' OptionalVisibility 'alias' OptionalLinkage Aliasee /// Aliasee @@ -1596,6 +1625,17 @@ bool LLParser::ParseValID(ValID &ID) { return false; } + // Standalone metadata reference + // !{ ..., !42, ... } + unsigned MID = 0; + if (!ParseUInt32(MID)) { + std::map::iterator I = MetadataCache.find(MID); + if (I == MetadataCache.end()) + return TokError("Unknown metadata reference"); + ID.ConstantVal = I->second; + return false; + } + // MDString: // ::= '!' STRINGCONSTANT std::string Str; diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index 7106689081d..41c2ee75c60 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -43,7 +43,8 @@ namespace llvm { std::map > ForwardRefTypes; std::map > ForwardRefTypeIDs; std::vector NumberedTypes; - + /// MetadataCache - This map keeps track of parsed metadata constants. + std::map MetadataCache; struct UpRefRecord { /// Loc - This is the location of the upref. LocTy Loc; @@ -139,6 +140,7 @@ namespace llvm { bool ParseGlobal(const std::string &Name, LocTy Loc, unsigned Linkage, bool HasLinkage, unsigned Visibility); bool ParseAlias(const std::string &Name, LocTy Loc, unsigned Visibility); + bool ParseStandaloneMetadata(); // Type Parsing. bool ParseType(PATypeHolder &Result, bool AllowVoid = false); diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 73b1ed656db..361096f94da 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -35,6 +35,7 @@ #include "llvm/Support/raw_ostream.h" #include #include +#include using namespace llvm; // Make virtual table appear in this compilation unit. @@ -945,25 +946,6 @@ static void WriteConstantInt(raw_ostream &Out, const Constant *CV, return; } - if (const MDNode *N = dyn_cast(CV)) { - Out << "!{"; - for (MDNode::const_elem_iterator I = N->elem_begin(), E = N->elem_end(); - I != E;) { - if (!*I) { - Out << "null"; - } else { - TypePrinter.print((*I)->getType(), Out); - Out << ' '; - WriteAsOperandInternal(Out, *I, TypePrinter, Machine); - } - - if (++I != E) - Out << ", "; - } - Out << "}"; - return; - } - if (const ConstantExpr *CE = dyn_cast(CV)) { Out << CE->getOpcodeName(); if (CE->isCompare()) @@ -1092,10 +1074,14 @@ class AssemblyWriter { TypePrinting TypePrinter; AssemblyAnnotationWriter *AnnotationWriter; std::vector NumberedTypes; + + // Each MDNode is assigned unique MetadataIDNo. + std::map MDNodes; + unsigned MetadataIDNo; public: inline AssemblyWriter(raw_ostream &o, SlotTracker &Mac, const Module *M, AssemblyAnnotationWriter *AAW) - : Out(o), Machine(Mac), TheModule(M), AnnotationWriter(AAW) { + : Out(o), Machine(Mac), TheModule(M), AnnotationWriter(AAW), MetadataIDNo(0) { AddModuleTypesToPrinter(TypePrinter, NumberedTypes, M); } @@ -1124,6 +1110,7 @@ private: void printModule(const Module *M); void printTypeSymbolTable(const TypeSymbolTable &ST); void printGlobal(const GlobalVariable *GV); + void printMDNode(const MDNode *Node, bool StandAlone); void printAlias(const GlobalAlias *GV); void printFunction(const Function *F); void printArgument(const Argument *FA, Attributes Attrs); @@ -1264,6 +1251,28 @@ 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(GV->getInitializer())) { + SmallVector 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(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 << " = "; @@ -1283,7 +1292,10 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { if (GV->hasInitializer()) { Out << ' '; - writeOperand(GV->getInitializer(), false); + if (MDNode *N = dyn_cast(GV->getInitializer())) + printMDNode(N, false); + else + writeOperand(GV->getInitializer(), false); } if (GV->hasSection()) @@ -1295,6 +1307,42 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { Out << '\n'; } +void AssemblyWriter::printMDNode(const MDNode *Node, + bool StandAlone) { + std::map::iterator MI = MDNodes.find(Node); + // If this node is already printed then just refer it using its Metadata + // id number. + if (MI != MDNodes.end()) { + Out << "metadata !" << 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(TV)) + 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()) diff --git a/test/Feature/mdnode2.ll b/test/Feature/mdnode2.ll new file mode 100644 index 00000000000..9feac7e1315 --- /dev/null +++ b/test/Feature/mdnode2.ll @@ -0,0 +1,7 @@ +; 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 +!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}