summaryrefslogtreecommitdiffstats
path: root/llvm/lib/AsmParser
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/AsmParser')
-rw-r--r--llvm/lib/AsmParser/LLLexer.cpp3
-rw-r--r--llvm/lib/AsmParser/LLParser.cpp170
-rw-r--r--llvm/lib/AsmParser/LLParser.h2
-rw-r--r--llvm/lib/AsmParser/LLToken.h3
4 files changed, 174 insertions, 4 deletions
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 1f34025b660..0b553bf991d 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -752,6 +752,8 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(critical);
KEYWORD(relbf);
KEYWORD(variable);
+ KEYWORD(vTableFuncs);
+ KEYWORD(virtFunc);
KEYWORD(aliasee);
KEYWORD(refs);
KEYWORD(typeIdInfo);
@@ -764,6 +766,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(offset);
KEYWORD(args);
KEYWORD(typeid);
+ KEYWORD(typeidCompatibleVTable);
KEYWORD(summary);
KEYWORD(typeTestRes);
KEYWORD(kind);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 2bd43478506..51fc5b6e1d2 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -832,6 +832,9 @@ bool LLParser::ParseSummaryEntry() {
case lltok::kw_typeid:
result = ParseTypeIdEntry(SummaryID);
break;
+ case lltok::kw_typeidCompatibleVTable:
+ result = ParseTypeIdCompatibleVtableEntry(SummaryID);
+ break;
default:
result = Error(Lex.getLoc(), "unexpected summary kind");
break;
@@ -7486,6 +7489,92 @@ bool LLParser::ParseTypeIdSummary(TypeIdSummary &TIS) {
return false;
}
+static ValueInfo EmptyVI =
+ ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8);
+
+/// TypeIdCompatibleVtableEntry
+/// ::= 'typeidCompatibleVTable' ':' '(' 'name' ':' STRINGCONSTANT ','
+/// TypeIdCompatibleVtableInfo
+/// ')'
+bool LLParser::ParseTypeIdCompatibleVtableEntry(unsigned ID) {
+ assert(Lex.getKind() == lltok::kw_typeidCompatibleVTable);
+ 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;
+
+ TypeIdCompatibleVtableInfo &TI =
+ Index->getOrInsertTypeIdCompatibleVtableSummary(Name);
+ if (ParseToken(lltok::comma, "expected ',' here") ||
+ ParseToken(lltok::kw_summary, "expected 'summary' here") ||
+ ParseToken(lltok::colon, "expected ':' here") ||
+ ParseToken(lltok::lparen, "expected '(' here"))
+ return true;
+
+ IdToIndexMapType IdToIndexMap;
+ // Parse each call edge
+ do {
+ uint64_t Offset;
+ 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"))
+ return true;
+
+ LocTy Loc = Lex.getLoc();
+ unsigned GVId;
+ ValueInfo VI;
+ if (ParseGVReference(VI, GVId))
+ return true;
+
+ // Keep track of the TypeIdCompatibleVtableInfo 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(TI.size(), Loc));
+ TI.push_back({Offset, VI});
+
+ if (ParseToken(lltok::rparen, "expected ')' in call"))
+ return true;
+ } while (EatIfPresent(lltok::comma));
+
+ // Now that the TI 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(TI[P.first].VTableVI == 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(&TI[P.first].VTableVI, P.second));
+ }
+ }
+
+ if (ParseToken(lltok::rparen, "expected ')' here") ||
+ 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;
+}
+
/// TypeTestResolution
/// ::= 'typeTestRes' ':' '(' 'kind' ':'
/// ( 'unsat' | 'byteArray' | 'inline' | 'single' | 'allOnes' ) ','
@@ -7994,6 +8083,7 @@ bool LLParser::ParseVariableSummary(std::string Name, GlobalValue::GUID GUID,
/*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false);
GlobalVarSummary::GVarFlags GVarFlags(/*ReadOnly*/ false);
std::vector<ValueInfo> Refs;
+ VTableFuncList VTableFuncs;
if (ParseToken(lltok::colon, "expected ':' here") ||
ParseToken(lltok::lparen, "expected '(' here") ||
ParseModuleReference(ModulePath) ||
@@ -8002,10 +8092,20 @@ bool LLParser::ParseVariableSummary(std::string Name, GlobalValue::GUID GUID,
ParseGVarFlags(GVarFlags))
return true;
- // Parse optional refs field
- if (EatIfPresent(lltok::comma)) {
- if (ParseOptionalRefs(Refs))
- return true;
+ // Parse optional fields
+ while (EatIfPresent(lltok::comma)) {
+ switch (Lex.getKind()) {
+ case lltok::kw_vTableFuncs:
+ if (ParseOptionalVTableFuncs(VTableFuncs))
+ return true;
+ break;
+ case lltok::kw_refs:
+ if (ParseOptionalRefs(Refs))
+ return true;
+ break;
+ default:
+ return Error(Lex.getLoc(), "expected optional variable summary field");
+ }
}
if (ParseToken(lltok::rparen, "expected ')' here"))
@@ -8015,6 +8115,7 @@ bool LLParser::ParseVariableSummary(std::string Name, GlobalValue::GUID GUID,
llvm::make_unique<GlobalVarSummary>(GVFlags, GVarFlags, std::move(Refs));
GS->setModulePath(ModulePath);
+ GS->setVTableFuncs(std::move(VTableFuncs));
AddGlobalValueToIndex(Name, GUID, (GlobalValue::LinkageTypes)GVFlags.Linkage,
ID, std::move(GS));
@@ -8235,6 +8336,67 @@ bool LLParser::ParseHotness(CalleeInfo::HotnessType &Hotness) {
return false;
}
+/// OptionalVTableFuncs
+/// := 'vTableFuncs' ':' '(' VTableFunc [',' VTableFunc]* ')'
+/// VTableFunc ::= '(' 'virtFunc' ':' GVReference ',' 'offset' ':' UInt64 ')'
+bool LLParser::ParseOptionalVTableFuncs(VTableFuncList &VTableFuncs) {
+ assert(Lex.getKind() == lltok::kw_vTableFuncs);
+ Lex.Lex();
+
+ if (ParseToken(lltok::colon, "expected ':' in vTableFuncs") |
+ ParseToken(lltok::lparen, "expected '(' in vTableFuncs"))
+ return true;
+
+ IdToIndexMapType IdToIndexMap;
+ // Parse each virtual function pair
+ do {
+ ValueInfo VI;
+ if (ParseToken(lltok::lparen, "expected '(' in vTableFunc") ||
+ ParseToken(lltok::kw_virtFunc, "expected 'callee' in vTableFunc") ||
+ ParseToken(lltok::colon, "expected ':'"))
+ return true;
+
+ LocTy Loc = Lex.getLoc();
+ unsigned GVId;
+ if (ParseGVReference(VI, GVId))
+ return true;
+
+ uint64_t Offset;
+ if (ParseToken(lltok::comma, "expected comma") ||
+ ParseToken(lltok::kw_offset, "expected offset") ||
+ ParseToken(lltok::colon, "expected ':'") || ParseUInt64(Offset))
+ return true;
+
+ // Keep track of the VTableFuncs 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(VTableFuncs.size(), Loc));
+ VTableFuncs.push_back({VI, Offset});
+
+ if (ParseToken(lltok::rparen, "expected ')' in vTableFunc"))
+ return true;
+ } while (EatIfPresent(lltok::comma));
+
+ // Now that the VTableFuncs 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(VTableFuncs[P.first].FuncVI == 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(&VTableFuncs[P.first].FuncVI, P.second));
+ }
+ }
+
+ if (ParseToken(lltok::rparen, "expected ')' in vTableFuncs"))
+ return true;
+
+ return false;
+}
+
/// OptionalRefs
/// := 'refs' ':' '(' GVReference [',' GVReference]* ')'
bool LLParser::ParseOptionalRefs(std::vector<ValueInfo> &Refs) {
diff --git a/llvm/lib/AsmParser/LLParser.h b/llvm/lib/AsmParser/LLParser.h
index ec4a61b5498..610e2e26200 100644
--- a/llvm/lib/AsmParser/LLParser.h
+++ b/llvm/lib/AsmParser/LLParser.h
@@ -369,9 +369,11 @@ namespace llvm {
IdToIndexMapType &IdToIndexMap, unsigned Index);
bool ParseVFuncId(FunctionSummary::VFuncId &VFuncId,
IdToIndexMapType &IdToIndexMap, unsigned Index);
+ bool ParseOptionalVTableFuncs(VTableFuncList &VTableFuncs);
bool ParseOptionalRefs(std::vector<ValueInfo> &Refs);
bool ParseTypeIdEntry(unsigned ID);
bool ParseTypeIdSummary(TypeIdSummary &TIS);
+ bool ParseTypeIdCompatibleVtableEntry(unsigned ID);
bool ParseTypeTestResolution(TypeTestResolution &TTRes);
bool ParseOptionalWpdResolutions(
std::map<uint64_t, WholeProgramDevirtResolution> &WPDResMap);
diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h
index f276a39037f..acdfaa5ae90 100644
--- a/llvm/lib/AsmParser/LLToken.h
+++ b/llvm/lib/AsmParser/LLToken.h
@@ -383,6 +383,8 @@ enum Kind {
kw_critical,
kw_relbf,
kw_variable,
+ kw_vTableFuncs,
+ kw_virtFunc,
kw_aliasee,
kw_refs,
kw_typeIdInfo,
@@ -395,6 +397,7 @@ enum Kind {
kw_offset,
kw_args,
kw_typeid,
+ kw_typeidCompatibleVTable,
kw_summary,
kw_typeTestRes,
kw_kind,
OpenPOWER on IntegriCloud