diff options
Diffstat (limited to 'lib/AsmParser/LLParser.cpp')
| -rw-r--r-- | lib/AsmParser/LLParser.cpp | 1596 | 
1 files changed, 1535 insertions, 61 deletions
| diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index c3ab95550e03..599b59bf61e8 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/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; +} | 
