aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AsmParser/LLLexer.cpp1
-rw-r--r--lib/AsmParser/LLParser.cpp43
-rw-r--r--lib/AsmParser/LLParser.h3
-rw-r--r--lib/AsmParser/LLToken.h3
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp29
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp31
-rw-r--r--lib/VMCore/AsmWriter.cpp25
-rw-r--r--lib/VMCore/Constants.cpp80
-rw-r--r--lib/VMCore/Type.cpp2
-rw-r--r--lib/VMCore/Verifier.cpp51
10 files changed, 262 insertions, 6 deletions
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index 95e6c90..d4815d8 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/lib/AsmParser/LLLexer.cpp
@@ -265,6 +265,7 @@ lltok::Kind LLLexer::LexToken() {
case ';':
SkipLineComment();
return LexToken();
+ case '!': return lltok::Metadata;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '-':
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index 7800b8f..177161e 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -1561,6 +1561,29 @@ bool LLParser::ParseValID(ValID &ID) {
ID.StrVal = Lex.getStrVal();
ID.Kind = ValID::t_LocalName;
break;
+ case lltok::Metadata: { // !{...} MDNode, !"foo" MDString
+ ID.Kind = ValID::t_Constant;
+ Lex.Lex();
+ if (Lex.getKind() == lltok::lbrace) {
+ // MDNode:
+ // ::= '!' '{' TypeAndValue (',' TypeAndValue)* '}'
+ SmallVector<Constant*, 16> Elts;
+ if (ParseMDNodeVector(Elts) ||
+ ParseToken(lltok::rbrace, "expected end of metadata node"))
+ return true;
+
+ ID.ConstantVal = MDNode::get(&Elts[0], Elts.size());
+ return false;
+ }
+
+ // MDString:
+ // ::= '!' STRINGCONSTANT
+ std::string Str;
+ if (ParseStringConstant(Str)) return true;
+
+ ID.ConstantVal = MDString::get(Str.data(), Str.data() + Str.size());
+ return false;
+ }
case lltok::APSInt:
ID.APSIntVal = Lex.getAPSIntVal();
ID.Kind = ValID::t_APSInt;
@@ -1661,7 +1684,7 @@ bool LLParser::ParseValID(ValID &ID) {
"array element #" + utostr(i) +
" is not of type '" +Elts[0]->getType()->getDescription());
}
-
+
ID.ConstantVal = ConstantArray::get(ATy, &Elts[0], Elts.size());
ID.Kind = ValID::t_Constant;
return false;
@@ -3221,3 +3244,21 @@ bool LLParser::ParseInsertValue(Instruction *&Inst, PerFunctionState &PFS) {
Inst = InsertValueInst::Create(Val0, Val1, Indices.begin(), Indices.end());
return false;
}
+
+//===----------------------------------------------------------------------===//
+// Embedded metadata.
+//===----------------------------------------------------------------------===//
+
+/// ParseMDNodeVector
+/// ::= TypeAndValue (',' TypeAndValue)*
+bool LLParser::ParseMDNodeVector(SmallVectorImpl<Constant*> &Elts) {
+ assert(Lex.getKind() == lltok::lbrace);
+ Lex.Lex();
+ do {
+ Constant *C;
+ if (ParseGlobalTypeAndValue(C)) return true;
+ Elts.push_back(C);
+ } while (EatIfPresent(lltok::comma));
+
+ return false;
+}
diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h
index 3fc2fd2..44f4c2a 100644
--- a/lib/AsmParser/LLParser.h
+++ b/lib/AsmParser/LLParser.h
@@ -27,6 +27,8 @@ namespace llvm {
class Instruction;
class Constant;
class GlobalValue;
+ class MDString;
+ class MDNode;
struct ValID;
class LLParser {
@@ -156,6 +158,7 @@ namespace llvm {
bool ParseGlobalValue(const Type *Ty, Constant *&V);
bool ParseGlobalTypeAndValue(Constant *&V);
bool ParseGlobalValueVector(SmallVectorImpl<Constant*> &Elts);
+ bool ParseMDNodeVector(SmallVectorImpl<Constant*> &);
// Function Semantic Analysis.
diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h
index ec3769b..35cb4db 100644
--- a/lib/AsmParser/LLToken.h
+++ b/lib/AsmParser/LLToken.h
@@ -115,6 +115,9 @@ namespace lltok {
LocalVar, // %foo %"foo"
StringConstant, // "foo"
+ // Metadata valued tokens.
+ Metadata, // !"foo" !{i8 42}
+
// Type valued tokens (TyVal).
Type,
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index dd9db8f..66ccdc2 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -286,10 +286,12 @@ void BitcodeReaderValueList::ResolveConstantForwardRefs() {
UserCS->getType()->isPacked());
} else if (isa<ConstantVector>(UserC)) {
NewC = ConstantVector::get(&NewOps[0], NewOps.size());
- } else {
- // Must be a constant expression.
+ } else if (isa<ConstantExpr>(UserC)) {
NewC = cast<ConstantExpr>(UserC)->getWithOperands(&NewOps[0],
NewOps.size());
+ } else {
+ assert(isa<MDNode>(UserC) && "Must be a metadata node.");
+ NewC = MDNode::get(&NewOps[0], NewOps.size());
}
UserC->replaceAllUsesWith(NewC);
@@ -999,6 +1001,29 @@ bool BitcodeReader::ParseConstants() {
AsmStr, ConstrStr, HasSideEffects);
break;
}
+ case bitc::CST_CODE_MDSTRING: {
+ if (Record.size() < 2) return Error("Invalid MDSTRING record");
+ unsigned MDStringLength = Record.size();
+ SmallString<8> String;
+ String.resize(MDStringLength);
+ for (unsigned i = 0; i != MDStringLength; ++i)
+ String[i] = Record[i];
+ V = MDString::get(String.c_str(), String.c_str() + MDStringLength);
+ break;
+ }
+ case bitc::CST_CODE_MDNODE: {
+ if (Record.empty() || Record.size() % 2 == 1)
+ return Error("Invalid CST_MDNODE record");
+
+ unsigned Size = Record.size();
+ SmallVector<Constant*, 8> Elts;
+ for (unsigned i = 0; i != Size; i += 2) {
+ const Type *Ty = getTypeByID(Record[i], false);
+ Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], Ty));
+ }
+ V = MDNode::get(&Elts[0], Elts.size());
+ break;
+ }
}
ValueList.AssignValue(V, NextCstNo);
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index d4d3443..c836d39 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -458,6 +458,8 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
unsigned String8Abbrev = 0;
unsigned CString7Abbrev = 0;
unsigned CString6Abbrev = 0;
+ unsigned MDString8Abbrev = 0;
+ unsigned MDString6Abbrev = 0;
// If this is a constant pool for the module, emit module-specific abbrevs.
if (isGlobal) {
// Abbrev for CST_CODE_AGGREGATE.
@@ -485,6 +487,19 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
CString6Abbrev = Stream.EmitAbbrev(Abbv);
+
+ // Abbrev for CST_CODE_MDSTRING.
+ Abbv = new BitCodeAbbrev();
+ Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_MDSTRING));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));
+ MDString8Abbrev = Stream.EmitAbbrev(Abbv);
+ // Abbrev for CST_CODE_MDSTRING.
+ Abbv = new BitCodeAbbrev();
+ Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_MDSTRING));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
+ MDString6Abbrev = Stream.EmitAbbrev(Abbv);
}
SmallVector<uint64_t, 64> Record;
@@ -678,6 +693,22 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
Record.push_back(CE->getPredicate());
break;
}
+ } else if (const MDString *S = dyn_cast<MDString>(C)) {
+ Code = bitc::CST_CODE_MDSTRING;
+ AbbrevToUse = MDString6Abbrev;
+ for (unsigned i = 0, e = S->size(); i != e; ++i) {
+ char V = S->begin()[i];
+ Record.push_back(V);
+
+ if (!BitCodeAbbrevOp::isChar6(V))
+ AbbrevToUse = MDString8Abbrev;
+ }
+ } else if (const MDNode *N = dyn_cast<MDNode>(C)) {
+ Code = bitc::CST_CODE_MDNODE;
+ for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
+ Record.push_back(VE.getTypeID(N->getOperand(i)->getType()));
+ Record.push_back(VE.getValueID(N->getOperand(i)));
+ }
} else {
assert(0 && "Unknown constant!");
}
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp
index 3f8be47..83fc35b 100644
--- a/lib/VMCore/AsmWriter.cpp
+++ b/lib/VMCore/AsmWriter.cpp
@@ -23,6 +23,7 @@
#include "llvm/InlineAsm.h"
#include "llvm/Instruction.h"
#include "llvm/Instructions.h"
+#include "llvm/Metadata.h"
#include "llvm/Module.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/TypeSymbolTable.h"
@@ -361,8 +362,8 @@ namespace {
return;
// If this is a structure or opaque type, add a name for the type.
- if ((isa<StructType>(Ty) || isa<OpaqueType>(Ty))
- && !TP.hasTypeName(Ty)) {
+ if (((isa<StructType>(Ty) && cast<StructType>(Ty)->getNumElements())
+ || isa<OpaqueType>(Ty)) && !TP.hasTypeName(Ty)) {
TP.addTypeName(Ty, "%"+utostr(unsigned(NumberedTypes.size())));
NumberedTypes.push_back(Ty);
}
@@ -935,7 +936,27 @@ static void WriteConstantInt(raw_ostream &Out, const Constant *CV,
Out << "undef";
return;
}
+
+ if (const MDString *S = dyn_cast<MDString>(CV)) {
+ Out << "!\"";
+ PrintEscapedString(S->begin(), S->size(), Out);
+ Out << '"';
+ return;
+ }
+ if (const MDNode *N = dyn_cast<MDNode>(CV)) {
+ Out << "!{";
+ for (MDNode::const_op_iterator I = N->op_begin(), E = N->op_end(); I != E;){
+ 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)) {
Out << CE->getOpcodeName();
if (CE->isCompare())
diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp
index 7cd3599..2afaa6c 100644
--- a/lib/VMCore/Constants.cpp
+++ b/lib/VMCore/Constants.cpp
@@ -17,7 +17,9 @@
#include "llvm/GlobalValue.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
+#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ManagedStatic.h"
@@ -1657,6 +1659,63 @@ void UndefValue::destroyConstant() {
destroyConstantImpl();
}
+//---- MDString::get() implementation
+//
+
+MDString::MDString(const char *begin, const char *end)
+ : Constant(Type::EmptyStructTy, MDStringVal, 0, 0),
+ StrBegin(begin), StrEnd(end) {}
+
+static ManagedStatic<StringMap<MDString*> > MDStringCache;
+
+MDString *MDString::get(const char *StrBegin, const char *StrEnd) {
+ StringMapEntry<MDString *> &Entry = MDStringCache->GetOrCreateValue(StrBegin,
+ StrEnd);
+ MDString *&S = Entry.getValue();
+ if (!S) S = new MDString(Entry.getKeyData(),
+ Entry.getKeyData() + Entry.getKeyLength());
+ return S;
+}
+
+void MDString::destroyConstant() {
+ MDStringCache->erase(MDStringCache->find(StrBegin, StrEnd));
+ destroyConstantImpl();
+}
+
+//---- MDNode::get() implementation
+//
+
+static ManagedStatic<FoldingSet<MDNode> > MDNodeSet;
+
+MDNode::MDNode(Constant*const* Vals, unsigned NumVals)
+ : Constant(Type::EmptyStructTy, MDNodeVal,
+ OperandTraits<MDNode>::op_end(this) - NumVals, NumVals) {
+ std::copy(Vals, Vals + NumVals, OperandList);
+}
+
+void MDNode::Profile(FoldingSetNodeID &ID) {
+ for (op_iterator I = op_begin(), E = op_end(); I != E; ++I)
+ ID.AddPointer(*I);
+}
+
+MDNode *MDNode::get(Constant*const* Vals, unsigned NumVals) {
+ FoldingSetNodeID ID;
+ for (unsigned i = 0; i != NumVals; ++i)
+ ID.AddPointer(Vals[i]);
+
+ void *InsertPoint;
+ if (MDNode *N = MDNodeSet->FindNodeOrInsertPos(ID, InsertPoint))
+ return N;
+
+ // InsertPoint will have been set by the FindNodeOrInsertPos call.
+ MDNode *N = new(NumVals) MDNode(Vals, NumVals);
+ MDNodeSet->InsertNode(N, InsertPoint);
+ return N;
+}
+
+void MDNode::destroyConstant() {
+ destroyConstantImpl();
+}
//---- ConstantExpr::get() implementations...
//
@@ -2741,3 +2800,24 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
// Delete the old constant!
destroyConstant();
}
+
+void MDNode::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) {
+ assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
+
+ SmallVector<Constant*, 8> Values;
+ Values.reserve(getNumOperands()); // Build replacement array...
+ for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
+ Constant *Val = getOperand(i);
+ if (Val == From) Val = cast<Constant>(To);
+ Values.push_back(Val);
+ }
+
+ Constant *Replacement = MDNode::get(&Values[0], Values.size());
+ assert(Replacement != this && "I didn't contain From!");
+
+ // Everyone using this now uses the replacement.
+ uncheckedReplaceAllUsesWith(Replacement);
+
+ // Delete the old constant!
+ destroyConstant();
+}
diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp
index 237ec05..c14d511 100644
--- a/lib/VMCore/Type.cpp
+++ b/lib/VMCore/Type.cpp
@@ -288,6 +288,8 @@ const IntegerType *Type::Int16Ty = new BuiltinIntegerType(16);
const IntegerType *Type::Int32Ty = new BuiltinIntegerType(32);
const IntegerType *Type::Int64Ty = new BuiltinIntegerType(64);
+const Type *Type::EmptyStructTy = StructType::get(NULL, NULL);
+
//===----------------------------------------------------------------------===//
// Derived Type Constructors
diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp
index 5af66df..df9acee 100644
--- a/lib/VMCore/Verifier.cpp
+++ b/lib/VMCore/Verifier.cpp
@@ -338,6 +338,36 @@ static RegisterPass<Verifier> X("verify", "Module Verifier");
#define Assert4(C, M, V1, V2, V3, V4) \
do { if (!(C)) { CheckFailed(M, V1, V2, V3, V4); return; } } while (0)
+/// Check whether or not a Value is metadata or made up of a constant
+/// expression involving metadata.
+static bool isMetadata(Value *X) {
+ SmallPtrSet<Value *, 8> Visited;
+ SmallVector<Value *, 8> Queue;
+ Queue.push_back(X);
+
+ while (!Queue.empty()) {
+ Value *V = Queue.back();
+ Queue.pop_back();
+ if (!Visited.insert(V))
+ continue;
+
+ if (isa<MDString>(V) || isa<MDNode>(V))
+ return true;
+ if (!isa<ConstantExpr>(V))
+ continue;
+ ConstantExpr *CE = cast<ConstantExpr>(V);
+
+ if (CE->getType() != Type::EmptyStructTy)
+ continue;
+
+ // The only constant expression that works on metadata type is select.
+ if (CE->getOpcode() != Instruction::Select) return false;
+
+ Queue.push_back(CE->getOperand(1));
+ Queue.push_back(CE->getOperand(2));
+ }
+ return false;
+}
void Verifier::visit(Instruction &I) {
for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
@@ -649,6 +679,7 @@ void Verifier::visitReturnInst(ReturnInst &RI) {
"Found return instr that returns non-void in Function of void "
"return type!", &RI, F->getReturnType());
else if (N == 1 && F->getReturnType() == RI.getOperand(0)->getType()) {
+ Assert1(!isMetadata(RI.getOperand(0)), "Invalid use of metadata!", &RI);
// Exactly one return value and it matches the return type. Good.
} else if (const StructType *STy = dyn_cast<StructType>(F->getReturnType())) {
// The return type is a struct; check for multiple return values.
@@ -696,6 +727,8 @@ void Verifier::visitSelectInst(SelectInst &SI) {
Assert1(SI.getTrueValue()->getType() == SI.getType(),
"Select values must have same type as select instruction!", &SI);
+ Assert1(!isMetadata(SI.getOperand(1)) && !isMetadata(SI.getOperand(2)),
+ "Invalid use of metadata!", &SI);
visitInstruction(SI);
}
@@ -951,6 +984,13 @@ void Verifier::visitPHINode(PHINode &PN) {
Assert1(PN.getType() == PN.getIncomingValue(i)->getType(),
"PHI node operands are not the same type as the result!", &PN);
+ // Check that it's not a PHI of metadata.
+ if (PN.getType() == Type::EmptyStructTy) {
+ for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
+ Assert1(!isMetadata(PN.getIncomingValue(i)),
+ "Invalid use of metadata!", &PN);
+ }
+
// All other PHI node constraints are checked in the visitBasicBlock method.
visitInstruction(PN);
@@ -981,6 +1021,14 @@ void Verifier::VerifyCallSite(CallSite CS) {
"Call parameter type does not match function signature!",
CS.getArgument(i), FTy->getParamType(i), I);
+ if (CS.getCalledValue()->getNameLen() < 5 ||
+ strncmp(CS.getCalledValue()->getNameStart(), "llvm.", 5) != 0) {
+ // Verify that none of the arguments are metadata...
+ for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
+ Assert2(!isMetadata(CS.getArgument(i)), "Invalid use of metadata!",
+ CS.getArgument(i), I);
+ }
+
const AttrListPtr &Attrs = CS.getAttributes();
Assert1(VerifyAttributeCount(Attrs, CS.arg_size()),
@@ -1152,6 +1200,7 @@ void Verifier::visitStoreInst(StoreInst &SI) {
cast<PointerType>(SI.getOperand(1)->getType())->getElementType();
Assert2(ElTy == SI.getOperand(0)->getType(),
"Stored value type does not match pointer operand type!", &SI, ElTy);
+ Assert1(!isMetadata(SI.getOperand(0)), "Invalid use of metadata!", &SI);
visitInstruction(SI);
}
@@ -1481,7 +1530,7 @@ bool Verifier::PerformTypeCheck(Intrinsic::ID ID, Function *F, const Type *Ty,
if (EltTy != Ty)
Suffix += "v" + utostr(NumElts);
- Suffix += "i" + utostr(GotBits);;
+ Suffix += "i" + utostr(GotBits);
// Check some constraints on various intrinsics.
switch (ID) {