diff options
Diffstat (limited to 'contrib/llvm/lib/AsmParser')
-rw-r--r-- | contrib/llvm/lib/AsmParser/LLLexer.cpp | 132 | ||||
-rw-r--r-- | contrib/llvm/lib/AsmParser/LLLexer.h | 13 | ||||
-rw-r--r-- | contrib/llvm/lib/AsmParser/LLParser.cpp | 1596 | ||||
-rw-r--r-- | contrib/llvm/lib/AsmParser/LLParser.h | 158 | ||||
-rw-r--r-- | contrib/llvm/lib/AsmParser/LLToken.h | 72 | ||||
-rw-r--r-- | contrib/llvm/lib/AsmParser/Parser.cpp | 114 |
6 files changed, 1933 insertions, 152 deletions
diff --git a/contrib/llvm/lib/AsmParser/LLLexer.cpp b/contrib/llvm/lib/AsmParser/LLLexer.cpp index d8be4ad42ad5..da9855ff630b 100644 --- a/contrib/llvm/lib/AsmParser/LLLexer.cpp +++ b/contrib/llvm/lib/AsmParser/LLLexer.cpp @@ -157,9 +157,10 @@ static const char *isLabelTail(const char *CurPtr) { // Lexer definition. //===----------------------------------------------------------------------===// -LLLexer::LLLexer(StringRef StartBuf, SourceMgr &sm, SMDiagnostic &Err, +LLLexer::LLLexer(StringRef StartBuf, SourceMgr &SM, SMDiagnostic &Err, LLVMContext &C) - : CurBuf(StartBuf), ErrorInfo(Err), SM(sm), Context(C), APFloatVal(0.0) { + : CurBuf(StartBuf), ErrorInfo(Err), SM(SM), Context(C), APFloatVal(0.0), + IgnoreColonInIdentifiers(false) { CurPtr = CurBuf.begin(); } @@ -219,6 +220,10 @@ lltok::Kind LLLexer::LexToken() { SkipLineComment(); continue; case '!': return LexExclaim(); + case '^': + return LexCaret(); + case ':': + return lltok::colon; case '#': return LexHash(); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': @@ -328,6 +333,22 @@ bool LLLexer::ReadVarName() { return false; } +// Lex an ID: [0-9]+. On success, the ID is stored in UIntVal and Token is +// returned, otherwise the Error token is returned. +lltok::Kind LLLexer::LexUIntID(lltok::Kind Token) { + if (!isdigit(static_cast<unsigned char>(CurPtr[0]))) + return lltok::Error; + + for (++CurPtr; isdigit(static_cast<unsigned char>(CurPtr[0])); ++CurPtr) + /*empty*/; + + uint64_t Val = atoull(TokStart + 1, CurPtr); + if ((unsigned)Val != Val) + Error("invalid value number (too large)!"); + UIntVal = unsigned(Val); + return Token; +} + lltok::Kind LLLexer::LexVar(lltok::Kind Var, lltok::Kind VarID) { // Handle StringConstant: \"[^\"]*\" if (CurPtr[0] == '"') { @@ -357,17 +378,7 @@ lltok::Kind LLLexer::LexVar(lltok::Kind Var, lltok::Kind VarID) { return Var; // Handle VarID: [0-9]+ - if (isdigit(static_cast<unsigned char>(CurPtr[0]))) { - for (++CurPtr; isdigit(static_cast<unsigned char>(CurPtr[0])); ++CurPtr) - /*empty*/; - - uint64_t Val = atoull(TokStart+1, CurPtr); - if ((unsigned)Val != Val) - Error("invalid value number (too large)!"); - UIntVal = unsigned(Val); - return VarID; - } - return lltok::Error; + return LexUIntID(VarID); } /// Lex all tokens that start with a % character. @@ -420,22 +431,18 @@ lltok::Kind LLLexer::LexExclaim() { return lltok::exclaim; } +/// Lex all tokens that start with a ^ character. +/// SummaryID ::= ^[0-9]+ +lltok::Kind LLLexer::LexCaret() { + // Handle SummaryID: ^[0-9]+ + return LexUIntID(lltok::SummaryID); +} + /// Lex all tokens that start with a # character. /// AttrGrpID ::= #[0-9]+ lltok::Kind LLLexer::LexHash() { // Handle AttrGrpID: #[0-9]+ - if (isdigit(static_cast<unsigned char>(CurPtr[0]))) { - for (++CurPtr; isdigit(static_cast<unsigned char>(CurPtr[0])); ++CurPtr) - /*empty*/; - - uint64_t Val = atoull(TokStart+1, CurPtr); - if ((unsigned)Val != Val) - Error("invalid value number (too large)!"); - UIntVal = unsigned(Val); - return lltok::AttrGrpID; - } - - return lltok::Error; + return LexUIntID(lltok::AttrGrpID); } /// Lex a label, integer type, keyword, or hexadecimal integer constant. @@ -457,8 +464,9 @@ lltok::Kind LLLexer::LexIdentifier() { KeywordEnd = CurPtr; } - // If we stopped due to a colon, this really is a label. - if (*CurPtr == ':') { + // If we stopped due to a colon, unless we were directed to ignore it, + // this really is a label. + if (!IgnoreColonInIdentifiers && *CurPtr == ':') { StrVal.assign(StartChar-1, CurPtr++); return lltok::LabelStr; } @@ -648,7 +656,9 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(nonnull); KEYWORD(noredzone); KEYWORD(noreturn); + KEYWORD(nocf_check); KEYWORD(nounwind); + KEYWORD(optforfuzzing); KEYWORD(optnone); KEYWORD(optsize); KEYWORD(readnone); @@ -663,6 +673,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(sspstrong); KEYWORD(strictfp); KEYWORD(safestack); + KEYWORD(shadowcallstack); KEYWORD(sanitize_address); KEYWORD(sanitize_hwaddress); KEYWORD(sanitize_thread); @@ -708,6 +719,73 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(catch); KEYWORD(filter); + // Summary index keywords. + KEYWORD(path); + KEYWORD(hash); + KEYWORD(gv); + KEYWORD(guid); + KEYWORD(name); + KEYWORD(summaries); + KEYWORD(flags); + KEYWORD(linkage); + KEYWORD(notEligibleToImport); + KEYWORD(live); + KEYWORD(dsoLocal); + KEYWORD(function); + KEYWORD(insts); + KEYWORD(funcFlags); + KEYWORD(readNone); + KEYWORD(readOnly); + KEYWORD(noRecurse); + KEYWORD(returnDoesNotAlias); + KEYWORD(calls); + KEYWORD(callee); + KEYWORD(hotness); + KEYWORD(unknown); + KEYWORD(hot); + KEYWORD(critical); + KEYWORD(relbf); + KEYWORD(variable); + KEYWORD(aliasee); + KEYWORD(refs); + KEYWORD(typeIdInfo); + KEYWORD(typeTests); + KEYWORD(typeTestAssumeVCalls); + KEYWORD(typeCheckedLoadVCalls); + KEYWORD(typeTestAssumeConstVCalls); + KEYWORD(typeCheckedLoadConstVCalls); + KEYWORD(vFuncId); + KEYWORD(offset); + KEYWORD(args); + KEYWORD(typeid); + KEYWORD(summary); + KEYWORD(typeTestRes); + KEYWORD(kind); + KEYWORD(unsat); + KEYWORD(byteArray); + KEYWORD(inline); + KEYWORD(single); + KEYWORD(allOnes); + KEYWORD(sizeM1BitWidth); + KEYWORD(alignLog2); + KEYWORD(sizeM1); + KEYWORD(bitMask); + KEYWORD(inlineBits); + KEYWORD(wpdResolutions); + KEYWORD(wpdRes); + KEYWORD(indir); + KEYWORD(singleImpl); + KEYWORD(branchFunnel); + KEYWORD(singleImplName); + KEYWORD(resByArg); + KEYWORD(byArg); + KEYWORD(uniformRetVal); + KEYWORD(uniqueRetVal); + KEYWORD(virtualConstProp); + KEYWORD(info); + KEYWORD(byte); + KEYWORD(bit); + #undef KEYWORD // Keywords for types. diff --git a/contrib/llvm/lib/AsmParser/LLLexer.h b/contrib/llvm/lib/AsmParser/LLLexer.h index 90bf17d7a747..21deb6e08910 100644 --- a/contrib/llvm/lib/AsmParser/LLLexer.h +++ b/contrib/llvm/lib/AsmParser/LLLexer.h @@ -42,6 +42,10 @@ namespace llvm { APFloat APFloatVal; APSInt APSIntVal; + // When false (default), an identifier ending in ':' is a label token. + // When true, the ':' is treated as a separate token. + bool IgnoreColonInIdentifiers; + public: explicit LLLexer(StringRef StartBuf, SourceMgr &SM, SMDiagnostic &, LLVMContext &C); @@ -59,8 +63,11 @@ namespace llvm { const APSInt &getAPSIntVal() const { return APSIntVal; } const APFloat &getAPFloatVal() const { return APFloatVal; } + void setIgnoreColonInIdentifiers(bool val) { + IgnoreColonInIdentifiers = val; + } - bool Error(LocTy L, const Twine &Msg) const; + bool Error(LocTy ErrorLoc, const Twine &Msg) const; bool Error(const Twine &Msg) const { return Error(getLoc(), Msg); } void Warning(LocTy WarningLoc, const Twine &Msg) const; @@ -81,15 +88,17 @@ namespace llvm { lltok::Kind LexDollar(); lltok::Kind LexExclaim(); lltok::Kind LexPercent(); + lltok::Kind LexUIntID(lltok::Kind Token); lltok::Kind LexVar(lltok::Kind Var, lltok::Kind VarID); lltok::Kind LexQuote(); lltok::Kind Lex0x(); lltok::Kind LexHash(); + lltok::Kind LexCaret(); uint64_t atoull(const char *Buffer, const char *End); uint64_t HexIntToVal(const char *Buffer, const char *End); void HexToIntPair(const char *Buffer, const char *End, uint64_t Pair[2]); - void FP80HexToIntPair(const char *Buff, const char *End, uint64_t Pair[2]); + void FP80HexToIntPair(const char *Buffer, const char *End, uint64_t Pair[2]); }; } // end namespace llvm diff --git a/contrib/llvm/lib/AsmParser/LLParser.cpp b/contrib/llvm/lib/AsmParser/LLParser.cpp index c3ab95550e03..599b59bf61e8 100644 --- a/contrib/llvm/lib/AsmParser/LLParser.cpp +++ b/contrib/llvm/lib/AsmParser/LLParser.cpp @@ -71,8 +71,8 @@ bool LLParser::Run() { Lex.getLoc(), "Can't read textual IR with a Context that discards named Values"); - return ParseTopLevelEntities() || - ValidateEndOfModule(); + return ParseTopLevelEntities() || ValidateEndOfModule() || + ValidateEndOfIndex(); } bool LLParser::parseStandaloneConstantValue(Constant *&C, @@ -120,6 +120,8 @@ void LLParser::restoreParsingState(const SlotMapping *Slots) { /// ValidateEndOfModule - Do final validity and sanity checks at the end of the /// module. bool LLParser::ValidateEndOfModule() { + if (!M) + return false; // Handle any function attribute group forward references. for (const auto &RAG : ForwardRefAttrGroups) { Value *V = RAG.first; @@ -258,11 +260,54 @@ bool LLParser::ValidateEndOfModule() { return false; } +/// Do final validity and sanity checks at the end of the index. +bool LLParser::ValidateEndOfIndex() { + if (!Index) + return false; + + if (!ForwardRefValueInfos.empty()) + return Error(ForwardRefValueInfos.begin()->second.front().second, + "use of undefined summary '^" + + Twine(ForwardRefValueInfos.begin()->first) + "'"); + + if (!ForwardRefAliasees.empty()) + return Error(ForwardRefAliasees.begin()->second.front().second, + "use of undefined summary '^" + + Twine(ForwardRefAliasees.begin()->first) + "'"); + + if (!ForwardRefTypeIds.empty()) + return Error(ForwardRefTypeIds.begin()->second.front().second, + "use of undefined type id summary '^" + + Twine(ForwardRefTypeIds.begin()->first) + "'"); + + return false; +} + //===----------------------------------------------------------------------===// // Top-Level Entities //===----------------------------------------------------------------------===// bool LLParser::ParseTopLevelEntities() { + // If there is no Module, then parse just the summary index entries. + if (!M) { + while (true) { + switch (Lex.getKind()) { + case lltok::Eof: + return false; + case lltok::SummaryID: + if (ParseSummaryEntry()) + return true; + break; + case lltok::kw_source_filename: + if (ParseSourceFileName()) + return true; + break; + default: + // Skip everything else + Lex.Lex(); + } + } + } while (true) { switch (Lex.getKind()) { default: return TokError("expected top-level entity"); @@ -282,6 +327,10 @@ bool LLParser::ParseTopLevelEntities() { case lltok::GlobalVar: if (ParseNamedGlobal()) return true; break; case lltok::ComdatVar: if (parseComdat()) return true; break; case lltok::exclaim: if (ParseStandaloneMetadata()) return true; break; + case lltok::SummaryID: + if (ParseSummaryEntry()) + return true; + break; case lltok::MetadataVar:if (ParseNamedMetadata()) return true; break; case lltok::kw_attributes: if (ParseUnnamedAttrGrp()) return true; break; case lltok::kw_uselistorder: if (ParseUseListOrder()) return true; break; @@ -327,7 +376,8 @@ bool LLParser::ParseTargetDefinition() { if (ParseToken(lltok::equal, "expected '=' after target datalayout") || ParseStringConstant(Str)) return true; - M->setDataLayout(Str); + if (DataLayoutStr.empty()) + M->setDataLayout(Str); return false; } } @@ -336,12 +386,12 @@ bool LLParser::ParseTargetDefinition() { /// ::= 'source_filename' '=' STRINGCONSTANT bool LLParser::ParseSourceFileName() { assert(Lex.getKind() == lltok::kw_source_filename); - std::string Str; Lex.Lex(); if (ParseToken(lltok::equal, "expected '=' after source_filename") || - ParseStringConstant(Str)) + ParseStringConstant(SourceFileName)) return true; - M->setSourceFileName(Str); + if (M) + M->setSourceFileName(SourceFileName); return false; } @@ -710,11 +760,87 @@ bool LLParser::ParseStandaloneMetadata() { return false; } +// Skips a single module summary entry. +bool LLParser::SkipModuleSummaryEntry() { + // Each module summary entry consists of a tag for the entry + // type, followed by a colon, then the fields surrounded by nested sets of + // parentheses. The "tag:" looks like a Label. Once parsing support is + // in place we will look for the tokens corresponding to the expected tags. + if (Lex.getKind() != lltok::kw_gv && Lex.getKind() != lltok::kw_module && + Lex.getKind() != lltok::kw_typeid) + return TokError( + "Expected 'gv', 'module', or 'typeid' at the start of summary entry"); + Lex.Lex(); + if (ParseToken(lltok::colon, "expected ':' at start of summary entry") || + ParseToken(lltok::lparen, "expected '(' at start of summary entry")) + return true; + // Now walk through the parenthesized entry, until the number of open + // parentheses goes back down to 0 (the first '(' was parsed above). + unsigned NumOpenParen = 1; + do { + switch (Lex.getKind()) { + case lltok::lparen: + NumOpenParen++; + break; + case lltok::rparen: + NumOpenParen--; + break; + case lltok::Eof: + return TokError("found end of file while parsing summary entry"); + default: + // Skip everything in between parentheses. + break; + } + Lex.Lex(); + } while (NumOpenParen > 0); + return false; +} + +/// SummaryEntry +/// ::= SummaryID '=' GVEntry | ModuleEntry | TypeIdEntry +bool LLParser::ParseSummaryEntry() { + assert(Lex.getKind() == lltok::SummaryID); + unsigned SummaryID = Lex.getUIntVal(); + + // For summary entries, colons should be treated as distinct tokens, + // not an indication of the end of a label token. + Lex.setIgnoreColonInIdentifiers(true); + + Lex.Lex(); + if (ParseToken(lltok::equal, "expected '=' here")) + return true; + + // If we don't have an index object, skip the summary entry. + if (!Index) + return SkipModuleSummaryEntry(); + + switch (Lex.getKind()) { + case lltok::kw_gv: + return ParseGVEntry(SummaryID); + case lltok::kw_module: + return ParseModuleEntry(SummaryID); + case lltok::kw_typeid: + return ParseTypeIdEntry(SummaryID); + break; + default: + return Error(Lex.getLoc(), "unexpected summary kind"); + } + Lex.setIgnoreColonInIdentifiers(false); + return false; +} + static bool isValidVisibilityForLinkage(unsigned V, unsigned L) { return !GlobalValue::isLocalLinkage((GlobalValue::LinkageTypes)L) || (GlobalValue::VisibilityTypes)V == GlobalValue::DefaultVisibility; } +// If there was an explicit dso_local, update GV. In the absence of an explicit +// dso_local we keep the default value. +static void maybeSetDSOLocal(bool DSOLocal, GlobalValue &GV) { + if (DSOLocal) + GV.setDSOLocal(true); +} + /// parseIndirectSymbol: /// ::= GlobalVar '=' OptionalLinkage OptionalPreemptionSpecifier /// OptionalVisibility OptionalDLLStorageClass @@ -749,11 +875,6 @@ bool LLParser::parseIndirectSymbol(const std::string &Name, LocTy NameLoc, return Error(NameLoc, "symbol with local linkage must have default visibility"); - if (DSOLocal && !IsAlias) { - return Error(NameLoc, - "dso_local is invalid on ifunc"); - } - Type *Ty; LocTy ExplicitTypeLoc = Lex.getLoc(); if (ParseType(Ty) || @@ -826,7 +947,7 @@ bool LLParser::parseIndirectSymbol(const std::string &Name, LocTy NameLoc, GA->setVisibility((GlobalValue::VisibilityTypes)Visibility); GA->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); GA->setUnnamedAddr(UnnamedAddr); - GA->setDSOLocal(DSOLocal); + maybeSetDSOLocal(DSOLocal, *GA); if (Name.empty()) NumberedVals.push_back(GA.get()); @@ -947,7 +1068,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, GV->setInitializer(Init); GV->setConstant(IsConstant); GV->setLinkage((GlobalValue::LinkageTypes)Linkage); - GV->setDSOLocal(DSOLocal); + maybeSetDSOLocal(DSOLocal, *GV); GV->setVisibility((GlobalValue::VisibilityTypes)Visibility); GV->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); GV->setExternallyInitialized(IsExternallyInitialized); @@ -1128,8 +1249,11 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B, case lltok::kw_nonlazybind: B.addAttribute(Attribute::NonLazyBind); break; case lltok::kw_noredzone: B.addAttribute(Attribute::NoRedZone); break; case lltok::kw_noreturn: B.addAttribute(Attribute::NoReturn); break; + case lltok::kw_nocf_check: B.addAttribute(Attribute::NoCfCheck); break; case lltok::kw_norecurse: B.addAttribute(Attribute::NoRecurse); break; case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); break; + case lltok::kw_optforfuzzing: + B.addAttribute(Attribute::OptForFuzzing); break; case lltok::kw_optnone: B.addAttribute(Attribute::OptimizeNone); break; case lltok::kw_optsize: B.addAttribute(Attribute::OptimizeForSize); break; case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break; @@ -1142,6 +1266,8 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B, case lltok::kw_sspstrong: B.addAttribute(Attribute::StackProtectStrong); break; case lltok::kw_safestack: B.addAttribute(Attribute::SafeStack); break; + case lltok::kw_shadowcallstack: + B.addAttribute(Attribute::ShadowCallStack); break; case lltok::kw_sanitize_address: B.addAttribute(Attribute::SanitizeAddress); break; case lltok::kw_sanitize_hwaddress: @@ -1465,7 +1591,9 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) { case lltok::kw_nonlazybind: case lltok::kw_noredzone: case lltok::kw_noreturn: + case lltok::kw_nocf_check: case lltok::kw_nounwind: + case lltok::kw_optforfuzzing: case lltok::kw_optnone: case lltok::kw_optsize: case lltok::kw_returns_twice: @@ -1477,6 +1605,7 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) { case lltok::kw_sspreq: case lltok::kw_sspstrong: case lltok::kw_safestack: + case lltok::kw_shadowcallstack: case lltok::kw_strictfp: case lltok::kw_uwtable: HaveError |= Error(Lex.getLoc(), "invalid use of function-only attribute"); @@ -1558,7 +1687,9 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) { case lltok::kw_nonlazybind: case lltok::kw_noredzone: case lltok::kw_noreturn: + case lltok::kw_nocf_check: case lltok::kw_nounwind: + case lltok::kw_optforfuzzing: case lltok::kw_optnone: case lltok::kw_optsize: case lltok::kw_returns_twice: @@ -1570,6 +1701,7 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) { case lltok::kw_sspreq: case lltok::kw_sspstrong: case lltok::kw_safestack: + case lltok::kw_shadowcallstack: case lltok::kw_strictfp: case lltok::kw_uwtable: HaveError |= Error(Lex.getLoc(), "invalid use of function-only attribute"); @@ -2609,11 +2741,24 @@ bool LLParser::PerFunctionState::FinishFunction() { return false; } +static bool isValidVariableType(Module *M, Type *Ty, Value *Val, bool IsCall) { + if (Val->getType() == Ty) + return true; + // For calls we also accept variables in the program address space + if (IsCall && isa<PointerType>(Ty)) { + Type *TyInProgAS = cast<PointerType>(Ty)->getElementType()->getPointerTo( + M->getDataLayout().getProgramAddressSpace()); + if (Val->getType() == TyInProgAS) + return true; + } + return false; +} + /// GetVal - Get a value with the specified name or ID, creating a /// forward reference record if needed. This can return null if the value /// exists but does not have the right type. Value *LLParser::PerFunctionState::GetVal(const std::string &Name, Type *Ty, - LocTy Loc) { + LocTy Loc, bool IsCall) { // Look this name up in the normal function symbol table. Value *Val = F.getValueSymbolTable()->lookup(Name); @@ -2627,7 +2772,8 @@ Value *LLParser::PerFunctionState::GetVal(const std::string &Name, Type *Ty, // If we have the value in the symbol table or fwd-ref table, return it. if (Val) { - if (Val->getType() == Ty) return Val; + if (isValidVariableType(P.M, Ty, Val, IsCall)) + return Val; if (Ty->isLabelTy()) P.Error(Loc, "'%" + Name + "' is not a basic block"); else @@ -2654,7 +2800,8 @@ Value *LLParser::PerFunctionState::GetVal(const std::string &Name, Type *Ty, return FwdVal; } -Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty, LocTy Loc) { +Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty, LocTy Loc, + bool IsCall) { // Look this name up in the normal function symbol table. Value *Val = ID < NumberedVals.size() ? NumberedVals[ID] : nullptr; @@ -2668,7 +2815,8 @@ Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty, LocTy Loc) { // If we have the value in the symbol table or fwd-ref table, return it. if (Val) { - if (Val->getType() == Ty) return Val; + if (isValidVariableType(P.M, Ty, Val, IsCall)) + return Val; if (Ty->isLabelTy()) P.Error(Loc, "'%" + Twine(ID) + "' is not a basic block"); else @@ -2759,13 +2907,13 @@ bool LLParser::PerFunctionState::SetInstName(int NameID, /// forward reference record if needed. BasicBlock *LLParser::PerFunctionState::GetBB(const std::string &Name, LocTy Loc) { - return dyn_cast_or_null<BasicBlock>(GetVal(Name, - Type::getLabelTy(F.getContext()), Loc)); + return dyn_cast_or_null<BasicBlock>( + GetVal(Name, Type::getLabelTy(F.getContext()), Loc, /*IsCall=*/false)); } BasicBlock *LLParser::PerFunctionState::GetBB(unsigned ID, LocTy Loc) { - return dyn_cast_or_null<BasicBlock>(GetVal(ID, - Type::getLabelTy(F.getContext()), Loc)); + return dyn_cast_or_null<BasicBlock>( + GetVal(ID, Type::getLabelTy(F.getContext()), Loc, /*IsCall=*/false)); } /// DefineBB - Define the specified basic block, which is either named or @@ -3384,7 +3532,7 @@ bool LLParser::ParseGlobalValue(Type *Ty, Constant *&C) { ValID ID; Value *V = nullptr; bool Parsed = ParseValID(ID) || - ConvertValIDToValue(Ty, ID, V, nullptr); + ConvertValIDToValue(Ty, ID, V, nullptr, /*IsCall=*/false); if (V && !(C = dyn_cast<Constant>(V))) return Error(ID.Loc, "global values must be constants"); return Parsed; @@ -3490,6 +3638,39 @@ template <class FieldTy> struct MDFieldImpl { : Val(std::move(Default)), Seen(false) {} }; +/// Structure to represent an optional metadata field that +/// can be of either type (A or B) and encapsulates the +/// MD<typeofA>Field and MD<typeofB>Field structs, so not +/// to reimplement the specifics for representing each Field. +template <class FieldTypeA, class FieldTypeB> struct MDEitherFieldImpl { + typedef MDEitherFieldImpl<FieldTypeA, FieldTypeB> ImplTy; + FieldTypeA A; + FieldTypeB B; + bool Seen; + + enum { + IsInvalid = 0, + IsTypeA = 1, + IsTypeB = 2 + } WhatIs; + + void assign(FieldTypeA A) { + Seen = true; + this->A = std::move(A); + WhatIs = IsTypeA; + } + + void assign(FieldTypeB B) { + Seen = true; + this->B = std::move(B); + WhatIs = IsTypeB; + } + + explicit MDEitherFieldImpl(FieldTypeA DefaultA, FieldTypeB DefaultB) + : A(std::move(DefaultA)), B(std::move(DefaultB)), Seen(false), + WhatIs(IsInvalid) {} +}; + struct MDUnsignedField : public MDFieldImpl<uint64_t> { uint64_t Max; @@ -3576,10 +3757,45 @@ struct MDFieldList : public MDFieldImpl<SmallVector<Metadata *, 4>> { }; struct ChecksumKindField : public MDFieldImpl<DIFile::ChecksumKind> { - ChecksumKindField() : ImplTy(DIFile::CSK_None) {} ChecksumKindField(DIFile::ChecksumKind CSKind) : ImplTy(CSKind) {} }; +struct MDSignedOrMDField : MDEitherFieldImpl<MDSignedField, MDField> { + MDSignedOrMDField(int64_t Default = 0, bool AllowNull = true) + : ImplTy(MDSignedField(Default), MDField(AllowNull)) {} + + MDSignedOrMDField(int64_t Default, int64_t Min, int64_t Max, + bool AllowNull = true) + : ImplTy(MDSignedField(Default, Min, Max), MDField(AllowNull)) {} + + bool isMDSignedField() const { return WhatIs == IsTypeA; } + bool isMDField() const { return WhatIs == IsTypeB; } + int64_t getMDSignedValue() const { + assert(isMDSignedField() && "Wrong field type"); + return A.Val; + } + Metadata *getMDFieldValue() const { + assert(isMDField() && "Wrong field type"); + return B.Val; + } +}; + +struct MDSignedOrUnsignedField + : MDEitherFieldImpl<MDSignedField, MDUnsignedField> { + MDSignedOrUnsignedField() : ImplTy(MDSignedField(0), MDUnsignedField(0)) {} + + bool isMDSignedField() const { return WhatIs == IsTypeA; } + bool isMDUnsignedField() const { return WhatIs == IsTypeB; } + int64_t getMDSignedValue() const { + assert(isMDSignedField() && "Wrong field type"); + return A.Val; + } + uint64_t getMDUnsignedValue() const { + assert(isMDUnsignedField() && "Wrong field type"); + return B.Val; + } +}; + } // end anonymous namespace namespace llvm { @@ -3834,6 +4050,50 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDField &Result) { } template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, + MDSignedOrMDField &Result) { + // Try to parse a signed int. + if (Lex.getKind() == lltok::APSInt) { + MDSignedField Res = Result.A; + if (!ParseMDField(Loc, Name, Res)) { + Result.assign(Res); + return false; + } + return true; + } + + // Otherwise, try to parse as an MDField. + MDField Res = Result.B; + if (!ParseMDField(Loc, Name, Res)) { + Result.assign(Res); + return false; + } + + return true; +} + +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, + MDSignedOrUnsignedField &Result) { + if (Lex.getKind() != lltok::APSInt) + return false; + + if (Lex.getAPSIntVal().isSigned()) { + MDSignedField Res = Result.A; + if (ParseMDField(Loc, Name, Res)) + return true; + Result.assign(Res); + return false; + } + + MDUnsignedField Res = Result.B; + if (ParseMDField(Loc, Name, Res)) + return true; + Result.assign(Res); + return false; +} + +template <> bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDStringField &Result) { LocTy ValueLoc = Lex.getLoc(); std::string S; @@ -3860,13 +4120,14 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDFieldList &Result) { template <> bool LLParser::ParseMDField(LocTy Loc, StringRef Name, ChecksumKindField &Result) { - if (Lex.getKind() != lltok::ChecksumKind) + Optional<DIFile::ChecksumKind> CSKind = + DIFile::getChecksumKind(Lex.getStrVal()); + + if (Lex.getKind() != lltok::ChecksumKind || !CSKind) return TokError( "invalid checksum kind" + Twine(" '") + Lex.getStrVal() + "'"); - DIFile::ChecksumKind CSKind = DIFile::getChecksumKind(Lex.getStrVal()); - - Result.assign(CSKind); + Result.assign(*CSKind); Lex.Lex(); return false; } @@ -3977,27 +4238,45 @@ bool LLParser::ParseGenericDINode(MDNode *&Result, bool IsDistinct) { /// ParseDISubrange: /// ::= !DISubrange(count: 30, lowerBound: 2) +/// ::= !DISubrange(count: !node, lowerBound: 2) bool LLParser::ParseDISubrange(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(count, MDSignedField, (-1, -1, INT64_MAX)); \ + REQUIRED(count, MDSignedOrMDField, (-1, -1, INT64_MAX, false)); \ OPTIONAL(lowerBound, MDSignedField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS - Result = GET_OR_DISTINCT(DISubrange, (Context, count.Val, lowerBound.Val)); + if (count.isMDSignedField()) + Result = GET_OR_DISTINCT( + DISubrange, (Context, count.getMDSignedValue(), lowerBound.Val)); + else if (count.isMDField()) + Result = GET_OR_DISTINCT( + DISubrange, (Context, count.getMDFieldValue(), lowerBound.Val)); + else + return true; + return false; } /// ParseDIEnumerator: -/// ::= !DIEnumerator(value: 30, name: "SomeKind") +/// ::= !DIEnumerator(value: 30, isUnsigned: true, name: "SomeKind") bool LLParser::ParseDIEnumerator(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ REQUIRED(name, MDStringField, ); \ - REQUIRED(value, MDSignedField, ); + REQUIRED(value, MDSignedOrUnsignedField, ); \ + OPTIONAL(isUnsigned, MDBoolField, (false)); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS - Result = GET_OR_DISTINCT(DIEnumerator, (Context, value.Val, name.Val)); + if (isUnsigned.Val && value.isMDSignedField()) + return TokError("unsigned enumerator with negative value"); + + int64_t Value = value.isMDSignedField() + ? value.getMDSignedValue() + : static_cast<int64_t>(value.getMDUnsignedValue()); + Result = + GET_OR_DISTINCT(DIEnumerator, (Context, Value, isUnsigned.Val, name.Val)); + return false; } @@ -4068,7 +4347,8 @@ bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) { OPTIONAL(runtimeLang, DwarfLangField, ); \ OPTIONAL(vtableHolder, MDField, ); \ OPTIONAL(templateParams, MDField, ); \ - OPTIONAL(identifier, MDStringField, ); + OPTIONAL(identifier, MDStringField, ); \ + OPTIONAL(discriminator, MDField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS @@ -4078,7 +4358,7 @@ bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) { Context, *identifier.Val, 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)) { + templateParams.Val, discriminator.Val)) { Result = CT; return false; } @@ -4089,7 +4369,8 @@ bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) { 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)); + runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val, + discriminator.Val)); return false; } @@ -4107,20 +4388,34 @@ bool LLParser::ParseDISubroutineType(MDNode *&Result, bool IsDistinct) { } /// ParseDIFileType: -/// ::= !DIFileType(filename: "path/to/file", directory: "/path/to/dir" +/// ::= !DIFileType(filename: "path/to/file", directory: "/path/to/dir", /// checksumkind: CSK_MD5, -/// checksum: "000102030405060708090a0b0c0d0e0f") +/// checksum: "000102030405060708090a0b0c0d0e0f", +/// source: "source file contents") bool LLParser::ParseDIFile(MDNode *&Result, bool IsDistinct) { + // The default constructed value for checksumkind is required, but will never + // be used, as the parser checks if the field was actually Seen before using + // the Val. #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ REQUIRED(filename, MDStringField, ); \ REQUIRED(directory, MDStringField, ); \ - OPTIONAL(checksumkind, ChecksumKindField, ); \ - OPTIONAL(checksum, MDStringField, ); + OPTIONAL(checksumkind, ChecksumKindField, (DIFile::CSK_MD5)); \ + OPTIONAL(checksum, MDStringField, ); \ + OPTIONAL(source, MDStringField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS + Optional<DIFile::ChecksumInfo<MDString *>> OptChecksum; + if (checksumkind.Seen && checksum.Seen) + OptChecksum.emplace(checksumkind.Val, checksum.Val); + else if (checksumkind.Seen || checksum.Seen) + return Lex.Error("'checksumkind' and 'checksum' must be provided together"); + + Optional<MDString *> OptSource; + if (source.Seen) + OptSource = source.Val; Result = GET_OR_DISTINCT(DIFile, (Context, filename.Val, directory.Val, - checksumkind.Val, checksum.Val)); + OptChecksum, OptSource)); return false; } @@ -4170,7 +4465,7 @@ bool LLParser::ParseDICompileUnit(MDNode *&Result, bool IsDistinct) { /// virtuality: DW_VIRTUALTIY_pure_virtual, /// virtualIndex: 10, thisAdjustment: 4, flags: 11, /// isOptimized: false, templateParams: !4, declaration: !5, -/// variables: !6, thrownTypes: !7) +/// retainedNodes: !6, thrownTypes: !7) bool LLParser::ParseDISubprogram(MDNode *&Result, bool IsDistinct) { auto Loc = Lex.getLoc(); #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ @@ -4192,7 +4487,7 @@ bool LLParser::ParseDISubprogram(MDNode *&Result, bool IsDistinct) { OPTIONAL(unit, MDField, ); \ OPTIONAL(templateParams, MDField, ); \ OPTIONAL(declaration, MDField, ); \ - OPTIONAL(variables, MDField, ); \ + OPTIONAL(retainedNodes, MDField, ); \ OPTIONAL(thrownTypes, MDField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS @@ -4208,7 +4503,7 @@ bool LLParser::ParseDISubprogram(MDNode *&Result, bool IsDistinct) { type.Val, isLocal.Val, isDefinition.Val, scopeLine.Val, containingType.Val, virtuality.Val, virtualIndex.Val, thisAdjustment.Val, flags.Val, isOptimized.Val, unit.Val, templateParams.Val, - declaration.Val, variables.Val, thrownTypes.Val)); + declaration.Val, retainedNodes.Val, thrownTypes.Val)); return false; } @@ -4391,6 +4686,22 @@ bool LLParser::ParseDILocalVariable(MDNode *&Result, bool IsDistinct) { return false; } +/// ParseDILabel: +/// ::= !DILabel(scope: !0, name: "foo", file: !1, line: 7) +bool LLParser::ParseDILabel(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(scope, MDField, (/* AllowNull */ false)); \ + REQUIRED(name, MDStringField, ); \ + REQUIRED(file, MDField, ); \ + REQUIRED(line, LineField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DILabel, + (Context, scope.Val, name.Val, file.Val, line.Val)); + return false; +} + /// ParseDIExpression: /// ::= !DIExpression(0, 7, -1) bool LLParser::ParseDIExpression(MDNode *&Result, bool IsDistinct) { @@ -4579,18 +4890,18 @@ bool LLParser::ParseMetadata(Metadata *&MD, PerFunctionState *PFS) { //===----------------------------------------------------------------------===// bool LLParser::ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V, - PerFunctionState *PFS) { + PerFunctionState *PFS, bool IsCall) { if (Ty->isFunctionTy()) return Error(ID.Loc, "functions are not values, refer to them as pointers"); switch (ID.Kind) { case ValID::t_LocalID: if (!PFS) return Error(ID.Loc, "invalid use of function-local name"); - V = PFS->GetVal(ID.UIntVal, Ty, ID.Loc); + V = PFS->GetVal(ID.UIntVal, Ty, ID.Loc, IsCall); return V == nullptr; case ValID::t_LocalName: if (!PFS) return Error(ID.Loc, "invalid use of function-local name"); - V = PFS->GetVal(ID.StrVal, Ty, ID.Loc); + V = PFS->GetVal(ID.StrVal, Ty, ID.Loc, IsCall); return V == nullptr; case ValID::t_InlineAsm: { if (!ID.FTy || !InlineAsm::Verify(ID.FTy, ID.StrVal2)) @@ -4706,7 +5017,7 @@ bool LLParser::parseConstantValue(Type *Ty, Constant *&C) { case ValID::t_ConstantStruct: case ValID::t_PackedConstantStruct: { Value *V; - if (ConvertValIDToValue(Ty, ID, V, /*PFS=*/nullptr)) + if (ConvertValIDToValue(Ty, ID, V, /*PFS=*/nullptr, /*IsCall=*/false)) return true; assert(isa<Constant>(V) && "Expected a constant value"); C = cast<Constant>(V); @@ -4723,7 +5034,8 @@ bool LLParser::parseConstantValue(Type *Ty, Constant *&C) { bool LLParser::ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS) { V = nullptr; ValID ID; - return ParseValID(ID, PFS) || ConvertValIDToValue(Ty, ID, V, PFS); + return ParseValID(ID, PFS) || + ConvertValIDToValue(Ty, ID, V, PFS, /*IsCall=*/false); } bool LLParser::ParseTypeAndValue(Value *&V, PerFunctionState *PFS) { @@ -4923,7 +5235,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { NumberedVals.push_back(Fn); Fn->setLinkage((GlobalValue::LinkageTypes)Linkage); - Fn->setDSOLocal(DSOLocal); + maybeSetDSOLocal(DSOLocal, *Fn); Fn->setVisibility((GlobalValue::VisibilityTypes)Visibility); Fn->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); Fn->setCallingConv(CC); @@ -5476,7 +5788,8 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { // Look up the callee. Value *Callee; - if (ConvertValIDToValue(PointerType::getUnqual(Ty), CalleeID, Callee, &PFS)) + if (ConvertValIDToValue(PointerType::getUnqual(Ty), CalleeID, Callee, &PFS, + /*IsCall=*/true)) return true; // Set up the Attribute for the function. @@ -6067,7 +6380,8 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, // Look up the callee. Value *Callee; - if (ConvertValIDToValue(PointerType::getUnqual(Ty), CalleeID, Callee, &PFS)) + if (ConvertValIDToValue(PointerType::getUnqual(Ty), CalleeID, Callee, &PFS, + /*IsCall=*/true)) return true; // Set up the Attribute for the function. @@ -6174,14 +6488,7 @@ int LLParser::ParseAlloc(Instruction *&Inst, PerFunctionState &PFS) { if (Size && !Size->getType()->isIntegerTy()) return Error(SizeLoc, "element count must have integer type"); - const DataLayout &DL = M->getDataLayout(); - unsigned AS = DL.getAllocaAddrSpace(); - if (AS != AddrSpace) { - // TODO: In the future it should be possible to specify addrspace per-alloca. - return Error(ASLoc, "address space must match datalayout"); - } - - AllocaInst *AI = new AllocaInst(Ty, AS, Size, Alignment); + AllocaInst *AI = new AllocaInst(Ty, AddrSpace, Size, Alignment); AI->setUsedWithInAlloca(IsInAlloca); AI->setSwiftError(IsSwiftError); Inst = AI; @@ -6567,8 +6874,8 @@ bool LLParser::sortUseListOrder(Value *V, ArrayRef<unsigned> Indexes, if (NumUses < 2) return Error(Loc, "value only has one use"); if (Order.size() != Indexes.size() || NumUses > Indexes.size()) - return Error(Loc, "wrong number of indexes, expected " + - Twine(std::distance(V->use_begin(), V->use_end()))); + return Error(Loc, + "wrong number of indexes, expected " + Twine(V->getNumUses())); V->sortUseList([&](const Use &L, const Use &R) { return Order.lookup(&L) < Order.lookup(&R); @@ -6680,3 +6987,1170 @@ bool LLParser::ParseUseListOrderBB() { return sortUseListOrder(V, Indexes, Loc); } + +/// ModuleEntry +/// ::= 'module' ':' '(' 'path' ':' STRINGCONSTANT ',' 'hash' ':' Hash ')' +/// Hash ::= '(' UInt32 ',' UInt32 ',' UInt32 ',' UInt32 ',' UInt32 ')' +bool LLParser::ParseModuleEntry(unsigned ID) { + assert(Lex.getKind() == lltok::kw_module); + Lex.Lex(); + + std::string Path; + if (ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here") || + ParseToken(lltok::kw_path, "expected 'path' here") || + ParseToken(lltok::colon, "expected ':' here") || + ParseStringConstant(Path) || + ParseToken(lltok::comma, "expected ',' here") || + ParseToken(lltok::kw_hash, "expected 'hash' here") || + ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here")) + return true; + + ModuleHash Hash; + if (ParseUInt32(Hash[0]) || ParseToken(lltok::comma, "expected ',' here") || + ParseUInt32(Hash[1]) || ParseToken(lltok::comma, "expected ',' here") || + ParseUInt32(Hash[2]) || ParseToken(lltok::comma, "expected ',' here") || + ParseUInt32(Hash[3]) || ParseToken(lltok::comma, "expected ',' here") || + ParseUInt32(Hash[4])) + return true; + + if (ParseToken(lltok::rparen, "expected ')' here") || + ParseToken(lltok::rparen, "expected ')' here")) + return true; + + auto ModuleEntry = Index->addModule(Path, ID, Hash); + ModuleIdMap[ID] = ModuleEntry->first(); + + return false; +} + +/// TypeIdEntry +/// ::= 'typeid' ':' '(' 'name' ':' STRINGCONSTANT ',' TypeIdSummary ')' +bool LLParser::ParseTypeIdEntry(unsigned ID) { + assert(Lex.getKind() == lltok::kw_typeid); + Lex.Lex(); + + std::string Name; + if (ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here") || + ParseToken(lltok::kw_name, "expected 'name' here") || + ParseToken(lltok::colon, "expected ':' here") || + ParseStringConstant(Name)) + return true; + + TypeIdSummary &TIS = Index->getOrInsertTypeIdSummary(Name); + if (ParseToken(lltok::comma, "expected ',' here") || + ParseTypeIdSummary(TIS) || ParseToken(lltok::rparen, "expected ')' here")) + return true; + + // Check if this ID was forward referenced, and if so, update the + // corresponding GUIDs. + auto FwdRefTIDs = ForwardRefTypeIds.find(ID); + if (FwdRefTIDs != ForwardRefTypeIds.end()) { + for (auto TIDRef : FwdRefTIDs->second) { + assert(!*TIDRef.first && + "Forward referenced type id GUID expected to be 0"); + *TIDRef.first = GlobalValue::getGUID(Name); + } + ForwardRefTypeIds.erase(FwdRefTIDs); + } + + return false; +} + +/// TypeIdSummary +/// ::= 'summary' ':' '(' TypeTestResolution [',' OptionalWpdResolutions]? ')' +bool LLParser::ParseTypeIdSummary(TypeIdSummary &TIS) { + if (ParseToken(lltok::kw_summary, "expected 'summary' here") || + ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here") || + ParseTypeTestResolution(TIS.TTRes)) + return true; + + if (EatIfPresent(lltok::comma)) { + // Expect optional wpdResolutions field + if (ParseOptionalWpdResolutions(TIS.WPDRes)) + return true; + } + + if (ParseToken(lltok::rparen, "expected ')' here")) + return true; + + return false; +} + +/// TypeTestResolution +/// ::= 'typeTestRes' ':' '(' 'kind' ':' +/// ( 'unsat' | 'byteArray' | 'inline' | 'single' | 'allOnes' ) ',' +/// 'sizeM1BitWidth' ':' SizeM1BitWidth [',' 'alignLog2' ':' UInt64]? +/// [',' 'sizeM1' ':' UInt64]? [',' 'bitMask' ':' UInt8]? +/// [',' 'inlinesBits' ':' UInt64]? ')' +bool LLParser::ParseTypeTestResolution(TypeTestResolution &TTRes) { + if (ParseToken(lltok::kw_typeTestRes, "expected 'typeTestRes' here") || + ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here") || + ParseToken(lltok::kw_kind, "expected 'kind' here") || + ParseToken(lltok::colon, "expected ':' here")) + return true; + + switch (Lex.getKind()) { + case lltok::kw_unsat: + TTRes.TheKind = TypeTestResolution::Unsat; + break; + case lltok::kw_byteArray: + TTRes.TheKind = TypeTestResolution::ByteArray; + break; + case lltok::kw_inline: + TTRes.TheKind = TypeTestResolution::Inline; + break; + case lltok::kw_single: + TTRes.TheKind = TypeTestResolution::Single; + break; + case lltok::kw_allOnes: + TTRes.TheKind = TypeTestResolution::AllOnes; + break; + default: + return Error(Lex.getLoc(), "unexpected TypeTestResolution kind"); + } + Lex.Lex(); + + if (ParseToken(lltok::comma, "expected ',' here") || + ParseToken(lltok::kw_sizeM1BitWidth, "expected 'sizeM1BitWidth' here") || + ParseToken(lltok::colon, "expected ':' here") || + ParseUInt32(TTRes.SizeM1BitWidth)) + return true; + + // Parse optional fields + while (EatIfPresent(lltok::comma)) { + switch (Lex.getKind()) { + case lltok::kw_alignLog2: + Lex.Lex(); + if (ParseToken(lltok::colon, "expected ':'") || + ParseUInt64(TTRes.AlignLog2)) + return true; + break; + case lltok::kw_sizeM1: + Lex.Lex(); + if (ParseToken(lltok::colon, "expected ':'") || ParseUInt64(TTRes.SizeM1)) + return true; + break; + case lltok::kw_bitMask: { + unsigned Val; + Lex.Lex(); + if (ParseToken(lltok::colon, "expected ':'") || ParseUInt32(Val)) + return true; + assert(Val <= 0xff); + TTRes.BitMask = (uint8_t)Val; + break; + } + case lltok::kw_inlineBits: + Lex.Lex(); + if (ParseToken(lltok::colon, "expected ':'") || + ParseUInt64(TTRes.InlineBits)) + return true; + break; + default: + return Error(Lex.getLoc(), "expected optional TypeTestResolution field"); + } + } + + if (ParseToken(lltok::rparen, "expected ')' here")) + return true; + + return false; +} + +/// OptionalWpdResolutions +/// ::= 'wpsResolutions' ':' '(' WpdResolution [',' WpdResolution]* ')' +/// WpdResolution ::= '(' 'offset' ':' UInt64 ',' WpdRes ')' +bool LLParser::ParseOptionalWpdResolutions( + std::map<uint64_t, WholeProgramDevirtResolution> &WPDResMap) { + if (ParseToken(lltok::kw_wpdResolutions, "expected 'wpdResolutions' here") || + ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here")) + return true; + + do { + uint64_t Offset; + WholeProgramDevirtResolution WPDRes; + if (ParseToken(lltok::lparen, "expected '(' here") || + ParseToken(lltok::kw_offset, "expected 'offset' here") || + ParseToken(lltok::colon, "expected ':' here") || ParseUInt64(Offset) || + ParseToken(lltok::comma, "expected ',' here") || ParseWpdRes(WPDRes) || + ParseToken(lltok::rparen, "expected ')' here")) + return true; + WPDResMap[Offset] = WPDRes; + } while (EatIfPresent(lltok::comma)); + + if (ParseToken(lltok::rparen, "expected ')' here")) + return true; + + return false; +} + +/// WpdRes +/// ::= 'wpdRes' ':' '(' 'kind' ':' 'indir' +/// [',' OptionalResByArg]? ')' +/// ::= 'wpdRes' ':' '(' 'kind' ':' 'singleImpl' +/// ',' 'singleImplName' ':' STRINGCONSTANT ',' +/// [',' OptionalResByArg]? ')' +/// ::= 'wpdRes' ':' '(' 'kind' ':' 'branchFunnel' +/// [',' OptionalResByArg]? ')' +bool LLParser::ParseWpdRes(WholeProgramDevirtResolution &WPDRes) { + if (ParseToken(lltok::kw_wpdRes, "expected 'wpdRes' here") || + ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here") || + ParseToken(lltok::kw_kind, "expected 'kind' here") || + ParseToken(lltok::colon, "expected ':' here")) + return true; + + switch (Lex.getKind()) { + case lltok::kw_indir: + WPDRes.TheKind = WholeProgramDevirtResolution::Indir; + break; + case lltok::kw_singleImpl: + WPDRes.TheKind = WholeProgramDevirtResolution::SingleImpl; + break; + case lltok::kw_branchFunnel: + WPDRes.TheKind = WholeProgramDevirtResolution::BranchFunnel; + break; + default: + return Error(Lex.getLoc(), "unexpected WholeProgramDevirtResolution kind"); + } + Lex.Lex(); + + // Parse optional fields + while (EatIfPresent(lltok::comma)) { + switch (Lex.getKind()) { + case lltok::kw_singleImplName: + Lex.Lex(); + if (ParseToken(lltok::colon, "expected ':' here") || + ParseStringConstant(WPDRes.SingleImplName)) + return true; + break; + case lltok::kw_resByArg: + if (ParseOptionalResByArg(WPDRes.ResByArg)) + return true; + break; + default: + return Error(Lex.getLoc(), + "expected optional WholeProgramDevirtResolution field"); + } + } + + if (ParseToken(lltok::rparen, "expected ')' here")) + return true; + + return false; +} + +/// OptionalResByArg +/// ::= 'wpdRes' ':' '(' ResByArg[, ResByArg]* ')' +/// ResByArg ::= Args ',' 'byArg' ':' '(' 'kind' ':' +/// ( 'indir' | 'uniformRetVal' | 'UniqueRetVal' | +/// 'virtualConstProp' ) +/// [',' 'info' ':' UInt64]? [',' 'byte' ':' UInt32]? +/// [',' 'bit' ':' UInt32]? ')' +bool LLParser::ParseOptionalResByArg( + std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg> + &ResByArg) { + if (ParseToken(lltok::kw_resByArg, "expected 'resByArg' here") || + ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here")) + return true; + + do { + std::vector<uint64_t> Args; + if (ParseArgs(Args) || ParseToken(lltok::comma, "expected ',' here") || + ParseToken(lltok::kw_byArg, "expected 'byArg here") || + ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here") || + ParseToken(lltok::kw_kind, "expected 'kind' here") || + ParseToken(lltok::colon, "expected ':' here")) + return true; + + WholeProgramDevirtResolution::ByArg ByArg; + switch (Lex.getKind()) { + case lltok::kw_indir: + ByArg.TheKind = WholeProgramDevirtResolution::ByArg::Indir; + break; + case lltok::kw_uniformRetVal: + ByArg.TheKind = WholeProgramDevirtResolution::ByArg::UniformRetVal; + break; + case lltok::kw_uniqueRetVal: + ByArg.TheKind = WholeProgramDevirtResolution::ByArg::UniqueRetVal; + break; + case lltok::kw_virtualConstProp: + ByArg.TheKind = WholeProgramDevirtResolution::ByArg::VirtualConstProp; + break; + default: + return Error(Lex.getLoc(), + "unexpected WholeProgramDevirtResolution::ByArg kind"); + } + Lex.Lex(); + + // Parse optional fields + while (EatIfPresent(lltok::comma)) { + switch (Lex.getKind()) { + case lltok::kw_info: + Lex.Lex(); + if (ParseToken(lltok::colon, "expected ':' here") || + ParseUInt64(ByArg.Info)) + return true; + break; + case lltok::kw_byte: + Lex.Lex(); + if (ParseToken(lltok::colon, "expected ':' here") || + ParseUInt32(ByArg.Byte)) + return true; + break; + case lltok::kw_bit: + Lex.Lex(); + if (ParseToken(lltok::colon, "expected ':' here") || + ParseUInt32(ByArg.Bit)) + return true; + break; + default: + return Error(Lex.getLoc(), + "expected optional whole program devirt field"); + } + } + + if (ParseToken(lltok::rparen, "expected ')' here")) + return true; + + ResByArg[Args] = ByArg; + } while (EatIfPresent(lltok::comma)); + + if (ParseToken(lltok::rparen, "expected ')' here")) + return true; + + return false; +} + +/// OptionalResByArg +/// ::= 'args' ':' '(' UInt64[, UInt64]* ')' +bool LLParser::ParseArgs(std::vector<uint64_t> &Args) { + if (ParseToken(lltok::kw_args, "expected 'args' here") || + ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here")) + return true; + + do { + uint64_t Val; + if (ParseUInt64(Val)) + return true; + Args.push_back(Val); + } while (EatIfPresent(lltok::comma)); + + if (ParseToken(lltok::rparen, "expected ')' here")) + return true; + + return false; +} + +static ValueInfo EmptyVI = + ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8); + +/// Stores the given Name/GUID and associated summary into the Index. +/// Also updates any forward references to the associated entry ID. +void LLParser::AddGlobalValueToIndex( + std::string Name, GlobalValue::GUID GUID, GlobalValue::LinkageTypes Linkage, + unsigned ID, std::unique_ptr<GlobalValueSummary> Summary) { + // First create the ValueInfo utilizing the Name or GUID. + ValueInfo VI; + if (GUID != 0) { + assert(Name.empty()); + VI = Index->getOrInsertValueInfo(GUID); + } else { + assert(!Name.empty()); + if (M) { + auto *GV = M->getNamedValue(Name); + assert(GV); + VI = Index->getOrInsertValueInfo(GV); + } else { + assert( + (!GlobalValue::isLocalLinkage(Linkage) || !SourceFileName.empty()) && + "Need a source_filename to compute GUID for local"); + GUID = GlobalValue::getGUID( + GlobalValue::getGlobalIdentifier(Name, Linkage, SourceFileName)); + VI = Index->getOrInsertValueInfo(GUID, Index->saveString(Name)); + } + } + + // Add the summary if one was provided. + if (Summary) + Index->addGlobalValueSummary(VI, std::move(Summary)); + + // Resolve forward references from calls/refs + auto FwdRefVIs = ForwardRefValueInfos.find(ID); + if (FwdRefVIs != ForwardRefValueInfos.end()) { + for (auto VIRef : FwdRefVIs->second) { + assert(*VIRef.first == EmptyVI && + "Forward referenced ValueInfo expected to be empty"); + *VIRef.first = VI; + } + ForwardRefValueInfos.erase(FwdRefVIs); + } + + // Resolve forward references from aliases + auto FwdRefAliasees = ForwardRefAliasees.find(ID); + if (FwdRefAliasees != ForwardRefAliasees.end()) { + for (auto AliaseeRef : FwdRefAliasees->second) { + assert(!AliaseeRef.first->hasAliasee() && + "Forward referencing alias already has aliasee"); + AliaseeRef.first->setAliasee(VI.getSummaryList().front().get()); + } + ForwardRefAliasees.erase(FwdRefAliasees); + } + + // Save the associated ValueInfo for use in later references by ID. + if (ID == NumberedValueInfos.size()) + NumberedValueInfos.push_back(VI); + else { + // Handle non-continuous numbers (to make test simplification easier). + if (ID > NumberedValueInfos.size()) + NumberedValueInfos.resize(ID + 1); + NumberedValueInfos[ID] = VI; + } +} + +/// ParseGVEntry +/// ::= 'gv' ':' '(' ('name' ':' STRINGCONSTANT | 'guid' ':' UInt64) +/// [',' 'summaries' ':' Summary[',' Summary]* ]? ')' +/// Summary ::= '(' (FunctionSummary | VariableSummary | AliasSummary) ')' +bool LLParser::ParseGVEntry(unsigned ID) { + assert(Lex.getKind() == lltok::kw_gv); + Lex.Lex(); + + if (ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here")) + return true; + + std::string Name; + GlobalValue::GUID GUID = 0; + switch (Lex.getKind()) { + case lltok::kw_name: + Lex.Lex(); + if (ParseToken(lltok::colon, "expected ':' here") || + ParseStringConstant(Name)) + return true; + // Can't create GUID/ValueInfo until we have the linkage. + break; + case lltok::kw_guid: + Lex.Lex(); + if (ParseToken(lltok::colon, "expected ':' here") || ParseUInt64(GUID)) + return true; + break; + default: + return Error(Lex.getLoc(), "expected name or guid tag"); + } + + if (!EatIfPresent(lltok::comma)) { + // No summaries. Wrap up. + if (ParseToken(lltok::rparen, "expected ')' here")) + return true; + // This was created for a call to an external or indirect target. + // A GUID with no summary came from a VALUE_GUID record, dummy GUID + // created for indirect calls with VP. A Name with no GUID came from + // an external definition. We pass ExternalLinkage since that is only + // used when the GUID must be computed from Name, and in that case + // the symbol must have external linkage. + AddGlobalValueToIndex(Name, GUID, GlobalValue::ExternalLinkage, ID, + nullptr); + return false; + } + + // Have a list of summaries + if (ParseToken(lltok::kw_summaries, "expected 'summaries' here") || + ParseToken(lltok::colon, "expected ':' here")) + return true; + + do { + if (ParseToken(lltok::lparen, "expected '(' here")) + return true; + switch (Lex.getKind()) { + case lltok::kw_function: + if (ParseFunctionSummary(Name, GUID, ID)) + return true; + break; + case lltok::kw_variable: + if (ParseVariableSummary(Name, GUID, ID)) + return true; + break; + case lltok::kw_alias: + if (ParseAliasSummary(Name, GUID, ID)) + return true; + break; + default: + return Error(Lex.getLoc(), "expected summary type"); + } + if (ParseToken(lltok::rparen, "expected ')' here")) + return true; + } while (EatIfPresent(lltok::comma)); + + if (ParseToken(lltok::rparen, "expected ')' here")) + return true; + + return false; +} + +/// FunctionSummary +/// ::= 'function' ':' '(' 'module' ':' ModuleReference ',' GVFlags +/// ',' 'insts' ':' UInt32 [',' OptionalFFlags]? [',' OptionalCalls]? +/// [',' OptionalTypeIdInfo]? [',' OptionalRefs]? ')' +bool LLParser::ParseFunctionSummary(std::string Name, GlobalValue::GUID GUID, + unsigned ID) { + assert(Lex.getKind() == lltok::kw_function); + Lex.Lex(); + + StringRef ModulePath; + GlobalValueSummary::GVFlags GVFlags = GlobalValueSummary::GVFlags( + /*Linkage=*/GlobalValue::ExternalLinkage, /*NotEligibleToImport=*/false, + /*Live=*/false, /*IsLocal=*/false); + unsigned InstCount; + std::vector<FunctionSummary::EdgeTy> Calls; + FunctionSummary::TypeIdInfo TypeIdInfo; + std::vector<ValueInfo> Refs; + // Default is all-zeros (conservative values). + FunctionSummary::FFlags FFlags = {}; + if (ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here") || + ParseModuleReference(ModulePath) || + ParseToken(lltok::comma, "expected ',' here") || ParseGVFlags(GVFlags) || + ParseToken(lltok::comma, "expected ',' here") || + ParseToken(lltok::kw_insts, "expected 'insts' here") || + ParseToken(lltok::colon, "expected ':' here") || ParseUInt32(InstCount)) + return true; + + // Parse optional fields + while (EatIfPresent(lltok::comma)) { + switch (Lex.getKind()) { + case lltok::kw_funcFlags: + if (ParseOptionalFFlags(FFlags)) + return true; + break; + case lltok::kw_calls: + if (ParseOptionalCalls(Calls)) + return true; + break; + case lltok::kw_typeIdInfo: + if (ParseOptionalTypeIdInfo(TypeIdInfo)) + return true; + break; + case lltok::kw_refs: + if (ParseOptionalRefs(Refs)) + return true; + break; + default: + return Error(Lex.getLoc(), "expected optional function summary field"); + } + } + + if (ParseToken(lltok::rparen, "expected ')' here")) + return true; + + auto FS = llvm::make_unique<FunctionSummary>( + GVFlags, InstCount, FFlags, std::move(Refs), std::move(Calls), + std::move(TypeIdInfo.TypeTests), + std::move(TypeIdInfo.TypeTestAssumeVCalls), + std::move(TypeIdInfo.TypeCheckedLoadVCalls), + std::move(TypeIdInfo.TypeTestAssumeConstVCalls), + std::move(TypeIdInfo.TypeCheckedLoadConstVCalls)); + + FS->setModulePath(ModulePath); + + AddGlobalValueToIndex(Name, GUID, (GlobalValue::LinkageTypes)GVFlags.Linkage, + ID, std::move(FS)); + + return false; +} + +/// VariableSummary +/// ::= 'variable' ':' '(' 'module' ':' ModuleReference ',' GVFlags +/// [',' OptionalRefs]? ')' +bool LLParser::ParseVariableSummary(std::string Name, GlobalValue::GUID GUID, + unsigned ID) { + assert(Lex.getKind() == lltok::kw_variable); + Lex.Lex(); + + StringRef ModulePath; + GlobalValueSummary::GVFlags GVFlags = GlobalValueSummary::GVFlags( + /*Linkage=*/GlobalValue::ExternalLinkage, /*NotEligibleToImport=*/false, + /*Live=*/false, /*IsLocal=*/false); + std::vector<ValueInfo> Refs; + if (ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here") || + ParseModuleReference(ModulePath) || + ParseToken(lltok::comma, "expected ',' here") || ParseGVFlags(GVFlags)) + return true; + + // Parse optional refs field + if (EatIfPresent(lltok::comma)) { + if (ParseOptionalRefs(Refs)) + return true; + } + + if (ParseToken(lltok::rparen, "expected ')' here")) + return true; + + auto GS = llvm::make_unique<GlobalVarSummary>(GVFlags, std::move(Refs)); + + GS->setModulePath(ModulePath); + + AddGlobalValueToIndex(Name, GUID, (GlobalValue::LinkageTypes)GVFlags.Linkage, + ID, std::move(GS)); + + return false; +} + +/// AliasSummary +/// ::= 'alias' ':' '(' 'module' ':' ModuleReference ',' GVFlags ',' +/// 'aliasee' ':' GVReference ')' +bool LLParser::ParseAliasSummary(std::string Name, GlobalValue::GUID GUID, + unsigned ID) { + assert(Lex.getKind() == lltok::kw_alias); + LocTy Loc = Lex.getLoc(); + Lex.Lex(); + + StringRef ModulePath; + GlobalValueSummary::GVFlags GVFlags = GlobalValueSummary::GVFlags( + /*Linkage=*/GlobalValue::ExternalLinkage, /*NotEligibleToImport=*/false, + /*Live=*/false, /*IsLocal=*/false); + if (ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here") || + ParseModuleReference(ModulePath) || + ParseToken(lltok::comma, "expected ',' here") || ParseGVFlags(GVFlags) || + ParseToken(lltok::comma, "expected ',' here") || + ParseToken(lltok::kw_aliasee, "expected 'aliasee' here") || + ParseToken(lltok::colon, "expected ':' here")) + return true; + + ValueInfo AliaseeVI; + unsigned GVId; + if (ParseGVReference(AliaseeVI, GVId)) + return true; + + if (ParseToken(lltok::rparen, "expected ')' here")) + return true; + + auto AS = llvm::make_unique<AliasSummary>(GVFlags); + + AS->setModulePath(ModulePath); + + // Record forward reference if the aliasee is not parsed yet. + if (AliaseeVI == EmptyVI) { + auto FwdRef = ForwardRefAliasees.insert( + std::make_pair(GVId, std::vector<std::pair<AliasSummary *, LocTy>>())); + FwdRef.first->second.push_back(std::make_pair(AS.get(), Loc)); + } else + AS->setAliasee(AliaseeVI.getSummaryList().front().get()); + + AddGlobalValueToIndex(Name, GUID, (GlobalValue::LinkageTypes)GVFlags.Linkage, + ID, std::move(AS)); + + return false; +} + +/// Flag +/// ::= [0|1] +bool LLParser::ParseFlag(unsigned &Val) { + if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) + return TokError("expected integer"); + Val = (unsigned)Lex.getAPSIntVal().getBoolValue(); + Lex.Lex(); + return false; +} + +/// OptionalFFlags +/// := 'funcFlags' ':' '(' ['readNone' ':' Flag]? +/// [',' 'readOnly' ':' Flag]? [',' 'noRecurse' ':' Flag]? +/// [',' 'returnDoesNotAlias' ':' Flag]? ')' +bool LLParser::ParseOptionalFFlags(FunctionSummary::FFlags &FFlags) { + assert(Lex.getKind() == lltok::kw_funcFlags); + Lex.Lex(); + + if (ParseToken(lltok::colon, "expected ':' in funcFlags") | + ParseToken(lltok::lparen, "expected '(' in funcFlags")) + return true; + + do { + unsigned Val; + switch (Lex.getKind()) { + case lltok::kw_readNone: + Lex.Lex(); + if (ParseToken(lltok::colon, "expected ':'") || ParseFlag(Val)) + return true; + FFlags.ReadNone = Val; + break; + case lltok::kw_readOnly: + Lex.Lex(); + if (ParseToken(lltok::colon, "expected ':'") || ParseFlag(Val)) + return true; + FFlags.ReadOnly = Val; + break; + case lltok::kw_noRecurse: + Lex.Lex(); + if (ParseToken(lltok::colon, "expected ':'") || ParseFlag(Val)) + return true; + FFlags.NoRecurse = Val; + break; + case lltok::kw_returnDoesNotAlias: + Lex.Lex(); + if (ParseToken(lltok::colon, "expected ':'") || ParseFlag(Val)) + return true; + FFlags.ReturnDoesNotAlias = Val; + break; + default: + return Error(Lex.getLoc(), "expected function flag type"); + } + } while (EatIfPresent(lltok::comma)); + + if (ParseToken(lltok::rparen, "expected ')' in funcFlags")) + return true; + + return false; +} + +/// OptionalCalls +/// := 'calls' ':' '(' Call [',' Call]* ')' +/// Call ::= '(' 'callee' ':' GVReference +/// [( ',' 'hotness' ':' Hotness | ',' 'relbf' ':' UInt32 )]? ')' +bool LLParser::ParseOptionalCalls(std::vector<FunctionSummary::EdgeTy> &Calls) { + assert(Lex.getKind() == lltok::kw_calls); + Lex.Lex(); + + if (ParseToken(lltok::colon, "expected ':' in calls") | + ParseToken(lltok::lparen, "expected '(' in calls")) + return true; + + IdToIndexMapType IdToIndexMap; + // Parse each call edge + do { + ValueInfo VI; + if (ParseToken(lltok::lparen, "expected '(' in call") || + ParseToken(lltok::kw_callee, "expected 'callee' in call") || + ParseToken(lltok::colon, "expected ':'")) + return true; + + LocTy Loc = Lex.getLoc(); + unsigned GVId; + if (ParseGVReference(VI, GVId)) + return true; + + CalleeInfo::HotnessType Hotness = CalleeInfo::HotnessType::Unknown; + unsigned RelBF = 0; + if (EatIfPresent(lltok::comma)) { + // Expect either hotness or relbf + if (EatIfPresent(lltok::kw_hotness)) { + if (ParseToken(lltok::colon, "expected ':'") || ParseHotness(Hotness)) + return true; + } else { + if (ParseToken(lltok::kw_relbf, "expected relbf") || + ParseToken(lltok::colon, "expected ':'") || ParseUInt32(RelBF)) + return true; + } + } + // Keep track of the Call array index needing a forward reference. + // We will save the location of the ValueInfo needing an update, but + // can only do so once the std::vector is finalized. + if (VI == EmptyVI) + IdToIndexMap[GVId].push_back(std::make_pair(Calls.size(), Loc)); + Calls.push_back(FunctionSummary::EdgeTy{VI, CalleeInfo(Hotness, RelBF)}); + + if (ParseToken(lltok::rparen, "expected ')' in call")) + return true; + } while (EatIfPresent(lltok::comma)); + + // Now that the Calls vector is finalized, it is safe to save the locations + // of any forward GV references that need updating later. + for (auto I : IdToIndexMap) { + for (auto P : I.second) { + assert(Calls[P.first].first == EmptyVI && + "Forward referenced ValueInfo expected to be empty"); + auto FwdRef = ForwardRefValueInfos.insert(std::make_pair( + I.first, std::vector<std::pair<ValueInfo *, LocTy>>())); + FwdRef.first->second.push_back( + std::make_pair(&Calls[P.first].first, P.second)); + } + } + + if (ParseToken(lltok::rparen, "expected ')' in calls")) + return true; + + return false; +} + +/// Hotness +/// := ('unknown'|'cold'|'none'|'hot'|'critical') +bool LLParser::ParseHotness(CalleeInfo::HotnessType &Hotness) { + switch (Lex.getKind()) { + case lltok::kw_unknown: + Hotness = CalleeInfo::HotnessType::Unknown; + break; + case lltok::kw_cold: + Hotness = CalleeInfo::HotnessType::Cold; + break; + case lltok::kw_none: + Hotness = CalleeInfo::HotnessType::None; + break; + case lltok::kw_hot: + Hotness = CalleeInfo::HotnessType::Hot; + break; + case lltok::kw_critical: + Hotness = CalleeInfo::HotnessType::Critical; + break; + default: + return Error(Lex.getLoc(), "invalid call edge hotness"); + } + Lex.Lex(); + return false; +} + +/// OptionalRefs +/// := 'refs' ':' '(' GVReference [',' GVReference]* ')' +bool LLParser::ParseOptionalRefs(std::vector<ValueInfo> &Refs) { + assert(Lex.getKind() == lltok::kw_refs); + Lex.Lex(); + + if (ParseToken(lltok::colon, "expected ':' in refs") | + ParseToken(lltok::lparen, "expected '(' in refs")) + return true; + + IdToIndexMapType IdToIndexMap; + // Parse each ref edge + do { + ValueInfo VI; + LocTy Loc = Lex.getLoc(); + unsigned GVId; + if (ParseGVReference(VI, GVId)) + return true; + + // Keep track of the Refs array index needing a forward reference. + // We will save the location of the ValueInfo needing an update, but + // can only do so once the std::vector is finalized. + if (VI == EmptyVI) + IdToIndexMap[GVId].push_back(std::make_pair(Refs.size(), Loc)); + Refs.push_back(VI); + } while (EatIfPresent(lltok::comma)); + + // Now that the Refs vector is finalized, it is safe to save the locations + // of any forward GV references that need updating later. + for (auto I : IdToIndexMap) { + for (auto P : I.second) { + assert(Refs[P.first] == EmptyVI && + "Forward referenced ValueInfo expected to be empty"); + auto FwdRef = ForwardRefValueInfos.insert(std::make_pair( + I.first, std::vector<std::pair<ValueInfo *, LocTy>>())); + FwdRef.first->second.push_back(std::make_pair(&Refs[P.first], P.second)); + } + } + + if (ParseToken(lltok::rparen, "expected ')' in refs")) + return true; + + return false; +} + +/// OptionalTypeIdInfo +/// := 'typeidinfo' ':' '(' [',' TypeTests]? [',' TypeTestAssumeVCalls]? +/// [',' TypeCheckedLoadVCalls]? [',' TypeTestAssumeConstVCalls]? +/// [',' TypeCheckedLoadConstVCalls]? ')' +bool LLParser::ParseOptionalTypeIdInfo( + FunctionSummary::TypeIdInfo &TypeIdInfo) { + assert(Lex.getKind() == lltok::kw_typeIdInfo); + Lex.Lex(); + + if (ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' in typeIdInfo")) + return true; + + do { + switch (Lex.getKind()) { + case lltok::kw_typeTests: + if (ParseTypeTests(TypeIdInfo.TypeTests)) + return true; + break; + case lltok::kw_typeTestAssumeVCalls: + if (ParseVFuncIdList(lltok::kw_typeTestAssumeVCalls, + TypeIdInfo.TypeTestAssumeVCalls)) + return true; + break; + case lltok::kw_typeCheckedLoadVCalls: + if (ParseVFuncIdList(lltok::kw_typeCheckedLoadVCalls, + TypeIdInfo.TypeCheckedLoadVCalls)) + return true; + break; + case lltok::kw_typeTestAssumeConstVCalls: + if (ParseConstVCallList(lltok::kw_typeTestAssumeConstVCalls, + TypeIdInfo.TypeTestAssumeConstVCalls)) + return true; + break; + case lltok::kw_typeCheckedLoadConstVCalls: + if (ParseConstVCallList(lltok::kw_typeCheckedLoadConstVCalls, + TypeIdInfo.TypeCheckedLoadConstVCalls)) + return true; + break; + default: + return Error(Lex.getLoc(), "invalid typeIdInfo list type"); + } + } while (EatIfPresent(lltok::comma)); + + if (ParseToken(lltok::rparen, "expected ')' in typeIdInfo")) + return true; + + return false; +} + +/// TypeTests +/// ::= 'typeTests' ':' '(' (SummaryID | UInt64) +/// [',' (SummaryID | UInt64)]* ')' +bool LLParser::ParseTypeTests(std::vector<GlobalValue::GUID> &TypeTests) { + assert(Lex.getKind() == lltok::kw_typeTests); + Lex.Lex(); + + if (ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' in typeIdInfo")) + return true; + + IdToIndexMapType IdToIndexMap; + do { + GlobalValue::GUID GUID = 0; + if (Lex.getKind() == lltok::SummaryID) { + unsigned ID = Lex.getUIntVal(); + LocTy Loc = Lex.getLoc(); + // Keep track of the TypeTests array index needing a forward reference. + // We will save the location of the GUID needing an update, but + // can only do so once the std::vector is finalized. + IdToIndexMap[ID].push_back(std::make_pair(TypeTests.size(), Loc)); + Lex.Lex(); + } else if (ParseUInt64(GUID)) + return true; + TypeTests.push_back(GUID); + } while (EatIfPresent(lltok::comma)); + + // Now that the TypeTests vector is finalized, it is safe to save the + // locations of any forward GV references that need updating later. + for (auto I : IdToIndexMap) { + for (auto P : I.second) { + assert(TypeTests[P.first] == 0 && + "Forward referenced type id GUID expected to be 0"); + auto FwdRef = ForwardRefTypeIds.insert(std::make_pair( + I.first, std::vector<std::pair<GlobalValue::GUID *, LocTy>>())); + FwdRef.first->second.push_back( + std::make_pair(&TypeTests[P.first], P.second)); + } + } + + if (ParseToken(lltok::rparen, "expected ')' in typeIdInfo")) + return true; + + return false; +} + +/// VFuncIdList +/// ::= Kind ':' '(' VFuncId [',' VFuncId]* ')' +bool LLParser::ParseVFuncIdList( + lltok::Kind Kind, std::vector<FunctionSummary::VFuncId> &VFuncIdList) { + assert(Lex.getKind() == Kind); + Lex.Lex(); + + if (ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here")) + return true; + + IdToIndexMapType IdToIndexMap; + do { + FunctionSummary::VFuncId VFuncId; + if (ParseVFuncId(VFuncId, IdToIndexMap, VFuncIdList.size())) + return true; + VFuncIdList.push_back(VFuncId); + } while (EatIfPresent(lltok::comma)); + + if (ParseToken(lltok::rparen, "expected ')' here")) + return true; + + // Now that the VFuncIdList vector is finalized, it is safe to save the + // locations of any forward GV references that need updating later. + for (auto I : IdToIndexMap) { + for (auto P : I.second) { + assert(VFuncIdList[P.first].GUID == 0 && + "Forward referenced type id GUID expected to be 0"); + auto FwdRef = ForwardRefTypeIds.insert(std::make_pair( + I.first, std::vector<std::pair<GlobalValue::GUID *, LocTy>>())); + FwdRef.first->second.push_back( + std::make_pair(&VFuncIdList[P.first].GUID, P.second)); + } + } + + return false; +} + +/// ConstVCallList +/// ::= Kind ':' '(' ConstVCall [',' ConstVCall]* ')' +bool LLParser::ParseConstVCallList( + lltok::Kind Kind, + std::vector<FunctionSummary::ConstVCall> &ConstVCallList) { + assert(Lex.getKind() == Kind); + Lex.Lex(); + + if (ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here")) + return true; + + IdToIndexMapType IdToIndexMap; + do { + FunctionSummary::ConstVCall ConstVCall; + if (ParseConstVCall(ConstVCall, IdToIndexMap, ConstVCallList.size())) + return true; + ConstVCallList.push_back(ConstVCall); + } while (EatIfPresent(lltok::comma)); + + if (ParseToken(lltok::rparen, "expected ')' here")) + return true; + + // Now that the ConstVCallList vector is finalized, it is safe to save the + // locations of any forward GV references that need updating later. + for (auto I : IdToIndexMap) { + for (auto P : I.second) { + assert(ConstVCallList[P.first].VFunc.GUID == 0 && + "Forward referenced type id GUID expected to be 0"); + auto FwdRef = ForwardRefTypeIds.insert(std::make_pair( + I.first, std::vector<std::pair<GlobalValue::GUID *, LocTy>>())); + FwdRef.first->second.push_back( + std::make_pair(&ConstVCallList[P.first].VFunc.GUID, P.second)); + } + } + + return false; +} + +/// ConstVCall +/// ::= VFuncId, Args +bool LLParser::ParseConstVCall(FunctionSummary::ConstVCall &ConstVCall, + IdToIndexMapType &IdToIndexMap, unsigned Index) { + if (ParseVFuncId(ConstVCall.VFunc, IdToIndexMap, Index) || + ParseToken(lltok::comma, "expected ',' here") || + ParseArgs(ConstVCall.Args)) + return true; + + return false; +} + +/// VFuncId +/// ::= 'vFuncId' ':' '(' (SummaryID | 'guid' ':' UInt64) ',' +/// 'offset' ':' UInt64 ')' +bool LLParser::ParseVFuncId(FunctionSummary::VFuncId &VFuncId, + IdToIndexMapType &IdToIndexMap, unsigned Index) { + assert(Lex.getKind() == lltok::kw_vFuncId); + Lex.Lex(); + + if (ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here")) + return true; + + if (Lex.getKind() == lltok::SummaryID) { + VFuncId.GUID = 0; + unsigned ID = Lex.getUIntVal(); + LocTy Loc = Lex.getLoc(); + // Keep track of the array index needing a forward reference. + // We will save the location of the GUID needing an update, but + // can only do so once the caller's std::vector is finalized. + IdToIndexMap[ID].push_back(std::make_pair(Index, Loc)); + Lex.Lex(); + } else if (ParseToken(lltok::kw_guid, "expected 'guid' here") || + ParseToken(lltok::colon, "expected ':' here") || + ParseUInt64(VFuncId.GUID)) + return true; + + if (ParseToken(lltok::comma, "expected ',' here") || + ParseToken(lltok::kw_offset, "expected 'offset' here") || + ParseToken(lltok::colon, "expected ':' here") || + ParseUInt64(VFuncId.Offset) || + ParseToken(lltok::rparen, "expected ')' here")) + return true; + + return false; +} + +/// GVFlags +/// ::= 'flags' ':' '(' 'linkage' ':' OptionalLinkageAux ',' +/// 'notEligibleToImport' ':' Flag ',' 'live' ':' Flag ',' +/// 'dsoLocal' ':' Flag ')' +bool LLParser::ParseGVFlags(GlobalValueSummary::GVFlags &GVFlags) { + assert(Lex.getKind() == lltok::kw_flags); + Lex.Lex(); + + bool HasLinkage; + if (ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::lparen, "expected '(' here") || + ParseToken(lltok::kw_linkage, "expected 'linkage' here") || + ParseToken(lltok::colon, "expected ':' here")) + return true; + + GVFlags.Linkage = parseOptionalLinkageAux(Lex.getKind(), HasLinkage); + assert(HasLinkage && "Linkage not optional in summary entry"); + Lex.Lex(); + + unsigned Flag; + if (ParseToken(lltok::comma, "expected ',' here") || + ParseToken(lltok::kw_notEligibleToImport, + "expected 'notEligibleToImport' here") || + ParseToken(lltok::colon, "expected ':' here") || ParseFlag(Flag)) + return true; + GVFlags.NotEligibleToImport = Flag; + + if (ParseToken(lltok::comma, "expected ',' here") || + ParseToken(lltok::kw_live, "expected 'live' here") || + ParseToken(lltok::colon, "expected ':' here") || ParseFlag(Flag)) + return true; + GVFlags.Live = Flag; + + if (ParseToken(lltok::comma, "expected ',' here") || + ParseToken(lltok::kw_dsoLocal, "expected 'dsoLocal' here") || + ParseToken(lltok::colon, "expected ':' here") || ParseFlag(Flag)) + return true; + GVFlags.DSOLocal = Flag; + + if (ParseToken(lltok::rparen, "expected ')' here")) + return true; + + return false; +} + +/// ModuleReference +/// ::= 'module' ':' UInt +bool LLParser::ParseModuleReference(StringRef &ModulePath) { + // Parse module id. + if (ParseToken(lltok::kw_module, "expected 'module' here") || + ParseToken(lltok::colon, "expected ':' here") || + ParseToken(lltok::SummaryID, "expected module ID")) + return true; + + unsigned ModuleID = Lex.getUIntVal(); + auto I = ModuleIdMap.find(ModuleID); + // We should have already parsed all module IDs + assert(I != ModuleIdMap.end()); + ModulePath = I->second; + return false; +} + +/// GVReference +/// ::= SummaryID +bool LLParser::ParseGVReference(ValueInfo &VI, unsigned &GVId) { + if (ParseToken(lltok::SummaryID, "expected GV ID")) + return true; + + GVId = Lex.getUIntVal(); + + // Check if we already have a VI for this GV + if (GVId < NumberedValueInfos.size()) { + assert(NumberedValueInfos[GVId] != EmptyVI); + VI = NumberedValueInfos[GVId]; + } else + // We will create a forward reference to the stored location. + VI = EmptyVI; + + return false; +} diff --git a/contrib/llvm/lib/AsmParser/LLParser.h b/contrib/llvm/lib/AsmParser/LLParser.h index 94e4c1ae96d5..811f96418fa5 100644 --- a/contrib/llvm/lib/AsmParser/LLParser.h +++ b/contrib/llvm/lib/AsmParser/LLParser.h @@ -20,6 +20,7 @@ #include "llvm/IR/Attributes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ModuleSummaryIndex.h" #include "llvm/IR/Operator.h" #include "llvm/IR/Type.h" #include "llvm/IR/ValueHandle.h" @@ -90,7 +91,10 @@ namespace llvm { private: LLVMContext &Context; LLLexer Lex; + // Module being parsed, null if we are only parsing summary index. Module *M; + // Summary index being parsed, null if we are only parsing Module. + ModuleSummaryIndex *Index; SlotMapping *Slots; // Instruction metadata resolution. Each instruction can have a list of @@ -139,16 +143,40 @@ namespace llvm { std::map<Value*, std::vector<unsigned> > ForwardRefAttrGroups; std::map<unsigned, AttrBuilder> NumberedAttrBuilders; + // Summary global value reference information. + std::map<unsigned, std::vector<std::pair<ValueInfo *, LocTy>>> + ForwardRefValueInfos; + std::map<unsigned, std::vector<std::pair<AliasSummary *, LocTy>>> + ForwardRefAliasees; + std::vector<ValueInfo> NumberedValueInfos; + + // Summary type id reference information. + std::map<unsigned, std::vector<std::pair<GlobalValue::GUID *, LocTy>>> + ForwardRefTypeIds; + + // Map of module ID to path. + std::map<unsigned, StringRef> ModuleIdMap; + /// Only the llvm-as tool may set this to false to bypass /// UpgradeDebuginfo so it can generate broken bitcode. bool UpgradeDebugInfo; + /// DataLayout string to override that in LLVM assembly. + StringRef DataLayoutStr; + + std::string SourceFileName; + public: LLParser(StringRef F, SourceMgr &SM, SMDiagnostic &Err, Module *M, - SlotMapping *Slots = nullptr, bool UpgradeDebugInfo = true) - : Context(M->getContext()), Lex(F, SM, Err, M->getContext()), M(M), + ModuleSummaryIndex *Index, LLVMContext &Context, + SlotMapping *Slots = nullptr, bool UpgradeDebugInfo = true, + StringRef DataLayoutString = "") + : Context(Context), Lex(F, SM, Err, Context), M(M), Index(Index), Slots(Slots), BlockAddressPFS(nullptr), - UpgradeDebugInfo(UpgradeDebugInfo) {} + UpgradeDebugInfo(UpgradeDebugInfo), DataLayoutStr(DataLayoutString) { + if (!DataLayoutStr.empty()) + M->setDataLayout(DataLayoutStr); + } bool Run(); bool parseStandaloneConstantValue(Constant *&C, const SlotMapping *Slots); @@ -174,12 +202,12 @@ namespace llvm { /// GetGlobalVal - Get a value with the specified name or ID, creating a /// forward reference record if needed. This can return null if the value /// exists but does not have the right type. - GlobalValue *GetGlobalVal(const std::string &N, Type *Ty, LocTy Loc); + GlobalValue *GetGlobalVal(const std::string &Name, Type *Ty, LocTy Loc); GlobalValue *GetGlobalVal(unsigned ID, Type *Ty, LocTy Loc); /// Get a Comdat with the specified name, creating a forward reference /// record if needed. - Comdat *getComdat(const std::string &N, LocTy Loc); + Comdat *getComdat(const std::string &Name, LocTy Loc); // Helper Routines. bool ParseToken(lltok::Kind T, const char *ErrMsg); @@ -232,6 +260,7 @@ namespace llvm { Loc = Lex.getLoc(); return ParseUInt64(Val); } + bool ParseFlag(unsigned &Val); bool ParseStringAttribute(AttrBuilder &B); @@ -241,12 +270,12 @@ namespace llvm { bool ParseOptionalAddrSpace(unsigned &AddrSpace); bool ParseOptionalParamAttrs(AttrBuilder &B); bool ParseOptionalReturnAttrs(AttrBuilder &B); - bool ParseOptionalLinkage(unsigned &Linkage, bool &HasLinkage, + bool ParseOptionalLinkage(unsigned &Res, bool &HasLinkage, unsigned &Visibility, unsigned &DLLStorageClass, bool &DSOLocal); void ParseOptionalDSOLocal(bool &DSOLocal); - void ParseOptionalVisibility(unsigned &Visibility); - void ParseOptionalDLLStorageClass(unsigned &DLLStorageClass); + void ParseOptionalVisibility(unsigned &Res); + void ParseOptionalDLLStorageClass(unsigned &Res); bool ParseOptionalCallingConv(unsigned &CC); bool ParseOptionalAlignment(unsigned &Alignment); bool ParseOptionalDerefAttrBytes(lltok::Kind AttrKind, uint64_t &Bytes); @@ -259,7 +288,7 @@ namespace llvm { bool ParseOptionalCommaAddrSpace(unsigned &AddrSpace, LocTy &Loc, bool &AteExtraComma); bool ParseOptionalCommaInAlloca(bool &IsInAlloca); - bool parseAllocSizeArguments(unsigned &ElemSizeArg, + bool parseAllocSizeArguments(unsigned &BaseSizeArg, Optional<unsigned> &HowManyArg); bool ParseIndexList(SmallVectorImpl<unsigned> &Indices, bool &AteExtraComma); @@ -274,6 +303,7 @@ namespace llvm { // Top-Level Entities bool ParseTopLevelEntities(); bool ValidateEndOfModule(); + bool ValidateEndOfIndex(); bool ParseTargetDefinition(); bool ParseModuleAsm(); bool ParseSourceFileName(); @@ -286,13 +316,13 @@ namespace llvm { bool ParseGlobalType(bool &IsConstant); bool ParseUnnamedGlobal(); bool ParseNamedGlobal(); - bool ParseGlobal(const std::string &Name, LocTy Loc, unsigned Linkage, + bool ParseGlobal(const std::string &Name, LocTy NameLoc, unsigned Linkage, bool HasLinkage, unsigned Visibility, unsigned DLLStorageClass, bool DSOLocal, GlobalVariable::ThreadLocalMode TLM, GlobalVariable::UnnamedAddr UnnamedAddr); - bool parseIndirectSymbol(const std::string &Name, LocTy Loc, - unsigned Linkage, unsigned Visibility, + bool parseIndirectSymbol(const std::string &Name, LocTy NameLoc, + unsigned L, unsigned Visibility, unsigned DLLStorageClass, bool DSOLocal, GlobalVariable::ThreadLocalMode TLM, GlobalVariable::UnnamedAddr UnnamedAddr); @@ -306,6 +336,48 @@ namespace llvm { std::vector<unsigned> &FwdRefAttrGrps, bool inAttrGrp, LocTy &BuiltinLoc); + // Module Summary Index Parsing. + bool SkipModuleSummaryEntry(); + bool ParseSummaryEntry(); + bool ParseModuleEntry(unsigned ID); + bool ParseModuleReference(StringRef &ModulePath); + bool ParseGVReference(ValueInfo &VI, unsigned &GVId); + bool ParseGVEntry(unsigned ID); + bool ParseFunctionSummary(std::string Name, GlobalValue::GUID, unsigned ID); + bool ParseVariableSummary(std::string Name, GlobalValue::GUID, unsigned ID); + bool ParseAliasSummary(std::string Name, GlobalValue::GUID, unsigned ID); + bool ParseGVFlags(GlobalValueSummary::GVFlags &GVFlags); + bool ParseOptionalFFlags(FunctionSummary::FFlags &FFlags); + bool ParseOptionalCalls(std::vector<FunctionSummary::EdgeTy> &Calls); + bool ParseHotness(CalleeInfo::HotnessType &Hotness); + bool ParseOptionalTypeIdInfo(FunctionSummary::TypeIdInfo &TypeIdInfo); + bool ParseTypeTests(std::vector<GlobalValue::GUID> &TypeTests); + bool ParseVFuncIdList(lltok::Kind Kind, + std::vector<FunctionSummary::VFuncId> &VFuncIdList); + bool ParseConstVCallList( + lltok::Kind Kind, + std::vector<FunctionSummary::ConstVCall> &ConstVCallList); + using IdToIndexMapType = + std::map<unsigned, std::vector<std::pair<unsigned, LocTy>>>; + bool ParseConstVCall(FunctionSummary::ConstVCall &ConstVCall, + IdToIndexMapType &IdToIndexMap, unsigned Index); + bool ParseVFuncId(FunctionSummary::VFuncId &VFuncId, + IdToIndexMapType &IdToIndexMap, unsigned Index); + bool ParseOptionalRefs(std::vector<ValueInfo> &Refs); + bool ParseTypeIdEntry(unsigned ID); + bool ParseTypeIdSummary(TypeIdSummary &TIS); + bool ParseTypeTestResolution(TypeTestResolution &TTRes); + bool ParseOptionalWpdResolutions( + std::map<uint64_t, WholeProgramDevirtResolution> &WPDResMap); + bool ParseWpdRes(WholeProgramDevirtResolution &WPDRes); + bool ParseOptionalResByArg( + std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg> + &ResByArg); + bool ParseArgs(std::vector<uint64_t> &Args); + void AddGlobalValueToIndex(std::string Name, GlobalValue::GUID, + GlobalValue::LinkageTypes Linkage, unsigned ID, + std::unique_ptr<GlobalValueSummary> Summary); + // Type Parsing. bool ParseType(Type *&Result, const Twine &Msg, bool AllowVoid = false); bool ParseType(Type *&Result, bool AllowVoid = false) { @@ -341,7 +413,7 @@ namespace llvm { /// number of it, otherwise it is -1. int FunctionNumber; public: - PerFunctionState(LLParser &p, Function &f, int FunctionNumber); + PerFunctionState(LLParser &p, Function &f, int functionNumber); ~PerFunctionState(); Function &getFunction() const { return F; } @@ -351,8 +423,8 @@ namespace llvm { /// GetVal - Get a value with the specified name or ID, creating a /// forward reference record if needed. This can return null if the value /// exists but does not have the right type. - Value *GetVal(const std::string &Name, Type *Ty, LocTy Loc); - Value *GetVal(unsigned ID, Type *Ty, LocTy Loc); + Value *GetVal(const std::string &Name, Type *Ty, LocTy Loc, bool IsCall); + Value *GetVal(unsigned ID, Type *Ty, LocTy Loc, bool IsCall); /// SetInstName - After an instruction is parsed and inserted into its /// basic block, this installs its name. @@ -374,7 +446,7 @@ namespace llvm { }; bool ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V, - PerFunctionState *PFS); + PerFunctionState *PFS, bool IsCall); bool parseConstantValue(Type *Ty, Constant *&C); bool ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS); @@ -425,7 +497,7 @@ namespace llvm { // Constant Parsing. bool ParseValID(ValID &ID, PerFunctionState *PFS = nullptr); - bool ParseGlobalValue(Type *Ty, Constant *&V); + bool ParseGlobalValue(Type *Ty, Constant *&C); bool ParseGlobalTypeAndValue(Constant *&V); bool ParseGlobalValueVector(SmallVectorImpl<Constant *> &Elts, Optional<unsigned> *InRangeOp = nullptr); @@ -435,9 +507,9 @@ namespace llvm { PerFunctionState *PFS); bool ParseMetadata(Metadata *&MD, PerFunctionState *PFS); bool ParseMDTuple(MDNode *&MD, bool IsDistinct = false); - bool ParseMDNode(MDNode *&MD); - bool ParseMDNodeTail(MDNode *&MD); - bool ParseMDNodeVector(SmallVectorImpl<Metadata *> &MDs); + bool ParseMDNode(MDNode *&N); + bool ParseMDNodeTail(MDNode *&N); + bool ParseMDNodeVector(SmallVectorImpl<Metadata *> &Elts); bool ParseMetadataAttachment(unsigned &Kind, MDNode *&MD); bool ParseInstructionMetadata(Instruction &Inst); bool ParseGlobalObjectMetadataAttachment(GlobalObject &GO); @@ -477,7 +549,7 @@ namespace llvm { enum InstResult { InstNormal = 0, InstError = 1, InstExtraComma = 2 }; int ParseInstruction(Instruction *&Inst, BasicBlock *BB, PerFunctionState &PFS); - bool ParseCmpPredicate(unsigned &Pred, unsigned Opc); + bool ParseCmpPredicate(unsigned &P, unsigned Opc); bool ParseRet(Instruction *&Inst, BasicBlock *BB, PerFunctionState &PFS); bool ParseBr(Instruction *&Inst, PerFunctionState &PFS); @@ -491,29 +563,29 @@ namespace llvm { bool ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS); bool ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS); - bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc, + bool ParseArithmetic(Instruction *&Inst, PerFunctionState &PFS, unsigned Opc, unsigned OperandType); - bool ParseLogical(Instruction *&I, PerFunctionState &PFS, unsigned Opc); - bool ParseCompare(Instruction *&I, PerFunctionState &PFS, unsigned Opc); - bool ParseCast(Instruction *&I, PerFunctionState &PFS, unsigned Opc); - bool ParseSelect(Instruction *&I, PerFunctionState &PFS); - bool ParseVA_Arg(Instruction *&I, PerFunctionState &PFS); - bool ParseExtractElement(Instruction *&I, PerFunctionState &PFS); - bool ParseInsertElement(Instruction *&I, PerFunctionState &PFS); - bool ParseShuffleVector(Instruction *&I, PerFunctionState &PFS); - int ParsePHI(Instruction *&I, PerFunctionState &PFS); - bool ParseLandingPad(Instruction *&I, PerFunctionState &PFS); - bool ParseCall(Instruction *&I, PerFunctionState &PFS, - CallInst::TailCallKind IsTail); - int ParseAlloc(Instruction *&I, PerFunctionState &PFS); - int ParseLoad(Instruction *&I, PerFunctionState &PFS); - int ParseStore(Instruction *&I, PerFunctionState &PFS); - int ParseCmpXchg(Instruction *&I, PerFunctionState &PFS); - int ParseAtomicRMW(Instruction *&I, PerFunctionState &PFS); - int ParseFence(Instruction *&I, PerFunctionState &PFS); - int ParseGetElementPtr(Instruction *&I, PerFunctionState &PFS); - int ParseExtractValue(Instruction *&I, PerFunctionState &PFS); - int ParseInsertValue(Instruction *&I, PerFunctionState &PFS); + bool ParseLogical(Instruction *&Inst, PerFunctionState &PFS, unsigned Opc); + bool ParseCompare(Instruction *&Inst, PerFunctionState &PFS, unsigned Opc); + bool ParseCast(Instruction *&Inst, PerFunctionState &PFS, unsigned Opc); + bool ParseSelect(Instruction *&Inst, PerFunctionState &PFS); + bool ParseVA_Arg(Instruction *&Inst, PerFunctionState &PFS); + bool ParseExtractElement(Instruction *&Inst, PerFunctionState &PFS); + bool ParseInsertElement(Instruction *&Inst, PerFunctionState &PFS); + bool ParseShuffleVector(Instruction *&Inst, PerFunctionState &PFS); + int ParsePHI(Instruction *&Inst, PerFunctionState &PFS); + bool ParseLandingPad(Instruction *&Inst, PerFunctionState &PFS); + bool ParseCall(Instruction *&Inst, PerFunctionState &PFS, + CallInst::TailCallKind TCK); + int ParseAlloc(Instruction *&Inst, PerFunctionState &PFS); + int ParseLoad(Instruction *&Inst, PerFunctionState &PFS); + int ParseStore(Instruction *&Inst, PerFunctionState &PFS); + int ParseCmpXchg(Instruction *&Inst, PerFunctionState &PFS); + int ParseAtomicRMW(Instruction *&Inst, PerFunctionState &PFS); + int ParseFence(Instruction *&Inst, PerFunctionState &PFS); + int ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS); + int ParseExtractValue(Instruction *&Inst, PerFunctionState &PFS); + int ParseInsertValue(Instruction *&Inst, PerFunctionState &PFS); // Use-list order directives. bool ParseUseListOrder(PerFunctionState *PFS = nullptr); diff --git a/contrib/llvm/lib/AsmParser/LLToken.h b/contrib/llvm/lib/AsmParser/LLToken.h index ad826cc4fd21..8d8c7e99656e 100644 --- a/contrib/llvm/lib/AsmParser/LLToken.h +++ b/contrib/llvm/lib/AsmParser/LLToken.h @@ -36,6 +36,7 @@ enum Kind { rparen, // ( ) exclaim, // ! bar, // | + colon, // : kw_x, kw_true, @@ -199,7 +200,9 @@ enum Kind { kw_nonnull, kw_noredzone, kw_noreturn, + kw_nocf_check, kw_nounwind, + kw_optforfuzzing, kw_optnone, kw_optsize, kw_readnone, @@ -212,6 +215,7 @@ enum Kind { kw_sspreq, kw_sspstrong, kw_safestack, + kw_shadowcallstack, kw_sret, kw_sanitize_thread, kw_sanitize_memory, @@ -344,10 +348,78 @@ enum Kind { kw_uselistorder, kw_uselistorder_bb, + // Summary index keywords + kw_path, + kw_hash, + kw_gv, + kw_guid, + kw_name, + kw_summaries, + kw_flags, + kw_linkage, + kw_notEligibleToImport, + kw_live, + kw_dsoLocal, + kw_function, + kw_insts, + kw_funcFlags, + kw_readNone, + kw_readOnly, + kw_noRecurse, + kw_returnDoesNotAlias, + kw_calls, + kw_callee, + kw_hotness, + kw_unknown, + kw_hot, + kw_critical, + kw_relbf, + kw_variable, + kw_aliasee, + kw_refs, + kw_typeIdInfo, + kw_typeTests, + kw_typeTestAssumeVCalls, + kw_typeCheckedLoadVCalls, + kw_typeTestAssumeConstVCalls, + kw_typeCheckedLoadConstVCalls, + kw_vFuncId, + kw_offset, + kw_args, + kw_typeid, + kw_summary, + kw_typeTestRes, + kw_kind, + kw_unsat, + kw_byteArray, + kw_inline, + kw_single, + kw_allOnes, + kw_sizeM1BitWidth, + kw_alignLog2, + kw_sizeM1, + kw_bitMask, + kw_inlineBits, + kw_wpdResolutions, + kw_wpdRes, + kw_indir, + kw_singleImpl, + kw_branchFunnel, + kw_singleImplName, + kw_resByArg, + kw_byArg, + kw_uniformRetVal, + kw_uniqueRetVal, + kw_virtualConstProp, + kw_info, + kw_byte, + kw_bit, + // Unsigned Valued tokens (UIntVal). GlobalID, // @42 LocalVarID, // %42 AttrGrpID, // #42 + SummaryID, // ^42 // String valued tokens (StrVal). LabelStr, // foo: diff --git a/contrib/llvm/lib/AsmParser/Parser.cpp b/contrib/llvm/lib/AsmParser/Parser.cpp index a43ae2b5577a..1205dff24e8a 100644 --- a/contrib/llvm/lib/AsmParser/Parser.cpp +++ b/contrib/llvm/lib/AsmParser/Parser.cpp @@ -15,6 +15,7 @@ #include "LLParser.h" #include "llvm/ADT/STLExtras.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ModuleSummaryIndex.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" @@ -22,32 +23,39 @@ #include <system_error> using namespace llvm; -bool llvm::parseAssemblyInto(MemoryBufferRef F, Module &M, SMDiagnostic &Err, - SlotMapping *Slots, bool UpgradeDebugInfo) { +bool llvm::parseAssemblyInto(MemoryBufferRef F, Module *M, + ModuleSummaryIndex *Index, SMDiagnostic &Err, + SlotMapping *Slots, bool UpgradeDebugInfo, + StringRef DataLayoutString) { SourceMgr SM; std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(F); SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); - return LLParser(F.getBuffer(), SM, Err, &M, Slots, UpgradeDebugInfo).Run(); + LLVMContext Context; + return LLParser(F.getBuffer(), SM, Err, M, Index, + M ? M->getContext() : Context, Slots, UpgradeDebugInfo, + DataLayoutString) + .Run(); } std::unique_ptr<Module> llvm::parseAssembly(MemoryBufferRef F, SMDiagnostic &Err, LLVMContext &Context, - SlotMapping *Slots, bool UpgradeDebugInfo) { + SlotMapping *Slots, bool UpgradeDebugInfo, + StringRef DataLayoutString) { std::unique_ptr<Module> M = make_unique<Module>(F.getBufferIdentifier(), Context); - if (parseAssemblyInto(F, *M, Err, Slots, UpgradeDebugInfo)) + if (parseAssemblyInto(F, M.get(), nullptr, Err, Slots, UpgradeDebugInfo, + DataLayoutString)) return nullptr; return M; } -std::unique_ptr<Module> llvm::parseAssemblyFile(StringRef Filename, - SMDiagnostic &Err, - LLVMContext &Context, - SlotMapping *Slots, - bool UpgradeDebugInfo) { +std::unique_ptr<Module> +llvm::parseAssemblyFile(StringRef Filename, SMDiagnostic &Err, + LLVMContext &Context, SlotMapping *Slots, + bool UpgradeDebugInfo, StringRef DataLayoutString) { ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = MemoryBuffer::getFileOrSTDIN(Filename); if (std::error_code EC = FileOrErr.getError()) { @@ -57,16 +65,84 @@ std::unique_ptr<Module> llvm::parseAssemblyFile(StringRef Filename, } return parseAssembly(FileOrErr.get()->getMemBufferRef(), Err, Context, Slots, - UpgradeDebugInfo); + UpgradeDebugInfo, DataLayoutString); +} + +ParsedModuleAndIndex llvm::parseAssemblyWithIndex( + MemoryBufferRef F, SMDiagnostic &Err, LLVMContext &Context, + SlotMapping *Slots, bool UpgradeDebugInfo, StringRef DataLayoutString) { + std::unique_ptr<Module> M = + make_unique<Module>(F.getBufferIdentifier(), Context); + std::unique_ptr<ModuleSummaryIndex> Index = + make_unique<ModuleSummaryIndex>(/*HaveGVs=*/true); + + if (parseAssemblyInto(F, M.get(), Index.get(), Err, Slots, UpgradeDebugInfo, + DataLayoutString)) + return {nullptr, nullptr}; + + return {std::move(M), std::move(Index)}; } -std::unique_ptr<Module> llvm::parseAssemblyString(StringRef AsmString, - SMDiagnostic &Err, - LLVMContext &Context, - SlotMapping *Slots, - bool UpgradeDebugInfo) { +ParsedModuleAndIndex llvm::parseAssemblyFileWithIndex( + StringRef Filename, SMDiagnostic &Err, LLVMContext &Context, + SlotMapping *Slots, bool UpgradeDebugInfo, StringRef DataLayoutString) { + ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = + MemoryBuffer::getFileOrSTDIN(Filename); + if (std::error_code EC = FileOrErr.getError()) { + Err = SMDiagnostic(Filename, SourceMgr::DK_Error, + "Could not open input file: " + EC.message()); + return {nullptr, nullptr}; + } + + return parseAssemblyWithIndex(FileOrErr.get()->getMemBufferRef(), Err, + Context, Slots, UpgradeDebugInfo, + DataLayoutString); +} + +std::unique_ptr<Module> +llvm::parseAssemblyString(StringRef AsmString, SMDiagnostic &Err, + LLVMContext &Context, SlotMapping *Slots, + bool UpgradeDebugInfo, StringRef DataLayoutString) { MemoryBufferRef F(AsmString, "<string>"); - return parseAssembly(F, Err, Context, Slots, UpgradeDebugInfo); + return parseAssembly(F, Err, Context, Slots, UpgradeDebugInfo, + DataLayoutString); +} + +static bool parseSummaryIndexAssemblyInto(MemoryBufferRef F, + ModuleSummaryIndex &Index, + SMDiagnostic &Err) { + SourceMgr SM; + std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(F); + SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); + + // The parser holds a reference to a context that is unused when parsing the + // index, but we need to initialize it. + LLVMContext unusedContext; + return LLParser(F.getBuffer(), SM, Err, nullptr, &Index, unusedContext).Run(); +} + +std::unique_ptr<ModuleSummaryIndex> +llvm::parseSummaryIndexAssembly(MemoryBufferRef F, SMDiagnostic &Err) { + std::unique_ptr<ModuleSummaryIndex> Index = + make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false); + + if (parseSummaryIndexAssemblyInto(F, *Index, Err)) + return nullptr; + + return Index; +} + +std::unique_ptr<ModuleSummaryIndex> +llvm::parseSummaryIndexAssemblyFile(StringRef Filename, SMDiagnostic &Err) { + ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = + MemoryBuffer::getFileOrSTDIN(Filename); + if (std::error_code EC = FileOrErr.getError()) { + Err = SMDiagnostic(Filename, SourceMgr::DK_Error, + "Could not open input file: " + EC.message()); + return nullptr; + } + + return parseSummaryIndexAssembly(FileOrErr.get()->getMemBufferRef(), Err); } Constant *llvm::parseConstantValue(StringRef Asm, SMDiagnostic &Err, @@ -75,7 +151,7 @@ Constant *llvm::parseConstantValue(StringRef Asm, SMDiagnostic &Err, std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Asm); SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); Constant *C; - if (LLParser(Asm, SM, Err, const_cast<Module *>(&M)) + if (LLParser(Asm, SM, Err, const_cast<Module *>(&M), nullptr, M.getContext()) .parseStandaloneConstantValue(C, Slots)) return nullptr; return C; @@ -104,7 +180,7 @@ Type *llvm::parseTypeAtBeginning(StringRef Asm, unsigned &Read, std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Asm); SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); Type *Ty; - if (LLParser(Asm, SM, Err, const_cast<Module *>(&M)) + if (LLParser(Asm, SM, Err, const_cast<Module *>(&M), nullptr, M.getContext()) .parseTypeAtBeginning(Ty, Read, Slots)) return nullptr; return Ty; |