[ThinLTO] Parse module summary index from assembly

Summary:
Adds assembly parsing support for the module summary index (follow on
to r333335 which added the assembly writing support).

I added support to llvm-as to invoke the index parsing, so that it can
create either a bitcode file with a Module and a per-module index, or
a combined index without a Module.

I will send follow on patches soon to do the following:
- add support to tools such as llvm-lto2 to parse the per-module indexes
from assembly instead of bitcode when testing the thin link.
- verification support.

Depends on D47844 and D47842.

Reviewers: pcc, dexonsmith, mehdi_amini

Subscribers: inglorion, eraman, steven_wu, llvm-commits

Differential Revision: https://reviews.llvm.org/D47905

llvm-svn: 335602
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 0d478d4..599b59b 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -71,8 +71,8 @@
         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 @@
 /// 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 @@
   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");
@@ -341,12 +386,12 @@
 ///   ::= '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;
 }
 
@@ -721,8 +766,12 @@
   // 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 (ParseToken(lltok::LabelStr,
-                 "expected 'label' at start of summary entry") ||
+  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
@@ -747,20 +796,36 @@
   return false;
 }
 
-/// ParseSummaryEntry:
-///   ::= SummaryID '=' ...
+/// SummaryEntry
+///   ::= SummaryID '=' GVEntry | ModuleEntry | TypeIdEntry
 bool LLParser::ParseSummaryEntry() {
   assert(Lex.getKind() == lltok::SummaryID);
-  // unsigned SummaryID = Lex.getUIntVal();
+  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;
 
-  // TODO: Support parsing into a ModuleSummaryIndex object saved in
-  // the LLParser. For now, skip the summary entry.
-  if (SkipModuleSummaryEntry())
-    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;
 }
 
@@ -6922,3 +6987,1170 @@
 
   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;
+}