diff options
Diffstat (limited to 'llvm/lib/AsmParser')
-rw-r--r-- | llvm/lib/AsmParser/LLLexer.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLParser.cpp | 170 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLParser.h | 2 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLToken.h | 3 |
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, |