aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/AsmParser
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/AsmParser')
-rw-r--r--contrib/llvm/lib/AsmParser/LLLexer.cpp132
-rw-r--r--contrib/llvm/lib/AsmParser/LLLexer.h13
-rw-r--r--contrib/llvm/lib/AsmParser/LLParser.cpp1596
-rw-r--r--contrib/llvm/lib/AsmParser/LLParser.h158
-rw-r--r--contrib/llvm/lib/AsmParser/LLToken.h72
-rw-r--r--contrib/llvm/lib/AsmParser/Parser.cpp114
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;