diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AsmParser/LLLexer.cpp | 1 | ||||
-rw-r--r-- | lib/AsmParser/LLParser.cpp | 43 | ||||
-rw-r--r-- | lib/AsmParser/LLParser.h | 3 | ||||
-rw-r--r-- | lib/AsmParser/LLToken.h | 3 | ||||
-rw-r--r-- | lib/Bitcode/Reader/BitcodeReader.cpp | 29 | ||||
-rw-r--r-- | lib/Bitcode/Writer/BitcodeWriter.cpp | 31 | ||||
-rw-r--r-- | lib/VMCore/AsmWriter.cpp | 25 | ||||
-rw-r--r-- | lib/VMCore/Constants.cpp | 80 | ||||
-rw-r--r-- | lib/VMCore/Type.cpp | 2 | ||||
-rw-r--r-- | lib/VMCore/Verifier.cpp | 51 |
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) { |