Support stand alone metadata syntax.
!0 = constant metadata !{i32 21, i32 22} @llvm.blah = constant metadata !{i32 1000, i16 200, metadata !0} llvm-svn: 74630
This commit is contained in:
parent
aa246cafaa
commit
39e64d452a
|
@ -109,6 +109,7 @@ bool LLParser::ParseTopLevelEntities() {
|
||||||
case lltok::StringConstant: // FIXME: REMOVE IN LLVM 3.0
|
case lltok::StringConstant: // FIXME: REMOVE IN LLVM 3.0
|
||||||
case lltok::LocalVar: if (ParseNamedType()) return true; break;
|
case lltok::LocalVar: if (ParseNamedType()) return true; break;
|
||||||
case lltok::GlobalVar: if (ParseNamedGlobal()) 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
|
// The Global variable production with no name can have many different
|
||||||
// optional leading prefixes, the production is:
|
// optional leading prefixes, the production is:
|
||||||
|
@ -355,6 +356,34 @@ bool LLParser::ParseNamedGlobal() {
|
||||||
return ParseAlias(Name, NameLoc, Visibility);
|
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:
|
/// ParseAlias:
|
||||||
/// ::= GlobalVar '=' OptionalVisibility 'alias' OptionalLinkage Aliasee
|
/// ::= GlobalVar '=' OptionalVisibility 'alias' OptionalLinkage Aliasee
|
||||||
/// Aliasee
|
/// Aliasee
|
||||||
|
@ -1596,6 +1625,17 @@ bool LLParser::ParseValID(ValID &ID) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Standalone metadata reference
|
||||||
|
// !{ ..., !42, ... }
|
||||||
|
unsigned MID = 0;
|
||||||
|
if (!ParseUInt32(MID)) {
|
||||||
|
std::map<unsigned, Constant *>::iterator I = MetadataCache.find(MID);
|
||||||
|
if (I == MetadataCache.end())
|
||||||
|
return TokError("Unknown metadata reference");
|
||||||
|
ID.ConstantVal = I->second;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// MDString:
|
// MDString:
|
||||||
// ::= '!' STRINGCONSTANT
|
// ::= '!' STRINGCONSTANT
|
||||||
std::string Str;
|
std::string Str;
|
||||||
|
|
|
@ -43,7 +43,8 @@ namespace llvm {
|
||||||
std::map<std::string, std::pair<PATypeHolder, LocTy> > ForwardRefTypes;
|
std::map<std::string, std::pair<PATypeHolder, LocTy> > ForwardRefTypes;
|
||||||
std::map<unsigned, std::pair<PATypeHolder, LocTy> > ForwardRefTypeIDs;
|
std::map<unsigned, std::pair<PATypeHolder, LocTy> > ForwardRefTypeIDs;
|
||||||
std::vector<PATypeHolder> NumberedTypes;
|
std::vector<PATypeHolder> NumberedTypes;
|
||||||
|
/// MetadataCache - This map keeps track of parsed metadata constants.
|
||||||
|
std::map<unsigned, Constant *> MetadataCache;
|
||||||
struct UpRefRecord {
|
struct UpRefRecord {
|
||||||
/// Loc - This is the location of the upref.
|
/// Loc - This is the location of the upref.
|
||||||
LocTy Loc;
|
LocTy Loc;
|
||||||
|
@ -139,6 +140,7 @@ namespace llvm {
|
||||||
bool ParseGlobal(const std::string &Name, LocTy Loc, unsigned Linkage,
|
bool ParseGlobal(const std::string &Name, LocTy Loc, unsigned Linkage,
|
||||||
bool HasLinkage, unsigned Visibility);
|
bool HasLinkage, unsigned Visibility);
|
||||||
bool ParseAlias(const std::string &Name, LocTy Loc, unsigned Visibility);
|
bool ParseAlias(const std::string &Name, LocTy Loc, unsigned Visibility);
|
||||||
|
bool ParseStandaloneMetadata();
|
||||||
|
|
||||||
// Type Parsing.
|
// Type Parsing.
|
||||||
bool ParseType(PATypeHolder &Result, bool AllowVoid = false);
|
bool ParseType(PATypeHolder &Result, bool AllowVoid = false);
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <map>
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
// Make virtual table appear in this compilation unit.
|
// Make virtual table appear in this compilation unit.
|
||||||
|
@ -945,25 +946,6 @@ static void WriteConstantInt(raw_ostream &Out, const Constant *CV,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const MDNode *N = dyn_cast<MDNode>(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<ConstantExpr>(CV)) {
|
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
|
||||||
Out << CE->getOpcodeName();
|
Out << CE->getOpcodeName();
|
||||||
if (CE->isCompare())
|
if (CE->isCompare())
|
||||||
|
@ -1092,10 +1074,14 @@ class AssemblyWriter {
|
||||||
TypePrinting TypePrinter;
|
TypePrinting TypePrinter;
|
||||||
AssemblyAnnotationWriter *AnnotationWriter;
|
AssemblyAnnotationWriter *AnnotationWriter;
|
||||||
std::vector<const Type*> NumberedTypes;
|
std::vector<const Type*> NumberedTypes;
|
||||||
|
|
||||||
|
// Each MDNode is assigned unique MetadataIDNo.
|
||||||
|
std::map<const MDNode *, unsigned> MDNodes;
|
||||||
|
unsigned MetadataIDNo;
|
||||||
public:
|
public:
|
||||||
inline AssemblyWriter(raw_ostream &o, SlotTracker &Mac, const Module *M,
|
inline AssemblyWriter(raw_ostream &o, SlotTracker &Mac, const Module *M,
|
||||||
AssemblyAnnotationWriter *AAW)
|
AssemblyAnnotationWriter *AAW)
|
||||||
: Out(o), Machine(Mac), TheModule(M), AnnotationWriter(AAW) {
|
: Out(o), Machine(Mac), TheModule(M), AnnotationWriter(AAW), MetadataIDNo(0) {
|
||||||
AddModuleTypesToPrinter(TypePrinter, NumberedTypes, M);
|
AddModuleTypesToPrinter(TypePrinter, NumberedTypes, M);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1124,6 +1110,7 @@ private:
|
||||||
void printModule(const Module *M);
|
void printModule(const Module *M);
|
||||||
void printTypeSymbolTable(const TypeSymbolTable &ST);
|
void printTypeSymbolTable(const TypeSymbolTable &ST);
|
||||||
void printGlobal(const GlobalVariable *GV);
|
void printGlobal(const GlobalVariable *GV);
|
||||||
|
void printMDNode(const MDNode *Node, bool StandAlone);
|
||||||
void printAlias(const GlobalAlias *GV);
|
void printAlias(const GlobalAlias *GV);
|
||||||
void printFunction(const Function *F);
|
void printFunction(const Function *F);
|
||||||
void printArgument(const Argument *FA, Attributes Attrs);
|
void printArgument(const Argument *FA, Attributes Attrs);
|
||||||
|
@ -1264,6 +1251,28 @@ static void PrintVisibility(GlobalValue::VisibilityTypes Vis,
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
|
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()) {
|
if (GV->hasName()) {
|
||||||
PrintLLVMName(Out, GV);
|
PrintLLVMName(Out, GV);
|
||||||
Out << " = ";
|
Out << " = ";
|
||||||
|
@ -1283,6 +1292,9 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
|
||||||
|
|
||||||
if (GV->hasInitializer()) {
|
if (GV->hasInitializer()) {
|
||||||
Out << ' ';
|
Out << ' ';
|
||||||
|
if (MDNode *N = dyn_cast<MDNode>(GV->getInitializer()))
|
||||||
|
printMDNode(N, false);
|
||||||
|
else
|
||||||
writeOperand(GV->getInitializer(), false);
|
writeOperand(GV->getInitializer(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1295,6 +1307,42 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
|
||||||
Out << '\n';
|
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()) {
|
||||||
|
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<MDNode>(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) {
|
void AssemblyWriter::printAlias(const GlobalAlias *GA) {
|
||||||
// Don't crash when dumping partially built GA
|
// Don't crash when dumping partially built GA
|
||||||
if (!GA->hasName())
|
if (!GA->hasName())
|
||||||
|
|
|
@ -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}
|
Loading…
Reference in New Issue