diff options
Diffstat (limited to 'contrib/llvm/lib/AsmParser/LLParser.cpp')
-rw-r--r-- | contrib/llvm/lib/AsmParser/LLParser.cpp | 1145 |
1 files changed, 989 insertions, 156 deletions
diff --git a/contrib/llvm/lib/AsmParser/LLParser.cpp b/contrib/llvm/lib/AsmParser/LLParser.cpp index d209a20..a52e20f 100644 --- a/contrib/llvm/lib/AsmParser/LLParser.cpp +++ b/contrib/llvm/lib/AsmParser/LLParser.cpp @@ -16,6 +16,8 @@ #include "llvm/IR/AutoUpgrade.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" @@ -23,6 +25,7 @@ #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/IR/ValueSymbolTable.h" +#include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/raw_ostream.h" @@ -115,10 +118,10 @@ bool LLParser::ValidateEndOfModule() { return Error(ForwardRefBlockAddresses.begin()->first.Loc, "expected function name in blockaddress"); - for (unsigned i = 0, e = NumberedTypes.size(); i != e; ++i) - if (NumberedTypes[i].second.isValid()) - return Error(NumberedTypes[i].second, - "use of undefined type '%" + Twine(i) + "'"); + for (const auto &NT : NumberedTypes) + if (NT.second.second.isValid()) + return Error(NT.second.second, + "use of undefined type '%" + Twine(NT.first) + "'"); for (StringMap<std::pair<Type*, LocTy> >::iterator I = NamedTypes.begin(), E = NamedTypes.end(); I != E; ++I) @@ -147,9 +150,10 @@ bool LLParser::ValidateEndOfModule() { Twine(ForwardRefMDNodes.begin()->first) + "'"); // Resolve metadata cycles. - for (auto &N : NumberedMetadata) - if (auto *U = cast_or_null<UniquableMDNode>(N)) - U->resolveCycles(); + for (auto &N : NumberedMetadata) { + if (N.second && !N.second->isResolved()) + N.second->resolveCycles(); + } // Look for intrinsic functions and CallInst that need to be upgraded for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ) @@ -302,9 +306,6 @@ bool LLParser::ParseUnnamedType() { ParseToken(lltok::kw_type, "expected 'type' after '='")) return true; - if (TypeID >= NumberedTypes.size()) - NumberedTypes.resize(TypeID+1); - Type *Result = nullptr; if (ParseStructDefinition(TypeLoc, "", NumberedTypes[TypeID], Result)) return true; @@ -359,13 +360,14 @@ bool LLParser::ParseDeclare() { } /// toplevelentity -/// ::= 'define' FunctionHeader '{' ... +/// ::= 'define' FunctionHeader (!dbg !56)* '{' ... bool LLParser::ParseDefine() { assert(Lex.getKind() == lltok::kw_define); Lex.Lex(); Function *F; return ParseFunctionHeader(F, true) || + ParseOptionalFunctionMetadata(*F) || ParseFunctionBody(*F); } @@ -525,19 +527,17 @@ bool LLParser::ParseMDNodeID(MDNode *&Result) { return true; // If not a forward reference, just return it now. - if (MID < NumberedMetadata.size() && NumberedMetadata[MID] != nullptr) { + if (NumberedMetadata.count(MID)) { Result = NumberedMetadata[MID]; return false; } // Otherwise, create MDNode forward reference. - MDNodeFwdDecl *FwdNode = MDNodeFwdDecl::get(Context, None); - ForwardRefMDNodes[MID] = std::make_pair(FwdNode, Lex.getLoc()); + auto &FwdRef = ForwardRefMDNodes[MID]; + FwdRef = std::make_pair(MDTuple::getTemporary(Context, None), Lex.getLoc()); - if (NumberedMetadata.size() <= MID) - NumberedMetadata.resize(MID+1); - NumberedMetadata[MID].reset(FwdNode); - Result = FwdNode; + Result = FwdRef.first.get(); + NumberedMetadata[MID].reset(Result); return false; } @@ -564,10 +564,7 @@ bool LLParser::ParseNamedMetadata() { NMD->addOperand(N); } while (EatIfPresent(lltok::comma)); - if (ParseToken(lltok::rbrace, "expected end of metadata node")) - return true; - - return false; + return ParseToken(lltok::rbrace, "expected end of metadata node"); } /// ParseStandaloneMetadata: @@ -597,17 +594,12 @@ bool LLParser::ParseStandaloneMetadata() { // See if this was forward referenced, if so, handle it. auto FI = ForwardRefMDNodes.find(MetadataID); if (FI != ForwardRefMDNodes.end()) { - MDNodeFwdDecl *Temp = FI->second.first; - Temp->replaceAllUsesWith(Init); - delete Temp; + FI->second.first->replaceAllUsesWith(Init); ForwardRefMDNodes.erase(FI); assert(NumberedMetadata[MetadataID] == Init && "Tracking VH didn't work"); } else { - if (MetadataID >= NumberedMetadata.size()) - NumberedMetadata.resize(MetadataID+1); - - if (NumberedMetadata[MetadataID] != nullptr) + if (NumberedMetadata.count(MetadataID)) return TokError("Metadata id is already used"); NumberedMetadata[MetadataID].reset(Init); } @@ -668,13 +660,11 @@ bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, unsigned L, auto *PTy = dyn_cast<PointerType>(AliaseeType); if (!PTy) return Error(AliaseeLoc, "An alias must have pointer type"); - Type *Ty = PTy->getElementType(); - unsigned AddrSpace = PTy->getAddressSpace(); // Okay, create the alias but do not insert it into the module yet. std::unique_ptr<GlobalAlias> GA( - GlobalAlias::create(Ty, AddrSpace, (GlobalValue::LinkageTypes)Linkage, - Name, Aliasee, /*Parent*/ nullptr)); + GlobalAlias::create(PTy, (GlobalValue::LinkageTypes)Linkage, Name, + Aliasee, /*Parent*/ nullptr)); GA->setThreadLocalMode(TLM); GA->setVisibility((GlobalValue::VisibilityTypes)Visibility); GA->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); @@ -756,7 +746,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, return true; } - if (Ty->isFunctionTy() || Ty->isLabelTy()) + if (Ty->isFunctionTy() || !PointerType::isValidElementType(Ty)) return Error(TyLoc, "invalid type for global variable"); GlobalValue *GVal = nullptr; @@ -783,7 +773,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, Name, nullptr, GlobalVariable::NotThreadLocal, AddrSpace); } else { - if (GVal->getType()->getElementType() != Ty) + if (GVal->getValueType() != Ty) return Error(TyLoc, "forward reference and definition of global have different types"); @@ -947,6 +937,7 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B, case lltok::kw_alwaysinline: B.addAttribute(Attribute::AlwaysInline); break; case lltok::kw_builtin: B.addAttribute(Attribute::Builtin); break; case lltok::kw_cold: B.addAttribute(Attribute::Cold); break; + case lltok::kw_convergent: B.addAttribute(Attribute::Convergent); break; case lltok::kw_inlinehint: B.addAttribute(Attribute::InlineHint); break; case lltok::kw_jumptable: B.addAttribute(Attribute::JumpTable); break; case lltok::kw_minsize: B.addAttribute(Attribute::MinSize); break; @@ -982,6 +973,7 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B, break; case lltok::kw_byval: case lltok::kw_dereferenceable: + case lltok::kw_dereferenceable_or_null: case lltok::kw_inalloca: case lltok::kw_nest: case lltok::kw_noalias: @@ -1226,11 +1218,18 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) { case lltok::kw_byval: B.addAttribute(Attribute::ByVal); break; case lltok::kw_dereferenceable: { uint64_t Bytes; - if (ParseOptionalDereferenceableBytes(Bytes)) + if (ParseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes)) return true; B.addDereferenceableAttr(Bytes); continue; } + case lltok::kw_dereferenceable_or_null: { + uint64_t Bytes; + if (ParseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes)) + return true; + B.addDereferenceableOrNullAttr(Bytes); + continue; + } case lltok::kw_inalloca: B.addAttribute(Attribute::InAlloca); break; case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break; case lltok::kw_nest: B.addAttribute(Attribute::Nest); break; @@ -1290,11 +1289,18 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) { return HaveError; case lltok::kw_dereferenceable: { uint64_t Bytes; - if (ParseOptionalDereferenceableBytes(Bytes)) + if (ParseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes)) return true; B.addDereferenceableAttr(Bytes); continue; } + case lltok::kw_dereferenceable_or_null: { + uint64_t Bytes; + if (ParseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes)) + return true; + B.addDereferenceableOrNullAttr(Bytes); + continue; + } case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break; case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break; case lltok::kw_nonnull: B.addAttribute(Attribute::NonNull); break; @@ -1481,31 +1487,53 @@ bool LLParser::ParseOptionalCallingConv(unsigned &CC) { return false; } +/// ParseMetadataAttachment +/// ::= !dbg !42 +bool LLParser::ParseMetadataAttachment(unsigned &Kind, MDNode *&MD) { + assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata attachment"); + + std::string Name = Lex.getStrVal(); + Kind = M->getMDKindID(Name); + Lex.Lex(); + + return ParseMDNode(MD); +} + /// ParseInstructionMetadata /// ::= !dbg !42 (',' !dbg !57)* -bool LLParser::ParseInstructionMetadata(Instruction *Inst, - PerFunctionState *PFS) { +bool LLParser::ParseInstructionMetadata(Instruction &Inst) { do { if (Lex.getKind() != lltok::MetadataVar) return TokError("expected metadata after comma"); - std::string Name = Lex.getStrVal(); - unsigned MDK = M->getMDKindID(Name); - Lex.Lex(); - + unsigned MDK; MDNode *N; - if (ParseMDNode(N)) + if (ParseMetadataAttachment(MDK, N)) return true; - Inst->setMetadata(MDK, N); + Inst.setMetadata(MDK, N); if (MDK == LLVMContext::MD_tbaa) - InstsWithTBAATag.push_back(Inst); + InstsWithTBAATag.push_back(&Inst); // If this is the end of the list, we're done. } while (EatIfPresent(lltok::comma)); return false; } +/// ParseOptionalFunctionMetadata +/// ::= (!dbg !57)* +bool LLParser::ParseOptionalFunctionMetadata(Function &F) { + while (Lex.getKind() == lltok::MetadataVar) { + unsigned MDK; + MDNode *N; + if (ParseMetadataAttachment(MDK, N)) + return true; + + F.setMetadata(MDK, N); + } + return false; +} + /// ParseOptionalAlignment /// ::= /* empty */ /// ::= 'align' 4 @@ -1522,12 +1550,19 @@ bool LLParser::ParseOptionalAlignment(unsigned &Alignment) { return false; } -/// ParseOptionalDereferenceableBytes +/// ParseOptionalDerefAttrBytes /// ::= /* empty */ -/// ::= 'dereferenceable' '(' 4 ')' -bool LLParser::ParseOptionalDereferenceableBytes(uint64_t &Bytes) { +/// ::= AttrKind '(' 4 ')' +/// +/// where AttrKind is either 'dereferenceable' or 'dereferenceable_or_null'. +bool LLParser::ParseOptionalDerefAttrBytes(lltok::Kind AttrKind, + uint64_t &Bytes) { + assert((AttrKind == lltok::kw_dereferenceable || + AttrKind == lltok::kw_dereferenceable_or_null) && + "contract!"); + Bytes = 0; - if (!EatIfPresent(lltok::kw_dereferenceable)) + if (!EatIfPresent(AttrKind)) return false; LocTy ParenLoc = Lex.getLoc(); if (!EatIfPresent(lltok::lparen)) @@ -1640,6 +1675,7 @@ bool LLParser::ParseIndexList(SmallVectorImpl<unsigned> &Indices, while (EatIfPresent(lltok::comma)) { if (Lex.getKind() == lltok::MetadataVar) { + if (Indices.empty()) return TokError("expected index"); AteExtraComma = true; return false; } @@ -1704,8 +1740,6 @@ bool LLParser::ParseType(Type *&Result, const Twine &Msg, bool AllowVoid) { case lltok::LocalVarID: { // Type ::= %4 - if (Lex.getUIntVal() >= NumberedTypes.size()) - NumberedTypes.resize(Lex.getUIntVal()+1); std::pair<Type*, LocTy> &Entry = NumberedTypes[Lex.getUIntVal()]; // If the type hasn't been defined yet, create a forward definition and @@ -2277,13 +2311,13 @@ bool LLParser::PerFunctionState::SetInstName(int NameID, /// forward reference record if needed. BasicBlock *LLParser::PerFunctionState::GetBB(const std::string &Name, LocTy Loc) { - return cast_or_null<BasicBlock>(GetVal(Name, - Type::getLabelTy(F.getContext()), Loc)); + return dyn_cast_or_null<BasicBlock>(GetVal(Name, + Type::getLabelTy(F.getContext()), Loc)); } BasicBlock *LLParser::PerFunctionState::GetBB(unsigned ID, LocTy Loc) { - return cast_or_null<BasicBlock>(GetVal(ID, - Type::getLabelTy(F.getContext()), Loc)); + return dyn_cast_or_null<BasicBlock>(GetVal(ID, + Type::getLabelTy(F.getContext()), Loc)); } /// DefineBB - Define the specified basic block, which is either named or @@ -2519,7 +2553,12 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { if (!F) { // Make a global variable as a placeholder for this reference. - GlobalValue *&FwdRef = ForwardRefBlockAddresses[Fn][Label]; + GlobalValue *&FwdRef = + ForwardRefBlockAddresses.insert(std::make_pair( + std::move(Fn), + std::map<ValID, GlobalValue *>())) + .first->second.insert(std::make_pair(std::move(Label), nullptr)) + .first->second; if (!FwdRef) FwdRef = new GlobalVariable(*M, Type::getInt8Ty(Context), false, GlobalValue::InternalLinkage, nullptr, ""); @@ -2616,8 +2655,15 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { return true; if (!Val0->getType()->isAggregateType()) return Error(ID.Loc, "insertvalue operand must be aggregate type"); - if (!ExtractValueInst::getIndexedType(Val0->getType(), Indices)) + Type *IndexedType = + ExtractValueInst::getIndexedType(Val0->getType(), Indices); + if (!IndexedType) return Error(ID.Loc, "invalid indices for insertvalue"); + if (IndexedType != Val1->getType()) + return Error(ID.Loc, "insertvalue operand and field disagree in type: '" + + getTypeString(Val1->getType()) + + "' instead of '" + getTypeString(IndexedType) + + "'"); ID.ConstantVal = ConstantExpr::getInsertValue(Val0, Val1, Indices); ID.Kind = ValID::t_Constant; return false; @@ -2772,24 +2818,63 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { unsigned Opc = Lex.getUIntVal(); SmallVector<Constant*, 16> Elts; bool InBounds = false; + Type *Ty; Lex.Lex(); + if (Opc == Instruction::GetElementPtr) InBounds = EatIfPresent(lltok::kw_inbounds); - if (ParseToken(lltok::lparen, "expected '(' in constantexpr") || - ParseGlobalValueVector(Elts) || + + if (ParseToken(lltok::lparen, "expected '(' in constantexpr")) + return true; + + LocTy ExplicitTypeLoc = Lex.getLoc(); + if (Opc == Instruction::GetElementPtr) { + if (ParseType(Ty) || + ParseToken(lltok::comma, "expected comma after getelementptr's type")) + return true; + } + + if (ParseGlobalValueVector(Elts) || ParseToken(lltok::rparen, "expected ')' in constantexpr")) return true; if (Opc == Instruction::GetElementPtr) { if (Elts.size() == 0 || !Elts[0]->getType()->getScalarType()->isPointerTy()) - return Error(ID.Loc, "getelementptr requires pointer operand"); + return Error(ID.Loc, "base of getelementptr must be a pointer"); + + Type *BaseType = Elts[0]->getType(); + auto *BasePointerType = cast<PointerType>(BaseType->getScalarType()); + if (Ty != BasePointerType->getElementType()) + return Error( + ExplicitTypeLoc, + "explicit pointee type doesn't match operand's pointee type"); ArrayRef<Constant *> Indices(Elts.begin() + 1, Elts.end()); - if (!GetElementPtrInst::getIndexedType(Elts[0]->getType(), Indices)) - return Error(ID.Loc, "invalid indices for getelementptr"); - ID.ConstantVal = ConstantExpr::getGetElementPtr(Elts[0], Indices, - InBounds); + for (Constant *Val : Indices) { + Type *ValTy = Val->getType(); + if (!ValTy->getScalarType()->isIntegerTy()) + return Error(ID.Loc, "getelementptr index must be an integer"); + if (ValTy->isVectorTy() != BaseType->isVectorTy()) + return Error(ID.Loc, "getelementptr index type missmatch"); + if (ValTy->isVectorTy()) { + unsigned ValNumEl = cast<VectorType>(ValTy)->getNumElements(); + unsigned PtrNumEl = cast<VectorType>(BaseType)->getNumElements(); + if (ValNumEl != PtrNumEl) + return Error( + ID.Loc, + "getelementptr vector index has a wrong number of elements"); + } + } + + SmallPtrSet<const Type*, 4> Visited; + if (!Indices.empty() && !Ty->isSized(&Visited)) + return Error(ID.Loc, "base element of getelementptr must be sized"); + + if (!GetElementPtrInst::getIndexedType(Ty, Indices)) + return Error(ID.Loc, "invalid getelementptr indices"); + ID.ConstantVal = + ConstantExpr::getGetElementPtr(Ty, Elts[0], Indices, InBounds); } else if (Opc == Instruction::Select) { if (Elts.size() != 3) return Error(ID.Loc, "expected three operands to select"); @@ -2905,7 +2990,7 @@ bool LLParser::ParseMDTuple(MDNode *&MD, bool IsDistinct) { /// MDNode: /// ::= !{ ... } /// ::= !7 -/// ::= !MDLocation(...) +/// ::= !DILocation(...) bool LLParser::ParseMDNode(MDNode *&N) { if (Lex.getKind() == lltok::MetadataVar) return ParseSpecializedMDNode(N); @@ -2923,28 +3008,269 @@ bool LLParser::ParseMDNodeTail(MDNode *&N) { return ParseMDNodeID(N); } -bool LLParser::ParseMDField(LocTy Loc, StringRef Name, - MDUnsignedField<uint32_t> &Result) { - if (Result.Seen) - return Error(Loc, - "field '" + Name + "' cannot be specified more than once"); +namespace { + +/// Structure to represent an optional metadata field. +template <class FieldTy> struct MDFieldImpl { + typedef MDFieldImpl ImplTy; + FieldTy Val; + bool Seen; + + void assign(FieldTy Val) { + Seen = true; + this->Val = std::move(Val); + } + explicit MDFieldImpl(FieldTy Default) + : Val(std::move(Default)), Seen(false) {} +}; + +struct MDUnsignedField : public MDFieldImpl<uint64_t> { + uint64_t Max; + + MDUnsignedField(uint64_t Default = 0, uint64_t Max = UINT64_MAX) + : ImplTy(Default), Max(Max) {} +}; +struct LineField : public MDUnsignedField { + LineField() : MDUnsignedField(0, UINT32_MAX) {} +}; +struct ColumnField : public MDUnsignedField { + ColumnField() : MDUnsignedField(0, UINT16_MAX) {} +}; +struct DwarfTagField : public MDUnsignedField { + DwarfTagField() : MDUnsignedField(0, dwarf::DW_TAG_hi_user) {} + DwarfTagField(dwarf::Tag DefaultTag) + : MDUnsignedField(DefaultTag, dwarf::DW_TAG_hi_user) {} +}; +struct DwarfAttEncodingField : public MDUnsignedField { + DwarfAttEncodingField() : MDUnsignedField(0, dwarf::DW_ATE_hi_user) {} +}; +struct DwarfVirtualityField : public MDUnsignedField { + DwarfVirtualityField() : MDUnsignedField(0, dwarf::DW_VIRTUALITY_max) {} +}; +struct DwarfLangField : public MDUnsignedField { + DwarfLangField() : MDUnsignedField(0, dwarf::DW_LANG_hi_user) {} +}; + +struct DIFlagField : public MDUnsignedField { + DIFlagField() : MDUnsignedField(0, UINT32_MAX) {} +}; + +struct MDSignedField : public MDFieldImpl<int64_t> { + int64_t Min; + int64_t Max; + + MDSignedField(int64_t Default = 0) + : ImplTy(Default), Min(INT64_MIN), Max(INT64_MAX) {} + MDSignedField(int64_t Default, int64_t Min, int64_t Max) + : ImplTy(Default), Min(Min), Max(Max) {} +}; + +struct MDBoolField : public MDFieldImpl<bool> { + MDBoolField(bool Default = false) : ImplTy(Default) {} +}; +struct MDField : public MDFieldImpl<Metadata *> { + bool AllowNull; + + MDField(bool AllowNull = true) : ImplTy(nullptr), AllowNull(AllowNull) {} +}; +struct MDConstant : public MDFieldImpl<ConstantAsMetadata *> { + MDConstant() : ImplTy(nullptr) {} +}; +struct MDStringField : public MDFieldImpl<MDString *> { + bool AllowEmpty; + MDStringField(bool AllowEmpty = true) + : ImplTy(nullptr), AllowEmpty(AllowEmpty) {} +}; +struct MDFieldList : public MDFieldImpl<SmallVector<Metadata *, 4>> { + MDFieldList() : ImplTy(SmallVector<Metadata *, 4>()) {} +}; + +} // end namespace + +namespace llvm { + +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, + MDUnsignedField &Result) { if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) return TokError("expected unsigned integer"); - uint64_t Val64 = Lex.getAPSIntVal().getLimitedValue(Result.Max + 1ull); - if (Val64 > Result.Max) + auto &U = Lex.getAPSIntVal(); + if (U.ugt(Result.Max)) return TokError("value for '" + Name + "' too large, limit is " + Twine(Result.Max)); - Result.assign(Val64); + Result.assign(U.getZExtValue()); + assert(Result.Val <= Result.Max && "Expected value in range"); Lex.Lex(); return false; } +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, LineField &Result) { + return ParseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result)); +} +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, ColumnField &Result) { + return ParseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result)); +} + +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, DwarfTagField &Result) { + if (Lex.getKind() == lltok::APSInt) + return ParseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result)); + + if (Lex.getKind() != lltok::DwarfTag) + return TokError("expected DWARF tag"); + + unsigned Tag = dwarf::getTag(Lex.getStrVal()); + if (Tag == dwarf::DW_TAG_invalid) + return TokError("invalid DWARF tag" + Twine(" '") + Lex.getStrVal() + "'"); + assert(Tag <= Result.Max && "Expected valid DWARF tag"); + + Result.assign(Tag); + Lex.Lex(); + return false; +} + +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, + DwarfVirtualityField &Result) { + if (Lex.getKind() == lltok::APSInt) + return ParseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result)); + + if (Lex.getKind() != lltok::DwarfVirtuality) + return TokError("expected DWARF virtuality code"); + + unsigned Virtuality = dwarf::getVirtuality(Lex.getStrVal()); + if (!Virtuality) + return TokError("invalid DWARF virtuality code" + Twine(" '") + + Lex.getStrVal() + "'"); + assert(Virtuality <= Result.Max && "Expected valid DWARF virtuality code"); + Result.assign(Virtuality); + Lex.Lex(); + return false; +} + +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, DwarfLangField &Result) { + if (Lex.getKind() == lltok::APSInt) + return ParseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result)); + + if (Lex.getKind() != lltok::DwarfLang) + return TokError("expected DWARF language"); + + unsigned Lang = dwarf::getLanguage(Lex.getStrVal()); + if (!Lang) + return TokError("invalid DWARF language" + Twine(" '") + Lex.getStrVal() + + "'"); + assert(Lang <= Result.Max && "Expected valid DWARF language"); + Result.assign(Lang); + Lex.Lex(); + return false; +} + +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, + DwarfAttEncodingField &Result) { + if (Lex.getKind() == lltok::APSInt) + return ParseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result)); + + if (Lex.getKind() != lltok::DwarfAttEncoding) + return TokError("expected DWARF type attribute encoding"); + + unsigned Encoding = dwarf::getAttributeEncoding(Lex.getStrVal()); + if (!Encoding) + return TokError("invalid DWARF type attribute encoding" + Twine(" '") + + Lex.getStrVal() + "'"); + assert(Encoding <= Result.Max && "Expected valid DWARF language"); + Result.assign(Encoding); + Lex.Lex(); + return false; +} + +/// DIFlagField +/// ::= uint32 +/// ::= DIFlagVector +/// ::= DIFlagVector '|' DIFlagFwdDecl '|' uint32 '|' DIFlagPublic +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, DIFlagField &Result) { + assert(Result.Max == UINT32_MAX && "Expected only 32-bits"); + + // Parser for a single flag. + auto parseFlag = [&](unsigned &Val) { + if (Lex.getKind() == lltok::APSInt && !Lex.getAPSIntVal().isSigned()) + return ParseUInt32(Val); + + if (Lex.getKind() != lltok::DIFlag) + return TokError("expected debug info flag"); + + Val = DINode::getFlag(Lex.getStrVal()); + if (!Val) + return TokError(Twine("invalid debug info flag flag '") + + Lex.getStrVal() + "'"); + Lex.Lex(); + return false; + }; + + // Parse the flags and combine them together. + unsigned Combined = 0; + do { + unsigned Val; + if (parseFlag(Val)) + return true; + Combined |= Val; + } while (EatIfPresent(lltok::bar)); + + Result.assign(Combined); + return false; +} + +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, + MDSignedField &Result) { + if (Lex.getKind() != lltok::APSInt) + return TokError("expected signed integer"); + + auto &S = Lex.getAPSIntVal(); + if (S < Result.Min) + return TokError("value for '" + Name + "' too small, limit is " + + Twine(Result.Min)); + if (S > Result.Max) + return TokError("value for '" + Name + "' too large, limit is " + + Twine(Result.Max)); + Result.assign(S.getExtValue()); + assert(Result.Val >= Result.Min && "Expected value in range"); + assert(Result.Val <= Result.Max && "Expected value in range"); + Lex.Lex(); + return false; +} + +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDBoolField &Result) { + switch (Lex.getKind()) { + default: + return TokError("expected 'true' or 'false'"); + case lltok::kw_true: + Result.assign(true); + break; + case lltok::kw_false: + Result.assign(false); + break; + } + Lex.Lex(); + return false; +} + +template <> bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDField &Result) { - if (Result.Seen) - return Error(Loc, - "field '" + Name + "' cannot be specified more than once"); + if (Lex.getKind() == lltok::kw_null) { + if (!Result.AllowNull) + return TokError("'" + Name + "' cannot be null"); + Lex.Lex(); + Result.assign(nullptr); + return false; + } Metadata *MD; if (ParseMetadata(MD, nullptr)) @@ -2954,16 +3280,44 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDField &Result) { return false; } -template <class ParserTy> -bool LLParser::ParseMDFieldsImpl(ParserTy parseField) { - assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); - Lex.Lex(); +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDConstant &Result) { + Metadata *MD; + if (ParseValueAsMetadata(MD, "expected constant", nullptr)) + return true; - if (ParseToken(lltok::lparen, "expected '(' here")) + Result.assign(cast<ConstantAsMetadata>(MD)); + return false; +} + +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDStringField &Result) { + LocTy ValueLoc = Lex.getLoc(); + std::string S; + if (ParseStringConstant(S)) return true; - if (EatIfPresent(lltok::rparen)) - return false; + if (!Result.AllowEmpty && S.empty()) + return Error(ValueLoc, "'" + Name + "' cannot be empty"); + + Result.assign(S.empty() ? nullptr : MDString::get(Context, S)); + return false; +} + +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDFieldList &Result) { + SmallVector<Metadata *, 4> MDs; + if (ParseMDNodeVector(MDs)) + return true; + + Result.assign(std::move(MDs)); + return false; +} + +} // end namespace llvm + +template <class ParserTy> +bool LLParser::ParseMDFieldsImplBody(ParserTy parseField) { do { if (Lex.getKind() != lltok::LabelStr) return TokError("expected field label here"); @@ -2972,56 +3326,502 @@ bool LLParser::ParseMDFieldsImpl(ParserTy parseField) { return true; } while (EatIfPresent(lltok::comma)); + return false; +} + +template <class ParserTy> +bool LLParser::ParseMDFieldsImpl(ParserTy parseField, LocTy &ClosingLoc) { + assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); + Lex.Lex(); + + if (ParseToken(lltok::lparen, "expected '(' here")) + return true; + if (Lex.getKind() != lltok::rparen) + if (ParseMDFieldsImplBody(parseField)) + return true; + + ClosingLoc = Lex.getLoc(); return ParseToken(lltok::rparen, "expected ')' here"); } +template <class FieldTy> +bool LLParser::ParseMDField(StringRef Name, FieldTy &Result) { + if (Result.Seen) + return TokError("field '" + Name + "' cannot be specified more than once"); + + LocTy Loc = Lex.getLoc(); + Lex.Lex(); + return ParseMDField(Loc, Name, Result); +} + bool LLParser::ParseSpecializedMDNode(MDNode *&N, bool IsDistinct) { assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); -#define DISPATCH_TO_PARSER(CLASS) \ + +#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) \ if (Lex.getStrVal() == #CLASS) \ return Parse##CLASS(N, IsDistinct); - - DISPATCH_TO_PARSER(MDLocation); -#undef DISPATCH_TO_PARSER +#include "llvm/IR/Metadata.def" return TokError("expected metadata type"); } -#define PARSE_MD_FIELD(NAME) \ +#define DECLARE_FIELD(NAME, TYPE, INIT) TYPE NAME INIT +#define NOP_FIELD(NAME, TYPE, INIT) +#define REQUIRE_FIELD(NAME, TYPE, INIT) \ + if (!NAME.Seen) \ + return Error(ClosingLoc, "missing required field '" #NAME "'"); +#define PARSE_MD_FIELD(NAME, TYPE, DEFAULT) \ + if (Lex.getStrVal() == #NAME) \ + return ParseMDField(#NAME, NAME); +#define PARSE_MD_FIELDS() \ + VISIT_MD_FIELDS(DECLARE_FIELD, DECLARE_FIELD) \ do { \ - if (Lex.getStrVal() == #NAME) { \ - LocTy Loc = Lex.getLoc(); \ - Lex.Lex(); \ - if (ParseMDField(Loc, #NAME, NAME)) \ - return true; \ - return false; \ - } \ - } while (0) - -/// ParseMDLocationFields: -/// ::= !MDLocation(line: 43, column: 8, scope: !5, inlinedAt: !6) -bool LLParser::ParseMDLocation(MDNode *&Result, bool IsDistinct) { - MDUnsignedField<uint32_t> line(0, ~0u >> 8); - MDUnsignedField<uint32_t> column(0, ~0u >> 24); - MDField scope; - MDField inlinedAt; - if (ParseMDFieldsImpl([&]() -> bool { - PARSE_MD_FIELD(line); - PARSE_MD_FIELD(column); - PARSE_MD_FIELD(scope); - PARSE_MD_FIELD(inlinedAt); - return TokError(Twine("invalid field '") + Lex.getStrVal() + "'"); - })) + LocTy ClosingLoc; \ + if (ParseMDFieldsImpl([&]() -> bool { \ + VISIT_MD_FIELDS(PARSE_MD_FIELD, PARSE_MD_FIELD) \ + return TokError(Twine("invalid field '") + Lex.getStrVal() + "'"); \ + }, ClosingLoc)) \ + return true; \ + VISIT_MD_FIELDS(NOP_FIELD, REQUIRE_FIELD) \ + } while (false) +#define GET_OR_DISTINCT(CLASS, ARGS) \ + (IsDistinct ? CLASS::getDistinct ARGS : CLASS::get ARGS) + +/// ParseDILocationFields: +/// ::= !DILocation(line: 43, column: 8, scope: !5, inlinedAt: !6) +bool LLParser::ParseDILocation(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(column, ColumnField, ); \ + REQUIRED(scope, MDField, (/* AllowNull */ false)); \ + OPTIONAL(inlinedAt, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT( + DILocation, (Context, line.Val, column.Val, scope.Val, inlinedAt.Val)); + return false; +} + +/// ParseGenericDINode: +/// ::= !GenericDINode(tag: 15, header: "...", operands: {...}) +bool LLParser::ParseGenericDINode(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(tag, DwarfTagField, ); \ + OPTIONAL(header, MDStringField, ); \ + OPTIONAL(operands, MDFieldList, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(GenericDINode, + (Context, tag.Val, header.Val, operands.Val)); + return false; +} + +/// ParseDISubrange: +/// ::= !DISubrange(count: 30, lowerBound: 2) +bool LLParser::ParseDISubrange(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(count, MDSignedField, (-1, -1, INT64_MAX)); \ + OPTIONAL(lowerBound, MDSignedField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DISubrange, (Context, count.Val, lowerBound.Val)); + return false; +} + +/// ParseDIEnumerator: +/// ::= !DIEnumerator(value: 30, name: "SomeKind") +bool LLParser::ParseDIEnumerator(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(name, MDStringField, ); \ + REQUIRED(value, MDSignedField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DIEnumerator, (Context, value.Val, name.Val)); + return false; +} + +/// ParseDIBasicType: +/// ::= !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32) +bool LLParser::ParseDIBasicType(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(tag, DwarfTagField, (dwarf::DW_TAG_base_type)); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(align, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(encoding, DwarfAttEncodingField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DIBasicType, (Context, tag.Val, name.Val, size.Val, + align.Val, encoding.Val)); + return false; +} + +/// ParseDIDerivedType: +/// ::= !DIDerivedType(tag: DW_TAG_pointer_type, name: "int", file: !0, +/// line: 7, scope: !1, baseType: !2, size: 32, +/// align: 32, offset: 0, flags: 0, extraData: !3) +bool LLParser::ParseDIDerivedType(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(tag, DwarfTagField, ); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(scope, MDField, ); \ + REQUIRED(baseType, MDField, ); \ + OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(align, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(offset, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(flags, DIFlagField, ); \ + OPTIONAL(extraData, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DIDerivedType, + (Context, tag.Val, name.Val, file.Val, line.Val, + scope.Val, baseType.Val, size.Val, align.Val, + offset.Val, flags.Val, extraData.Val)); + return false; +} + +bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(tag, DwarfTagField, ); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(scope, MDField, ); \ + OPTIONAL(baseType, MDField, ); \ + OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(align, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(offset, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(flags, DIFlagField, ); \ + OPTIONAL(elements, MDField, ); \ + OPTIONAL(runtimeLang, DwarfLangField, ); \ + OPTIONAL(vtableHolder, MDField, ); \ + OPTIONAL(templateParams, MDField, ); \ + OPTIONAL(identifier, MDStringField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT( + DICompositeType, + (Context, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val, + size.Val, align.Val, offset.Val, flags.Val, elements.Val, + runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val)); + return false; +} + +bool LLParser::ParseDISubroutineType(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(flags, DIFlagField, ); \ + REQUIRED(types, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DISubroutineType, (Context, flags.Val, types.Val)); + return false; +} + +/// ParseDIFileType: +/// ::= !DIFileType(filename: "path/to/file", directory: "/path/to/dir") +bool LLParser::ParseDIFile(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(filename, MDStringField, ); \ + REQUIRED(directory, MDStringField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DIFile, (Context, filename.Val, directory.Val)); + return false; +} + +/// ParseDICompileUnit: +/// ::= !DICompileUnit(language: DW_LANG_C99, file: !0, producer: "clang", +/// isOptimized: true, flags: "-O2", runtimeVersion: 1, +/// splitDebugFilename: "abc.debug", emissionKind: 1, +/// enums: !1, retainedTypes: !2, subprograms: !3, +/// globals: !4, imports: !5, dwoId: 0x0abcd) +bool LLParser::ParseDICompileUnit(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(language, DwarfLangField, ); \ + REQUIRED(file, MDField, (/* AllowNull */ false)); \ + OPTIONAL(producer, MDStringField, ); \ + OPTIONAL(isOptimized, MDBoolField, ); \ + OPTIONAL(flags, MDStringField, ); \ + OPTIONAL(runtimeVersion, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(splitDebugFilename, MDStringField, ); \ + OPTIONAL(emissionKind, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(enums, MDField, ); \ + OPTIONAL(retainedTypes, MDField, ); \ + OPTIONAL(subprograms, MDField, ); \ + OPTIONAL(globals, MDField, ); \ + OPTIONAL(imports, MDField, ); \ + OPTIONAL(dwoId, MDUnsignedField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DICompileUnit, + (Context, language.Val, file.Val, producer.Val, + isOptimized.Val, flags.Val, runtimeVersion.Val, + splitDebugFilename.Val, emissionKind.Val, enums.Val, + retainedTypes.Val, subprograms.Val, globals.Val, + imports.Val, dwoId.Val)); + return false; +} + +/// ParseDISubprogram: +/// ::= !DISubprogram(scope: !0, name: "foo", linkageName: "_Zfoo", +/// file: !1, line: 7, type: !2, isLocal: false, +/// isDefinition: true, scopeLine: 8, containingType: !3, +/// virtuality: DW_VIRTUALTIY_pure_virtual, +/// virtualIndex: 10, flags: 11, +/// isOptimized: false, function: void ()* @_Z3foov, +/// templateParams: !4, declaration: !5, variables: !6) +bool LLParser::ParseDISubprogram(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(scope, MDField, ); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(linkageName, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(type, MDField, ); \ + OPTIONAL(isLocal, MDBoolField, ); \ + OPTIONAL(isDefinition, MDBoolField, (true)); \ + OPTIONAL(scopeLine, LineField, ); \ + OPTIONAL(containingType, MDField, ); \ + OPTIONAL(virtuality, DwarfVirtualityField, ); \ + OPTIONAL(virtualIndex, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(flags, DIFlagField, ); \ + OPTIONAL(isOptimized, MDBoolField, ); \ + OPTIONAL(function, MDConstant, ); \ + OPTIONAL(templateParams, MDField, ); \ + OPTIONAL(declaration, MDField, ); \ + OPTIONAL(variables, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT( + DISubprogram, (Context, scope.Val, name.Val, linkageName.Val, file.Val, + line.Val, type.Val, isLocal.Val, isDefinition.Val, + scopeLine.Val, containingType.Val, virtuality.Val, + virtualIndex.Val, flags.Val, isOptimized.Val, function.Val, + templateParams.Val, declaration.Val, variables.Val)); + return false; +} + +/// ParseDILexicalBlock: +/// ::= !DILexicalBlock(scope: !0, file: !2, line: 7, column: 9) +bool LLParser::ParseDILexicalBlock(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(scope, MDField, (/* AllowNull */ false)); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(column, ColumnField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT( + DILexicalBlock, (Context, scope.Val, file.Val, line.Val, column.Val)); + return false; +} + +/// ParseDILexicalBlockFile: +/// ::= !DILexicalBlockFile(scope: !0, file: !2, discriminator: 9) +bool LLParser::ParseDILexicalBlockFile(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(scope, MDField, (/* AllowNull */ false)); \ + OPTIONAL(file, MDField, ); \ + REQUIRED(discriminator, MDUnsignedField, (0, UINT32_MAX)); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DILexicalBlockFile, + (Context, scope.Val, file.Val, discriminator.Val)); + return false; +} + +/// ParseDINamespace: +/// ::= !DINamespace(scope: !0, file: !2, name: "SomeNamespace", line: 9) +bool LLParser::ParseDINamespace(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(scope, MDField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(line, LineField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DINamespace, + (Context, scope.Val, file.Val, name.Val, line.Val)); + return false; +} + +/// ParseDITemplateTypeParameter: +/// ::= !DITemplateTypeParameter(name: "Ty", type: !1) +bool LLParser::ParseDITemplateTypeParameter(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(name, MDStringField, ); \ + REQUIRED(type, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = + GET_OR_DISTINCT(DITemplateTypeParameter, (Context, name.Val, type.Val)); + return false; +} + +/// ParseDITemplateValueParameter: +/// ::= !DITemplateValueParameter(tag: DW_TAG_template_value_parameter, +/// name: "V", type: !1, value: i32 7) +bool LLParser::ParseDITemplateValueParameter(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(tag, DwarfTagField, (dwarf::DW_TAG_template_value_parameter)); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(type, MDField, ); \ + REQUIRED(value, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DITemplateValueParameter, + (Context, tag.Val, name.Val, type.Val, value.Val)); + return false; +} + +/// ParseDIGlobalVariable: +/// ::= !DIGlobalVariable(scope: !0, name: "foo", linkageName: "foo", +/// file: !1, line: 7, type: !2, isLocal: false, +/// isDefinition: true, variable: i32* @foo, +/// declaration: !3) +bool LLParser::ParseDIGlobalVariable(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(name, MDStringField, (/* AllowEmpty */ false)); \ + OPTIONAL(scope, MDField, ); \ + OPTIONAL(linkageName, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(type, MDField, ); \ + OPTIONAL(isLocal, MDBoolField, ); \ + OPTIONAL(isDefinition, MDBoolField, (true)); \ + OPTIONAL(variable, MDConstant, ); \ + OPTIONAL(declaration, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DIGlobalVariable, + (Context, scope.Val, name.Val, linkageName.Val, + file.Val, line.Val, type.Val, isLocal.Val, + isDefinition.Val, variable.Val, declaration.Val)); + return false; +} + +/// ParseDILocalVariable: +/// ::= !DILocalVariable(tag: DW_TAG_arg_variable, scope: !0, name: "foo", +/// file: !1, line: 7, type: !2, arg: 2, flags: 7) +bool LLParser::ParseDILocalVariable(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(tag, DwarfTagField, ); \ + REQUIRED(scope, MDField, (/* AllowNull */ false)); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(type, MDField, ); \ + OPTIONAL(arg, MDUnsignedField, (0, UINT8_MAX)); \ + OPTIONAL(flags, DIFlagField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DILocalVariable, + (Context, tag.Val, scope.Val, name.Val, file.Val, + line.Val, type.Val, arg.Val, flags.Val)); + return false; +} + +/// ParseDIExpression: +/// ::= !DIExpression(0, 7, -1) +bool LLParser::ParseDIExpression(MDNode *&Result, bool IsDistinct) { + assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); + Lex.Lex(); + + if (ParseToken(lltok::lparen, "expected '(' here")) + return true; + + SmallVector<uint64_t, 8> Elements; + if (Lex.getKind() != lltok::rparen) + do { + if (Lex.getKind() == lltok::DwarfOp) { + if (unsigned Op = dwarf::getOperationEncoding(Lex.getStrVal())) { + Lex.Lex(); + Elements.push_back(Op); + continue; + } + return TokError(Twine("invalid DWARF op '") + Lex.getStrVal() + "'"); + } + + if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) + return TokError("expected unsigned integer"); + + auto &U = Lex.getAPSIntVal(); + if (U.ugt(UINT64_MAX)) + return TokError("element too large, limit is " + Twine(UINT64_MAX)); + Elements.push_back(U.getZExtValue()); + Lex.Lex(); + } while (EatIfPresent(lltok::comma)); + + if (ParseToken(lltok::rparen, "expected ')' here")) return true; - if (!scope.Seen) - return TokError("missing required field 'scope'"); + Result = GET_OR_DISTINCT(DIExpression, (Context, Elements)); + return false; +} - auto get = (IsDistinct ? MDLocation::getDistinct : MDLocation::get); - Result = get(Context, line.Val, column.Val, scope.Val, inlinedAt.Val); +/// ParseDIObjCProperty: +/// ::= !DIObjCProperty(name: "foo", file: !1, line: 7, setter: "setFoo", +/// getter: "getFoo", attributes: 7, type: !2) +bool LLParser::ParseDIObjCProperty(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(setter, MDStringField, ); \ + OPTIONAL(getter, MDStringField, ); \ + OPTIONAL(attributes, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(type, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DIObjCProperty, + (Context, name.Val, file.Val, line.Val, setter.Val, + getter.Val, attributes.Val, type.Val)); return false; } + +/// ParseDIImportedEntity: +/// ::= !DIImportedEntity(tag: DW_TAG_imported_module, scope: !0, entity: !1, +/// line: 7, name: "foo") +bool LLParser::ParseDIImportedEntity(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(tag, DwarfTagField, ); \ + REQUIRED(scope, MDField, ); \ + OPTIONAL(entity, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(name, MDStringField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DIImportedEntity, (Context, tag.Val, scope.Val, + entity.Val, line.Val, name.Val)); + return false; +} + #undef PARSE_MD_FIELD +#undef NOP_FIELD +#undef REQUIRE_FIELD +#undef DECLARE_FIELD /// ParseMetadataAsValue /// ::= metadata i32 %local @@ -3044,10 +3844,11 @@ bool LLParser::ParseMetadataAsValue(Value *&V, PerFunctionState &PFS) { /// ::= i32 %local /// ::= i32 @global /// ::= i32 7 -bool LLParser::ParseValueAsMetadata(Metadata *&MD, PerFunctionState *PFS) { +bool LLParser::ParseValueAsMetadata(Metadata *&MD, const Twine &TypeMsg, + PerFunctionState *PFS) { Type *Ty; LocTy Loc; - if (ParseType(Ty, "expected metadata operand", Loc)) + if (ParseType(Ty, TypeMsg, Loc)) return true; if (Ty->isMetadataTy()) return Error(Loc, "invalid metadata-value-metadata roundtrip"); @@ -3067,7 +3868,7 @@ bool LLParser::ParseValueAsMetadata(Metadata *&MD, PerFunctionState *PFS) { /// ::= !42 /// ::= !{...} /// ::= !"string" -/// ::= !MDLocation(...) +/// ::= !DILocation(...) bool LLParser::ParseMetadata(Metadata *&MD, PerFunctionState *PFS) { if (Lex.getKind() == lltok::MetadataVar) { MDNode *N; @@ -3080,7 +3881,7 @@ bool LLParser::ParseMetadata(Metadata *&MD, PerFunctionState *PFS) { // ValueAsMetadata: // <type> <value> if (Lex.getKind() != lltok::exclaim) - return ParseValueAsMetadata(MD, PFS); + return ParseValueAsMetadata(MD, "expected metadata operand", PFS); // '!'. assert(Lex.getKind() == lltok::exclaim && "Expected '!' here"); @@ -3570,7 +4371,9 @@ bool LLParser::ParseBasicBlock(PerFunctionState &PFS) { } BasicBlock *BB = PFS.DefineBB(Name, NameLoc); - if (!BB) return true; + if (!BB) + return Error(NameLoc, + "unable to create block named '" + Name + "'"); std::string NameStr; @@ -3604,7 +4407,7 @@ bool LLParser::ParseBasicBlock(PerFunctionState &PFS) { // With a normal result, we check to see if the instruction is followed by // a comma and metadata. if (EatIfPresent(lltok::comma)) - if (ParseInstructionMetadata(Inst, &PFS)) + if (ParseInstructionMetadata(*Inst)) return true; break; case InstExtraComma: @@ -3612,7 +4415,7 @@ bool LLParser::ParseBasicBlock(PerFunctionState &PFS) { // If the instruction parser ate an extra comma at the end of it, it // *must* be followed by metadata. - if (ParseInstructionMetadata(Inst, &PFS)) + if (ParseInstructionMetadata(*Inst)) return true; break; } @@ -3958,10 +4761,8 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { // If RetType is a non-function pointer type, then this is the short syntax // for the call, which means that RetType is just the return type. Infer the // rest of the function argument types from the arguments that are present. - PointerType *PFTy = nullptr; - FunctionType *Ty = nullptr; - if (!(PFTy = dyn_cast<PointerType>(RetType)) || - !(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) { + FunctionType *Ty = dyn_cast<FunctionType>(RetType); + if (!Ty) { // Pull out the types of all of the arguments... std::vector<Type*> ParamTypes; for (unsigned i = 0, e = ArgList.size(); i != e; ++i) @@ -3971,12 +4772,12 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { return Error(RetTypeLoc, "Invalid result type for LLVM function"); Ty = FunctionType::get(RetType, ParamTypes, false); - PFTy = PointerType::getUnqual(Ty); } // Look up the callee. Value *Callee; - if (ConvertValIDToValue(PFTy, CalleeID, Callee, &PFS)) return true; + if (ConvertValIDToValue(PointerType::getUnqual(Ty), CalleeID, Callee, &PFS)) + return true; // Set up the Attribute for the function. SmallVector<AttributeSet, 8> Attrs; @@ -4012,15 +4813,19 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { if (I != E) return Error(CallLoc, "not enough parameters specified for call"); - if (FnAttrs.hasAttributes()) + if (FnAttrs.hasAttributes()) { + if (FnAttrs.hasAlignmentAttr()) + return Error(CallLoc, "invoke instructions may not have an alignment"); + Attrs.push_back(AttributeSet::get(RetType->getContext(), AttributeSet::FunctionIndex, FnAttrs)); + } // Finish off the Attribute and check them AttributeSet PAL = AttributeSet::get(Context, Attrs); - InvokeInst *II = InvokeInst::Create(Callee, NormalBB, UnwindBB, Args); + InvokeInst *II = InvokeInst::Create(Ty, Callee, NormalBB, UnwindBB, Args); II->setCallingConv(CC); II->setAttributes(PAL); ForwardRefAttrGroups[II] = FwdRefAttrGrps; @@ -4301,7 +5106,7 @@ bool LLParser::ParseLandingPad(Instruction *&Inst, PerFunctionState &PFS) { ParseTypeAndValue(PersFn, PersFnLoc, PFS)) return true; - LandingPadInst *LP = LandingPadInst::Create(Ty, PersFn, 0); + std::unique_ptr<LandingPadInst> LP(LandingPadInst::Create(Ty, PersFn, 0)); LP->setCleanup(EatIfPresent(lltok::kw_cleanup)); while (Lex.getKind() == lltok::kw_catch || Lex.getKind() == lltok::kw_filter){ @@ -4315,10 +5120,8 @@ bool LLParser::ParseLandingPad(Instruction *&Inst, PerFunctionState &PFS) { Value *V; LocTy VLoc; - if (ParseTypeAndValue(V, VLoc, PFS)) { - delete LP; + if (ParseTypeAndValue(V, VLoc, PFS)) return true; - } // A 'catch' type expects a non-array constant. A filter clause expects an // array constant. @@ -4330,10 +5133,13 @@ bool LLParser::ParseLandingPad(Instruction *&Inst, PerFunctionState &PFS) { Error(VLoc, "'filter' clause has an invalid type"); } - LP->addClause(cast<Constant>(V)); + Constant *CV = dyn_cast<Constant>(V); + if (!CV) + return Error(VLoc, "clause argument must be a constant"); + LP->addClause(CV); } - Inst = LP; + Inst = LP.release(); return false; } @@ -4371,10 +5177,8 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, // If RetType is a non-function pointer type, then this is the short syntax // for the call, which means that RetType is just the return type. Infer the // rest of the function argument types from the arguments that are present. - PointerType *PFTy = nullptr; - FunctionType *Ty = nullptr; - if (!(PFTy = dyn_cast<PointerType>(RetType)) || - !(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) { + FunctionType *Ty = dyn_cast<FunctionType>(RetType); + if (!Ty) { // Pull out the types of all of the arguments... std::vector<Type*> ParamTypes; for (unsigned i = 0, e = ArgList.size(); i != e; ++i) @@ -4384,12 +5188,12 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, return Error(RetTypeLoc, "Invalid result type for LLVM function"); Ty = FunctionType::get(RetType, ParamTypes, false); - PFTy = PointerType::getUnqual(Ty); } // Look up the callee. Value *Callee; - if (ConvertValIDToValue(PFTy, CalleeID, Callee, &PFS)) return true; + if (ConvertValIDToValue(PointerType::getUnqual(Ty), CalleeID, Callee, &PFS)) + return true; // Set up the Attribute for the function. SmallVector<AttributeSet, 8> Attrs; @@ -4425,15 +5229,19 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, if (I != E) return Error(CallLoc, "not enough parameters specified for call"); - if (FnAttrs.hasAttributes()) + if (FnAttrs.hasAttributes()) { + if (FnAttrs.hasAlignmentAttr()) + return Error(CallLoc, "call instructions may not have an alignment"); + Attrs.push_back(AttributeSet::get(RetType->getContext(), AttributeSet::FunctionIndex, FnAttrs)); + } // Finish off the Attribute and check them AttributeSet PAL = AttributeSet::get(Context, Attrs); - CallInst *CI = CallInst::Create(Callee, Args); + CallInst *CI = CallInst::Create(Ty, Callee, Args); CI->setTailCallKind(TCK); CI->setCallingConv(CC); CI->setAttributes(PAL); @@ -4450,13 +5258,16 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, /// ::= 'alloca' 'inalloca'? Type (',' TypeAndValue)? (',' 'align' i32)? int LLParser::ParseAlloc(Instruction *&Inst, PerFunctionState &PFS) { Value *Size = nullptr; - LocTy SizeLoc; + LocTy SizeLoc, TyLoc; unsigned Alignment = 0; Type *Ty = nullptr; bool IsInAlloca = EatIfPresent(lltok::kw_inalloca); - if (ParseType(Ty)) return true; + if (ParseType(Ty, TyLoc)) return true; + + if (Ty->isFunctionTy() || !PointerType::isValidElementType(Ty)) + return Error(TyLoc, "invalid type for alloca"); bool AteExtraComma = false; if (EatIfPresent(lltok::comma)) { @@ -4503,20 +5314,27 @@ int LLParser::ParseLoad(Instruction *&Inst, PerFunctionState &PFS) { Lex.Lex(); } - if (ParseTypeAndValue(Val, Loc, PFS) || + Type *Ty; + LocTy ExplicitTypeLoc = Lex.getLoc(); + if (ParseType(Ty) || + ParseToken(lltok::comma, "expected comma after load's type") || + ParseTypeAndValue(Val, Loc, PFS) || ParseScopeAndOrdering(isAtomic, Scope, Ordering) || ParseOptionalCommaAlign(Alignment, AteExtraComma)) return true; - if (!Val->getType()->isPointerTy() || - !cast<PointerType>(Val->getType())->getElementType()->isFirstClassType()) + if (!Val->getType()->isPointerTy() || !Ty->isFirstClassType()) return Error(Loc, "load operand must be a pointer to a first class type"); if (isAtomic && !Alignment) return Error(Loc, "atomic load must have explicit non-zero alignment"); if (Ordering == Release || Ordering == AcquireRelease) return Error(Loc, "atomic load cannot use Release ordering"); - Inst = new LoadInst(Val, "", isVolatile, Alignment, Ordering, Scope); + if (Ty != cast<PointerType>(Val->getType())->getElementType()) + return Error(ExplicitTypeLoc, + "explicit pointee type doesn't match operand's pointee type"); + + Inst = new LoadInst(Ty, Val, "", isVolatile, Alignment, Ordering, Scope); return AteExtraComma ? InstExtraComma : InstNormal; } @@ -4702,13 +5520,22 @@ int LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) { bool InBounds = EatIfPresent(lltok::kw_inbounds); - if (ParseTypeAndValue(Ptr, Loc, PFS)) return true; + Type *Ty = nullptr; + LocTy ExplicitTypeLoc = Lex.getLoc(); + if (ParseType(Ty) || + ParseToken(lltok::comma, "expected comma after getelementptr's type") || + ParseTypeAndValue(Ptr, Loc, PFS)) + return true; Type *BaseType = Ptr->getType(); PointerType *BasePointerType = dyn_cast<PointerType>(BaseType->getScalarType()); if (!BasePointerType) return Error(Loc, "base of getelementptr must be a pointer"); + if (Ty != BasePointerType->getElementType()) + return Error(ExplicitTypeLoc, + "explicit pointee type doesn't match operand's pointee type"); + SmallVector<Value*, 16> Indices; bool AteExtraComma = false; while (EatIfPresent(lltok::comma)) { @@ -4731,12 +5558,13 @@ int LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) { Indices.push_back(Val); } - if (!Indices.empty() && !BasePointerType->getElementType()->isSized()) + SmallPtrSet<const Type*, 4> Visited; + if (!Indices.empty() && !Ty->isSized(&Visited)) return Error(Loc, "base element of getelementptr must be sized"); - if (!GetElementPtrInst::getIndexedType(BaseType, Indices)) + if (!GetElementPtrInst::getIndexedType(Ty, Indices)) return Error(Loc, "invalid getelementptr indices"); - Inst = GetElementPtrInst::Create(Ptr, Indices); + Inst = GetElementPtrInst::Create(Ty, Ptr, Indices); if (InBounds) cast<GetElementPtrInst>(Inst)->setIsInBounds(true); return AteExtraComma ? InstExtraComma : InstNormal; @@ -4776,8 +5604,13 @@ int LLParser::ParseInsertValue(Instruction *&Inst, PerFunctionState &PFS) { if (!Val0->getType()->isAggregateType()) return Error(Loc0, "insertvalue operand must be aggregate type"); - if (!ExtractValueInst::getIndexedType(Val0->getType(), Indices)) + Type *IndexedType = ExtractValueInst::getIndexedType(Val0->getType(), Indices); + if (!IndexedType) return Error(Loc0, "invalid indices for insertvalue"); + if (IndexedType != Val1->getType()) + return Error(Loc1, "insertvalue operand and field disagree in type: '" + + getTypeString(Val1->getType()) + "' instead of '" + + getTypeString(IndexedType) + "'"); Inst = InsertValueInst::Create(Val0, Val1, Indices); return AteExtraComma ? InstExtraComma : InstNormal; } |