//===--- ParseSIL.cpp - SIL File Parsing logic ----------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "SILParserFunctionBuilder.h"
#include "SILParserState.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/NameLookupRequests.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/SILGenRequests.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/Basic/Defer.h"
#include "swift/Demangling/Demangle.h"
#include "swift/Parse/Lexer.h"
#include "swift/Parse/ParseSILSupport.h"
#include "swift/Parse/Parser.h"
#include "swift/SIL/AbstractionPattern.h"
#include "swift/SIL/InstructionUtils.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILUndef.h"
#include "swift/SIL/TypeLowering.h"
#include "swift/Subsystems.h"
#include "swift/Syntax/SyntaxKind.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/SaveAndRestore.h"

using namespace swift;
using namespace swift::syntax;

//===----------------------------------------------------------------------===//
// SILParserState implementation
//===----------------------------------------------------------------------===//

SILParserState::~SILParserState() {
  if (!ForwardRefFns.empty()) {
    for (auto Entry : ForwardRefFns) {
      if (Entry.second.Loc.isValid()) {
        M.getASTContext().Diags.diagnose(Entry.second.Loc,
                                         diag::sil_use_of_undefined_value,
                                         Entry.first.str());
      }
    }
  }

  // Turn any debug-info-only function declarations into zombies.
  for (auto *Fn : PotentialZombieFns)
    if (Fn->isExternalDeclaration()) {
      Fn->setInlined();
      M.eraseFunction(Fn);
    }
}

std::unique_ptr<SILModule>
ParseSILModuleRequest::evaluate(Evaluator &evaluator,
                                ASTLoweringDescriptor desc) const {
  auto *SF = desc.getSourceFileToParse();
  assert(SF);

  auto bufferID = SF->getBufferID();
  assert(bufferID);

  auto silMod = SILModule::createEmptyModule(desc.context, desc.conv,
                                             desc.opts);
  SILParserState parserState(*silMod.get());
  Parser parser(*bufferID, *SF, &parserState);
  PrettyStackTraceParser StackTrace(parser);

  auto hadError = parser.parseTopLevelSIL();
  if (hadError) {
    // The rest of the SIL pipeline expects well-formed SIL, so if we encounter
    // a parsing error, just return an empty SIL module.
    //
    // Because the SIL parser's notion of failing with an error is distinct from
    // the ASTContext's notion of having emitted a diagnostic, it's possible for
    // the parser to fail silently without emitting a diagnostic. This assertion
    // ensures that +asserts builds will fail fast. If you crash here, please go
    // back and add a diagnostic after identifying where the SIL parser failed.
    assert(SF->getASTContext().hadError() &&
           "Failed to parse SIL but did not emit any errors!");
    return SILModule::createEmptyModule(desc.context, desc.conv, desc.opts);
  }
  return silMod;
}

//===----------------------------------------------------------------------===//
// SILParser
//===----------------------------------------------------------------------===//

namespace {
  struct ParsedSubstitution {
    SourceLoc loc;
    Type replacement;
  };

  struct ParsedSpecAttr {
    ArrayRef<RequirementRepr> requirements;
    bool exported;
    SILSpecializeAttr::SpecializationKind kind;
    SILFunction *target = nullptr;
    Identifier spiGroupID;
    ModuleDecl *spiModule;
  };

  class SILParser {
    friend SILParserState;
  public:
    Parser &P;
    SILModule &SILMod;
    SILParserState &TUState;
    SILFunction *F = nullptr;
    GenericEnvironment *ContextGenericEnv = nullptr;
    GenericParamList *ContextGenericParams = nullptr;

  private:
    /// HadError - Have we seen an error parsing this function?
    bool HadError = false;

    /// Data structures used to perform name lookup of basic blocks.
    llvm::DenseMap<Identifier, SILBasicBlock*> BlocksByName;
    llvm::DenseMap<SILBasicBlock*,
                   Located<Identifier>> UndefinedBlocks;

    /// Data structures used to perform name lookup for local values.
    llvm::StringMap<ValueBase*> LocalValues;
    llvm::StringMap<SourceLoc> ForwardRefLocalValues;

    /// A callback to be invoked every time a type was deserialized.
    std::function<void(Type)> ParsedTypeCallback;

    Type performTypeResolution(TypeRepr *TyR, bool IsSILType,
                               GenericEnvironment *GenericEnv,
                               GenericParamList *GenericParams);

    void convertRequirements(ArrayRef<RequirementRepr> From,
                             SmallVectorImpl<Requirement> &To);

    ProtocolConformanceRef parseProtocolConformanceHelper(
        ProtocolDecl *&proto,
        GenericEnvironment *GenericEnv,
        GenericParamList *WitnessParams);

  public:
    SILParser(Parser &P)
        : P(P), SILMod(static_cast<SILParserState *>(P.SIL)->M),
          TUState(*static_cast<SILParserState *>(P.SIL)),
          ParsedTypeCallback([](Type ty) {}) {}

    ~SILParser();

    /// diagnoseProblems - After a function is fully parse, emit any diagnostics
    /// for errors and return true if there were any.
    bool diagnoseProblems();

    /// getGlobalNameForReference - Given a reference to a global name, look it
    /// up and return an appropriate SIL function.
    SILFunction *getGlobalNameForReference(Identifier Name,
                                           CanSILFunctionType Ty,
                                           SourceLoc Loc,
                                           bool IgnoreFwdRef = false);
    /// getGlobalNameForDefinition - Given a definition of a global name, look
    /// it up and return an appropriate SIL function.
    SILFunction *getGlobalNameForDefinition(Identifier Name,
                                            CanSILFunctionType Ty,
                                            SourceLoc Loc);

    /// getBBForDefinition - Return the SILBasicBlock for a definition of the
    /// specified block.
    SILBasicBlock *getBBForDefinition(Identifier Name, SourceLoc Loc);
    
    /// getBBForReference - return the SILBasicBlock of the specified name.  The
    /// source location is used to diagnose a failure if the block ends up never
    /// being defined.
    SILBasicBlock *getBBForReference(Identifier Name, SourceLoc Loc);

    struct UnresolvedValueName {
      StringRef Name;
      SourceLoc NameLoc;

      bool isUndef() const { return Name == "undef"; }
    };

    /// getLocalValue - Get a reference to a local value with the specified name
    /// and type.
    SILValue getLocalValue(UnresolvedValueName Name, SILType Type,
                           SILLocation L, SILBuilder &B);

    /// setLocalValue - When an instruction or block argument is defined, this
    /// method is used to register it and update our symbol table.
    void setLocalValue(ValueBase *Value, StringRef Name, SourceLoc NameLoc);

    SILDebugLocation getDebugLoc(SILBuilder & B, SILLocation Loc) {
      return SILDebugLocation(Loc, F->getDebugScope());
    }

    /// @{ Primitive parsing.

    /// \verbatim
    ///   sil-identifier ::= [A-Za-z_0-9]+
    /// \endverbatim
    bool parseSILIdentifier(Identifier &Result, SourceLoc &Loc,
                            const Diagnostic &D);

    template<typename ...DiagArgTypes, typename ...ArgTypes>
    bool parseSILIdentifier(Identifier &Result, Diag<DiagArgTypes...> ID,
                            ArgTypes... Args) {
      SourceLoc L;
      return parseSILIdentifier(Result, L, Diagnostic(ID, Args...));
    }

    template <typename T, typename... DiagArgTypes, typename... ArgTypes>
    bool parseSILIdentifierSwitch(T &Result, ArrayRef<StringRef> Strings,
                                  Diag<DiagArgTypes...> ID, ArgTypes... Args) {
      Identifier TmpResult;
      SourceLoc L;
      if (parseSILIdentifier(TmpResult, L, Diagnostic(ID, Args...))) {
        return true;
      }

      auto Iter = std::find(Strings.begin(), Strings.end(), TmpResult.str());
      if (Iter == Strings.end()) {
        P.diagnose(P.Tok, Diagnostic(ID, Args...));
        return true;
      }

      Result = T(*Iter);
      return false;
    }

    template<typename ...DiagArgTypes, typename ...ArgTypes>
    bool parseSILIdentifier(Identifier &Result, SourceLoc &L,
                            Diag<DiagArgTypes...> ID, ArgTypes... Args) {
      return parseSILIdentifier(Result, L, Diagnostic(ID, Args...));
    }

    bool parseVerbatim(StringRef identifier);

    template <typename T>
    bool parseInteger(T &Result, const Diagnostic &D) {
      if (!P.Tok.is(tok::integer_literal)) {
        P.diagnose(P.Tok, D);
        return true;
      }
      bool error = parseIntegerLiteral(P.Tok.getText(), 0, Result);
      P.consumeToken(tok::integer_literal);
      return error;
    }

    template <typename T>
    bool parseIntegerLiteral(StringRef text, unsigned radix, T &result) {
      text = prepareIntegerLiteralForParsing(text);
      return text.getAsInteger(radix, result);
    }

    StringRef prepareIntegerLiteralForParsing(StringRef text) {
      // tok::integer_literal can contain characters that the library
      // parsing routines don't expect.
      if (text.contains('_'))
        text = P.copyAndStripUnderscores(text);
      return text;
    }

    /// @}

    /// @{ Type parsing.
    bool parseASTType(CanType &result,
                      GenericEnvironment *genericEnv=nullptr,
                      GenericParamList *genericParams=nullptr);
    bool parseASTType(CanType &result,
                      SourceLoc &TypeLoc,
                      GenericEnvironment *genericEnv=nullptr,
                      GenericParamList *genericParams=nullptr) {
      TypeLoc = P.Tok.getLoc();
      return parseASTType(result, genericEnv, genericParams);
    }
    bool parseSILOwnership(ValueOwnershipKind &OwnershipKind) {
      // We parse here @ <identifier>.
      if (!P.consumeIf(tok::at_sign)) {
        // If we fail, we must have @any ownership. We check elsewhere in the
        // parser that this matches what the function signature wants.
        OwnershipKind = OwnershipKind::None;
        return false;
      }

      StringRef AllOwnershipKinds[3] = {"unowned", "owned",
                                        "guaranteed"};
      return parseSILIdentifierSwitch(OwnershipKind, AllOwnershipKinds,
                                      diag::expected_sil_value_ownership_kind);
    }
    void bindSILGenericParams(TypeRepr *TyR);
    bool parseSILType(SILType &Result,
                      GenericEnvironment *&parsedGenericEnv,
                      GenericParamList *&parsedGenericParams,
                      bool IsFuncDecl=false,
                      GenericEnvironment *parentGenericEnv=nullptr,
                      GenericParamList *parentGenericParams=nullptr);
    bool parseSILType(SILType &Result) {
      GenericEnvironment *IgnoredEnv = nullptr;
      GenericParamList *IgnoredParams = nullptr;
      return parseSILType(Result, IgnoredEnv, IgnoredParams);
    }
    bool parseSILType(SILType &Result, SourceLoc &TypeLoc) {
      TypeLoc = P.Tok.getLoc();
      return parseSILType(Result);
    }
    bool parseSILType(SILType &Result, SourceLoc &TypeLoc,
                      GenericEnvironment *&parsedGenericEnv,
                      GenericParamList *&parsedGenericParams,
                      GenericEnvironment *parentGenericEnv = nullptr,
                      GenericParamList *parentGenericParams = nullptr) {
      TypeLoc = P.Tok.getLoc();
      return parseSILType(Result, parsedGenericEnv, parsedGenericParams,
                          false, parentGenericEnv, parentGenericParams);
    }
    /// @}

    bool parseSILDottedPath(ValueDecl *&Decl,
                            SmallVectorImpl<ValueDecl *> &values);
    bool parseSILDottedPath(ValueDecl *&Decl) {
      SmallVector<ValueDecl *, 4> values;
      return parseSILDottedPath(Decl, values);
    }
    bool parseSILDottedPathWithoutPound(ValueDecl *&Decl,
                                        SmallVectorImpl<ValueDecl *> &values);
    bool parseSILDottedPathWithoutPound(ValueDecl *&Decl) {
      SmallVector<ValueDecl *, 4> values;
      return parseSILDottedPathWithoutPound(Decl, values);
    }
    /// At the time of calling this function, we may not have the type of the
    /// Decl yet. So we return a SILDeclRef on the first lookup result and also
    /// return all the lookup results. After parsing the expected type, the
    /// caller of this function can choose the one that has the expected type.
    bool parseSILDeclRef(SILDeclRef &Result,
                         SmallVectorImpl<ValueDecl *> &values);
    bool parseSILDeclRef(SILDeclRef &Result) {
      SmallVector<ValueDecl *, 4> values;
      return parseSILDeclRef(Result, values);
    }
    bool parseSILDeclRef(SILDeclRef &Member, bool FnTypeRequired);
    bool parseGlobalName(Identifier &Name);
    bool parseValueName(UnresolvedValueName &Name);
    bool parseValueRef(SILValue &Result, SILType Ty, SILLocation Loc,
                       SILBuilder &B);
    bool parseTypedValueRef(SILValue &Result, SourceLoc &Loc, SILBuilder &B);
    bool parseTypedValueRef(SILValue &Result, SILBuilder &B) {
      SourceLoc Tmp;
      return parseTypedValueRef(Result, Tmp, B);
    }
    bool parseSILOpcode(SILInstructionKind &Opcode, SourceLoc &OpcodeLoc,
                        StringRef &OpcodeName);
    bool parseSILDebugVar(SILDebugVariable &Var);

    /// Parses the basic block arguments as part of branch instruction.
    bool parseSILBBArgsAtBranch(SmallVector<SILValue, 6> &Args, SILBuilder &B);

    bool parseSILLocation(SILLocation &L);
    bool parseScopeRef(SILDebugScope *&DS);
    bool parseSILDebugLocation(SILLocation &L, SILBuilder &B,
                               bool parsedComma = false);
    bool parseSpecificSILInstruction(SILBuilder &B, SILInstructionKind Opcode,
                                     SourceLoc OpcodeLoc, StringRef OpcodeName,
                                     SILInstruction *&ResultVal);

    bool parseSILInstruction(SILBuilder &B);
    bool parseCallInstruction(SILLocation InstLoc,
                              SILInstructionKind Opcode, SILBuilder &B,
                              SILInstruction *&ResultVal);
    bool parseSILFunctionRef(SILLocation InstLoc, SILFunction *&ResultFn);

    bool parseSILBasicBlock(SILBuilder &B);
    bool parseKeyPathPatternComponent(KeyPathPatternComponent &component,
                                      SmallVectorImpl<SILType> &operandTypes,
                                      SourceLoc componentLoc,
                                      Identifier componentKind,
                                      SILLocation InstLoc,
                                      GenericEnvironment *patternEnv,
                                      GenericParamList *patternParams);
    bool isStartOfSILInstruction();

    bool parseSubstitutions(SmallVectorImpl<ParsedSubstitution> &parsed,
                            GenericEnvironment *GenericEnv=nullptr,
                            GenericParamList *GenericParams=nullptr);

    ProtocolConformanceRef parseProtocolConformance(
        ProtocolDecl *&proto,
        GenericEnvironment *&genericEnv,
        GenericParamList *&genericParams);
    ProtocolConformanceRef
    parseProtocolConformance() {
      ProtocolDecl *dummy = nullptr;
      GenericEnvironment *genericEnv = nullptr;
      GenericParamList *genericParams = nullptr;
      return parseProtocolConformance(dummy, genericEnv, genericParams);
    }

    Optional<llvm::coverage::Counter>
    parseSILCoverageExpr(llvm::coverage::CounterExpressionBuilder &Builder);

    template <class T>
    struct ParsedEnum {
      Optional<T> Value;
      StringRef Name;
      SourceLoc Loc;

      bool isSet() const { return Value.hasValue(); }
      T operator*() const { return *Value; }
    };

    template <class T>
    void setEnum(ParsedEnum<T> &existing,
                 T value, StringRef name, SourceLoc loc) {
      if (existing.Value) {
        if (*existing.Value == value) {
          P.diagnose(loc, diag::duplicate_attribute, /*modifier*/ 1);
        } else {
          P.diagnose(loc, diag::mutually_exclusive_attrs, name,
                     existing.Name, /*modifier*/ 1);
        }
        P.diagnose(existing.Loc, diag::previous_attribute, /*modifier*/ 1);
      }
      existing.Value = value;
      existing.Name = name;
      existing.Loc = loc;
    }

    template <class T>
    void maybeSetEnum(bool allowed, ParsedEnum<T> &existing,
                      T value, StringRef name, SourceLoc loc) {
      if (allowed)
        setEnum(existing, value, name, loc);
      else
        P.diagnose(loc, diag::unknown_attribute, name);
    }
  };
} // end anonymous namespace

bool SILParser::parseSILIdentifier(Identifier &Result, SourceLoc &Loc,
                                   const Diagnostic &D) {
  switch (P.Tok.getKind()) {
  case tok::identifier:
  case tok::dollarident:
    Result = P.Context.getIdentifier(P.Tok.getText());
    break;
  case tok::string_literal: {
    // Drop the double quotes.
    StringRef rawString = P.Tok.getText().drop_front().drop_back();
    Result = P.Context.getIdentifier(rawString);
    break;
  }
  case tok::oper_binary_unspaced:  // fixme?
  case tok::oper_binary_spaced:
  case tok::kw_init:
    // A binary operator or `init` can be part of a SILDeclRef.
    Result = P.Context.getIdentifier(P.Tok.getText());
    break;
  default:
    // If it's some other keyword, grab an identifier for it.
    if (P.Tok.isKeyword()) {
      Result = P.Context.getIdentifier(P.Tok.getText());
      break;
    }
    P.diagnose(P.Tok, D);
    return true;
  }

  Loc = P.Tok.getLoc();
  P.consumeToken();
  return false;
}

bool SILParser::parseVerbatim(StringRef name) {
  Identifier tok;
  SourceLoc loc;

  if (parseSILIdentifier(tok, loc, diag::expected_tok_in_sil_instr, name)) {
    return true;
  }
  if (tok.str() != name) {
    P.diagnose(loc, diag::expected_tok_in_sil_instr, name);
    return true;
  }
  return false;
}

SILParser::~SILParser() {
  for (auto &Entry : ForwardRefLocalValues) {
    if (ValueBase *dummyVal = LocalValues[Entry.first()]) {
      dummyVal->replaceAllUsesWith(SILUndef::get(dummyVal->getType(), SILMod));
      SILInstruction::destroy(cast<GlobalAddrInst>(dummyVal));
      SILMod.deallocateInst(cast<GlobalAddrInst>(dummyVal));
    }
  }
}


/// diagnoseProblems - After a function is fully parse, emit any diagnostics
/// for errors and return true if there were any.
bool SILParser::diagnoseProblems() {
  // Check for any uses of basic blocks that were not defined.
  if (!UndefinedBlocks.empty()) {
    // FIXME: These are going to come out in nondeterministic order.
    for (auto Entry : UndefinedBlocks)
      P.diagnose(Entry.second.Loc, diag::sil_undefined_basicblock_use,
                 Entry.second.Item);

    HadError = true;
  }
  
  if (!ForwardRefLocalValues.empty()) {
    // FIXME: These are going to come out in nondeterministic order.
    for (auto &Entry : ForwardRefLocalValues)
      P.diagnose(Entry.second, diag::sil_use_of_undefined_value,
                 Entry.first());
    HadError = true;
  }
  
  return HadError;
}

/// getGlobalNameForDefinition - Given a definition of a global name, look
/// it up and return an appropriate SIL function.
SILFunction *SILParser::getGlobalNameForDefinition(Identifier name,
                                                   CanSILFunctionType ty,
                                                   SourceLoc sourceLoc) {
  SILParserFunctionBuilder builder(SILMod);
  auto silLoc = RegularLocation(sourceLoc);

  // Check to see if a function of this name has been forward referenced.  If so
  // complete the forward reference.
  auto iter = TUState.ForwardRefFns.find(name);
  if (iter != TUState.ForwardRefFns.end()) {
    SILFunction *fn = iter->second.Item;

    // Verify that the types match up.
    if (fn->getLoweredFunctionType() != ty) {
      P.diagnose(sourceLoc, diag::sil_value_use_type_mismatch, name.str(),
                 fn->getLoweredFunctionType(), ty);
      P.diagnose(iter->second.Loc, diag::sil_prior_reference);
      fn = builder.createFunctionForForwardReference("" /*name*/, ty, silLoc);
    }

    assert(fn->isExternalDeclaration() && "Forward defns cannot have bodies!");
    TUState.ForwardRefFns.erase(iter);

    // Move the function to this position in the module.
    //
    // FIXME: Should we move this functionality into SILParserFunctionBuilder?
    SILMod.getFunctionList().remove(fn);
    SILMod.getFunctionList().push_back(fn);

    return fn;
  }

  // If we don't have a forward reference, make sure the function hasn't been
  // defined already.
  if (SILMod.lookUpFunction(name.str()) != nullptr) {
    P.diagnose(sourceLoc, diag::sil_value_redefinition, name.str());
    return builder.createFunctionForForwardReference("" /*name*/, ty, silLoc);
  }

  // Otherwise, this definition is the first use of this name.
  return builder.createFunctionForForwardReference(name.str(), ty, silLoc);
}

/// getGlobalNameForReference - Given a reference to a global name, look it
/// up and return an appropriate SIL function.
SILFunction *SILParser::getGlobalNameForReference(Identifier name,
                                                  CanSILFunctionType funcTy,
                                                  SourceLoc sourceLoc,
                                                  bool ignoreFwdRef) {
  SILParserFunctionBuilder builder(SILMod);
  auto silLoc = RegularLocation(sourceLoc);

  // Check to see if we have a function by this name already.
  if (SILFunction *fn = SILMod.lookUpFunction(name.str())) {
    // If so, check for matching types.
    if (fn->getLoweredFunctionType() == funcTy) {
      return fn;
    }

    P.diagnose(sourceLoc, diag::sil_value_use_type_mismatch, name.str(),
               fn->getLoweredFunctionType(), funcTy);

    return builder.createFunctionForForwardReference("" /*name*/, funcTy,
                                                     silLoc);
  }
  
  // If we didn't find a function, create a new one - it must be a forward
  // reference.
  auto *fn =
      builder.createFunctionForForwardReference(name.str(), funcTy, silLoc);
  TUState.ForwardRefFns[name] = {fn, ignoreFwdRef ? SourceLoc() : sourceLoc};
  return fn;
}

/// getBBForDefinition - Return the SILBasicBlock for a definition of the
/// specified block.
SILBasicBlock *SILParser::getBBForDefinition(Identifier Name, SourceLoc Loc) {
  // If there was no name specified for this block, just create a new one.
  if (Name.empty())
    return F->createBasicBlock();

  SILBasicBlock *&BB = BlocksByName[Name];
  // If the block has never been named yet, just create it.
  if (BB == nullptr)
    return BB = F->createBasicBlock();

  // If it already exists, it was either a forward reference or a redefinition.
  // If it is a forward reference, it should be in our undefined set.
  if (!UndefinedBlocks.erase(BB)) {
    // If we have a redefinition, return a new BB to avoid inserting
    // instructions after the terminator.
    P.diagnose(Loc, diag::sil_basicblock_redefinition, Name);
    HadError = true;
    return F->createBasicBlock();
  }

  // FIXME: Splice the block to the end of the function so they come out in the
  // right order.
  return BB;
}

/// getBBForReference - return the SILBasicBlock of the specified name.  The
/// source location is used to diagnose a failure if the block ends up never
/// being defined.
SILBasicBlock *SILParser::getBBForReference(Identifier Name, SourceLoc Loc) {
  // If the block has already been created, use it.
  SILBasicBlock *&BB = BlocksByName[Name];
  if (BB != nullptr)
    return BB;

  // Otherwise, create it and remember that this is a forward reference so
  // that we can diagnose use without definition problems.
  BB = F->createBasicBlock();
  UndefinedBlocks[BB] = {Name, Loc};
  return BB;
}

///   sil-global-name:
///     '@' identifier
bool SILParser::parseGlobalName(Identifier &Name) {
  return P.parseToken(tok::at_sign, diag::expected_sil_value_name) ||
         parseSILIdentifier(Name, diag::expected_sil_value_name);
}

/// getLocalValue - Get a reference to a local value with the specified name
/// and type.
SILValue SILParser::getLocalValue(UnresolvedValueName Name, SILType Type,
                                  SILLocation Loc, SILBuilder &B) {
  if (Name.isUndef())
    return SILUndef::get(Type, B.getFunction());

  // Check to see if this is already defined.
  ValueBase *&Entry = LocalValues[Name.Name];

  if (Entry) {
    // If this value is already defined, check it to make sure types match.
    SILType EntryTy = Entry->getType();

    if (EntryTy != Type) {
      HadError = true;
      P.diagnose(Name.NameLoc, diag::sil_value_use_type_mismatch, Name.Name,
                 EntryTy.getASTType(), Type.getASTType());
      // Make sure to return something of the requested type.
      return SILUndef::get(Type, B.getFunction());
    }

    return SILValue(Entry);
  }
  
  // Otherwise, this is a forward reference.  Create a dummy node to represent
  // it until we see a real definition.
  ForwardRefLocalValues[Name.Name] = Name.NameLoc;

  Entry = new (SILMod) GlobalAddrInst(getDebugLoc(B, Loc), Type);
  return Entry;
}

/// setLocalValue - When an instruction or block argument is defined, this
/// method is used to register it and update our symbol table.
void SILParser::setLocalValue(ValueBase *Value, StringRef Name,
                              SourceLoc NameLoc) {
  ValueBase *&Entry = LocalValues[Name];

  // If this value was already defined, it is either a redefinition, or a
  // specification for a forward referenced value.
  if (Entry) {
    if (!ForwardRefLocalValues.erase(Name)) {
      P.diagnose(NameLoc, diag::sil_value_redefinition, Name);
      HadError = true;
      return;
    }

    // If the forward reference was of the wrong type, diagnose this now.
    if (Entry->getType() != Value->getType()) {
      P.diagnose(NameLoc, diag::sil_value_def_type_mismatch, Name,
                 Entry->getType().getASTType(),
                 Value->getType().getASTType());
      HadError = true;
    } else {
      // Forward references only live here if they have a single result.
      Entry->replaceAllUsesWith(Value);
      SILInstruction::destroy(cast<GlobalAddrInst>(Entry));
      SILMod.deallocateInst(cast<GlobalAddrInst>(Entry));
    }
    Entry = Value;
    return;
  }

  // Otherwise, just store it in our map.
  Entry = Value;
}


//===----------------------------------------------------------------------===//
// SIL Parsing Logic
//===----------------------------------------------------------------------===//

/// parseSILLinkage - Parse a linkage specifier if present.
///   sil-linkage:
///     /*empty*/          // default depends on whether this is a definition
///     'public'
///     'hidden'
///     'shared'
///     'private'
///     'public_external'
///     'hidden_external'
///     'private_external'
static bool parseSILLinkage(Optional<SILLinkage> &Result, Parser &P) {
  // Begin by initializing result to our base value of None.
  Result = None;

  // Unfortunate collision with access control keywords.
  if (P.Tok.is(tok::kw_public)) {
    Result = SILLinkage::Public;
    P.consumeToken();
    return false;
  }

  // Unfortunate collision with access control keywords.
  if (P.Tok.is(tok::kw_private)) {
    Result = SILLinkage::Private;
    P.consumeToken();
    return false;
  }

  // If we do not have an identifier, bail. All SILLinkages that we are parsing
  // are identifiers.
  if (P.Tok.isNot(tok::identifier))
    return false;

  // Then use a string switch to try and parse the identifier.
  Result = llvm::StringSwitch<Optional<SILLinkage>>(P.Tok.getText())
    .Case("non_abi", SILLinkage::PublicNonABI)
    .Case("hidden", SILLinkage::Hidden)
    .Case("shared", SILLinkage::Shared)
    .Case("public_external", SILLinkage::PublicExternal)
    .Case("hidden_external", SILLinkage::HiddenExternal)
    .Case("shared_external", SILLinkage::SharedExternal)
    .Case("private_external", SILLinkage::PrivateExternal)
    .Default(None);

  // If we succeed, consume the token.
  if (Result) {
    P.consumeToken(tok::identifier);
  }

  return false;
}

/// Given whether it's known to be a definition, resolve an optional
/// SIL linkage to a real one.
static SILLinkage resolveSILLinkage(Optional<SILLinkage> linkage,
                                    bool isDefinition) {
  if (linkage.hasValue()) {
    return linkage.getValue();
  } else if (isDefinition) {
    return SILLinkage::DefaultForDefinition;
  } else {
    return SILLinkage::DefaultForDeclaration;
  }
}

static bool parseSILOptional(StringRef &Result, SourceLoc &Loc, SILParser &SP) {
  if (SP.P.consumeIf(tok::l_square)) {
    Identifier Id;
    SP.parseSILIdentifier(Id, Loc, diag::expected_in_attribute_list);
    SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
    Result = Id.str();
    return true;
  }
  return false;
}

static bool parseSILOptional(StringRef &Result, SILParser &SP) {
  SourceLoc Loc;
  return parseSILOptional(Result, Loc, SP);
}

/// Parse an option attribute ('[' Expected ']')?
static bool parseSILOptional(bool &Result, SILParser &SP, StringRef Expected) {
  StringRef Optional;
  if (parseSILOptional(Optional, SP)) {
    if (Optional != Expected)
      return true;
    Result = true;
  }
  return false;
}

/// Remap RequirementReps to Requirements.
void SILParser::convertRequirements(ArrayRef<RequirementRepr> From,
                                    SmallVectorImpl<Requirement> &To) {
  if (From.empty()) {
    To.clear();
    return;
  }

  // Use parser lexical scopes to resolve references
  // to the generic parameters.
  auto ResolveToInterfaceType = [&](TypeRepr *TyR) -> Type {
    return performTypeResolution(TyR, /*IsSILType=*/false,
                                 ContextGenericEnv, ContextGenericParams)
        ->mapTypeOutOfContext();
  };

  for (auto &Req : From) {
    if (Req.getKind() == RequirementReprKind::SameType) {
      auto FirstType = ResolveToInterfaceType(Req.getFirstTypeRepr());
      auto SecondType = ResolveToInterfaceType(Req.getSecondTypeRepr());
      Requirement ConvertedRequirement(RequirementKind::SameType, FirstType,
                                       SecondType);
      To.push_back(ConvertedRequirement);
      continue;
    }

    if (Req.getKind() == RequirementReprKind::TypeConstraint) {
      auto Subject = ResolveToInterfaceType(Req.getSubjectRepr());
      auto Constraint = ResolveToInterfaceType(Req.getConstraintRepr());
      Requirement ConvertedRequirement(RequirementKind::Conformance, Subject,
                                       Constraint);
      To.push_back(ConvertedRequirement);
      continue;
    }

    if (Req.getKind() == RequirementReprKind::LayoutConstraint) {
      auto Subject = ResolveToInterfaceType(Req.getSubjectRepr());
      Requirement ConvertedRequirement(RequirementKind::Layout, Subject,
                                       Req.getLayoutConstraint());
      To.push_back(ConvertedRequirement);
      continue;
    }
    llvm_unreachable("Unsupported requirement kind");
  }
}

static bool parseDeclSILOptional(bool *isTransparent,
                                 IsSerialized_t *isSerialized,
                                 bool *isCanonical,
                                 bool *hasOwnershipSSA,
                                 IsThunk_t *isThunk,
                                 IsDynamicallyReplaceable_t *isDynamic,
                                 IsExactSelfClass_t *isExactSelfClass,
                                 SILFunction **dynamicallyReplacedFunction,
                                 Identifier *objCReplacementFor,
                                 SILFunction::Purpose *specialPurpose,
                                 Inline_t *inlineStrategy,
                                 OptimizationMode *optimizationMode,
                                 bool *isLet,
                                 bool *isWeakImported,
                                 AvailabilityContext *availability,
                                 bool *isWithoutActuallyEscapingThunk,
                                 SmallVectorImpl<std::string> *Semantics,
                                 SmallVectorImpl<ParsedSpecAttr> *SpecAttrs,
                                 ValueDecl **ClangDecl,
                                 EffectsKind *MRK, SILParser &SP,
                                 SILModule &M) {
  while (SP.P.consumeIf(tok::l_square)) {
    if (isLet && SP.P.Tok.is(tok::kw_let)) {
      *isLet = true;
      SP.P.consumeToken(tok::kw_let);
      SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
      continue;
    }
    else if (SP.P.Tok.isNot(tok::identifier)) {
      SP.P.diagnose(SP.P.Tok, diag::expected_in_attribute_list);
      return true;
    } else if (isTransparent && SP.P.Tok.getText() == "transparent")
      *isTransparent = true;
    else if (isSerialized && SP.P.Tok.getText() == "serialized")
      *isSerialized = IsSerialized;
    else if (isDynamic && SP.P.Tok.getText() == "dynamically_replacable")
      *isDynamic = IsDynamic;
    else if (isExactSelfClass && SP.P.Tok.getText() == "exact_self_class")
      *isExactSelfClass = IsExactSelfClass;
    else if (isSerialized && SP.P.Tok.getText() == "serializable")
      *isSerialized = IsSerializable;
    else if (isCanonical && SP.P.Tok.getText() == "canonical")
      *isCanonical = true;
    else if (hasOwnershipSSA && SP.P.Tok.getText() == "ossa")
      *hasOwnershipSSA = true;
    else if (isThunk && SP.P.Tok.getText() == "thunk")
      *isThunk = IsThunk;
    else if (isThunk && SP.P.Tok.getText() == "signature_optimized_thunk")
      *isThunk = IsSignatureOptimizedThunk;
    else if (isThunk && SP.P.Tok.getText() == "reabstraction_thunk")
      *isThunk = IsReabstractionThunk;
    else if (isWithoutActuallyEscapingThunk
             && SP.P.Tok.getText() == "without_actually_escaping")
      *isWithoutActuallyEscapingThunk = true;
    else if (specialPurpose && SP.P.Tok.getText() == "global_init")
      *specialPurpose = SILFunction::Purpose::GlobalInit;
    else if (specialPurpose && SP.P.Tok.getText() == "lazy_getter")
      *specialPurpose = SILFunction::Purpose::LazyPropertyGetter;
    else if (specialPurpose && SP.P.Tok.getText() == "global_init_once_fn")
      *specialPurpose = SILFunction::Purpose::GlobalInitOnceFunction;
    else if (isWeakImported && SP.P.Tok.getText() == "weak_imported") {
      if (M.getASTContext().LangOpts.Target.isOSBinFormatCOFF())
        SP.P.diagnose(SP.P.Tok, diag::attr_unsupported_on_target,
                      SP.P.Tok.getText(),
                      M.getASTContext().LangOpts.Target.str());
      else
        *isWeakImported = true;
    } else if (availability && SP.P.Tok.getText() == "available") {
      SP.P.consumeToken(tok::identifier);

      SourceRange range;
      llvm::VersionTuple version;
      if (SP.P.parseVersionTuple(version, range,
                                 diag::sil_availability_expected_version))
        return true;

      *availability = AvailabilityContext(VersionRange::allGTE(version));

      SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
      continue;
    } else if (inlineStrategy && SP.P.Tok.getText() == "noinline")
      *inlineStrategy = NoInline;
    else if (optimizationMode && SP.P.Tok.getText() == "Onone")
      *optimizationMode = OptimizationMode::NoOptimization;
    else if (optimizationMode && SP.P.Tok.getText() == "Ospeed")
      *optimizationMode = OptimizationMode::ForSpeed;
    else if (optimizationMode && SP.P.Tok.getText() == "Osize")
      *optimizationMode = OptimizationMode::ForSize;
    else if (inlineStrategy && SP.P.Tok.getText() == "always_inline")
      *inlineStrategy = AlwaysInline;
    else if (MRK && SP.P.Tok.getText() == "readnone")
      *MRK = EffectsKind::ReadNone;
    else if (MRK && SP.P.Tok.getText() == "readonly")
      *MRK = EffectsKind::ReadOnly;
    else if (MRK && SP.P.Tok.getText() == "readwrite")
      *MRK = EffectsKind::ReadWrite;
    else if (MRK && SP.P.Tok.getText() == "releasenone")
      *MRK = EffectsKind::ReleaseNone;
    else if  (dynamicallyReplacedFunction && SP.P.Tok.getText() == "dynamic_replacement_for") {
      SP.P.consumeToken(tok::identifier);
      if (SP.P.Tok.getKind() != tok::string_literal) {
        SP.P.diagnose(SP.P.Tok, diag::expected_in_attribute_list);
        return true;
      }
      // Drop the double quotes.
      StringRef replacedFunc = SP.P.Tok.getText().drop_front().drop_back();
      SILFunction *Func = M.lookUpFunction(replacedFunc.str());
      if (!Func) {
        Identifier Id = SP.P.Context.getIdentifier(replacedFunc);
        SP.P.diagnose(SP.P.Tok, diag::sil_dynamically_replaced_func_not_found,
                      Id);
        return true;
      }
      *dynamicallyReplacedFunction = Func;
      SP.P.consumeToken(tok::string_literal);

      SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
      continue;
    } else if (objCReplacementFor &&
               SP.P.Tok.getText() == "objc_replacement_for") {
      SP.P.consumeToken(tok::identifier);
      if (SP.P.Tok.getKind() != tok::string_literal) {
        SP.P.diagnose(SP.P.Tok, diag::expected_in_attribute_list);
        return true;
      }
      // Drop the double quotes.
      StringRef replacedFunc = SP.P.Tok.getText().drop_front().drop_back();
      *objCReplacementFor = SP.P.Context.getIdentifier(replacedFunc);
      SP.P.consumeToken(tok::string_literal);

      SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
      continue;
    } else if (Semantics && SP.P.Tok.getText() == "_semantics") {
      SP.P.consumeToken(tok::identifier);
      if (SP.P.Tok.getKind() != tok::string_literal) {
        SP.P.diagnose(SP.P.Tok, diag::expected_in_attribute_list);
        return true;
      }
  
      // Drop the double quotes.
      StringRef rawString = SP.P.Tok.getText().drop_front().drop_back();
      Semantics->push_back(rawString.str());
      SP.P.consumeToken(tok::string_literal);

      SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
      continue;
    } else if (SpecAttrs && SP.P.Tok.getText() == "_specialize") {
      SourceLoc AtLoc = SP.P.Tok.getLoc();
      SourceLoc Loc(AtLoc);

      // Parse a _specialized attribute, building a parsed substitution list
      // and pushing a new ParsedSpecAttr on the SpecAttrs list. Conformances
      // cannot be generated until the function declaration is fully parsed so
      // that the function's generic signature can be consulted.
      ParsedSpecAttr SpecAttr;
      SpecAttr.requirements = {};
      SpecAttr.exported = false;
      SpecAttr.kind = SILSpecializeAttr::SpecializationKind::Full;
      SpecializeAttr *Attr;
      StringRef targetFunctionName;
      ModuleDecl *module = nullptr;

      if (!SP.P.parseSpecializeAttribute(
              tok::r_square, AtLoc, Loc, Attr,
              [&targetFunctionName](Parser &P) -> bool {
                if (P.Tok.getKind() != tok::string_literal) {
                  P.diagnose(P.Tok, diag::expected_in_attribute_list);
                  return true;
                }
                // Drop the double quotes.
                targetFunctionName = P.Tok.getText().drop_front().drop_back();

                P.consumeToken(tok::string_literal);
                return true;
              },
              [&module](Parser &P) -> bool {
                if (P.Tok.getKind() != tok::identifier) {
                  P.diagnose(P.Tok, diag::expected_in_attribute_list);
                  return true;
                }
                auto ident = P.Context.getIdentifier(P.Tok.getText());
                module = P.Context.getModuleByIdentifier(ident);
                assert(module);
                P.consumeToken();
                return true;
              }))
        return true;
      SILFunction *targetFunction = nullptr;
      if (!targetFunctionName.empty()) {
        targetFunction = M.lookUpFunction(targetFunctionName.str());
        if (!targetFunction) {
          Identifier Id = SP.P.Context.getIdentifier(targetFunctionName);
          SP.P.diagnose(SP.P.Tok, diag::sil_specialize_target_func_not_found,
                        Id);
          return true;
        }
      }
      // Convert SpecializeAttr into ParsedSpecAttr.
      SpecAttr.requirements = Attr->getTrailingWhereClause()->getRequirements();
      SpecAttr.kind = Attr->getSpecializationKind() ==
                              swift::SpecializeAttr::SpecializationKind::Full
                          ? SILSpecializeAttr::SpecializationKind::Full
                          : SILSpecializeAttr::SpecializationKind::Partial;
      SpecAttr.exported = Attr->isExported();
      SpecAttr.target = targetFunction;
      SpecAttrs->emplace_back(SpecAttr);
      if (!Attr->getSPIGroups().empty()) {
        SpecAttr.spiGroupID = Attr->getSPIGroups()[0];
      }
      continue;
    }
    else if (ClangDecl && SP.P.Tok.getText() == "clang") {
      SP.P.consumeToken(tok::identifier);
      if (SP.parseSILDottedPathWithoutPound(*ClangDecl))
        return true;

      SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
      continue;
    }
    else {
      SP.P.diagnose(SP.P.Tok, diag::expected_in_attribute_list);
      return true;
    }
    SP.P.consumeToken(tok::identifier);
    SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
  }
  return false;
}

Type SILParser::performTypeResolution(TypeRepr *TyR, bool IsSILType,
                                      GenericEnvironment *GenericEnv,
                                      GenericParamList *GenericParams) {
  if (GenericEnv == nullptr)
    GenericEnv = ContextGenericEnv;

  return swift::performTypeResolution(TyR, P.Context,
                                      /*isSILMode=*/true, IsSILType,
                                      GenericEnv, GenericParams,
                                      &P.SF);
}

/// Find the top-level ValueDecl or Module given a name.
static llvm::PointerUnion<ValueDecl *, ModuleDecl *>
lookupTopDecl(Parser &P, DeclBaseName Name, bool typeLookup) {
  // Use UnqualifiedLookup to look through all of the imports.
  UnqualifiedLookupOptions options;
  if (typeLookup)
    options |= UnqualifiedLookupFlags::TypeLookup;

  auto &ctx = P.SF.getASTContext();
  auto descriptor = UnqualifiedLookupDescriptor(DeclNameRef(Name), &P.SF);
  auto lookup = evaluateOrDefault(ctx.evaluator,
                                  UnqualifiedLookupRequest{descriptor}, {});
  assert(lookup.size() == 1);
  return lookup.back().getValueDecl();
}

/// Find the ValueDecl given an interface type and a member name.
static ValueDecl *lookupMember(Parser &P, Type Ty, DeclBaseName Name,
                               SourceLoc Loc,
                               SmallVectorImpl<ValueDecl *> &Lookup,
                               bool ExpectMultipleResults) {
  Type CheckTy = Ty;
  if (auto MetaTy = CheckTy->getAs<AnyMetatypeType>())
    CheckTy = MetaTy->getInstanceType();

  if (auto nominal = CheckTy->getAnyNominal()) {
    if (Name == DeclBaseName::createDestructor() &&
        isa<ClassDecl>(nominal)) {
      auto *classDecl = cast<ClassDecl>(nominal);
      Lookup.push_back(classDecl->getDestructor());
    } else {
      auto found = nominal->lookupDirect(Name);
      Lookup.append(found.begin(), found.end());
    }
  } else if (auto moduleTy = CheckTy->getAs<ModuleType>()) {
    moduleTy->getModule()->lookupValue(Name, NLKind::QualifiedLookup, Lookup);
  } else {
    P.diagnose(Loc, diag::sil_member_lookup_bad_type, Name, Ty);
    return nullptr;
  }

  if (Lookup.empty() || (!ExpectMultipleResults && Lookup.size() != 1)) {
    P.diagnose(Loc, diag::sil_named_member_decl_not_found, Name, Ty);
    return nullptr;
  }
  return Lookup[0];
}

bool SILParser::parseASTType(CanType &result,
                             GenericEnvironment *genericEnv,
                             GenericParamList *genericParams) {
  ParserResult<TypeRepr> parsedType = P.parseType();
  if (parsedType.isNull()) return true;

  bool wantInterfaceType = true;
  if (genericEnv == nullptr) {
    genericEnv = ContextGenericEnv;
    wantInterfaceType = false;
  }
  if (genericParams == nullptr)
    genericParams = ContextGenericParams;

  bindSILGenericParams(parsedType.get());

  const auto resolvedType =
      performTypeResolution(parsedType.get(), /*isSILType=*/false,
                            genericEnv, genericParams);
  if (resolvedType->hasError())
    return true;

  if (wantInterfaceType)
    result = resolvedType->mapTypeOutOfContext()->getCanonicalType();
  else
    result = resolvedType->getCanonicalType();

  // Invoke the callback on the parsed type.
  ParsedTypeCallback(resolvedType);
  return false;
}

void SILParser::bindSILGenericParams(TypeRepr *TyR) {
  // Resolve the generic environments for parsed generic function and box types.
  class HandleSILGenericParamsWalker : public ASTWalker {
    SourceFile *SF;

  public:
    HandleSILGenericParamsWalker(SourceFile *SF) : SF(SF) {}

    bool walkToTypeReprPre(TypeRepr *T) override {
      if (auto fnType = dyn_cast<FunctionTypeRepr>(T)) {
        if (auto *genericParams = fnType->getGenericParams()) {
          auto *env = handleSILGenericParams(genericParams, SF);
          fnType->setGenericEnvironment(env);
        }

        if (auto *genericParams = fnType->getPatternGenericParams()) {
          auto *env = handleSILGenericParams(genericParams, SF);
          fnType->setPatternGenericEnvironment(env);
        }
      }

      if (auto boxType = dyn_cast<SILBoxTypeRepr>(T)) {
        if (auto *genericParams = boxType->getGenericParams()) {
          auto *env = handleSILGenericParams(genericParams, SF);
          boxType->setGenericEnvironment(env);
        }
      }

      return true;
    }
  };

  TyR->walk(HandleSILGenericParamsWalker(&P.SF));
}

///   sil-type:
///     '$' '*'? attribute-list (generic-params)? type
///
bool SILParser::parseSILType(SILType &Result,
                             GenericEnvironment *&ParsedGenericEnv,
                             GenericParamList *&ParsedGenericParams,
                             bool IsFuncDecl,
                             GenericEnvironment *OuterGenericEnv,
                             GenericParamList *OuterGenericParams) {
  ParsedGenericEnv = nullptr;
  ParsedGenericParams = nullptr;

  if (OuterGenericEnv == nullptr)
    OuterGenericEnv = ContextGenericEnv;
  if (OuterGenericParams == nullptr)
    OuterGenericParams = ContextGenericParams;

  if (P.parseToken(tok::sil_dollar, diag::expected_sil_type))
    return true;

  // If we have a '*', then this is an address type.
  SILValueCategory category = SILValueCategory::Object;
  if (P.Tok.isAnyOperator() && P.Tok.getText().startswith("*")) {
    category = SILValueCategory::Address;
    P.consumeStartingCharacterOfCurrentToken();
  }

  // Parse attributes.
  ParamDecl::Specifier specifier;
  SourceLoc specifierLoc;
  TypeAttributes attrs;
  P.parseTypeAttributeList(specifier, specifierLoc, attrs);

  // Global functions are implicitly @convention(thin) if not specified otherwise.
  if (IsFuncDecl && !attrs.has(TAK_convention)) {
    // Use a random location.
    attrs.setAttr(TAK_convention, P.PreviousLoc);
    attrs.ConventionArguments =
      TypeAttributes::Convention::makeSwiftConvention("thin");
  }

  ParserResult<TypeRepr> TyR = P.parseType(diag::expected_sil_type,
                                           /*isSILFuncDecl*/ IsFuncDecl);

  if (TyR.isNull())
    return true;

  bindSILGenericParams(TyR.get());
  
  // Apply attributes to the type.
  auto *attrRepr =
      P.applyAttributeToType(TyR.get(), attrs, specifier, specifierLoc);
  const auto Ty =
      performTypeResolution(attrRepr, /*IsSILType=*/true,
                            OuterGenericEnv, OuterGenericParams);
  if (Ty->hasError())
    return true;

  // Save the top-level function generic environment if there was one.
  if (auto fnType = dyn_cast<FunctionTypeRepr>(TyR.get())) {
    if (auto *genericEnv = fnType->getGenericEnvironment())
      ParsedGenericEnv = genericEnv;
    if (auto *genericParams = fnType->getGenericParams())
      ParsedGenericParams = genericParams;
  }

  Result = SILType::getPrimitiveType(Ty->getCanonicalType(),
                                     category);

  // Invoke the callback on the parsed type.
  ParsedTypeCallback(Ty);

  return false;
}

bool SILParser::parseSILDottedPath(ValueDecl *&Decl,
                                   SmallVectorImpl<ValueDecl *> &values) {
  if (P.parseToken(tok::pound, diag::expected_sil_constant))
    return true;
  return parseSILDottedPathWithoutPound(Decl, values);
}

bool SILParser::parseSILDottedPathWithoutPound(ValueDecl *&Decl,
                                   SmallVectorImpl<ValueDecl *> &values) {
  // Handle sil-dotted-path.
  Identifier Id;
  SmallVector<DeclBaseName, 4> FullName;
  SmallVector<SourceLoc, 4> Locs;
  do {
    Locs.push_back(P.Tok.getLoc());
    switch (P.Tok.getKind()) {
    case tok::kw_subscript:
      P.consumeToken();
      FullName.push_back(DeclBaseName::createSubscript());
      break;
    case tok::kw_init:
      P.consumeToken();
      FullName.push_back(DeclBaseName::createConstructor());
      break;
    case tok::kw_deinit:
      P.consumeToken();
      FullName.push_back(DeclBaseName::createDestructor());
      break;
    default:
      if (parseSILIdentifier(Id, diag::expected_sil_constant))
        return true;
      FullName.push_back(Id);
      break;
    }
  } while (P.consumeIf(tok::period));

  // Look up ValueDecl from a dotted path. If there are multiple components,
  // the first one must be a type declaration.
  ValueDecl *VD;
  llvm::PointerUnion<ValueDecl*, ModuleDecl *> Res = lookupTopDecl(
    P, FullName[0], /*typeLookup=*/FullName.size() > 1);
  // It is possible that the last member lookup can return multiple lookup
  // results. One example is the overloaded member functions.
  if (Res.is<ModuleDecl*>()) {
    assert(FullName.size() > 1 &&
           "A single module is not a full path to SILDeclRef");
    auto Mod = Res.get<ModuleDecl*>();
    values.clear();
    VD = lookupMember(P, ModuleType::get(Mod), FullName[1], Locs[1], values,
                      FullName.size() == 2/*ExpectMultipleResults*/);
    for (unsigned I = 2, E = FullName.size(); I < E; ++I) {
      values.clear();
      VD = lookupMember(P, VD->getInterfaceType(), FullName[I], Locs[I], values,
                        I == FullName.size() - 1/*ExpectMultipleResults*/);
    }
  } else {
    VD = Res.get<ValueDecl*>();
    for (unsigned I = 1, E = FullName.size(); I < E; ++I) {
      values.clear();
      VD = lookupMember(P, VD->getInterfaceType(), FullName[I], Locs[I], values,
                        I == FullName.size() - 1/*ExpectMultipleResults*/);
    }
  }
  Decl = VD;
  return false;
}

static Optional<AccessorKind> getAccessorKind(StringRef ident) {
  return llvm::StringSwitch<Optional<AccessorKind>>(ident)
           .Case("getter", AccessorKind::Get)
           .Case("setter", AccessorKind::Set)
           .Case("addressor", AccessorKind::Address)
           .Case("mutableAddressor", AccessorKind::MutableAddress)
           .Case("read", AccessorKind::Read)
           .Case("modify", AccessorKind::Modify)
           .Default(None);
}

///  sil-decl-ref ::= '#' sil-identifier ('.' sil-identifier)* sil-decl-subref?
///  sil-decl-subref ::= '!' sil-decl-subref-part ('.' sil-decl-lang)?
///                      ('.' sil-decl-autodiff)?
///  sil-decl-subref ::= '!' sil-decl-lang
///  sil-decl-subref ::= '!' sil-decl-autodiff
///  sil-decl-subref-part ::= 'getter'
///  sil-decl-subref-part ::= 'setter'
///  sil-decl-subref-part ::= 'allocator'
///  sil-decl-subref-part ::= 'initializer'
///  sil-decl-subref-part ::= 'enumelt'
///  sil-decl-subref-part ::= 'destroyer'
///  sil-decl-subref-part ::= 'globalaccessor'
///  sil-decl-lang ::= 'foreign'
///  sil-decl-autodiff ::= sil-decl-autodiff-kind '.' sil-decl-autodiff-indices
///  sil-decl-autodiff-kind ::= 'jvp'
///  sil-decl-autodiff-kind ::= 'vjp'
///  sil-decl-autodiff-indices ::= [SU]+
bool SILParser::parseSILDeclRef(SILDeclRef &Result,
                                SmallVectorImpl<ValueDecl *> &values) {
  ValueDecl *VD;
  if (parseSILDottedPath(VD, values))
    return true;

  // Initialize SILDeclRef components.
  SILDeclRef::Kind Kind = SILDeclRef::Kind::Func;
  bool IsObjC = false;
  AutoDiffDerivativeFunctionIdentifier *DerivativeId = nullptr;

  if (!P.consumeIf(tok::sil_exclamation)) {
    // Construct SILDeclRef.
    Result = SILDeclRef(VD, Kind, IsObjC, DerivativeId);
    return false;
  }

  // Handle SILDeclRef components. ParseState tracks the last parsed component.
  //
  // When ParseState is 0, accept kind (`func|getter|setter|...`) and set
  // ParseState to 1.
  //
  // Always accept `foreign` and derivative function identifier.
  unsigned ParseState = 0;
  Identifier Id;
  do {
    if (P.Tok.is(tok::identifier)) {
      auto IdLoc = P.Tok.getLoc();
      if (parseSILIdentifier(Id, diag::expected_sil_constant))
        return true;
      Optional<AccessorKind> accessorKind;
      if (!ParseState && Id.str() == "func") {
        Kind = SILDeclRef::Kind::Func;
        ParseState = 1;
      } else if (!ParseState &&
                 (accessorKind = getAccessorKind(Id.str())).hasValue()) {
        // Drill down to the corresponding accessor for each declaration,
        // compacting away decls that lack it.
        size_t destI = 0;
        for (size_t srcI = 0, e = values.size(); srcI != e; ++srcI) {
          if (auto storage = dyn_cast<AbstractStorageDecl>(values[srcI]))
            if (auto accessor = storage->getOpaqueAccessor(*accessorKind))
              values[destI++] = accessor;
        }
        values.resize(destI);

        // Complain if none of the decls had a corresponding accessor.
        if (destI == 0) {
          P.diagnose(IdLoc, diag::referenced_value_no_accessor, 0);
          return true;
        }

        Kind = SILDeclRef::Kind::Func;
        VD = values[0];
        ParseState = 1;
      } else if (!ParseState && Id.str() == "allocator") {
        Kind = SILDeclRef::Kind::Allocator;
        ParseState = 1;
      } else if (!ParseState && Id.str() == "initializer") {
        Kind = SILDeclRef::Kind::Initializer;
        ParseState = 1;
      } else if (!ParseState && Id.str() == "enumelt") {
        Kind = SILDeclRef::Kind::EnumElement;
        ParseState = 1;
      } else if (!ParseState && Id.str() == "destroyer") {
        Kind = SILDeclRef::Kind::Destroyer;
        ParseState = 1;
      } else if (!ParseState && Id.str() == "deallocator") {
        Kind = SILDeclRef::Kind::Deallocator;
        ParseState = 1;
      } else if (!ParseState && Id.str() == "globalaccessor") {
        Kind = SILDeclRef::Kind::GlobalAccessor;
        ParseState = 1;
      } else if (!ParseState && Id.str() == "ivardestroyer") {
        Kind = SILDeclRef::Kind::IVarDestroyer;
        ParseState = 1;
      } else if (!ParseState && Id.str() == "ivarinitializer") {
        Kind = SILDeclRef::Kind::IVarInitializer;
        ParseState = 1;
      } else if (!ParseState && Id.str() == "defaultarg") {
        Kind = SILDeclRef::Kind::IVarInitializer;
        ParseState = 1;
      } else if (!ParseState && Id.str() == "propertyinit") {
        Kind = SILDeclRef::Kind::StoredPropertyInitializer;
        ParseState = 1;
      } else if (!ParseState && Id.str() == "backinginit") {
        Kind = SILDeclRef::Kind::PropertyWrapperBackingInitializer;
        ParseState = 1;
      } else if (Id.str() == "foreign") {
        IsObjC = true;
        break;
      } else if (Id.str() == "jvp" || Id.str() == "vjp") {
        IndexSubset *parameterIndices = nullptr;
        GenericSignature derivativeGenSig;
        // Parse derivative function kind.
        AutoDiffDerivativeFunctionKind derivativeKind(Id.str());
        if (!P.consumeIf(tok::period)) {
          P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, ".");
          return true;
        }
        // Parse parameter indices.
        parameterIndices =
            IndexSubset::getFromString(SILMod.getASTContext(), P.Tok.getText());
        if (!parameterIndices) {
          P.diagnose(P.Tok, diag::invalid_index_subset);
          return true;
        }
        P.consumeToken();
        // Parse derivative generic signature (optional).
        if (P.Tok.is(tok::oper_binary_unspaced) && P.Tok.getText() == ".<") {
          P.consumeStartingCharacterOfCurrentToken(tok::period);
          // Create a new scope to avoid type redefinition errors.
          auto *genericParams = P.maybeParseGenericParams().getPtrOrNull();
          assert(genericParams);
          auto *derivativeGenEnv = handleSILGenericParams(genericParams, &P.SF);
          derivativeGenSig = derivativeGenEnv->getGenericSignature();
        }
        DerivativeId = AutoDiffDerivativeFunctionIdentifier::get(
            derivativeKind, parameterIndices, derivativeGenSig,
            SILMod.getASTContext());
        break;
      } else {
        break;
      }
    } else
      break;

  } while (P.consumeIf(tok::period));

  // Construct SILDeclRef.
  Result = SILDeclRef(VD, Kind, IsObjC, DerivativeId);
  return false;
}

/// parseValueName - Parse a value name without a type available yet.
///
///     sil-value-name:
///       sil-local-name
///       'undef'
///
bool SILParser::parseValueName(UnresolvedValueName &Result) {
  Result.Name = P.Tok.getText();

  if (P.Tok.is(tok::kw_undef)) {
    Result.NameLoc = P.consumeToken(tok::kw_undef);
    return false;
  }

  // Parse the local-name.
  if (P.parseToken(tok::sil_local_name, Result.NameLoc,
                   diag::expected_sil_value_name))
    return true;

  return false;
}

/// parseValueRef - Parse a value, given a contextual type.
///
///     sil-value-ref:
///       sil-local-name
///
bool SILParser::parseValueRef(SILValue &Result, SILType Ty,
                              SILLocation Loc, SILBuilder &B) {
  UnresolvedValueName Name;
  if (parseValueName(Name)) return true;
  Result = getLocalValue(Name, Ty, Loc, B);
  return false;
}

/// parseTypedValueRef - Parse a type/value reference pair.
///
///    sil-typed-valueref:
///       sil-value-ref ':' sil-type
///
bool SILParser::parseTypedValueRef(SILValue &Result, SourceLoc &Loc,
                                   SILBuilder &B) {
  Loc = P.Tok.getLoc();

  UnresolvedValueName Name;
  SILType Ty;
  if (parseValueName(Name) ||
      P.parseToken(tok::colon, diag::expected_sil_colon_value_ref) ||
      parseSILType(Ty))
    return true;
  
  Result = getLocalValue(Name, Ty, RegularLocation(Loc), B);
  return false;
}

/// Look up whether the given string corresponds to a SIL opcode.
static Optional<SILInstructionKind> getOpcodeByName(StringRef OpcodeName) {
  return llvm::StringSwitch<Optional<SILInstructionKind>>(OpcodeName)
  #define FULL_INST(Id, TextualName, Parent, MemBehavior, MayRelease) \
    .Case(#TextualName, SILInstructionKind::Id)
  #include "swift/SIL/SILNodes.def"
    .Default(None);
}

/// getInstructionKind - This method maps the string form of a SIL instruction
/// opcode to an enum.
bool SILParser::parseSILOpcode(SILInstructionKind &Opcode, SourceLoc &OpcodeLoc,
                               StringRef &OpcodeName) {
  OpcodeLoc = P.Tok.getLoc();
  OpcodeName = P.Tok.getText();
  // Parse this textually to avoid Swift keywords (like 'return') from
  // interfering with opcode recognition.
  auto MaybeOpcode = getOpcodeByName(OpcodeName);
  if (!MaybeOpcode) {
    P.diagnose(OpcodeLoc, diag::expected_sil_instr_opcode);
    return true;
  }

  Opcode = MaybeOpcode.getValue();
  P.consumeToken();
  return false;
}

static bool peekSILDebugLocation(Parser &P) {
  auto T = P.peekToken().getText();
  return P.Tok.is(tok::comma) && (T == "loc" || T == "scope");
}

bool SILParser::parseSILDebugVar(SILDebugVariable &Var) {
  while (P.Tok.is(tok::comma) && !peekSILDebugLocation(P)) {
    P.consumeToken();
    StringRef Key = P.Tok.getText();
    if (Key == "name") {
      P.consumeToken();
      if (P.Tok.getKind() != tok::string_literal) {
        P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "string");
        return true;
      }
      // Drop the double quotes.
      StringRef Val = P.Tok.getText().drop_front().drop_back();
      Var.Name = Val;
    } else if (Key == "argno") {
      P.consumeToken();
      if (P.Tok.getKind() != tok::integer_literal) {
        P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "integer");
        return true;
      }
      uint16_t ArgNo;
      if (parseIntegerLiteral(P.Tok.getText(), 0, ArgNo))
        return true;
      Var.ArgNo = ArgNo;
    } else if (Key == "let") {
      Var.Constant = true;
    } else if (Key == "var") {
      Var.Constant = false; 
    } else if (Key == "loc") {
      Var.Constant = false; 
    } else {
      P.diagnose(P.Tok, diag::sil_dbg_unknown_key, Key);
      return true;
    }
    P.consumeToken();
  }
  return false;
}

bool SILParser::parseSILBBArgsAtBranch(SmallVector<SILValue, 6> &Args,
                                       SILBuilder &B) {
  if (P.Tok.is(tok::l_paren)) {
    SourceLoc LParenLoc = P.consumeToken(tok::l_paren);
    SourceLoc RParenLoc;

    bool HasError = false;
    if (P.parseList(tok::r_paren, LParenLoc, RParenLoc,
                    /*AllowSepAfterLast=*/false,
                    diag::sil_basicblock_arg_rparen,
                    SyntaxKind::Unknown,
                    [&]() -> ParserStatus {
                      SILValue Arg;
                      SourceLoc ArgLoc;
                      if (parseTypedValueRef(Arg, ArgLoc, B)) {
                        HasError = true;
                        return makeParserError();
                      }
                      Args.push_back(Arg);
                      return makeParserSuccess();
                    }).isErrorOrHasCompletion() || HasError)
      return true;
  }
  return false;
}

/// Parse the substitution list for an apply instruction or
/// specialized protocol conformance.
bool SILParser::parseSubstitutions(SmallVectorImpl<ParsedSubstitution> &parsed,
                                   GenericEnvironment *GenericEnv,
                                   GenericParamList *GenericParams) {
  // Check for an opening '<' bracket.
  if (!P.startsWithLess(P.Tok))
    return false;
  
  if (GenericEnv == nullptr)
    GenericEnv = ContextGenericEnv;
  if (GenericParams == nullptr)
    GenericParams = ContextGenericParams;

  P.consumeStartingLess();
  
  // Parse a list of Substitutions.
  do {
    SourceLoc Loc = P.Tok.getLoc();

    // Parse substitution as AST type.
    ParserResult<TypeRepr> TyR = P.parseType();
    if (TyR.isNull())
      return true;

    const auto Ty =
        performTypeResolution(TyR.get(), /*IsSILType=*/false,
                              GenericEnv, GenericParams);
    if (Ty->hasError())
      return true;
    parsed.push_back({Loc, Ty});
  } while (P.consumeIf(tok::comma));
  
  // Consume the closing '>'.
  if (!P.startsWithGreater(P.Tok)) {
    P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, ">");
    return true;
  }
  P.consumeStartingGreater();
  
  return false;
}

/// Collect conformances by looking up the conformance from replacement
/// type and protocol decl.
static bool getConformancesForSubstitution(Parser &P,
              ExistentialLayout::ProtocolTypeArrayRef protocols,
              Type subReplacement,
              SourceLoc loc,
              SmallVectorImpl<ProtocolConformanceRef> &conformances) {
  auto M = P.SF.getParentModule();

  for (auto protoTy : protocols) {
    auto conformance = M->lookupConformance(subReplacement,
                                            protoTy->getDecl());
    if (conformance.isInvalid()) {
      P.diagnose(loc, diag::sil_substitution_mismatch, subReplacement, protoTy);
      return true;
    }
    conformances.push_back(conformance);
  }

  return false;
}

/// Reconstruct an AST substitution map from parsed substitutions.
SubstitutionMap getApplySubstitutionsFromParsed(
                             SILParser &SP,
                             GenericEnvironment *env,
                             ArrayRef<ParsedSubstitution> parses) {
  if (parses.empty()) {
    assert(!env);
    return SubstitutionMap();
  }

  assert(env);

  auto loc = parses[0].loc;

  // Ensure that we have the right number of type arguments.
  auto genericSig = env->getGenericSignature();
  if (parses.size() != genericSig->getGenericParams().size()) {
    bool hasTooFew = parses.size() < genericSig->getGenericParams().size();
    SP.P.diagnose(loc,
                  hasTooFew ? diag::sil_missing_substitutions
                            : diag::sil_too_many_substitutions);
    return SubstitutionMap();
  }

  bool failed = false;
  auto subMap = SubstitutionMap::get(
      genericSig,
      [&](SubstitutableType *type) -> Type {
        auto genericParam = dyn_cast<GenericTypeParamType>(type);
        if (!genericParam)
          return nullptr;

        auto index = genericSig->getGenericParamOrdinal(genericParam);
        assert(index < genericSig->getGenericParams().size());
        assert(index < parses.size());

        // Provide the replacement type.
        return parses[index].replacement;
      },
      [&](CanType dependentType, Type replacementType,
          ProtocolDecl *proto) -> ProtocolConformanceRef {
        auto M = SP.P.SF.getParentModule();
        if (auto conformance = M->lookupConformance(replacementType, proto))
          return conformance;

        SP.P.diagnose(loc, diag::sil_substitution_mismatch, replacementType,
                      proto->getDeclaredInterfaceType());
        failed = true;

        return ProtocolConformanceRef(proto);
      });

  return failed ? SubstitutionMap() : subMap;
}

static ArrayRef<ProtocolConformanceRef>
collectExistentialConformances(Parser &P, CanType conformingType, SourceLoc loc,
                               CanType protocolType) {
  auto layout = protocolType.getExistentialLayout();

  if (layout.requiresClass()) {
    if (!conformingType->mayHaveSuperclass() &&
        !conformingType->isObjCExistentialType()) {
      P.diagnose(loc, diag::sil_not_class, conformingType);
    }
  }

  // FIXME: Check superclass also.

  auto protocols = layout.getProtocols();
  if (protocols.empty())
    return {};

  SmallVector<ProtocolConformanceRef, 2> conformances;
  getConformancesForSubstitution(P, protocols, conformingType,
                                 loc, conformances);

  return P.Context.AllocateCopy(conformances);
}

/// sil-loc ::= 'loc' string-literal ':' [0-9]+ ':' [0-9]+
bool SILParser::parseSILLocation(SILLocation &Loc) {
  SILLocation::DebugLoc L;
  if (parseVerbatim("loc"))
    return true;

  if (P.Tok.getKind() != tok::string_literal) {
    P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "string");
    return true;
  }
  // Drop the double quotes.
  StringRef File = P.Tok.getText().drop_front().drop_back();
  L.Filename = P.Context.getIdentifier(File).str().data();
  P.consumeToken(tok::string_literal);
  if (P.parseToken(tok::colon, diag::expected_colon_in_sil_location))
    return true;
  if (parseInteger(L.Line, diag::sil_invalid_line_in_sil_location))
    return true;
  if (P.parseToken(tok::colon, diag::expected_colon_in_sil_location))
    return true;
  if (parseInteger(L.Column, diag::sil_invalid_column_in_sil_location))
    return true;

  Loc.setDebugInfoLoc(L);
  return false;
}

bool SILParser::parseScopeRef(SILDebugScope *&DS) {
  unsigned Slot;
  SourceLoc SlotLoc = P.Tok.getLoc();
  if (parseInteger(Slot, diag::sil_invalid_scope_slot))
    return true;

  DS = TUState.ScopeSlots[Slot];
  if (!DS) {
    P.diagnose(SlotLoc, diag::sil_scope_undeclared, Slot);
    return true;
  }
  return false;
}

///  (',' sil-loc)? (',' sil-scope-ref)?
bool SILParser::parseSILDebugLocation(SILLocation &L, SILBuilder &B,
                                      bool parsedComma) {
  // Parse the debug information, if any.
  if (P.Tok.is(tok::comma)) {
    P.consumeToken();
    parsedComma = true;
  }
  if (!parsedComma)
    return false;

  bool requireScope = false;
  if (P.Tok.getText() == "loc") {
    if (parseSILLocation(L))
      return true;

    if (P.Tok.is(tok::comma)) {
      P.consumeToken();
      requireScope = true;
    }
  }
  if (P.Tok.getText() == "scope" || requireScope) {
    parseVerbatim("scope");
    SILDebugScope *DS = nullptr;
    if (parseScopeRef(DS))
      return true;
    if (DS)
      B.setCurrentDebugScope(DS);
  }
  return false;
}

static bool parseLoadOwnershipQualifier(LoadOwnershipQualifier &Result,
                                        SILParser &P) {
  StringRef Str;
  // If we do not parse '[' ... ']', we have unqualified. Set value and return.
  if (!parseSILOptional(Str, P)) {
    Result = LoadOwnershipQualifier::Unqualified;
    return false;
  }

  // Then try to parse one of our other qualifiers. We do not support parsing
  // unqualified here so we use that as our fail value.
  auto Tmp = llvm::StringSwitch<LoadOwnershipQualifier>(Str)
                 .Case("take", LoadOwnershipQualifier::Take)
                 .Case("copy", LoadOwnershipQualifier::Copy)
                 .Case("trivial", LoadOwnershipQualifier::Trivial)
                 .Default(LoadOwnershipQualifier::Unqualified);

  // Thus return true (following the conventions in this file) if we fail.
  if (Tmp == LoadOwnershipQualifier::Unqualified)
    return true;

  // Otherwise, assign Result and return false.
  Result = Tmp;
  return false;
}

static bool parseStoreOwnershipQualifier(StoreOwnershipQualifier &Result,
                                         SILParser &P) {
  StringRef Str;
  // If we do not parse '[' ... ']', we have unqualified. Set value and return.
  if (!parseSILOptional(Str, P)) {
    Result = StoreOwnershipQualifier::Unqualified;
    return false;
  }

  // Then try to parse one of our other qualifiers. We do not support parsing
  // unqualified here so we use that as our fail value.
  auto Tmp = llvm::StringSwitch<StoreOwnershipQualifier>(Str)
                 .Case("init", StoreOwnershipQualifier::Init)
                 .Case("assign", StoreOwnershipQualifier::Assign)
                 .Case("trivial", StoreOwnershipQualifier::Trivial)
                 .Default(StoreOwnershipQualifier::Unqualified);

  // Thus return true (following the conventions in this file) if we fail.
  if (Tmp == StoreOwnershipQualifier::Unqualified)
    return true;

  // Otherwise, assign Result and return false.
  Result = Tmp;
  return false;
}

static bool parseAssignOwnershipQualifier(AssignOwnershipQualifier &Result,
                                          SILParser &P) {
  StringRef Str;
  // If we do not parse '[' ... ']', we have unknown. Set value and return.
  if (!parseSILOptional(Str, P)) {
    Result = AssignOwnershipQualifier::Unknown;
    return false;
  }

  // Then try to parse one of our other initialization kinds. We do not support
  // parsing unknown here so we use that as our fail value.
  auto Tmp = llvm::StringSwitch<AssignOwnershipQualifier>(Str)
                 .Case("reassign", AssignOwnershipQualifier::Reassign)
                 .Case("reinit", AssignOwnershipQualifier::Reinit)
                 .Case("init", AssignOwnershipQualifier::Init)
                 .Default(AssignOwnershipQualifier::Unknown);

  // Thus return true (following the conventions in this file) if we fail.
  if (Tmp == AssignOwnershipQualifier::Unknown)
    return true;

  // Otherwise, assign Result and return false.
  Result = Tmp;
  return false;
}

// Parse a list of integer indices, prefaced with the given string label.
// Returns true on error.
static bool parseIndexList(Parser &P, StringRef label,
                           SmallVectorImpl<unsigned> &indices,
                           const Diagnostic &parseIndexDiag) {
  SourceLoc loc;
  // Parse `[<label> <integer_literal>...]`.
  if (P.parseToken(tok::l_square, diag::sil_autodiff_expected_lsquare,
                   "index list") ||
      P.parseSpecificIdentifier(
          label, diag::sil_autodiff_expected_index_list_label, label))
    return true;
  while (P.Tok.is(tok::integer_literal)) {
    unsigned index;
    if (P.parseUnsignedInteger(index, loc, parseIndexDiag))
      return true;
    indices.push_back(index);
  }
  if (P.parseToken(tok::r_square, diag::sil_autodiff_expected_rsquare,
                   "index list"))
    return true;
  return false;
};

/// sil-differentiability-witness-config-and-function ::=
///   '[' 'parameters' index-subset ']'
///   '[' 'results' index-subset ']'
///   ('<' 'where' derivative-generic-signature-requirements '>')?
///   sil-function-ref
///
/// e.g. parameters 0 1] [results 0] <T where T: Differentiable>
///      @foo : <T> $(T) -> T
static Optional<std::pair<AutoDiffConfig, SILFunction *>>
parseSILDifferentiabilityWitnessConfigAndFunction(Parser &P, SILParser &SP,
                                                  SILLocation L) {
  // Parse parameter and result indices.
  SmallVector<unsigned, 8> rawParameterIndices;
  SmallVector<unsigned, 8> rawResultIndices;
  if (parseIndexList(P, "parameters", rawParameterIndices,
                     diag::sil_autodiff_expected_parameter_index))
    return {};
  if (parseIndexList(P, "results", rawResultIndices,
                     diag::sil_autodiff_expected_result_index))
    return {};
  // Parse witness generic parameter clause.
  GenericSignature witnessGenSig = GenericSignature();
  SourceLoc witnessGenSigStartLoc = P.getEndOfPreviousLoc();
  {
    auto *genericParams = P.maybeParseGenericParams().getPtrOrNull();
    if (genericParams) {
      auto *witnessGenEnv = handleSILGenericParams(genericParams, &P.SF);
      witnessGenSig = witnessGenEnv->getGenericSignature();
    }
  }
  // Parse original function name and type.
  SILFunction *originalFunction = nullptr;
  if (SP.parseSILFunctionRef(L, originalFunction))
    return {};
  // Resolve parsed witness generic signature.
  if (witnessGenSig) {
    auto origGenSig =
        originalFunction->getLoweredFunctionType()->getSubstGenericSignature();
    // Check whether original function generic signature and parsed witness
    // generic have the same generic parameters.
    auto areGenericParametersConsistent = [&]() {
      llvm::SmallDenseSet<GenericParamKey, 4> genericParamKeys;
      for (auto *origGP : origGenSig->getGenericParams())
        genericParamKeys.insert(GenericParamKey(origGP));
      for (auto *witnessGP : witnessGenSig->getGenericParams())
        if (!genericParamKeys.erase(GenericParamKey(witnessGP)))
          return false;
      return genericParamKeys.empty();
    };
    if (!areGenericParametersConsistent()) {
      P.diagnose(witnessGenSigStartLoc,
                 diag::sil_diff_witness_invalid_generic_signature,
                 witnessGenSig->getAsString(), origGenSig->getAsString());
      return {};
    }
    // Combine parsed witness requirements with original function generic
    // signature requirements to form full witness generic signature.
    SmallVector<Requirement, 4> witnessRequirements(
        witnessGenSig->getRequirements().begin(),
        witnessGenSig->getRequirements().end());
    witnessGenSig = evaluateOrDefault(
        P.Context.evaluator,
        AbstractGenericSignatureRequest{origGenSig.getPointer(),
                                        /*addedGenericParams=*/{},
                                        std::move(witnessRequirements)},
        nullptr);
  }
  auto origFnType = originalFunction->getLoweredFunctionType();
  auto *parameterIndices = IndexSubset::get(
      P.Context, origFnType->getNumParameters(), rawParameterIndices);
  auto *resultIndices = IndexSubset::get(P.Context, origFnType->getNumResults(),
                                         rawResultIndices);
  AutoDiffConfig config(parameterIndices, resultIndices, witnessGenSig);
  return std::make_pair(config, originalFunction);
}

bool SILParser::parseSILDeclRef(SILDeclRef &Member, bool FnTypeRequired) {
  SourceLoc TyLoc;
  SmallVector<ValueDecl *, 4> values;
  if (parseSILDeclRef(Member, values))
    return true;

  // : ( or : < means that what follows is function type.
  if (!P.Tok.is(tok::colon))
    return false;

  if (FnTypeRequired &&
      !P.peekToken().is(tok::l_paren) &&
      !P.startsWithLess(P.peekToken()))
    return false;

  // Type of the SILDeclRef is optional to be compatible with the old format.
  if (!P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":")) {
    // Parse the type for SILDeclRef.
    ParserResult<TypeRepr> TyR = P.parseType();
    if (TyR.isNull())
      return true;

    bindSILGenericParams(TyR.get());

    // The type can be polymorphic.
    GenericEnvironment *genericEnv = nullptr;
    GenericParamList *genericParams = nullptr;
    if (auto *fnType = dyn_cast<FunctionTypeRepr>(TyR.get())) {
      genericEnv = fnType->getGenericEnvironment();
      genericParams = fnType->getGenericParams();
    }

    const auto Ty =
        performTypeResolution(TyR.get(), /*IsSILType=*/false,
                              genericEnv, genericParams);
    if (Ty->hasError())
      return true;

    // Pick the ValueDecl that has the right type.
    ValueDecl *TheDecl = nullptr;
    auto declTy = Ty->getCanonicalType();
    for (unsigned I = 0, E = values.size(); I < E; ++I) {
      auto *decl = values[I];

      auto lookupTy =
        decl->getInterfaceType()
            ->removeArgumentLabels(decl->getNumCurryLevels());
      if (declTy == lookupTy->getCanonicalType()) {
        TheDecl = decl;
        // Update SILDeclRef to point to the right Decl.
        Member.loc = decl;
        break;
      }
      if (values.size() == 1 && !TheDecl) {
        P.diagnose(TyLoc, diag::sil_member_decl_type_mismatch, declTy,
                   lookupTy);
        return true;
      }
    }
    if (!TheDecl) {
      P.diagnose(TyLoc, diag::sil_member_decl_not_found);
      return true;
    }
  }
  return false;
}

bool
SILParser::parseKeyPathPatternComponent(KeyPathPatternComponent &component,
                                        SmallVectorImpl<SILType> &operandTypes,
                                        SourceLoc componentLoc,
                                        Identifier componentKind,
                                        SILLocation InstLoc,
                                        GenericEnvironment *patternEnv,
                                        GenericParamList *patternParams) {
   auto parseComponentIndices =
     [&](SmallVectorImpl<KeyPathPatternComponent::Index> &indexes) -> bool {
       while (true) {
         unsigned index;
         CanType formalTy;
         SILType loweredTy;
         if (P.parseToken(tok::oper_prefix,
                          diag::expected_tok_in_sil_instr, "%")
             || P.parseToken(tok::sil_dollar,
                             diag::expected_tok_in_sil_instr, "$"))
           return true;
         
         if (!P.Tok.is(tok::integer_literal)
             || parseIntegerLiteral(P.Tok.getText(), 0, index))
           return true;
         
         P.consumeToken(tok::integer_literal);
         
         SourceLoc formalTyLoc;
         SourceLoc loweredTyLoc;
         GenericEnvironment *ignoredParsedEnv = nullptr;
         GenericParamList *ignoredParsedParams = nullptr;
         if (P.parseToken(tok::colon,
                          diag::expected_tok_in_sil_instr, ":")
             || P.parseToken(tok::sil_dollar,
                             diag::expected_tok_in_sil_instr, "$")
             || parseASTType(formalTy, formalTyLoc,
                             patternEnv, patternParams)
             || P.parseToken(tok::colon,
                             diag::expected_tok_in_sil_instr, ":")
             || parseSILType(loweredTy, loweredTyLoc,
                             ignoredParsedEnv, ignoredParsedParams,
                             patternEnv, patternParams))
           return true;
         
         if (patternEnv)
           loweredTy = SILType::getPrimitiveType(
             loweredTy.getASTType()->mapTypeOutOfContext()
               ->getCanonicalType(),
             loweredTy.getCategory());

         // Formal type must be hashable.
         auto proto = P.Context.getProtocol(KnownProtocolKind::Hashable);
         Type contextFormalTy = formalTy;
         if (patternEnv)
           contextFormalTy = patternEnv->mapTypeIntoContext(formalTy);
         auto lookup = P.SF.getParentModule()->lookupConformance(
                                                 contextFormalTy, proto);
         if (lookup.isInvalid()) {
           P.diagnose(formalTyLoc,
                      diag::sil_keypath_index_not_hashable,
                      formalTy);
           return true;
         }
         auto conformance = ProtocolConformanceRef(lookup);

         indexes.push_back({index, formalTy, loweredTy, conformance});
         
         if (operandTypes.size() <= index)
           operandTypes.resize(index+1);
         if (operandTypes[index] && operandTypes[index] != loweredTy) {
           P.diagnose(loweredTyLoc,
                      diag::sil_keypath_index_operand_type_conflict,
                      index,
                      operandTypes[index].getASTType(),
                      loweredTy.getASTType());
           return true;
         }
         operandTypes[index] = loweredTy;
         
         if (P.consumeIf(tok::comma))
           continue;
         if (P.consumeIf(tok::r_square))
           break;
         return true;
       }
       return false;
     };
  
  if (componentKind.str() == "stored_property") {
    ValueDecl *prop;
    CanType ty;
    if (parseSILDottedPath(prop)
        || P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":")
        || P.parseToken(tok::sil_dollar,
                        diag::expected_tok_in_sil_instr, "$")
        || parseASTType(ty, patternEnv, patternParams))
      return true;
    component =
      KeyPathPatternComponent::forStoredProperty(cast<VarDecl>(prop), ty);
    return false;
  } else if (componentKind.str() == "gettable_property"
             || componentKind.str() == "settable_property") {
    bool isSettable = componentKind.str()[0] == 's';
    
    CanType componentTy;
    if (P.parseToken(tok::sil_dollar,diag::expected_tok_in_sil_instr,"$")
        || parseASTType(componentTy, patternEnv, patternParams)
        || P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ","))
      return true;
    
    SILFunction *idFn = nullptr;
    SILDeclRef idDecl;
    VarDecl *idProperty = nullptr;
    SILFunction *getter = nullptr;
    SILFunction *setter = nullptr;
    SILFunction *equals = nullptr;
    SILFunction *hash = nullptr;
    AbstractStorageDecl *externalDecl = nullptr;
    SubstitutionMap externalSubs;
    SmallVector<KeyPathPatternComponent::Index, 4> indexes;
    while (true) {
      Identifier subKind;
      SourceLoc subKindLoc;
      if (parseSILIdentifier(subKind, subKindLoc,
                             diag::sil_keypath_expected_component_kind))
        return true;

      if (subKind.str() == "id") {
        // The identifier can be either a function ref, a SILDeclRef
        // to a class or protocol method, or a decl ref to a property:
        // @static_fn_ref : $...
        // #Type.method!whatever : (T) -> ...
        // ##Type.property
        if (P.Tok.is(tok::at_sign)) {
          if (parseSILFunctionRef(InstLoc, idFn))
            return true;
        } else if (P.Tok.is(tok::pound)) {
          if (P.peekToken().is(tok::pound)) {
            ValueDecl *propertyValueDecl;
            P.consumeToken(tok::pound);
            if (parseSILDottedPath(propertyValueDecl))
              return true;
            idProperty = cast<VarDecl>(propertyValueDecl);
          } else if (parseSILDeclRef(idDecl, /*fnType*/ true))
            return true;
        } else {
          P.diagnose(subKindLoc, diag::expected_tok_in_sil_instr, "# or @");
          return true;
        }
      } else if (subKind.str() == "getter" || subKind.str() == "setter") {
        bool isSetter = subKind.str()[0] == 's';
        if (parseSILFunctionRef(InstLoc, isSetter ? setter : getter))
          return true;
      } else if (subKind.str() == "indices") {
        if (P.parseToken(tok::l_square,
                         diag::expected_tok_in_sil_instr, "[")
            || parseComponentIndices(indexes))
          return true;
      } else if (subKind.str() == "indices_equals") {
        if (parseSILFunctionRef(InstLoc, equals))
          return true;
      } else if (subKind.str() == "indices_hash") {
        if (parseSILFunctionRef(InstLoc, hash))
          return true;
      } else if (subKind.str() == "external") {
        ValueDecl *parsedExternalDecl;
        SmallVector<ParsedSubstitution, 4> parsedSubs;

        if (parseSILDottedPath(parsedExternalDecl)
            || parseSubstitutions(parsedSubs, patternEnv, patternParams))
          return true;

        externalDecl = cast<AbstractStorageDecl>(parsedExternalDecl);

        if (!parsedSubs.empty()) {
          auto genericEnv = externalDecl->getInnermostDeclContext()
                                        ->getGenericEnvironmentOfContext();
          if (!genericEnv) {
            P.diagnose(P.Tok,
                       diag::sil_substitutions_on_non_polymorphic_type);
            return true;
          }
          externalSubs = getApplySubstitutionsFromParsed(*this, genericEnv,
                                                         parsedSubs);
          if (!externalSubs) return true;

          // Map the substitutions out of the pattern context so that they
          // use interface types.
          externalSubs =
            externalSubs.mapReplacementTypesOutOfContext().getCanonical();
        }

      } else {
        P.diagnose(subKindLoc, diag::sil_keypath_unknown_component_kind,
                   subKind);
        return true;
      }
      
      if (!P.consumeIf(tok::comma))
        break;
    }
    
    if ((idFn == nullptr && idDecl.isNull() && idProperty == nullptr)
        || getter == nullptr
        || (isSettable && setter == nullptr)) {
      P.diagnose(componentLoc,
                 diag::sil_keypath_computed_property_missing_part,
                 isSettable);
      return true;
    }
    
    if ((idFn != nullptr) + (!idDecl.isNull()) + (idProperty != nullptr)
          != 1) {
      P.diagnose(componentLoc,
                 diag::sil_keypath_computed_property_missing_part,
                 isSettable);
      return true;
    }
    
    KeyPathPatternComponent::ComputedPropertyId id;
    if (idFn)
      id = idFn;
    else if (!idDecl.isNull())
      id = idDecl;
    else if (idProperty)
      id = idProperty;
    else
      llvm_unreachable("no id?!");
    
    auto indexesCopy = P.Context.AllocateCopy(indexes);
    
    if (!indexes.empty() && (!equals || !hash)) {
      P.diagnose(componentLoc,
                 diag::sil_keypath_computed_property_missing_part,
                 isSettable);
    }
    
    if (isSettable) {
      component = KeyPathPatternComponent::forComputedSettableProperty(
                             id, getter, setter,
                             indexesCopy, equals, hash,
                             externalDecl, externalSubs, componentTy);
    } else {
      component = KeyPathPatternComponent::forComputedGettableProperty(
                             id, getter,
                             indexesCopy, equals, hash,
                             externalDecl, externalSubs, componentTy);
    }
    return false;
  } else if (componentKind.str() == "optional_wrap"
               || componentKind.str() == "optional_chain"
               || componentKind.str() == "optional_force") {
    CanType ty;
    if (P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":")
        || P.parseToken(tok::sil_dollar, diag::expected_tok_in_sil_instr, "$")
        || parseASTType(ty, patternEnv, patternParams))
      return true;
    KeyPathPatternComponent::Kind kind;
    
    if (componentKind.str() == "optional_wrap") {
      kind = KeyPathPatternComponent::Kind::OptionalWrap;
    } else if (componentKind.str() == "optional_chain") {
      kind = KeyPathPatternComponent::Kind::OptionalChain;
    } else if (componentKind.str() == "optional_force") {
      kind = KeyPathPatternComponent::Kind::OptionalForce;
    } else {
      llvm_unreachable("unpossible");
    }
    
    component = KeyPathPatternComponent::forOptional(kind, ty);
    return false;
  } else if (componentKind.str() == "tuple_element") {
    unsigned tupleIndex;
    CanType ty;

    if (P.parseToken(tok::pound, diag::expected_sil_constant)
        || parseInteger(tupleIndex, diag::expected_sil_tuple_index)
        || P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":")
        || P.parseToken(tok::sil_dollar, diag::expected_tok_in_sil_instr, "$")
        || parseASTType(ty, patternEnv, patternParams))
      return true;
      
    component = KeyPathPatternComponent::forTupleElement(tupleIndex, ty);
    return false;
  } else {
    P.diagnose(componentLoc, diag::sil_keypath_unknown_component_kind,
               componentKind);
    return true;
  }
}

bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
                                            SILInstructionKind Opcode,
                                            SourceLoc OpcodeLoc,
                                            StringRef OpcodeName,
                                            SILInstruction *&ResultVal) {
  SmallVector<SILValue, 4> OpList;
  SILValue Val;
  SILType Ty;
  SILLocation InstLoc = RegularLocation(OpcodeLoc);

  auto parseFormalTypeAndValue = [&](CanType &formalType,
                                     SILValue &value) -> bool {
    return (parseASTType(formalType) || parseVerbatim("in")
            || parseTypedValueRef(value, B));
  };

  OpenedExistentialAccess AccessKind;
  auto parseOpenExistAddrKind = [&]() -> bool {
    Identifier accessKindToken;
    SourceLoc accessKindLoc;
    if (parseSILIdentifier(accessKindToken, accessKindLoc,
                           diag::expected_tok_in_sil_instr,
                           "opened existential access kind")) {
      return true;
    }
    auto kind =
        llvm::StringSwitch<Optional<OpenedExistentialAccess>>(
            accessKindToken.str())
            .Case("mutable_access", OpenedExistentialAccess::Mutable)
            .Case("immutable_access", OpenedExistentialAccess::Immutable)
            .Default(None);

    if (kind) {
      AccessKind = kind.getValue();
      return false;
    }
    P.diagnose(accessKindLoc, diag::expected_tok_in_sil_instr,
               "opened existential access kind");
    return true;
  };

  CanType SourceType, TargetType;
  SILValue SourceAddr, DestAddr;
  auto parseSourceAndDestAddress = [&] {
    return parseFormalTypeAndValue(SourceType, SourceAddr) ||
           parseVerbatim("to") || parseFormalTypeAndValue(TargetType, DestAddr);
  };

  Identifier SuccessBBName, FailureBBName;
  SourceLoc SuccessBBLoc, FailureBBLoc;
  auto parseConditionalBranchDestinations = [&] {
    return P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
           parseSILIdentifier(SuccessBBName, SuccessBBLoc,
                              diag::expected_sil_block_name) ||
           P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
           parseSILIdentifier(FailureBBName, FailureBBLoc,
                              diag::expected_sil_block_name) ||
           parseSILDebugLocation(InstLoc, B);
  };

  // Validate the opcode name, and do opcode-specific parsing logic based on the
  // opcode we find.

  switch (Opcode) {
  case SILInstructionKind::AllocBoxInst: {
    bool hasDynamicLifetime = false;
    if (parseSILOptional(hasDynamicLifetime, *this, "dynamic_lifetime"))
      return true;

    SILType Ty;
    if (parseSILType(Ty))
      return true;
    SILDebugVariable VarInfo;
    if (parseSILDebugVar(VarInfo))
      return true;
    if (parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createAllocBox(InstLoc, Ty.castTo<SILBoxType>(), VarInfo,
                                 hasDynamicLifetime);
    break;
  }
  case SILInstructionKind::ApplyInst:
  case SILInstructionKind::BeginApplyInst:
  case SILInstructionKind::PartialApplyInst:
  case SILInstructionKind::TryApplyInst:
    if (parseCallInstruction(InstLoc, Opcode, B, ResultVal))
      return true;
    break;
  case SILInstructionKind::AbortApplyInst:
  case SILInstructionKind::EndApplyInst: {
    UnresolvedValueName argName;
    if (parseValueName(argName))
      return true;

    if (parseSILDebugLocation(InstLoc, B))
      return true;

    SILType expectedTy = SILType::getSILTokenType(P.Context);
    SILValue op = getLocalValue(argName, expectedTy, InstLoc, B);

    if (Opcode == SILInstructionKind::AbortApplyInst) {
      ResultVal = B.createAbortApply(InstLoc, op);
    } else {
      ResultVal = B.createEndApply(InstLoc, op);
    }
    break;
  }
  case SILInstructionKind::IntegerLiteralInst: {
    SILType Ty;
    if (parseSILType(Ty) ||
        P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ","))
      return true;

    bool Negative = false;
    if (P.Tok.isAnyOperator() && P.Tok.getText() == "-") {
      Negative = true;
      P.consumeToken();
    }
    if (P.Tok.getKind() != tok::integer_literal) {
      P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "integer");
      return true;
    }

    auto intTy = Ty.getAs<AnyBuiltinIntegerType>();
    if (!intTy) {
      P.diagnose(P.Tok, diag::sil_integer_literal_not_integer_type);
      return true;
    }

    StringRef text = prepareIntegerLiteralForParsing(P.Tok.getText());

    bool error;
    APInt value = intTy->getWidth().parse(text, 0, Negative, &error);
    if (error) {
      P.diagnose(P.Tok, diag::sil_integer_literal_not_well_formed, intTy);
      return true;
    }

    P.consumeToken(tok::integer_literal);
    if (parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createIntegerLiteral(InstLoc, Ty, value);
    break;
  }
  case SILInstructionKind::FloatLiteralInst: {
    SILType Ty;
    if (parseSILType(Ty) ||
        P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ","))
      return true;

    // The value is expressed as bits.
    if (P.Tok.getKind() != tok::integer_literal) {
      P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "integer");
      return true;
    }

    auto floatTy = Ty.getAs<BuiltinFloatType>();
    if (!floatTy) {
      P.diagnose(P.Tok, diag::sil_float_literal_not_float_type);
      return true;
    }

    StringRef text = prepareIntegerLiteralForParsing(P.Tok.getText());

    APInt bits(floatTy->getBitWidth(), 0);
    bool error = text.getAsInteger(0, bits);
    assert(!error && "float_literal token did not parse as APInt?!");
    (void)error;

    if (bits.getBitWidth() != floatTy->getBitWidth())
      bits = bits.zextOrTrunc(floatTy->getBitWidth());

    APFloat value(floatTy->getAPFloatSemantics(), bits);
    if (parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createFloatLiteral(InstLoc, Ty, value);
    P.consumeToken(tok::integer_literal);
    break;
  }
  case SILInstructionKind::StringLiteralInst: {
    if (P.Tok.getKind() != tok::identifier) {
      P.diagnose(P.Tok, diag::sil_string_no_encoding);
      return true;
    }

    StringLiteralInst::Encoding encoding;
    if (P.Tok.getText() == "utf8") {
      encoding = StringLiteralInst::Encoding::UTF8;
    } else if (P.Tok.getText() == "objc_selector") {
      encoding = StringLiteralInst::Encoding::ObjCSelector;
    } else if (P.Tok.getText() == "bytes") {
      encoding = StringLiteralInst::Encoding::Bytes;
    } else {
      P.diagnose(P.Tok, diag::sil_string_invalid_encoding, P.Tok.getText());
      return true;
    }
    P.consumeToken(tok::identifier);

    if (P.Tok.getKind() != tok::string_literal) {
      P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "string");
      return true;
    }

    // Parse the string.
    SmallVector<Lexer::StringSegment, 1> segments;
    P.L->getStringLiteralSegments(P.Tok, segments);
    assert(segments.size() == 1);

    P.consumeToken(tok::string_literal);
    if (parseSILDebugLocation(InstLoc, B))
      return true;

    SmallVector<char, 128> stringBuffer;

    if (encoding == StringLiteralInst::Encoding::Bytes) {
      // Decode hex bytes.
      CharSourceRange rawStringRange(segments.front().Loc,
                                     segments.front().Length);
      StringRef rawString = P.SourceMgr.extractText(rawStringRange);
      if (rawString.size() & 1) {
        P.diagnose(P.Tok, diag::expected_tok_in_sil_instr,
                   "even number of hex bytes");
        return true;
      }
      while (!rawString.empty()) {
        unsigned byte1 = llvm::hexDigitValue(rawString[0]);
        unsigned byte2 = llvm::hexDigitValue(rawString[1]);
        if (byte1 == -1U || byte2 == -1U) {
          P.diagnose(P.Tok, diag::expected_tok_in_sil_instr,
                     "hex bytes should contain 0-9, a-f, A-F only");
          return true;
        }
        stringBuffer.push_back((unsigned char)(byte1 << 4) | byte2);
        rawString = rawString.drop_front(2);
      }

      ResultVal = B.createStringLiteral(InstLoc, stringBuffer, encoding);
      break;
    }

    StringRef string =
        P.L->getEncodedStringSegment(segments.front(), stringBuffer);
    ResultVal = B.createStringLiteral(InstLoc, string, encoding);
    break;
  }

  case SILInstructionKind::CondFailInst: {

    if (parseTypedValueRef(Val, B))
      return true;

    SmallVector<char, 128> stringBuffer;
    StringRef message;
    if (P.consumeIf(tok::comma)) {
      // Parse the string.
      if (P.Tok.getKind() != tok::string_literal) {
        P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "string");
        return true;
      }
      SmallVector<Lexer::StringSegment, 1> segments;
      P.L->getStringLiteralSegments(P.Tok, segments);
      assert(segments.size() == 1);

      P.consumeToken(tok::string_literal);
      message = P.L->getEncodedStringSegment(segments.front(), stringBuffer);
    }
    if (parseSILDebugLocation(InstLoc, B))
      return true;

    ResultVal = B.createCondFail(InstLoc, Val, message);
    break;
  }

  case SILInstructionKind::AllocValueBufferInst: {
    SILType Ty;
    if (parseSILType(Ty) || parseVerbatim("in") || parseTypedValueRef(Val, B) ||
        parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createAllocValueBuffer(InstLoc, Ty, Val);
    break;
  }
  case SILInstructionKind::ProjectValueBufferInst: {
    SILType Ty;
    if (parseSILType(Ty) || parseVerbatim("in") || parseTypedValueRef(Val, B) ||
        parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createProjectValueBuffer(InstLoc, Ty, Val);
    break;
  }
  case SILInstructionKind::DeallocValueBufferInst: {
    SILType Ty;
    if (parseSILType(Ty) || parseVerbatim("in") || parseTypedValueRef(Val, B) ||
        parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createDeallocValueBuffer(InstLoc, Ty, Val);
    break;
  }

  case SILInstructionKind::ProjectBoxInst: {
    if (parseTypedValueRef(Val, B) ||
        P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ","))
      return true;

    if (!P.Tok.is(tok::integer_literal)) {
      P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "integer");
      return true;
    }

    unsigned Index;
    bool error = parseIntegerLiteral(P.Tok.getText(), 0, Index);
    assert(!error && "project_box index did not parse as integer?!");
    (void)error;

    P.consumeToken(tok::integer_literal);
    if (parseSILDebugLocation(InstLoc, B))
      return true;

    ResultVal = B.createProjectBox(InstLoc, Val, Index);
    break;
  }

  case SILInstructionKind::ProjectExistentialBoxInst: {
    SILType Ty;
    if (parseSILType(Ty) || parseVerbatim("in") || parseTypedValueRef(Val, B) ||
        parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createProjectExistentialBox(InstLoc, Ty, Val);
    break;
  }

  case SILInstructionKind::FunctionRefInst: {
    SILFunction *Fn;
    if (parseSILFunctionRef(InstLoc, Fn) || parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createFunctionRef(InstLoc, Fn);
    break;
  }

  case SILInstructionKind::DynamicFunctionRefInst: {
    SILFunction *Fn;
    if (parseSILFunctionRef(InstLoc, Fn) || parseSILDebugLocation(InstLoc, B))
      return true;
    // Set a forward reference's dynamic property for the first time.
    if (!Fn->isDynamicallyReplaceable()) {
      if (!Fn->empty()) {
        P.diagnose(P.Tok, diag::expected_dynamic_func_attr);
        return true;
      }
      Fn->setIsDynamic();
    }
    ResultVal = B.createDynamicFunctionRef(InstLoc, Fn);
    break;
  }
  case SILInstructionKind::PreviousDynamicFunctionRefInst: {
    SILFunction *Fn;
    if (parseSILFunctionRef(InstLoc, Fn) || parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createPreviousDynamicFunctionRef(InstLoc, Fn);
    break;
  }

  case SILInstructionKind::BuiltinInst: {
    if (P.Tok.getKind() != tok::string_literal) {
      P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "builtin name");
      return true;
    }
    StringRef Str = P.Tok.getText();
    Identifier Id = P.Context.getIdentifier(Str.substr(1, Str.size() - 2));
    P.consumeToken(tok::string_literal);

    // Find the builtin in the Builtin module
    SmallVector<ValueDecl *, 2> foundBuiltins;
    P.Context.TheBuiltinModule->lookupMember(
        foundBuiltins, P.Context.TheBuiltinModule, Id, Identifier());
    if (foundBuiltins.empty()) {
      P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "builtin name");
      return true;
    }
    assert(foundBuiltins.size() == 1 && "ambiguous builtin name?!");

    auto *builtinFunc = cast<FuncDecl>(foundBuiltins[0]);
    GenericEnvironment *genericEnv = builtinFunc->getGenericEnvironment();

    SmallVector<ParsedSubstitution, 4> parsedSubs;
    SubstitutionMap subMap;
    if (parseSubstitutions(parsedSubs))
      return true;

    if (!parsedSubs.empty()) {
      if (!genericEnv) {
        P.diagnose(P.Tok, diag::sil_substitutions_on_non_polymorphic_type);
        return true;
      }
      subMap = getApplySubstitutionsFromParsed(*this, genericEnv, parsedSubs);
      if (!subMap)
        return true;
    }

    if (P.Tok.getKind() != tok::l_paren) {
      P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "(");
      return true;
    }
    P.consumeToken(tok::l_paren);

    SmallVector<SILValue, 4> Args;
    while (true) {
      if (P.consumeIf(tok::r_paren))
        break;

      SILValue Val;
      if (parseTypedValueRef(Val, B))
        return true;
      Args.push_back(Val);
      if (P.consumeIf(tok::comma))
        continue;
      if (P.consumeIf(tok::r_paren))
        break;
      P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, ")' or ',");
      return true;
    }

    if (P.Tok.getKind() != tok::colon) {
      P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, ":");
      return true;
    }
    P.consumeToken(tok::colon);

    SILType ResultTy;
    if (parseSILType(ResultTy))
      return true;

    if (parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createBuiltin(InstLoc, Id, ResultTy, subMap, Args);
    break;
  }
  case SILInstructionKind::OpenExistentialAddrInst:
    if (parseOpenExistAddrKind() || parseTypedValueRef(Val, B) ||
        parseVerbatim("to") || parseSILType(Ty) ||
        parseSILDebugLocation(InstLoc, B))
      return true;

    ResultVal = B.createOpenExistentialAddr(InstLoc, Val, Ty, AccessKind);
    break;

  case SILInstructionKind::OpenExistentialBoxInst:
    if (parseTypedValueRef(Val, B) || parseVerbatim("to") || parseSILType(Ty) ||
        parseSILDebugLocation(InstLoc, B))
      return true;

    ResultVal = B.createOpenExistentialBox(InstLoc, Val, Ty);
    break;

  case SILInstructionKind::OpenExistentialBoxValueInst:
    if (parseTypedValueRef(Val, B) || parseVerbatim("to") || parseSILType(Ty) ||
        parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createOpenExistentialBoxValue(InstLoc, Val, Ty);
    break;

  case SILInstructionKind::OpenExistentialMetatypeInst:
    if (parseTypedValueRef(Val, B) || parseVerbatim("to") || parseSILType(Ty) ||
        parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createOpenExistentialMetatype(InstLoc, Val, Ty);
    break;

  case SILInstructionKind::OpenExistentialRefInst:
    if (parseTypedValueRef(Val, B) || parseVerbatim("to") || parseSILType(Ty) ||
        parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createOpenExistentialRef(InstLoc, Val, Ty);
    break;

  case SILInstructionKind::OpenExistentialValueInst:
    if (parseTypedValueRef(Val, B) || parseVerbatim("to") || parseSILType(Ty) ||
        parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createOpenExistentialValue(InstLoc, Val, Ty);
    break;

#define UNARY_INSTRUCTION(ID)                                                  \
  case SILInstructionKind::ID##Inst:                                           \
    if (parseTypedValueRef(Val, B))                                            \
      return true;                                                             \
    if (parseSILDebugLocation(InstLoc, B))                                     \
      return true;                                                             \
    ResultVal = B.create##ID(InstLoc, Val);                                    \
    break;

#define REFCOUNTING_INSTRUCTION(ID)                                            \
  case SILInstructionKind::ID##Inst: {                                         \
    Atomicity atomicity = Atomicity::Atomic;                                   \
    StringRef Optional;                                                        \
    if (parseSILOptional(Optional, *this)) {                                   \
      if (Optional == "nonatomic") {                                           \
        atomicity = Atomicity::NonAtomic;                                      \
      } else {                                                                 \
        return true;                                                           \
      }                                                                        \
    }                                                                          \
    if (parseTypedValueRef(Val, B))                                            \
      return true;                                                             \
    if (parseSILDebugLocation(InstLoc, B))                                     \
      return true;                                                             \
    ResultVal = B.create##ID(InstLoc, Val, atomicity);                         \
  } break;

    UNARY_INSTRUCTION(ClassifyBridgeObject)
    UNARY_INSTRUCTION(ValueToBridgeObject)
    UNARY_INSTRUCTION(FixLifetime)
    UNARY_INSTRUCTION(EndLifetime)
    UNARY_INSTRUCTION(CopyBlock)
    UNARY_INSTRUCTION(IsUnique)
    UNARY_INSTRUCTION(DestroyAddr)
    UNARY_INSTRUCTION(CopyValue)
    UNARY_INSTRUCTION(DestroyValue)
    UNARY_INSTRUCTION(EndBorrow)
    UNARY_INSTRUCTION(DestructureStruct)
    UNARY_INSTRUCTION(DestructureTuple)
    UNARY_INSTRUCTION(HopToExecutor)
    REFCOUNTING_INSTRUCTION(UnmanagedReleaseValue)
    REFCOUNTING_INSTRUCTION(UnmanagedRetainValue)
    REFCOUNTING_INSTRUCTION(UnmanagedAutoreleaseValue)
    REFCOUNTING_INSTRUCTION(StrongRetain)
    REFCOUNTING_INSTRUCTION(StrongRelease)
    REFCOUNTING_INSTRUCTION(AutoreleaseValue)
    REFCOUNTING_INSTRUCTION(SetDeallocating)
    REFCOUNTING_INSTRUCTION(ReleaseValue)
    REFCOUNTING_INSTRUCTION(RetainValue)
    REFCOUNTING_INSTRUCTION(ReleaseValueAddr)
    REFCOUNTING_INSTRUCTION(RetainValueAddr)
#define UNCHECKED_REF_STORAGE(Name, ...)                                       \
  UNARY_INSTRUCTION(StrongCopy##Name##Value)
#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...)            \
  REFCOUNTING_INSTRUCTION(StrongRetain##Name)                                  \
  REFCOUNTING_INSTRUCTION(Name##Retain)                                        \
  REFCOUNTING_INSTRUCTION(Name##Release)                                       \
  UNARY_INSTRUCTION(StrongCopy##Name##Value)
#include "swift/AST/ReferenceStorage.def"
#undef UNARY_INSTRUCTION
#undef REFCOUNTING_INSTRUCTION

  case SILInstructionKind::BeginCOWMutationInst: {
    bool native = false;
    if (parseSILOptional(native, *this, "native") ||
        parseTypedValueRef(Val, B) ||
        parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createBeginCOWMutation(InstLoc, Val, native);
    break;
  }
  case SILInstructionKind::EndCOWMutationInst: {
    bool keepUnique = false;
    if (parseSILOptional(keepUnique, *this, "keep_unique") ||
        parseTypedValueRef(Val, B) ||
        parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createEndCOWMutation(InstLoc, Val, keepUnique);
    break;
  }
  case SILInstructionKind::IsEscapingClosureInst: {
    bool IsObjcVerifcationType = false;
    if (parseSILOptional(IsObjcVerifcationType, *this, "objc"))
      return true;
    if (parseTypedValueRef(Val, B) || parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createIsEscapingClosure(
        InstLoc, Val,
        IsObjcVerifcationType ? IsEscapingClosureInst::ObjCEscaping
                              : IsEscapingClosureInst::WithoutActuallyEscaping);
    break;
  }

  case SILInstructionKind::DebugValueInst:
  case SILInstructionKind::DebugValueAddrInst: {
    SILDebugVariable VarInfo;
    if (parseTypedValueRef(Val, B) || parseSILDebugVar(VarInfo) ||
        parseSILDebugLocation(InstLoc, B))
      return true;
    if (Opcode == SILInstructionKind::DebugValueInst)
      ResultVal = B.createDebugValue(InstLoc, Val, VarInfo);
    else
      ResultVal = B.createDebugValueAddr(InstLoc, Val, VarInfo);
    break;
  }

    // unchecked_ownership_conversion <reg> : <type>, <ownership> to <ownership>
  case SILInstructionKind::UncheckedOwnershipConversionInst: {
    ValueOwnershipKind LHSKind = OwnershipKind::None;
    ValueOwnershipKind RHSKind = OwnershipKind::None;
    SourceLoc Loc;

    if (parseTypedValueRef(Val, Loc, B) ||
        P.parseToken(tok::comma, diag::expected_sil_colon,
                     "unchecked_ownership_conversion value ownership kind "
                     "conversion specification") ||
        parseSILOwnership(LHSKind) || parseVerbatim("to") ||
        parseSILOwnership(RHSKind) || parseSILDebugLocation(InstLoc, B)) {
      return true;
    }

    if (Val.getOwnershipKind() != LHSKind) {
      return true;
    }

    ResultVal = B.createUncheckedOwnershipConversion(InstLoc, Val, RHSKind);
    break;
  }

  case SILInstructionKind::LoadInst: {
    LoadOwnershipQualifier Qualifier;
    SourceLoc AddrLoc;

    if (parseLoadOwnershipQualifier(Qualifier, *this) ||
        parseTypedValueRef(Val, AddrLoc, B) ||
        parseSILDebugLocation(InstLoc, B))
      return true;

    ResultVal = B.createLoad(InstLoc, Val, Qualifier);
    break;
  }

  case SILInstructionKind::LoadBorrowInst: {
    SourceLoc AddrLoc;

    if (parseTypedValueRef(Val, AddrLoc, B) ||
        parseSILDebugLocation(InstLoc, B))
      return true;

    ResultVal = B.createLoadBorrow(InstLoc, Val);
    break;
  }

  case SILInstructionKind::BeginBorrowInst: {
    SourceLoc AddrLoc;

    if (parseTypedValueRef(Val, AddrLoc, B) ||
        parseSILDebugLocation(InstLoc, B))
      return true;

    ResultVal = B.createBeginBorrow(InstLoc, Val);
    break;
  }

#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...)             \
  case SILInstructionKind::Load##Name##Inst: {                                 \
    bool isTake = false;                                                       \
    SourceLoc addrLoc;                                                         \
    if (parseSILOptional(isTake, *this, "take") ||                             \
        parseTypedValueRef(Val, addrLoc, B) ||                                 \
        parseSILDebugLocation(InstLoc, B))                                     \
      return true;                                                             \
    if (!Val->getType().is<Name##StorageType>()) {                             \
      P.diagnose(addrLoc, diag::sil_operand_not_ref_storage_address, "source", \
                 OpcodeName, ReferenceOwnership::Name);                        \
    }                                                                          \
    ResultVal = B.createLoad##Name(InstLoc, Val, IsTake_t(isTake));            \
    break;                                                                     \
  }
#include "swift/AST/ReferenceStorage.def"

  case SILInstructionKind::CopyBlockWithoutEscapingInst: {
    SILValue Closure;
    if (parseTypedValueRef(Val, B) || parseVerbatim("withoutEscaping") ||
        parseTypedValueRef(Closure, B) || parseSILDebugLocation(InstLoc, B))
      return true;

    ResultVal = B.createCopyBlockWithoutEscaping(InstLoc, Val, Closure);
    break;
  }

  case SILInstructionKind::MarkDependenceInst: {
    SILValue Base;
    if (parseTypedValueRef(Val, B) || parseVerbatim("on") ||
        parseTypedValueRef(Base, B) || parseSILDebugLocation(InstLoc, B))
      return true;

    ResultVal = B.createMarkDependence(InstLoc, Val, Base);
    break;
  }

  case SILInstructionKind::KeyPathInst: {
    SmallVector<KeyPathPatternComponent, 4> components;
    SILType Ty;
    if (parseSILType(Ty) ||
        P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ","))
      return true;

    GenericParamList *patternParams = nullptr;
    GenericEnvironment *patternEnv = nullptr;
    CanType rootType;
    StringRef objcString;
    SmallVector<SILType, 4> operandTypes;
    {
      patternParams = P.maybeParseGenericParams().getPtrOrNull();
      patternEnv = handleSILGenericParams(patternParams, &P.SF);

      if (P.parseToken(tok::l_paren, diag::expected_tok_in_sil_instr, "("))
        return true;

      while (true) {
        Identifier componentKind;
        SourceLoc componentLoc;
        if (parseSILIdentifier(componentKind, componentLoc,
                               diag::sil_keypath_expected_component_kind))
          return true;

        if (componentKind.str() == "root") {
          if (P.parseToken(tok::sil_dollar, diag::expected_tok_in_sil_instr,
                           "$") ||
              parseASTType(rootType, patternEnv, patternParams))
            return true;
        } else if (componentKind.str() == "objc") {
          auto tok = P.Tok;
          if (P.parseToken(tok::string_literal, diag::expected_tok_in_sil_instr,
                           "string literal"))
            return true;

          auto objcStringValue = tok.getText().drop_front().drop_back();
          objcString =
              StringRef(P.Context.AllocateCopy<char>(objcStringValue.begin(),
                                                     objcStringValue.end()),
                        objcStringValue.size());
        } else {
          KeyPathPatternComponent component;
          if (parseKeyPathPatternComponent(component, operandTypes,
                                           componentLoc, componentKind, InstLoc,
                                           patternEnv, patternParams))
            return true;
          components.push_back(component);
        }

        if (!P.consumeIf(tok::semi))
          break;
      }

      if (P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")") ||
          parseSILDebugLocation(InstLoc, B))
        return true;
    }

    if (rootType.isNull())
      P.diagnose(InstLoc.getSourceLoc(), diag::sil_keypath_no_root);

    SmallVector<ParsedSubstitution, 4> parsedSubs;
    if (parseSubstitutions(parsedSubs, ContextGenericEnv, ContextGenericParams))
      return true;

    SubstitutionMap subMap;
    if (!parsedSubs.empty()) {
      if (!patternEnv) {
        P.diagnose(InstLoc.getSourceLoc(),
                   diag::sil_substitutions_on_non_polymorphic_type);
        return true;
      }

      subMap = getApplySubstitutionsFromParsed(*this, patternEnv, parsedSubs);
      if (!subMap)
        return true;
    }

    SmallVector<SILValue, 4> operands;

    if (P.consumeIf(tok::l_paren)) {
      while (true) {
        SILValue v;

        if (operands.size() >= operandTypes.size() ||
            !operandTypes[operands.size()]) {
          P.diagnose(P.Tok, diag::sil_keypath_no_use_of_operand_in_pattern,
                     operands.size());
          return true;
        }

        auto ty = operandTypes[operands.size()].subst(SILMod, subMap);

        if (parseValueRef(v, ty, RegularLocation(P.Tok.getLoc()), B))
          return true;
        operands.push_back(v);

        if (P.consumeIf(tok::comma))
          continue;
        if (P.consumeIf(tok::r_paren))
          break;
        return true;
      }
    }

    if (parseSILDebugLocation(InstLoc, B))
      return true;

    CanGenericSignature canSig;
    if (patternEnv && patternEnv->getGenericSignature()) {
      canSig = patternEnv->getGenericSignature().getCanonicalSignature();
    }
    CanType leafType;
    if (!components.empty())
      leafType = components.back().getComponentType();
    else
      leafType = rootType;
    auto pattern = KeyPathPattern::get(B.getModule(), canSig, rootType,
                                       leafType, components, objcString);

    ResultVal = B.createKeyPath(InstLoc, pattern, subMap, operands, Ty);
    break;
  }

    // Conversion instructions.
  case SILInstructionKind::UncheckedRefCastInst:
  case SILInstructionKind::UncheckedAddrCastInst:
  case SILInstructionKind::UncheckedTrivialBitCastInst:
  case SILInstructionKind::UncheckedBitwiseCastInst:
  case SILInstructionKind::UncheckedValueCastInst:
  case SILInstructionKind::UpcastInst:
  case SILInstructionKind::AddressToPointerInst:
  case SILInstructionKind::BridgeObjectToRefInst:
  case SILInstructionKind::BridgeObjectToWordInst:
  case SILInstructionKind::RefToRawPointerInst:
  case SILInstructionKind::RawPointerToRefInst:
#define LOADABLE_REF_STORAGE(Name, ...)                                        \
  case SILInstructionKind::RefTo##Name##Inst:                                  \
  case SILInstructionKind::Name##ToRefInst:
#include "swift/AST/ReferenceStorage.def"
  case SILInstructionKind::ThinFunctionToPointerInst:
  case SILInstructionKind::PointerToThinFunctionInst:
  case SILInstructionKind::ThinToThickFunctionInst:
  case SILInstructionKind::ThickToObjCMetatypeInst:
  case SILInstructionKind::ObjCToThickMetatypeInst:
  case SILInstructionKind::ConvertFunctionInst:
  case SILInstructionKind::ConvertEscapeToNoEscapeInst:
  case SILInstructionKind::ObjCExistentialMetatypeToObjectInst:
  case SILInstructionKind::ObjCMetatypeToObjectInst: {
    SILType Ty;
    Identifier ToToken;
    SourceLoc ToLoc;
    bool not_guaranteed = false;
    bool without_actually_escaping = false;
    if (Opcode == SILInstructionKind::ConvertEscapeToNoEscapeInst) {
      StringRef attrName;
      if (parseSILOptional(attrName, *this)) {
        if (attrName.equals("not_guaranteed"))
          not_guaranteed = true;
        else
          return true;
      }
    }
    if (parseTypedValueRef(Val, B) ||
        parseSILIdentifier(ToToken, ToLoc, diag::expected_tok_in_sil_instr,
                           "to"))
      return true;

    if (ToToken.str() != "to") {
      P.diagnose(ToLoc, diag::expected_tok_in_sil_instr, "to");
      return true;
    }
    if (Opcode == SILInstructionKind::ConvertFunctionInst) {
      StringRef attrName;
      if (parseSILOptional(attrName, *this)) {
        if (attrName.equals("without_actually_escaping"))
          without_actually_escaping = true;
        else
          return true;
      }
    }
    if (parseSILType(Ty) || parseSILDebugLocation(InstLoc, B))
      return true;

    switch (Opcode) {
    default:
      llvm_unreachable("Out of sync with parent switch");
    case SILInstructionKind::UncheckedRefCastInst:
      ResultVal = B.createUncheckedRefCast(InstLoc, Val, Ty);
      break;
    case SILInstructionKind::UncheckedAddrCastInst:
      ResultVal = B.createUncheckedAddrCast(InstLoc, Val, Ty);
      break;
    case SILInstructionKind::UncheckedTrivialBitCastInst:
      ResultVal = B.createUncheckedTrivialBitCast(InstLoc, Val, Ty);
      break;
    case SILInstructionKind::UncheckedBitwiseCastInst:
      ResultVal = B.createUncheckedBitwiseCast(InstLoc, Val, Ty);
      break;
    case SILInstructionKind::UncheckedValueCastInst:
      ResultVal = B.createUncheckedValueCast(InstLoc, Val, Ty);
      break;
    case SILInstructionKind::UpcastInst:
      ResultVal = B.createUpcast(InstLoc, Val, Ty);
      break;
    case SILInstructionKind::ConvertFunctionInst:
      ResultVal =
          B.createConvertFunction(InstLoc, Val, Ty, without_actually_escaping);
      break;
    case SILInstructionKind::ConvertEscapeToNoEscapeInst:
      ResultVal =
          B.createConvertEscapeToNoEscape(InstLoc, Val, Ty, !not_guaranteed);
      break;
    case SILInstructionKind::AddressToPointerInst:
      ResultVal = B.createAddressToPointer(InstLoc, Val, Ty);
      break;
    case SILInstructionKind::BridgeObjectToRefInst:
      ResultVal = B.createBridgeObjectToRef(InstLoc, Val, Ty);
      break;
    case SILInstructionKind::BridgeObjectToWordInst:
      ResultVal = B.createBridgeObjectToWord(InstLoc, Val);
      break;
    case SILInstructionKind::RefToRawPointerInst:
      ResultVal = B.createRefToRawPointer(InstLoc, Val, Ty);
      break;
    case SILInstructionKind::RawPointerToRefInst:
      ResultVal = B.createRawPointerToRef(InstLoc, Val, Ty);
      break;
#define LOADABLE_REF_STORAGE(Name, ...)                                        \
  case SILInstructionKind::RefTo##Name##Inst:                                  \
    ResultVal = B.createRefTo##Name(InstLoc, Val, Ty);                         \
    break;                                                                     \
  case SILInstructionKind::Name##ToRefInst:                                    \
    ResultVal = B.create##Name##ToRef(InstLoc, Val, Ty);                       \
    break;
#include "swift/AST/ReferenceStorage.def"
    case SILInstructionKind::ThinFunctionToPointerInst:
      ResultVal = B.createThinFunctionToPointer(InstLoc, Val, Ty);
      break;
    case SILInstructionKind::PointerToThinFunctionInst:
      ResultVal = B.createPointerToThinFunction(InstLoc, Val, Ty);
      break;
    case SILInstructionKind::ThinToThickFunctionInst:
      ResultVal = B.createThinToThickFunction(InstLoc, Val, Ty);
      break;
    case SILInstructionKind::ThickToObjCMetatypeInst:
      ResultVal = B.createThickToObjCMetatype(InstLoc, Val, Ty);
      break;
    case SILInstructionKind::ObjCToThickMetatypeInst:
      ResultVal = B.createObjCToThickMetatype(InstLoc, Val, Ty);
      break;
    case SILInstructionKind::ObjCMetatypeToObjectInst:
      ResultVal = B.createObjCMetatypeToObject(InstLoc, Val, Ty);
      break;
    case SILInstructionKind::ObjCExistentialMetatypeToObjectInst:
      ResultVal = B.createObjCExistentialMetatypeToObject(InstLoc, Val, Ty);
      break;
    }
    break;
  }
  case SILInstructionKind::PointerToAddressInst: {
    SILType Ty;
    Identifier ToToken;
    SourceLoc ToLoc;
    StringRef attr;
    if (parseTypedValueRef(Val, B) ||
        parseSILIdentifier(ToToken, ToLoc, diag::expected_tok_in_sil_instr,
                           "to"))
      return true;
    if (parseSILOptional(attr, *this) && attr.empty())
      return true;
    if (parseSILType(Ty) || parseSILDebugLocation(InstLoc, B))
      return true;

    bool isStrict = attr.equals("strict");
    bool isInvariant = attr.equals("invariant");

    if (ToToken.str() != "to") {
      P.diagnose(ToLoc, diag::expected_tok_in_sil_instr, "to");
      return true;
    }

    ResultVal =
        B.createPointerToAddress(InstLoc, Val, Ty, isStrict, isInvariant);
    break;
  }
  case SILInstructionKind::RefToBridgeObjectInst: {
    SILValue BitsVal;
    if (parseTypedValueRef(Val, B) ||
        P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
        parseTypedValueRef(BitsVal, B) || parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createRefToBridgeObject(InstLoc, Val, BitsVal);
    break;
  }

  case SILInstructionKind::CheckedCastAddrBranchInst: {
    Identifier consumptionKindToken;
    SourceLoc consumptionKindLoc;
    if (parseSILIdentifier(consumptionKindToken, consumptionKindLoc,
                           diag::expected_tok_in_sil_instr,
                           "cast consumption kind")) {
      return true;
    }
    // NOTE: BorrowAlways is not a supported cast kind for address types, so we
    // purposely do not parse it here.
    auto kind = llvm::StringSwitch<Optional<CastConsumptionKind>>(
                    consumptionKindToken.str())
                    .Case("take_always", CastConsumptionKind::TakeAlways)
                    .Case("take_on_success", CastConsumptionKind::TakeOnSuccess)
                    .Case("copy_on_success", CastConsumptionKind::CopyOnSuccess)
                    .Default(None);

    if (!kind) {
      P.diagnose(consumptionKindLoc, diag::expected_tok_in_sil_instr,
                 "cast consumption kind");
      return true;
    }
    auto consumptionKind = kind.getValue();

    if (parseSourceAndDestAddress() || parseConditionalBranchDestinations() ||
        parseSILDebugLocation(InstLoc, B))
      return true;

    ResultVal = B.createCheckedCastAddrBranch(
        InstLoc, consumptionKind, SourceAddr, SourceType, DestAddr, TargetType,
        getBBForReference(SuccessBBName, SuccessBBLoc),
        getBBForReference(FailureBBName, FailureBBLoc));
    break;
  }
  case SILInstructionKind::UncheckedRefCastAddrInst:
    if (parseSourceAndDestAddress() || parseSILDebugLocation(InstLoc, B))
      return true;

    ResultVal = B.createUncheckedRefCastAddr(InstLoc, SourceAddr, SourceType,
                                             DestAddr, TargetType);
    break;

  case SILInstructionKind::UnconditionalCheckedCastAddrInst:
    if (parseSourceAndDestAddress() || parseSILDebugLocation(InstLoc, B))
      return true;

    ResultVal = B.createUnconditionalCheckedCastAddr(
        InstLoc, SourceAddr, SourceType, DestAddr, TargetType);
    break;

  case SILInstructionKind::UnconditionalCheckedCastValueInst: {
    if (parseASTType(SourceType) || parseVerbatim("in") ||
        parseTypedValueRef(Val, B) || parseVerbatim("to") ||
        parseASTType(TargetType) || parseSILDebugLocation(InstLoc, B))
      return true;

    auto opaque = Lowering::AbstractionPattern::getOpaque();
    ResultVal = B.createUnconditionalCheckedCastValue(
        InstLoc, Val, SourceType, F->getLoweredType(opaque, TargetType),
        TargetType);
    break;
  }

  case SILInstructionKind::UnconditionalCheckedCastInst: {
    if (parseTypedValueRef(Val, B) || parseVerbatim("to") ||
        parseASTType(TargetType))
      return true;

    if (parseSILDebugLocation(InstLoc, B))
      return true;

    auto opaque = Lowering::AbstractionPattern::getOpaque();
    ResultVal = B.createUnconditionalCheckedCast(
        InstLoc, Val, F->getLoweredType(opaque, TargetType), TargetType);
    break;
  }

  case SILInstructionKind::CheckedCastBranchInst: {
    bool isExact = false;
    if (Opcode == SILInstructionKind::CheckedCastBranchInst &&
        parseSILOptional(isExact, *this, "exact"))
      return true;

    if (parseTypedValueRef(Val, B) || parseVerbatim("to") ||
        parseASTType(TargetType) || parseConditionalBranchDestinations())
      return true;

    auto opaque = Lowering::AbstractionPattern::getOpaque();
    ResultVal = B.createCheckedCastBranch(
        InstLoc, isExact, Val, F->getLoweredType(opaque, TargetType),
        TargetType, getBBForReference(SuccessBBName, SuccessBBLoc),
        getBBForReference(FailureBBName, FailureBBLoc));
    break;
  }
  case SILInstructionKind::CheckedCastValueBranchInst: {
    if (parseASTType(SourceType) || parseVerbatim("in") ||
        parseTypedValueRef(Val, B) || parseVerbatim("to") ||
        parseASTType(TargetType) || parseConditionalBranchDestinations())
      return true;

    auto opaque = Lowering::AbstractionPattern::getOpaque();
    ResultVal = B.createCheckedCastValueBranch(
        InstLoc, Val, SourceType, F->getLoweredType(opaque, TargetType),
        TargetType, getBBForReference(SuccessBBName, SuccessBBLoc),
        getBBForReference(FailureBBName, FailureBBLoc));
    break;
  }

  case SILInstructionKind::MarkUninitializedInst: {
    if (P.parseToken(tok::l_square, diag::expected_tok_in_sil_instr, "["))
      return true;

    Identifier KindId;
    SourceLoc KindLoc = P.Tok.getLoc();
    if (P.consumeIf(tok::kw_var))
      KindId = P.Context.getIdentifier("var");
    else if (P.parseIdentifier(KindId, KindLoc, /*diagnoseDollarPrefix=*/false,
                               diag::expected_tok_in_sil_instr, "kind"))
      return true;

    if (P.parseToken(tok::r_square, diag::expected_tok_in_sil_instr, "]"))
      return true;

    MarkUninitializedInst::Kind Kind;
    if (KindId.str() == "var")
      Kind = MarkUninitializedInst::Var;
    else if (KindId.str() == "rootself")
      Kind = MarkUninitializedInst::RootSelf;
    else if (KindId.str() == "crossmodulerootself")
      Kind = MarkUninitializedInst::CrossModuleRootSelf;
    else if (KindId.str() == "derivedself")
      Kind = MarkUninitializedInst::DerivedSelf;
    else if (KindId.str() == "derivedselfonly")
      Kind = MarkUninitializedInst::DerivedSelfOnly;
    else if (KindId.str() == "delegatingself")
      Kind = MarkUninitializedInst::DelegatingSelf;
    else if (KindId.str() == "delegatingselfallocated")
      Kind = MarkUninitializedInst::DelegatingSelfAllocated;
    else {
      P.diagnose(KindLoc, diag::expected_tok_in_sil_instr,
                 "var, rootself, crossmodulerootself, derivedself, "
                 "derivedselfonly, delegatingself, or delegatingselfallocated");
      return true;
    }

    if (parseTypedValueRef(Val, B) || parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createMarkUninitialized(InstLoc, Val, Kind);
    break;
  }

  case SILInstructionKind::MarkFunctionEscapeInst: {
    SmallVector<SILValue, 4> OpList;
    do {
      if (parseTypedValueRef(Val, B))
        return true;
      OpList.push_back(Val);
    } while (!peekSILDebugLocation(P) && P.consumeIf(tok::comma));

    if (parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createMarkFunctionEscape(InstLoc, OpList);
    break;
  }

  case SILInstructionKind::AssignInst:
  case SILInstructionKind::StoreInst: {
    UnresolvedValueName From;
    SourceLoc ToLoc, AddrLoc;
    Identifier ToToken;
    SILValue AddrVal;
    StoreOwnershipQualifier StoreQualifier;
    AssignOwnershipQualifier AssignQualifier;
    bool IsStore = Opcode == SILInstructionKind::StoreInst;
    bool IsAssign = Opcode == SILInstructionKind::AssignInst;
    if (parseValueName(From) ||
        parseSILIdentifier(ToToken, ToLoc, diag::expected_tok_in_sil_instr,
                           "to"))
      return true;

    if (IsStore && parseStoreOwnershipQualifier(StoreQualifier, *this))
      return true;

    if (IsAssign && parseAssignOwnershipQualifier(AssignQualifier, *this))
      return true;

    if (parseTypedValueRef(AddrVal, AddrLoc, B) ||
        parseSILDebugLocation(InstLoc, B))
      return true;

    if (ToToken.str() != "to") {
      P.diagnose(ToLoc, diag::expected_tok_in_sil_instr, "to");
      return true;
    }

    if (!AddrVal->getType().isAddress()) {
      P.diagnose(AddrLoc, diag::sil_operand_not_address, "destination",
                 OpcodeName);
      return true;
    }

    SILType ValType = AddrVal->getType().getObjectType();

    if (IsStore) {
      ResultVal =
          B.createStore(InstLoc, getLocalValue(From, ValType, InstLoc, B),
                        AddrVal, StoreQualifier);
    } else {
      assert(IsAssign);

      ResultVal =
          B.createAssign(InstLoc, getLocalValue(From, ValType, InstLoc, B),
                         AddrVal, AssignQualifier);
    }

    break;
  }

  case SILInstructionKind::AssignByWrapperInst: {
    SILValue Src, DestAddr, InitFn, SetFn;
    SourceLoc DestLoc;
    AssignOwnershipQualifier AssignQualifier;
    if (parseTypedValueRef(Src, B) || parseVerbatim("to") ||
        parseAssignOwnershipQualifier(AssignQualifier, *this) ||
        parseTypedValueRef(DestAddr, DestLoc, B) ||
        P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
        parseVerbatim("init") || parseTypedValueRef(InitFn, B) ||
        P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
        parseVerbatim("set") || parseTypedValueRef(SetFn, B) ||
        parseSILDebugLocation(InstLoc, B))
      return true;

    if (!DestAddr->getType().isAddress()) {
      P.diagnose(DestLoc, diag::sil_operand_not_address, "destination",
                 OpcodeName);
      return true;
    }

    ResultVal = B.createAssignByWrapper(InstLoc, Src, DestAddr, InitFn, SetFn,
                                        AssignQualifier);
    break;
  }

  case SILInstructionKind::BeginAccessInst:
  case SILInstructionKind::BeginUnpairedAccessInst:
  case SILInstructionKind::EndAccessInst:
  case SILInstructionKind::EndUnpairedAccessInst: {
    ParsedEnum<SILAccessKind> kind;
    ParsedEnum<SILAccessEnforcement> enforcement;
    ParsedEnum<bool> aborting;
    ParsedEnum<bool> noNestedConflict;
    ParsedEnum<bool> fromBuiltin;

    bool isBeginAccess =
        (Opcode == SILInstructionKind::BeginAccessInst ||
         Opcode == SILInstructionKind::BeginUnpairedAccessInst);
    bool wantsEnforcement =
        (isBeginAccess || Opcode == SILInstructionKind::EndUnpairedAccessInst);

    while (P.consumeIf(tok::l_square)) {
      Identifier ident;
      SourceLoc identLoc;
      if (parseSILIdentifier(ident, identLoc,
                             diag::expected_in_attribute_list)) {
        if (P.consumeIf(tok::r_square)) {
          continue;
        } else {
          return true;
        }
      }
      StringRef attr = ident.str();

      auto setEnforcement = [&](SILAccessEnforcement value) {
        maybeSetEnum(wantsEnforcement, enforcement, value, attr, identLoc);
      };
      auto setKind = [&](SILAccessKind value) {
        maybeSetEnum(isBeginAccess, kind, value, attr, identLoc);
      };
      auto setAborting = [&](bool value) {
        maybeSetEnum(!isBeginAccess, aborting, value, attr, identLoc);
      };
      auto setNoNestedConflict = [&](bool value) {
        maybeSetEnum(isBeginAccess, noNestedConflict, value, attr, identLoc);
      };
      auto setFromBuiltin = [&](bool value) {
        maybeSetEnum(Opcode != SILInstructionKind::EndAccessInst, fromBuiltin,
                     value, attr, identLoc);
      };

      if (attr == "unknown") {
        setEnforcement(SILAccessEnforcement::Unknown);
      } else if (attr == "static") {
        setEnforcement(SILAccessEnforcement::Static);
      } else if (attr == "dynamic") {
        setEnforcement(SILAccessEnforcement::Dynamic);
      } else if (attr == "unsafe") {
        setEnforcement(SILAccessEnforcement::Unsafe);
      } else if (attr == "init") {
        setKind(SILAccessKind::Init);
      } else if (attr == "read") {
        setKind(SILAccessKind::Read);
      } else if (attr == "modify") {
        setKind(SILAccessKind::Modify);
      } else if (attr == "deinit") {
        setKind(SILAccessKind::Deinit);
      } else if (attr == "abort") {
        setAborting(true);
      } else if (attr == "no_nested_conflict") {
        setNoNestedConflict(true);
      } else if (attr == "builtin") {
        setFromBuiltin(true);
      } else {
        P.diagnose(identLoc, diag::unknown_attribute, attr);
      }

      if (!P.consumeIf(tok::r_square))
        return true;
    }

    if (isBeginAccess && !kind.isSet()) {
      P.diagnose(OpcodeLoc, diag::sil_expected_access_kind, OpcodeName);
      kind.Value = SILAccessKind::Read;
    }

    if (wantsEnforcement && !enforcement.isSet()) {
      P.diagnose(OpcodeLoc, diag::sil_expected_access_enforcement, OpcodeName);
      enforcement.Value = SILAccessEnforcement::Unsafe;
    }

    if (!isBeginAccess && !aborting.isSet())
      aborting.Value = false;

    if (isBeginAccess && !noNestedConflict.isSet())
      noNestedConflict.Value = false;

    if (!fromBuiltin.isSet())
      fromBuiltin.Value = false;

    SILValue addrVal;
    SourceLoc addrLoc;
    if (parseTypedValueRef(addrVal, addrLoc, B))
      return true;

    SILValue bufferVal;
    SourceLoc bufferLoc;
    if (Opcode == SILInstructionKind::BeginUnpairedAccessInst &&
        (P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
         parseTypedValueRef(bufferVal, bufferLoc, B)))
      return true;

    if (parseSILDebugLocation(InstLoc, B))
      return true;

    if (!addrVal->getType().isAddress()) {
      P.diagnose(addrLoc, diag::sil_operand_not_address, "operand", OpcodeName);
      return true;
    }

    if (Opcode == SILInstructionKind::BeginAccessInst) {
      ResultVal = B.createBeginAccess(InstLoc, addrVal, *kind, *enforcement,
                                      *noNestedConflict, *fromBuiltin);
    } else if (Opcode == SILInstructionKind::EndAccessInst) {
      ResultVal = B.createEndAccess(InstLoc, addrVal, *aborting);
    } else if (Opcode == SILInstructionKind::BeginUnpairedAccessInst) {
      ResultVal = B.createBeginUnpairedAccess(InstLoc, addrVal, bufferVal,
                                              *kind, *enforcement,
                                              *noNestedConflict, *fromBuiltin);
    } else {
      ResultVal = B.createEndUnpairedAccess(InstLoc, addrVal, *enforcement,
                                            *aborting, *fromBuiltin);
    }
    break;
  }

#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...)             \
  case SILInstructionKind::Store##Name##Inst:
#include "swift/AST/ReferenceStorage.def"
  case SILInstructionKind::StoreBorrowInst: {
    UnresolvedValueName from;
    bool isRefStorage = false;
#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...)             \
  isRefStorage |= Opcode == SILInstructionKind::Store##Name##Inst;
#include "swift/AST/ReferenceStorage.def"

    SourceLoc toLoc, addrLoc;
    Identifier toToken;
    SILValue addrVal;
    bool isInit = false;
    if (parseValueName(from) ||
        parseSILIdentifier(toToken, toLoc, diag::expected_tok_in_sil_instr,
                           "to") ||
        (isRefStorage && parseSILOptional(isInit, *this, "initialization")) ||
        parseTypedValueRef(addrVal, addrLoc, B) ||
        parseSILDebugLocation(InstLoc, B))
      return true;

    if (toToken.str() != "to") {
      P.diagnose(toLoc, diag::expected_tok_in_sil_instr, "to");
      return true;
    }

    if (!addrVal->getType().isAddress()) {
      P.diagnose(addrLoc, diag::sil_operand_not_address, "destination",
                 OpcodeName);
      return true;
    }

    if (Opcode == SILInstructionKind::StoreBorrowInst) {
      SILType valueTy = addrVal->getType().getObjectType();
      ResultVal = B.createStoreBorrow(
          InstLoc, getLocalValue(from, valueTy, InstLoc, B), addrVal);
      break;
    }

#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...)             \
  if (Opcode == SILInstructionKind::Store##Name##Inst) {                       \
    auto refType = addrVal->getType().getAs<Name##StorageType>();              \
    if (!refType) {                                                            \
      P.diagnose(addrLoc, diag::sil_operand_not_ref_storage_address,           \
                 "destination", OpcodeName, ReferenceOwnership::Name);         \
      return true;                                                             \
    }                                                                          \
    auto valueTy = SILType::getPrimitiveObjectType(refType.getReferentType()); \
    ResultVal =                                                                \
        B.createStore##Name(InstLoc, getLocalValue(from, valueTy, InstLoc, B), \
                            addrVal, IsInitialization_t(isInit));              \
    break;                                                                     \
  }
#include "swift/AST/ReferenceStorage.def"

    break;
  }
  case SILInstructionKind::AllocStackInst:
  case SILInstructionKind::MetatypeInst: {

    bool hasDynamicLifetime = false;
    if (Opcode == SILInstructionKind::AllocStackInst &&
        parseSILOptional(hasDynamicLifetime, *this, "dynamic_lifetime"))
      return true;

    SILType Ty;
    if (parseSILType(Ty))
      return true;

    if (Opcode == SILInstructionKind::AllocStackInst) {
      SILDebugVariable VarInfo;
      if (parseSILDebugVar(VarInfo) || parseSILDebugLocation(InstLoc, B))
        return true;
      ResultVal = B.createAllocStack(InstLoc, Ty, VarInfo, hasDynamicLifetime);
    } else {
      assert(Opcode == SILInstructionKind::MetatypeInst);
      if (parseSILDebugLocation(InstLoc, B))
        return true;
      ResultVal = B.createMetatype(InstLoc, Ty);
    }
    break;
  }
  case SILInstructionKind::AllocRefInst:
  case SILInstructionKind::AllocRefDynamicInst: {
    bool IsObjC = false;
    bool OnStack = false;
    SmallVector<SILType, 2> ElementTypes;
    SmallVector<SILValue, 2> ElementCounts;
    while (P.consumeIf(tok::l_square)) {
      Identifier Id;
      parseSILIdentifier(Id, diag::expected_in_attribute_list);
      StringRef Optional = Id.str();
      if (Optional == "objc") {
        IsObjC = true;
      } else if (Optional == "stack") {
        OnStack = true;
      } else if (Optional == "tail_elems") {
        SILType ElemTy;
        if (parseSILType(ElemTy) || !P.Tok.isAnyOperator() ||
            P.Tok.getText() != "*")
          return true;
        P.consumeToken();

        SILValue ElemCount;
        if (parseTypedValueRef(ElemCount, B))
          return true;

        ElementTypes.push_back(ElemTy);
        ElementCounts.push_back(ElemCount);
      } else {
        return true;
      }
      P.parseToken(tok::r_square, diag::expected_in_attribute_list);
    }
    SILValue Metadata;
    if (Opcode == SILInstructionKind::AllocRefDynamicInst) {
      if (parseTypedValueRef(Metadata, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ","))
        return true;
    }

    SILType ObjectType;
    if (parseSILType(ObjectType))
      return true;

    if (parseSILDebugLocation(InstLoc, B))
      return true;

    if (IsObjC && !ElementTypes.empty()) {
      P.diagnose(P.Tok, diag::sil_objc_with_tail_elements);
      return true;
    }
    if (Opcode == SILInstructionKind::AllocRefDynamicInst) {
      if (OnStack)
        return true;

      ResultVal = B.createAllocRefDynamic(InstLoc, Metadata, ObjectType, IsObjC,
                                          ElementTypes, ElementCounts);
    } else {
      ResultVal = B.createAllocRef(InstLoc, ObjectType, IsObjC, OnStack,
                                   ElementTypes, ElementCounts);
    }
    break;
  }

  case SILInstructionKind::DeallocStackInst:
    if (parseTypedValueRef(Val, B) || parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createDeallocStack(InstLoc, Val);
    break;
  case SILInstructionKind::DeallocRefInst: {
    bool OnStack = false;
    if (parseSILOptional(OnStack, *this, "stack"))
      return true;

    if (parseTypedValueRef(Val, B) || parseSILDebugLocation(InstLoc, B))
      return true;
    ResultVal = B.createDeallocRef(InstLoc, Val, OnStack);
    break;
  }
  case SILInstructionKind::DeallocPartialRefInst: {
    SILValue Metatype, Instance;
    if (parseTypedValueRef(Instance, B) ||
        P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
        parseTypedValueRef(Metatype, B) || parseSILDebugLocation(InstLoc, B))
      return true;

    ResultVal = B.createDeallocPartialRef(InstLoc, Instance, Metatype);
    break;
  }
    case SILInstructionKind::DeallocBoxInst:
      if (parseTypedValueRef(Val, B) || parseSILDebugLocation(InstLoc, B))
        return true;

      ResultVal = B.createDeallocBox(InstLoc, Val);
      break;
    case SILInstructionKind::ValueMetatypeInst:
    case SILInstructionKind::ExistentialMetatypeInst: {
      SILType Ty;
      if (parseSILType(Ty) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseTypedValueRef(Val, B) || parseSILDebugLocation(InstLoc, B))
        return true;
      switch (Opcode) {
      default:
        llvm_unreachable("Out of sync with parent switch");
      case SILInstructionKind::ValueMetatypeInst:
        ResultVal = B.createValueMetatype(InstLoc, Ty, Val);
        break;
      case SILInstructionKind::ExistentialMetatypeInst:
        ResultVal = B.createExistentialMetatype(InstLoc, Ty, Val);
        break;
      case SILInstructionKind::DeallocBoxInst:
        ResultVal = B.createDeallocBox(InstLoc, Val);
        break;
      }
      break;
    }
    case SILInstructionKind::DeallocExistentialBoxInst: {
      CanType ConcreteTy;
      if (parseTypedValueRef(Val, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          P.parseToken(tok::sil_dollar, diag::expected_tok_in_sil_instr, "$") ||
          parseASTType(ConcreteTy) || parseSILDebugLocation(InstLoc, B))
        return true;

      ResultVal = B.createDeallocExistentialBox(InstLoc, ConcreteTy, Val);
      break;
    }
    case SILInstructionKind::TupleInst: {
      // Tuple instructions have two different syntaxes, one for simple tuple
      // types, one for complicated ones.
      if (P.Tok.isNot(tok::sil_dollar)) {
        // If there is no type, parse the simple form.
        if (P.parseToken(tok::l_paren, diag::expected_tok_in_sil_instr, "("))
          return true;

        // TODO: Check for a type here.  This is how tuples with "interesting"
        // types are described.

        // This form is used with tuples that have elements with no names or
        // default values.
        SmallVector<TupleTypeElt, 4> TypeElts;
        if (P.Tok.isNot(tok::r_paren)) {
          do {
            if (parseTypedValueRef(Val, B))
              return true;
            OpList.push_back(Val);
            TypeElts.push_back(Val->getType().getASTType());
          } while (P.consumeIf(tok::comma));
        }
        HadError |=
            P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")");

        auto Ty = TupleType::get(TypeElts, P.Context);
        auto Ty2 = SILType::getPrimitiveObjectType(Ty->getCanonicalType());
        if (parseSILDebugLocation(InstLoc, B))
          return true;
        ResultVal = B.createTuple(InstLoc, Ty2, OpList);
        break;
      }

      // Otherwise, parse the fully general form.
      SILType Ty;
      if (parseSILType(Ty) ||
          P.parseToken(tok::l_paren, diag::expected_tok_in_sil_instr, "("))
        return true;

      TupleType *TT = Ty.getAs<TupleType>();
      if (TT == nullptr) {
        P.diagnose(OpcodeLoc, diag::expected_tuple_type_in_tuple);
        return true;
      }

      SmallVector<TupleTypeElt, 4> TypeElts;
      if (P.Tok.isNot(tok::r_paren)) {
        do {
          if (TypeElts.size() > TT->getNumElements()) {
            P.diagnose(P.Tok, diag::sil_tuple_inst_wrong_value_count,
                       TT->getNumElements());
            return true;
          }
          Type EltTy = TT->getElement(TypeElts.size()).getType();
          if (parseValueRef(
                  Val,
                  SILType::getPrimitiveObjectType(EltTy->getCanonicalType()),
                  RegularLocation(P.Tok.getLoc()), B))
            return true;
          OpList.push_back(Val);
          TypeElts.push_back(Val->getType().getASTType());
        } while (P.consumeIf(tok::comma));
      }
      HadError |= P.parseToken(tok::r_paren,
                               diag::expected_tok_in_sil_instr,")");

      if (TypeElts.size() != TT->getNumElements()) {
        P.diagnose(OpcodeLoc, diag::sil_tuple_inst_wrong_value_count,
                   TT->getNumElements());
        return true;
      }

      if (parseSILDebugLocation(InstLoc, B))
        return true;
      ResultVal = B.createTuple(InstLoc, Ty, OpList);
      break;
    }
    case SILInstructionKind::EnumInst: {
      SILType Ty;
      SILDeclRef Elt;
      SILValue Operand;
      if (parseSILType(Ty) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILDeclRef(Elt))
        return true;

      if (P.Tok.is(tok::comma) && !peekSILDebugLocation(P)) {
        P.consumeToken(tok::comma);
        if (parseTypedValueRef(Operand, B))
          return true;
      }

      if (parseSILDebugLocation(InstLoc, B))
        return true;
      ResultVal = B.createEnum(InstLoc, Operand,
                               cast<EnumElementDecl>(Elt.getDecl()), Ty);
      break;
    }
    case SILInstructionKind::InitEnumDataAddrInst:
    case SILInstructionKind::UncheckedEnumDataInst:
    case SILInstructionKind::UncheckedTakeEnumDataAddrInst: {
      SILValue Operand;
      SILDeclRef EltRef;
      if (parseTypedValueRef(Operand, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILDeclRef(EltRef) || parseSILDebugLocation(InstLoc, B))
        return true;

      EnumElementDecl *Elt = cast<EnumElementDecl>(EltRef.getDecl());
      auto ResultTy = Operand->getType().getEnumElementType(
          Elt, SILMod, B.getTypeExpansionContext());

      switch (Opcode) {
      case swift::SILInstructionKind::InitEnumDataAddrInst:
        ResultVal = B.createInitEnumDataAddr(InstLoc, Operand, Elt, ResultTy);
        break;
      case swift::SILInstructionKind::UncheckedTakeEnumDataAddrInst:
        ResultVal =
            B.createUncheckedTakeEnumDataAddr(InstLoc, Operand, Elt, ResultTy);
        break;
      case swift::SILInstructionKind::UncheckedEnumDataInst:
        ResultVal = B.createUncheckedEnumData(InstLoc, Operand, Elt, ResultTy);
        break;
      default:
        llvm_unreachable("switch out of sync");
      }
      break;
    }
    case SILInstructionKind::InjectEnumAddrInst: {
      SILValue Operand;
      SILDeclRef EltRef;
      if (parseTypedValueRef(Operand, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILDeclRef(EltRef) || parseSILDebugLocation(InstLoc, B))
        return true;

      EnumElementDecl *Elt = cast<EnumElementDecl>(EltRef.getDecl());
      ResultVal = B.createInjectEnumAddr(InstLoc, Operand, Elt);
      break;
    }
    case SILInstructionKind::TupleElementAddrInst:
    case SILInstructionKind::TupleExtractInst: {
      SourceLoc NameLoc;
      if (parseTypedValueRef(Val, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ","))
        return true;

      unsigned Field = 0;
      TupleType *TT = Val->getType().getAs<TupleType>();
      if (P.Tok.isNot(tok::integer_literal) ||
          parseIntegerLiteral(P.Tok.getText(), 10, Field) ||
          Field >= TT->getNumElements()) {
        P.diagnose(P.Tok, diag::sil_tuple_inst_wrong_field);
        return true;
      }
      P.consumeToken(tok::integer_literal);
      if (parseSILDebugLocation(InstLoc, B))
        return true;
      auto ResultTy = TT->getElement(Field).getType()->getCanonicalType();
      if (Opcode == SILInstructionKind::TupleElementAddrInst)
        ResultVal = B.createTupleElementAddr(
            InstLoc, Val, Field, SILType::getPrimitiveAddressType(ResultTy));
      else
        ResultVal = B.createTupleExtract(
            InstLoc, Val, Field, SILType::getPrimitiveObjectType(ResultTy));
      break;
    }
    case SILInstructionKind::ReturnInst: {
      if (parseTypedValueRef(Val, B) || parseSILDebugLocation(InstLoc, B))
        return true;
      ResultVal = B.createReturn(InstLoc, Val);
      break;
    }
    case SILInstructionKind::ThrowInst: {
      if (parseTypedValueRef(Val, B) || parseSILDebugLocation(InstLoc, B))
        return true;
      ResultVal = B.createThrow(InstLoc, Val);
      break;
    }
    case SILInstructionKind::UnwindInst: {
      if (parseSILDebugLocation(InstLoc, B))
        return true;
      ResultVal = B.createUnwind(InstLoc);
      break;
    }
    case SILInstructionKind::YieldInst: {
      SmallVector<SILValue, 6> values;

      // Parse a parenthesized (unless length-1), comma-separated list
      // of yielded values.
      if (P.consumeIf(tok::l_paren)) {
        if (!P.Tok.is(tok::r_paren)) {
          do {
            if (parseTypedValueRef(Val, B))
              return true;
            values.push_back(Val);
          } while (P.consumeIf(tok::comma));
        }

        if (P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")"))
          return true;

      } else {
        if (parseTypedValueRef(Val, B))
          return true;
        values.push_back(Val);
      }

      Identifier resumeName, unwindName;
      SourceLoc resumeLoc, unwindLoc;
      if (P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseVerbatim("resume") ||
          parseSILIdentifier(resumeName, resumeLoc,
                             diag::expected_sil_block_name) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseVerbatim("unwind") ||
          parseSILIdentifier(unwindName, unwindLoc,
                             diag::expected_sil_block_name) ||
          parseSILDebugLocation(InstLoc, B))
        return true;

      auto resumeBB = getBBForReference(resumeName, resumeLoc);
      auto unwindBB = getBBForReference(unwindName, unwindLoc);
      ResultVal = B.createYield(InstLoc, values, resumeBB, unwindBB);
      break;
    }
    case SILInstructionKind::BranchInst: {
      Identifier BBName;
      SourceLoc NameLoc;
      if (parseSILIdentifier(BBName, NameLoc, diag::expected_sil_block_name))
        return true;

      SmallVector<SILValue, 6> Args;
      if (parseSILBBArgsAtBranch(Args, B))
        return true;

      if (parseSILDebugLocation(InstLoc, B))
        return true;

      // Note, the basic block here could be a reference to an undefined
      // basic block, which will be parsed later on.
      ResultVal =
          B.createBranch(InstLoc, getBBForReference(BBName, NameLoc), Args);
      break;
    }
    case SILInstructionKind::CondBranchInst: {
      UnresolvedValueName Cond;
      Identifier BBName, BBName2;
      SourceLoc NameLoc, NameLoc2;
      SmallVector<SILValue, 6> Args, Args2;
      if (parseValueName(Cond) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILIdentifier(BBName, NameLoc, diag::expected_sil_block_name) ||
          parseSILBBArgsAtBranch(Args, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILIdentifier(BBName2, NameLoc2,
                             diag::expected_sil_block_name) ||
          parseSILBBArgsAtBranch(Args2, B) || parseSILDebugLocation(InstLoc, B))
        return true;

      auto I1Ty = SILType::getBuiltinIntegerType(1, SILMod.getASTContext());
      SILValue CondVal = getLocalValue(Cond, I1Ty, InstLoc, B);
      ResultVal = B.createCondBranch(
          InstLoc, CondVal, getBBForReference(BBName, NameLoc), Args,
          getBBForReference(BBName2, NameLoc2), Args2);
      break;
    }
    case SILInstructionKind::UnreachableInst:
      if (parseSILDebugLocation(InstLoc, B))
        return true;
      ResultVal = B.createUnreachable(InstLoc);
      break;

    case SILInstructionKind::ClassMethodInst:
    case SILInstructionKind::SuperMethodInst:
    case SILInstructionKind::ObjCMethodInst:
    case SILInstructionKind::ObjCSuperMethodInst: {
      SILDeclRef Member;
      SILType MethodTy;
      SourceLoc TyLoc;
      SmallVector<ValueDecl *, 4> values;
      if (parseTypedValueRef(Val, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ","))
        return true;

      if (parseSILDeclRef(Member, true))
        return true;

      if (P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILType(MethodTy, TyLoc) || parseSILDebugLocation(InstLoc, B))
        return true;

      switch (Opcode) {
      default:
        llvm_unreachable("Out of sync with parent switch");
      case SILInstructionKind::ClassMethodInst:
        ResultVal = B.createClassMethod(InstLoc, Val, Member, MethodTy);
        break;
      case SILInstructionKind::SuperMethodInst:
        ResultVal = B.createSuperMethod(InstLoc, Val, Member, MethodTy);
        break;
      case SILInstructionKind::ObjCMethodInst:
        ResultVal = B.createObjCMethod(InstLoc, Val, Member, MethodTy);
        break;
      case SILInstructionKind::ObjCSuperMethodInst:
        ResultVal = B.createObjCSuperMethod(InstLoc, Val, Member, MethodTy);
        break;
      }
      break;
    }
    case SILInstructionKind::WitnessMethodInst: {
      CanType LookupTy;
      SILDeclRef Member;
      SILType MethodTy;
      SourceLoc TyLoc;
      if (P.parseToken(tok::sil_dollar, diag::expected_tok_in_sil_instr, "$") ||
          parseASTType(LookupTy) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ","))
        return true;
      if (parseSILDeclRef(Member, true))
        return true;
      // Optional operand.
      SILValue Operand;
      if (P.Tok.is(tok::comma)) {
        P.consumeToken(tok::comma);
        if (parseTypedValueRef(Operand, B))
          return true;
      }
      if (P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":") ||
          parseSILType(MethodTy, TyLoc) || parseSILDebugLocation(InstLoc, B))
        return true;

      // If LookupTy is a non-archetype, look up its conformance.
      ProtocolDecl *proto =
          dyn_cast<ProtocolDecl>(Member.getDecl()->getDeclContext());
      if (!proto) {
        P.diagnose(TyLoc, diag::sil_witness_method_not_protocol);
        return true;
      }
      auto conformance =
          P.SF.getParentModule()->lookupConformance(LookupTy, proto);
      if (conformance.isInvalid()) {
        P.diagnose(TyLoc, diag::sil_witness_method_type_does_not_conform);
        return true;
      }

      ResultVal = B.createWitnessMethod(InstLoc, LookupTy, conformance, Member,
                                        MethodTy);
      break;
    }
    case SILInstructionKind::CopyAddrInst: {
      bool IsTake = false, IsInit = false;
      UnresolvedValueName SrcLName;
      SILValue DestLVal;
      SourceLoc ToLoc, DestLoc;
      Identifier ToToken;
      if (parseSILOptional(IsTake, *this, "take") || parseValueName(SrcLName) ||
          parseSILIdentifier(ToToken, ToLoc, diag::expected_tok_in_sil_instr,
                             "to") ||
          parseSILOptional(IsInit, *this, "initialization") ||
          parseTypedValueRef(DestLVal, DestLoc, B) ||
          parseSILDebugLocation(InstLoc, B))
        return true;

      if (ToToken.str() != "to") {
        P.diagnose(ToLoc, diag::expected_tok_in_sil_instr, "to");
        return true;
      }

      if (!DestLVal->getType().isAddress()) {
        P.diagnose(DestLoc, diag::sil_invalid_instr_operands);
        return true;
      }

      SILValue SrcLVal =
          getLocalValue(SrcLName, DestLVal->getType(), InstLoc, B);
      ResultVal = B.createCopyAddr(InstLoc, SrcLVal, DestLVal, IsTake_t(IsTake),
                                   IsInitialization_t(IsInit));
      break;
    }
    case SILInstructionKind::BindMemoryInst: {
      SILValue IndexVal;
      Identifier ToToken;
      SourceLoc ToLoc;
      SILType EltTy;
      if (parseTypedValueRef(Val, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseTypedValueRef(IndexVal, B) ||
          parseSILIdentifier(ToToken, ToLoc, diag::expected_tok_in_sil_instr,
                             "to") ||
          parseSILType(EltTy) || parseSILDebugLocation(InstLoc, B))
        return true;

      if (ToToken.str() != "to") {
        P.diagnose(ToLoc, diag::expected_tok_in_sil_instr, "to");
        return true;
      }
      ResultVal = B.createBindMemory(InstLoc, Val, IndexVal, EltTy);
      break;
    }
    case SILInstructionKind::ObjectInst:
    case SILInstructionKind::StructInst: {
      SILType Ty;
      if (parseSILType(Ty) ||
          P.parseToken(tok::l_paren, diag::expected_tok_in_sil_instr, "("))
        return true;

      // Parse a list of SILValue.
      bool OpsAreTailElems = false;
      unsigned NumBaseElems = 0;
      if (P.Tok.isNot(tok::r_paren)) {
        do {
          if (Opcode == SILInstructionKind::ObjectInst) {
            if (parseSILOptional(OpsAreTailElems, *this, "tail_elems"))
              return true;
          }
          if (parseTypedValueRef(Val, B))
            return true;
          OpList.push_back(Val);
          if (!OpsAreTailElems)
            NumBaseElems = OpList.size();
        } while (P.consumeIf(tok::comma));
      }
      if (P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")") ||
          parseSILDebugLocation(InstLoc, B))
        return true;

      if (Opcode == SILInstructionKind::StructInst) {
        ResultVal = B.createStruct(InstLoc, Ty, OpList);
      } else {
        ResultVal = B.createObject(InstLoc, Ty, OpList, NumBaseElems);
      }
      break;
    }
    case SILInstructionKind::StructElementAddrInst:
    case SILInstructionKind::StructExtractInst: {
      ValueDecl *FieldV;
      SourceLoc NameLoc = P.Tok.getLoc();
      if (parseTypedValueRef(Val, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILDottedPath(FieldV) || parseSILDebugLocation(InstLoc, B))
        return true;
      if (!FieldV || !isa<VarDecl>(FieldV)) {
        P.diagnose(NameLoc, diag::sil_struct_inst_wrong_field);
        return true;
      }
      VarDecl *Field = cast<VarDecl>(FieldV);

      // FIXME: substitution means this type should be explicit to improve
      // performance.
      auto ResultTy = Val->getType().getFieldType(Field, SILMod,
                                                  B.getTypeExpansionContext());
      if (Opcode == SILInstructionKind::StructElementAddrInst)
        ResultVal = B.createStructElementAddr(InstLoc, Val, Field,
                                              ResultTy.getAddressType());
      else
        ResultVal = B.createStructExtract(InstLoc, Val, Field,
                                          ResultTy.getObjectType());
      break;
    }
    case SILInstructionKind::RefElementAddrInst: {
      ValueDecl *FieldV;
      SourceLoc NameLoc;
      bool IsImmutable = false;
      if (parseSILOptional(IsImmutable, *this, "immutable") ||
          parseTypedValueRef(Val, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILDottedPath(FieldV) || parseSILDebugLocation(InstLoc, B))
        return true;
      if (!FieldV || !isa<VarDecl>(FieldV)) {
        P.diagnose(NameLoc, diag::sil_ref_inst_wrong_field);
        return true;
      }
      VarDecl *Field = cast<VarDecl>(FieldV);
      auto ResultTy = Val->getType().getFieldType(Field, SILMod,
                                                  B.getTypeExpansionContext());
      ResultVal = B.createRefElementAddr(InstLoc, Val, Field, ResultTy,
                                         IsImmutable);
      break;
    }
    case SILInstructionKind::RefTailAddrInst: {
      SourceLoc NameLoc;
      SILType ResultObjTy;
      bool IsImmutable = false;
      if (parseSILOptional(IsImmutable, *this, "immutable") ||
          parseTypedValueRef(Val, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILType(ResultObjTy) || parseSILDebugLocation(InstLoc, B))
        return true;
      SILType ResultTy = ResultObjTy.getAddressType();
      ResultVal = B.createRefTailAddr(InstLoc, Val, ResultTy, IsImmutable);
      break;
    }
    case SILInstructionKind::IndexAddrInst: {
      SILValue IndexVal;
      if (parseTypedValueRef(Val, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseTypedValueRef(IndexVal, B) || parseSILDebugLocation(InstLoc, B))
        return true;
      ResultVal = B.createIndexAddr(InstLoc, Val, IndexVal);
      break;
    }
    case SILInstructionKind::TailAddrInst: {
      SILValue IndexVal;
      SILType ResultObjTy;
      if (parseTypedValueRef(Val, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseTypedValueRef(IndexVal, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILType(ResultObjTy) || parseSILDebugLocation(InstLoc, B))
        return true;
      SILType ResultTy = ResultObjTy.getAddressType();
      ResultVal = B.createTailAddr(InstLoc, Val, IndexVal, ResultTy);
      break;
    }
    case SILInstructionKind::IndexRawPointerInst: {
      SILValue IndexVal;
      if (parseTypedValueRef(Val, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseTypedValueRef(IndexVal, B) || parseSILDebugLocation(InstLoc, B))
        return true;
      ResultVal = B.createIndexRawPointer(InstLoc, Val, IndexVal);
      break;
    }
    case SILInstructionKind::ObjCProtocolInst: {
      Identifier ProtocolName;
      SILType Ty;
      if (P.parseToken(tok::pound, diag::expected_sil_constant) ||
          parseSILIdentifier(ProtocolName, diag::expected_sil_constant) ||
          P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":") ||
          parseSILType(Ty) || parseSILDebugLocation(InstLoc, B))
        return true;
      // Find the decl for the protocol name.
      ValueDecl *VD;
      SmallVector<ValueDecl *, 4> CurModuleResults;
      // Perform a module level lookup on the first component of the
      // fully-qualified name.
      P.SF.getParentModule()->lookupValue(
          ProtocolName, NLKind::UnqualifiedLookup, CurModuleResults);
      assert(CurModuleResults.size() == 1);
      VD = CurModuleResults[0];
      ResultVal = B.createObjCProtocol(InstLoc, cast<ProtocolDecl>(VD), Ty);
      break;
    }
    case SILInstructionKind::AllocGlobalInst: {
      Identifier GlobalName;
      SourceLoc IdLoc;
      if (P.parseToken(tok::at_sign, diag::expected_sil_value_name) ||
          parseSILIdentifier(GlobalName, IdLoc,
                             diag::expected_sil_value_name) ||
          parseSILDebugLocation(InstLoc, B))
        return true;

      // Go through list of global variables in the SILModule.
      SILGlobalVariable *global = SILMod.lookUpGlobalVariable(GlobalName.str());
      if (!global) {
        P.diagnose(IdLoc, diag::sil_global_variable_not_found, GlobalName);
        return true;
      }

      ResultVal = B.createAllocGlobal(InstLoc, global);
      break;
    }
    case SILInstructionKind::GlobalAddrInst:
    case SILInstructionKind::GlobalValueInst: {
      Identifier GlobalName;
      SourceLoc IdLoc;
      SILType Ty;
      if (P.parseToken(tok::at_sign, diag::expected_sil_value_name) ||
          parseSILIdentifier(GlobalName, IdLoc,
                             diag::expected_sil_value_name) ||
          P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":") ||
          parseSILType(Ty) || parseSILDebugLocation(InstLoc, B))
        return true;

      // Go through list of global variables in the SILModule.
      SILGlobalVariable *global = SILMod.lookUpGlobalVariable(GlobalName.str());
      if (!global) {
        P.diagnose(IdLoc, diag::sil_global_variable_not_found, GlobalName);
        return true;
      }

      SILType expectedType = (Opcode == SILInstructionKind::GlobalAddrInst
                                  ? global->getLoweredType().getAddressType()
                                  : global->getLoweredType());
      if (expectedType != Ty) {
        P.diagnose(IdLoc, diag::sil_value_use_type_mismatch, GlobalName.str(),
                   global->getLoweredType().getASTType(), Ty.getASTType());
        return true;
      }

      if (Opcode == SILInstructionKind::GlobalAddrInst) {
        ResultVal = B.createGlobalAddr(InstLoc, global);
      } else {
        ResultVal = B.createGlobalValue(InstLoc, global);
      }
      break;
    }
    case SILInstructionKind::BaseAddrForOffsetInst: {
      SILType Ty;
      if (parseSILType(Ty))
        return true;
      if (parseSILDebugLocation(InstLoc, B))
        return true;
      ResultVal = B.createBaseAddrForOffset(InstLoc, Ty);
      break;
    }
    case SILInstructionKind::SelectEnumInst:
    case SILInstructionKind::SelectEnumAddrInst: {
      if (parseTypedValueRef(Val, B))
        return true;

      SmallVector<std::pair<EnumElementDecl *, UnresolvedValueName>, 4>
          CaseValueNames;
      Optional<UnresolvedValueName> DefaultValueName;
      while (P.consumeIf(tok::comma)) {
        Identifier BBName;
        SourceLoc BBLoc;
        // Parse 'default' sil-value.
        UnresolvedValueName tmp;
        if (P.consumeIf(tok::kw_default)) {
          if (parseValueName(tmp))
            return true;
          DefaultValueName = tmp;
          break;
        }

        // Parse 'case' sil-decl-ref ':' sil-value.
        if (P.consumeIf(tok::kw_case)) {
          SILDeclRef ElemRef;
          if (parseSILDeclRef(ElemRef))
            return true;
          assert(ElemRef.hasDecl() && isa<EnumElementDecl>(ElemRef.getDecl()));
          P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":");
          parseValueName(tmp);
          CaseValueNames.push_back(
              std::make_pair(cast<EnumElementDecl>(ElemRef.getDecl()), tmp));
          continue;
        }

        P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "case or default");
        return true;
      }

      // Parse the type of the result operands.
      SILType ResultType;
      if (P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":") ||
          parseSILType(ResultType) || parseSILDebugLocation(InstLoc, B))
        return true;

      // Resolve the results.
      SmallVector<std::pair<EnumElementDecl *, SILValue>, 4> CaseValues;
      SILValue DefaultValue;
      if (DefaultValueName)
        DefaultValue = getLocalValue(*DefaultValueName, ResultType, InstLoc, B);
      for (auto &caseName : CaseValueNames)
        CaseValues.push_back(std::make_pair(
            caseName.first,
            getLocalValue(caseName.second, ResultType, InstLoc, B)));

      if (Opcode == SILInstructionKind::SelectEnumInst)
        ResultVal = B.createSelectEnum(InstLoc, Val, ResultType, DefaultValue,
                                       CaseValues);
      else
        ResultVal = B.createSelectEnumAddr(InstLoc, Val, ResultType,
                                           DefaultValue, CaseValues);
      break;
    }

    case SILInstructionKind::SwitchEnumInst:
    case SILInstructionKind::SwitchEnumAddrInst: {
      if (parseTypedValueRef(Val, B))
        return true;

      SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 4> CaseBBs;
      SILBasicBlock *DefaultBB = nullptr;
      while (!peekSILDebugLocation(P) && P.consumeIf(tok::comma)) {
        Identifier BBName;
        SourceLoc BBLoc;
        // Parse 'default' sil-identifier.
        if (P.consumeIf(tok::kw_default)) {
          parseSILIdentifier(BBName, BBLoc, diag::expected_sil_block_name);
          DefaultBB = getBBForReference(BBName, BBLoc);
          break;
        }

        // Parse 'case' sil-decl-ref ':' sil-identifier.
        if (P.consumeIf(tok::kw_case)) {
          SILDeclRef ElemRef;
          if (parseSILDeclRef(ElemRef))
            return true;
          assert(ElemRef.hasDecl() && isa<EnumElementDecl>(ElemRef.getDecl()));
          P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":");
          parseSILIdentifier(BBName, BBLoc, diag::expected_sil_block_name);
          CaseBBs.push_back({cast<EnumElementDecl>(ElemRef.getDecl()),
                             getBBForReference(BBName, BBLoc)});
          continue;
        }

        P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "case or default");
        return true;
      }
      if (parseSILDebugLocation(InstLoc, B))
        return true;
      if (Opcode == SILInstructionKind::SwitchEnumInst)
        ResultVal = B.createSwitchEnum(InstLoc, Val, DefaultBB, CaseBBs);
      else
        ResultVal = B.createSwitchEnumAddr(InstLoc, Val, DefaultBB, CaseBBs);
      break;
    }
    case SILInstructionKind::SwitchValueInst: {
      if (parseTypedValueRef(Val, B))
        return true;

      SmallVector<std::pair<SILValue, SILBasicBlock *>, 4> CaseBBs;
      SILBasicBlock *DefaultBB = nullptr;
      while (!peekSILDebugLocation(P) && P.consumeIf(tok::comma)) {
        Identifier BBName;
        SourceLoc BBLoc;
        SILValue CaseVal;

        // Parse 'default' sil-identifier.
        if (P.consumeIf(tok::kw_default)) {
          parseSILIdentifier(BBName, BBLoc, diag::expected_sil_block_name);
          DefaultBB = getBBForReference(BBName, BBLoc);
          break;
        }

        // Parse 'case' value-ref ':' sil-identifier.
        if (P.consumeIf(tok::kw_case)) {
          if (parseValueRef(CaseVal, Val->getType(),
                            RegularLocation(P.Tok.getLoc()), B)) {
            // TODO: Issue a proper error message here
            P.diagnose(P.Tok, diag::expected_tok_in_sil_instr,
                       "reference to a value");
            return true;
          }

          auto intTy = Val->getType().getAs<BuiltinIntegerType>();
          auto functionTy = Val->getType().getAs<SILFunctionType>();
          if (!intTy && !functionTy) {
            P.diagnose(P.Tok, diag::sil_integer_literal_not_integer_type);
            return true;
          }

          if (intTy) {
            // If it is a switch on an integer type, check that all case values
            // are integer literals or undef.
            if (!isa<SILUndef>(CaseVal)) {
              auto *IL = dyn_cast<IntegerLiteralInst>(CaseVal);
              if (!IL) {
                P.diagnose(P.Tok, diag::sil_integer_literal_not_integer_type);
                return true;
              }
              APInt CaseValue = IL->getValue();

              if (CaseValue.getBitWidth() != intTy->getGreatestWidth())
                CaseVal = B.createIntegerLiteral(
                    IL->getLoc(), Val->getType(),
                    CaseValue.zextOrTrunc(intTy->getGreatestWidth()));
            }
          }

          if (functionTy) {
            // If it is a switch on a function type, check that all case values
            // are function references or undef.
            if (!isa<SILUndef>(CaseVal)) {
              auto *FR = dyn_cast<FunctionRefInst>(CaseVal);
              if (!FR) {
                if (auto *CF = dyn_cast<ConvertFunctionInst>(CaseVal)) {
                  FR = dyn_cast<FunctionRefInst>(CF->getOperand());
                }
              }
              if (!FR) {
                P.diagnose(P.Tok, diag::sil_integer_literal_not_integer_type);
                return true;
              }
            }
          }

          P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":");
          parseSILIdentifier(BBName, BBLoc, diag::expected_sil_block_name);
          CaseBBs.push_back({CaseVal, getBBForReference(BBName, BBLoc)});
          continue;
        }

        P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "case or default");
        return true;
      }
      if (parseSILDebugLocation(InstLoc, B))
        return true;
      ResultVal = B.createSwitchValue(InstLoc, Val, DefaultBB, CaseBBs);
      break;
    }
    case SILInstructionKind::SelectValueInst: {
      if (parseTypedValueRef(Val, B))
        return true;

      SmallVector<std::pair<UnresolvedValueName, UnresolvedValueName>, 4>
          CaseValueAndResultNames;
      Optional<UnresolvedValueName> DefaultResultName;
      while (P.consumeIf(tok::comma)) {
        Identifier BBName;
        SourceLoc BBLoc;
        // Parse 'default' sil-value.
        UnresolvedValueName tmp;
        if (P.consumeIf(tok::kw_default)) {
          if (parseValueName(tmp))
            return true;
          DefaultResultName = tmp;
          break;
        }

        // Parse 'case' sil-decl-ref ':' sil-value.
        if (P.consumeIf(tok::kw_case)) {
          UnresolvedValueName casevalue;
          parseValueName(casevalue);
          P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":");
          parseValueName(tmp);
          CaseValueAndResultNames.push_back(std::make_pair(casevalue, tmp));
          continue;
        }

        P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "case or default");
        return true;
      }

      if (!DefaultResultName) {
        P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "default");
        return true;
      }

      // Parse the type of the result operands.
      SILType ResultType;
      if (P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":") ||
          parseSILType(ResultType) || parseSILDebugLocation(InstLoc, B))
        return true;

      // Resolve the results.
      SmallVector<std::pair<SILValue, SILValue>, 4> CaseValues;
      SILValue DefaultValue;
      if (DefaultResultName)
        DefaultValue =
            getLocalValue(*DefaultResultName, ResultType, InstLoc, B);
      SILType ValType = Val->getType();
      for (auto &caseName : CaseValueAndResultNames)
        CaseValues.push_back(std::make_pair(
            getLocalValue(caseName.first, ValType, InstLoc, B),
            getLocalValue(caseName.second, ResultType, InstLoc, B)));

      ResultVal = B.createSelectValue(InstLoc, Val, ResultType, DefaultValue,
                                      CaseValues);
      break;
    }
    case SILInstructionKind::DeinitExistentialAddrInst: {
      if (parseTypedValueRef(Val, B) || parseSILDebugLocation(InstLoc, B))
        return true;
      ResultVal = B.createDeinitExistentialAddr(InstLoc, Val);
      break;
    }
    case SILInstructionKind::DeinitExistentialValueInst: {
      if (parseTypedValueRef(Val, B) || parseSILDebugLocation(InstLoc, B))
        return true;
      ResultVal = B.createDeinitExistentialValue(InstLoc, Val);
      break;
    }
    case SILInstructionKind::InitExistentialAddrInst: {
      CanType Ty;
      SourceLoc TyLoc;
      if (parseTypedValueRef(Val, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          P.parseToken(tok::sil_dollar, diag::expected_tok_in_sil_instr, "$") ||
          parseASTType(Ty, TyLoc) || parseSILDebugLocation(InstLoc, B))
        return true;

      // Lower the type at the abstraction level of the existential.
      auto archetype = OpenedArchetypeType::get(Val->getType().getASTType())
                           ->getCanonicalType();

      auto &F = B.getFunction();
      SILType LoweredTy =
          F.getLoweredType(Lowering::AbstractionPattern(archetype), Ty)
              .getAddressType();

      // Collect conformances for the type.
      ArrayRef<ProtocolConformanceRef> conformances =
          collectExistentialConformances(P, Ty, TyLoc,
                                         Val->getType().getASTType());

      ResultVal = B.createInitExistentialAddr(InstLoc, Val, Ty, LoweredTy,
                                              conformances);
      break;
    }
    case SILInstructionKind::InitExistentialValueInst: {
      CanType FormalConcreteTy;
      SILType ExistentialTy;
      SourceLoc TyLoc;

      if (parseTypedValueRef(Val, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          P.parseToken(tok::sil_dollar, diag::expected_tok_in_sil_instr, "$") ||
          parseASTType(FormalConcreteTy, TyLoc) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILType(ExistentialTy) || parseSILDebugLocation(InstLoc, B))
        return true;

      ArrayRef<ProtocolConformanceRef> conformances =
          collectExistentialConformances(P, FormalConcreteTy, TyLoc,
                                         ExistentialTy.getASTType());

      ResultVal = B.createInitExistentialValue(
          InstLoc, ExistentialTy, FormalConcreteTy, Val, conformances);
      break;
    }
    case SILInstructionKind::AllocExistentialBoxInst: {
      SILType ExistentialTy;
      CanType ConcreteFormalTy;
      SourceLoc TyLoc;

      if (parseSILType(ExistentialTy) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          P.parseToken(tok::sil_dollar, diag::expected_tok_in_sil_instr, "$") ||
          parseASTType(ConcreteFormalTy, TyLoc) ||
          parseSILDebugLocation(InstLoc, B))
        return true;

      // Collect conformances for the type.
      ArrayRef<ProtocolConformanceRef> conformances =
          collectExistentialConformances(P, ConcreteFormalTy, TyLoc,
                                         ExistentialTy.getASTType());

      ResultVal = B.createAllocExistentialBox(InstLoc, ExistentialTy,
                                              ConcreteFormalTy, conformances);

      break;
    }
    case SILInstructionKind::InitExistentialRefInst: {
      CanType FormalConcreteTy;
      SILType ExistentialTy;
      SourceLoc TyLoc;

      if (parseTypedValueRef(Val, B) ||
          P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":") ||
          P.parseToken(tok::sil_dollar, diag::expected_tok_in_sil_instr, "$") ||
          parseASTType(FormalConcreteTy, TyLoc) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILType(ExistentialTy) || parseSILDebugLocation(InstLoc, B))
        return true;

      ArrayRef<ProtocolConformanceRef> conformances =
          collectExistentialConformances(P, FormalConcreteTy, TyLoc,
                                         ExistentialTy.getASTType());

      // FIXME: Conformances in InitExistentialRefInst is currently not included
      // in SIL.rst.
      ResultVal = B.createInitExistentialRef(
          InstLoc, ExistentialTy, FormalConcreteTy, Val, conformances);
      break;
    }
    case SILInstructionKind::InitExistentialMetatypeInst: {
      SourceLoc TyLoc;
      SILType ExistentialTy;
      if (parseTypedValueRef(Val, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILType(ExistentialTy, TyLoc) ||
          parseSILDebugLocation(InstLoc, B))
        return true;

      auto baseExType = ExistentialTy.getASTType();
      auto formalConcreteType = Val->getType().getASTType();
      while (auto instExType = dyn_cast<ExistentialMetatypeType>(baseExType)) {
        baseExType = instExType.getInstanceType();
        formalConcreteType =
            cast<MetatypeType>(formalConcreteType).getInstanceType();
      }

      ArrayRef<ProtocolConformanceRef> conformances =
          collectExistentialConformances(P, formalConcreteType, TyLoc,
                                         baseExType);

      ResultVal = B.createInitExistentialMetatype(InstLoc, Val, ExistentialTy,
                                                  conformances);
      break;
    }
    case SILInstructionKind::DynamicMethodBranchInst: {
      SILDeclRef Member;
      Identifier BBName, BBName2;
      SourceLoc NameLoc, NameLoc2;
      if (parseTypedValueRef(Val, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILDeclRef(Member) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILIdentifier(BBName, NameLoc, diag::expected_sil_block_name) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILIdentifier(BBName2, NameLoc2,
                             diag::expected_sil_block_name) ||
          parseSILDebugLocation(InstLoc, B))
        return true;

      ResultVal = B.createDynamicMethodBranch(
          InstLoc, Val, Member, getBBForReference(BBName, NameLoc),
          getBBForReference(BBName2, NameLoc2));
      break;
    }
    case SILInstructionKind::ProjectBlockStorageInst: {
      if (parseTypedValueRef(Val, B) || parseSILDebugLocation(InstLoc, B))
        return true;

      ResultVal = B.createProjectBlockStorage(InstLoc, Val);
      break;
    }
    case SILInstructionKind::InitBlockStorageHeaderInst: {
      Identifier invoke, type;
      SourceLoc invokeLoc, typeLoc;

      UnresolvedValueName invokeName;
      SILType invokeTy;
      GenericEnvironment *invokeGenericEnv = nullptr;
      GenericParamList *invokeGenericParams = nullptr;

      SILType blockType;
      SmallVector<ParsedSubstitution, 4> parsedSubs;

      if (parseTypedValueRef(Val, B) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILIdentifier(invoke, invokeLoc, diag::expected_tok_in_sil_instr,
                             "invoke") ||
          parseValueName(invokeName) || parseSubstitutions(parsedSubs) ||
          P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":") ||
          parseSILType(invokeTy, invokeGenericEnv, invokeGenericParams) ||
          P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
          parseSILIdentifier(type, typeLoc, diag::expected_tok_in_sil_instr,
                             "type") ||
          parseSILType(blockType) || parseSILDebugLocation(InstLoc, B))
        return true;

      if (invoke.str() != "invoke") {
        P.diagnose(invokeLoc, diag::expected_tok_in_sil_instr, "invoke");
        return true;
      }
      if (type.str() != "type") {
        P.diagnose(invokeLoc, diag::expected_tok_in_sil_instr, "type");
        return true;
      }

      auto invokeVal = getLocalValue(invokeName, invokeTy, InstLoc, B);

      SubstitutionMap subMap;
      if (!parsedSubs.empty()) {
        if (!invokeGenericEnv) {
          P.diagnose(typeLoc, diag::sil_substitutions_on_non_polymorphic_type);
          return true;
        }

        subMap = getApplySubstitutionsFromParsed(*this, invokeGenericEnv,
                                                 parsedSubs);
        if (!subMap)
          return true;
      }

      ResultVal = B.createInitBlockStorageHeader(InstLoc, Val, invokeVal,
                                                 blockType, subMap);
      break;
    }
    case SILInstructionKind::DifferentiableFunctionInst: {
      // e.g. differentiable_function [parameters 0 1 2] [results 0] %0 : $T
      //
      // e.g. differentiable_function [parameters 0 1 2] [results 0] %0 : $T
      //          with_derivative {%1 : $T, %2 : $T}
      //                           ^~ jvp   ^~ vjp
      // Parse `[parameters <integer_literal>...]`.
      SmallVector<unsigned, 8> rawParameterIndices;
      if (parseIndexList(P, "parameters", rawParameterIndices,
                         diag::sil_autodiff_expected_parameter_index))
        return true;
      SmallVector<unsigned, 2> rawResultIndices;
      if (parseIndexList(P, "results", rawResultIndices,
                         diag::sil_autodiff_expected_result_index))
        return true;
      // Parse the original function value.
      SILValue original;
      SourceLoc originalOperandLoc;
      if (parseTypedValueRef(original, originalOperandLoc, B))
        return true;
      auto fnType = original->getType().getAs<SILFunctionType>();
      if (!fnType) {
        P.diagnose(originalOperandLoc,
                   diag::sil_inst_autodiff_expected_function_type_operand);
        return true;
      }
      Optional<std::pair<SILValue, SILValue>> derivativeFunctions = None;
      // Parse an optional operand list
      //   `with_derivative { <operand> , <operand> }`.
      if (P.Tok.is(tok::identifier) && P.Tok.getText() == "with_derivative") {
        P.consumeToken(tok::identifier);
        // Parse derivative function values as an operand list.
        // FIXME(rxwei): Change this to *not* require a type signature once
        // we can infer derivative function types.
        derivativeFunctions = std::make_pair(SILValue(), SILValue());
        if (P.parseToken(
                tok::l_brace,
                diag::sil_inst_autodiff_operand_list_expected_lbrace) ||
            parseTypedValueRef(derivativeFunctions->first, B) ||
            P.parseToken(tok::comma,
                         diag::sil_inst_autodiff_operand_list_expected_comma) ||
            parseTypedValueRef(derivativeFunctions->second, B) ||
            P.parseToken(tok::r_brace,
                         diag::sil_inst_autodiff_operand_list_expected_rbrace))
          return true;
      }
      if (parseSILDebugLocation(InstLoc, B))
        return true;
      auto *parameterIndices = IndexSubset::get(
          P.Context, fnType->getNumParameters(), rawParameterIndices);
      auto *resultIndices = IndexSubset::get(
          P.Context,
          fnType->getNumResults() + fnType->getNumIndirectMutatingParameters(),
          rawResultIndices);
      ResultVal = B.createDifferentiableFunction(InstLoc, parameterIndices,
                                                 resultIndices, original,
                                                 derivativeFunctions);
      break;
    }
    case SILInstructionKind::LinearFunctionInst: {
      // e.g. linear_function [parameters 0 1 2] %0 : $T
      // e.g. linear_function [parameters 0 1 2] %0 : $T with_transpose %1 : $T
      // Parse `[parameters <integer_literal>...]`.
      SmallVector<unsigned, 8> rawParameterIndices;
      if (parseIndexList(P, "parameters", rawParameterIndices,
                         diag::sil_autodiff_expected_parameter_index))
        return true;
      // Parse the original function value.
      SILValue original;
      SourceLoc originalOperandLoc;
      if (parseTypedValueRef(original, originalOperandLoc, B))
        return true;
      auto fnType = original->getType().getAs<SILFunctionType>();
      if (!fnType) {
        P.diagnose(originalOperandLoc,
                   diag::sil_inst_autodiff_expected_function_type_operand);
        return true;
      }
      // Parse an optional transpose function.
      Optional<SILValue> transpose = None;
      if (P.Tok.is(tok::identifier) && P.Tok.getText() == "with_transpose") {
        P.consumeToken(tok::identifier);
        transpose = SILValue();
        if (parseTypedValueRef(*transpose, B))
          return true;
      }
      if (parseSILDebugLocation(InstLoc, B))
        return true;
      auto *parameterIndicesSubset = IndexSubset::get(
          P.Context, fnType->getNumParameters(), rawParameterIndices);
      ResultVal = B.createLinearFunction(
          InstLoc, parameterIndicesSubset, original, transpose);
      break;
    }
    case SILInstructionKind::DifferentiableFunctionExtractInst: {
      // Parse the rest of the instruction: an extractee, a differentiable
      // function operand, an optional explicit extractee type, and a debug
      // location.
      NormalDifferentiableFunctionTypeComponent extractee;
      StringRef extracteeNames[3] = {"original", "jvp", "vjp"};
      SILValue functionOperand;
      SourceLoc lastLoc;
      if (P.parseToken(
              tok::l_square,
              diag::sil_inst_autodiff_expected_differentiable_extractee_kind) ||
          parseSILIdentifierSwitch(
              extractee, extracteeNames,
              diag::sil_inst_autodiff_expected_differentiable_extractee_kind) ||
          P.parseToken(tok::r_square, diag::sil_autodiff_expected_rsquare,
                       "extractee kind"))
        return true;
      if (parseTypedValueRef(functionOperand, B))
        return true;
      // Parse an optional explicit extractee type.
      Optional<SILType> extracteeType = None;
      if (P.consumeIf(tok::kw_as)) {
        extracteeType = SILType();
        if (parseSILType(*extracteeType))
          return true;
      }
      if (parseSILDebugLocation(InstLoc, B))
        return true;
      ResultVal = B.createDifferentiableFunctionExtract(
          InstLoc, extractee, functionOperand, extracteeType);
      break;
    }
    case SILInstructionKind::LinearFunctionExtractInst: {
      // Parse the rest of the instruction: an extractee, a linear function
      // operand, and a debug location.
      LinearDifferentiableFunctionTypeComponent extractee;
      StringRef extracteeNames[2] = {"original", "transpose"};
      SILValue functionOperand;
      SourceLoc lastLoc;
      if (P.parseToken(tok::l_square,
              diag::sil_inst_autodiff_expected_linear_extractee_kind) ||
          parseSILIdentifierSwitch(extractee, extracteeNames,
              diag::sil_inst_autodiff_expected_linear_extractee_kind) ||
          P.parseToken(tok::r_square, diag::sil_autodiff_expected_rsquare,
                       "extractee kind"))
        return true;
      if (parseTypedValueRef(functionOperand, B) ||
          parseSILDebugLocation(InstLoc, B))
        return true;
      ResultVal = B.createLinearFunctionExtract(
          InstLoc, extractee, functionOperand);
      break;
    }
    case SILInstructionKind::DifferentiabilityWitnessFunctionInst: {
      // e.g. differentiability_witness_function
      //      [jvp] [parameters 0 1] [results 0] <T where T: Differentiable>
      //      @foo : <T> $(T) -> T
      DifferentiabilityWitnessFunctionKind witnessKind;
      StringRef witnessKindNames[3] = {"jvp", "vjp", "transpose"};
      if (P.parseToken(
              tok::l_square,
              diag::
                  sil_inst_autodiff_expected_differentiability_witness_kind) ||
          parseSILIdentifierSwitch(
              witnessKind, witnessKindNames,
              diag::
                  sil_inst_autodiff_expected_differentiability_witness_kind) ||
          P.parseToken(tok::r_square, diag::sil_autodiff_expected_rsquare,
                       "differentiability witness function kind"))
        return true;
      SourceLoc keyStartLoc = P.Tok.getLoc();
      auto configAndFn =
          parseSILDifferentiabilityWitnessConfigAndFunction(P, *this, InstLoc);
      if (!configAndFn)
        return true;
      auto config = configAndFn->first;
      auto originalFn = configAndFn->second;
      auto *witness = SILMod.lookUpDifferentiabilityWitness(
          {originalFn->getName(), config});
      if (!witness) {
        P.diagnose(keyStartLoc, diag::sil_diff_witness_undefined);
        return true;
      }
      // Parse an optional explicit function type.
      Optional<SILType> functionType = None;
      if (P.consumeIf(tok::kw_as)) {
        functionType = SILType();
        if (parseSILType(*functionType))
          return true;
      }
      ResultVal = B.createDifferentiabilityWitnessFunction(
          InstLoc, witnessKind, witness, functionType);
      break;
    }
    case SILInstructionKind::AwaitAsyncContinuationInst: {
      // 'await_async_continuation' operand, 'resume' bb, 'error' bb
      Identifier ResumeBBName, ErrorBBName{};
      SourceLoc ResumeNameLoc, ErrorNameLoc{};
      if (parseTypedValueRef(Val, B)
          || P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",")
          || P.parseSpecificIdentifier("resume", diag::expected_tok_in_sil_instr, "resume")
          || parseSILIdentifier(ResumeBBName, ResumeNameLoc, diag::expected_sil_block_name)) {
        return true;
      }
      
      if (P.consumeIf(tok::comma)) {
          if (P.parseSpecificIdentifier("error", diag::expected_tok_in_sil_instr, "error")
              || parseSILIdentifier(ErrorBBName, ErrorNameLoc, diag::expected_sil_block_name)
              || parseSILDebugLocation(InstLoc, B)) {
            return true;
          }
      }
      
      SILBasicBlock *resumeBB, *errorBB = nullptr;
      resumeBB = getBBForReference(ResumeBBName, ResumeNameLoc);
      if (!ErrorBBName.empty()) {
        errorBB = getBBForReference(ErrorBBName, ErrorNameLoc);
      }
      ResultVal = B.createAwaitAsyncContinuation(InstLoc, Val, resumeBB, errorBB);
      break;
    }
    case SILInstructionKind::GetAsyncContinuationInst:
    case SILInstructionKind::GetAsyncContinuationAddrInst: {
      // 'get_async_continuation'      '[throws]'? type
      // 'get_async_continuation_addr' '[throws]'? type ',' operand
      bool throws = false;
      if (P.consumeIf(tok::l_square)) {
        if (P.parseToken(tok::kw_throws, diag::expected_tok_in_sil_instr, "throws")
            || P.parseToken(tok::r_square, diag::expected_tok_in_sil_instr, "]"))
          return true;
        
        throws = true;
      }
      
      CanType resumeTy;
      if (parseASTType(resumeTy)) {
        return true;
      }
      
      SILValue resumeBuffer;
      if (Opcode == SILInstructionKind::GetAsyncContinuationAddrInst) {
        if (P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",")
            || parseTypedValueRef(resumeBuffer, B)) {
          return true;
        }
      }
      
      if (parseSILDebugLocation(InstLoc, B))
        return true;
      
      if (Opcode == SILInstructionKind::GetAsyncContinuationAddrInst) {
        ResultVal = B.createGetAsyncContinuationAddr(InstLoc, resumeBuffer,
                                                     resumeTy, throws);
      } else {
        ResultVal = B.createGetAsyncContinuation(InstLoc, resumeTy, throws);
      }
      break;
    }

    }

    return false;
}

/// sil-instruction-result ::= sil-value-name '='
/// sil-instruction-result ::= '(' sil-value-name? ')'
/// sil-instruction-result ::= '(' sil-value-name (',' sil-value-name)* ')'
/// sil-instruction-source-info ::= (',' sil-scope-ref)? (',' sil-loc)?
/// sil-instruction-def ::=
///   (sil-instruction-result '=')? sil-instruction sil-instruction-source-info
bool SILParser::parseSILInstruction(SILBuilder &B) {
  // We require SIL instructions to be at the start of a line to assist
  // recovery.
  if (!P.Tok.isAtStartOfLine()) {
    P.diagnose(P.Tok, diag::expected_sil_instr_start_of_line);
    return true;
  }

  if (!B.hasValidInsertionPoint()) {
    P.diagnose(P.Tok, diag::expected_sil_block_name);
    return true;
  }

  SmallVector<Located<StringRef>, 4> resultNames;
  SourceLoc resultClauseBegin;

  // If the instruction has a name '%foo =', parse it.
  if (P.Tok.is(tok::sil_local_name)) {
    resultClauseBegin = P.Tok.getLoc();
    resultNames.push_back({P.Tok.getText(), P.Tok.getLoc()});
    P.consumeToken(tok::sil_local_name);

    // If the instruction has a '(%foo, %bar) = ', parse it.
  } else if (P.consumeIf(tok::l_paren)) {
    resultClauseBegin = P.PreviousLoc;

    if (!P.consumeIf(tok::r_paren)) {
      while (true) {
        if (!P.Tok.is(tok::sil_local_name)) {
          P.diagnose(P.Tok, diag::expected_sil_value_name);
          return true;
        }

        resultNames.push_back({P.Tok.getText(), P.Tok.getLoc()});
        P.consumeToken(tok::sil_local_name);

        if (P.consumeIf(tok::comma))
          continue;
        if (P.consumeIf(tok::r_paren))
          break;

        P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, ",");
        return true;
      }
    }
  }

  if (resultClauseBegin.isValid()) {
    if (P.parseToken(tok::equal, diag::expected_equal_in_sil_instr))
      return true;
  }

  SILInstructionKind Opcode;
  SourceLoc OpcodeLoc;
  StringRef OpcodeName;

  // Parse the opcode name.
  if (parseSILOpcode(Opcode, OpcodeLoc, OpcodeName))
    return true;

  // Perform opcode specific parsing.
  SILInstruction *ResultVal;
  if (parseSpecificSILInstruction(B, Opcode, OpcodeLoc, OpcodeName, ResultVal))
    return true;

  // Match the results clause if we had one.
  if (resultClauseBegin.isValid()) {
    auto results = ResultVal->getResults();
    if (results.size() != resultNames.size()) {
      P.diagnose(resultClauseBegin, diag::wrong_result_count_in_sil_instr,
                 results.size());
    } else {
      for (size_t i : indices(results)) {
        setLocalValue(results[i], resultNames[i].Item, resultNames[i].Loc);
      }
    }
  }

  return false;
}

bool SILParser::parseCallInstruction(SILLocation InstLoc,
                                     SILInstructionKind Opcode, SILBuilder &B,
                                     SILInstruction *&ResultVal) {
  UnresolvedValueName FnName;
  SmallVector<UnresolvedValueName, 4> ArgNames;

  auto PartialApplyConvention = ParameterConvention::Direct_Owned;
  bool IsNonThrowingApply = false;
  bool IsNoEscape = false;
  StringRef AttrName;

  while (parseSILOptional(AttrName, *this)) {
    if (AttrName.equals("nothrow"))
      IsNonThrowingApply = true;
    else if (AttrName.equals("callee_guaranteed"))
      PartialApplyConvention = ParameterConvention::Direct_Guaranteed;
    else if (AttrName.equals("on_stack"))
      IsNoEscape = true;
    else
      return true;
  }
  
  if (parseValueName(FnName))
    return true;
  SmallVector<ParsedSubstitution, 4> parsedSubs;
  if (parseSubstitutions(parsedSubs))
    return true;
    
  if (P.parseToken(tok::l_paren, diag::expected_tok_in_sil_instr, "("))
    return true;

  if (P.Tok.isNot(tok::r_paren)) {
    do {
      UnresolvedValueName Arg;
      if (parseValueName(Arg)) return true;
      ArgNames.push_back(Arg);
    } while (P.consumeIf(tok::comma));
  }

  SILType Ty;
  SourceLoc TypeLoc;
  GenericEnvironment *GenericEnv = nullptr;
  GenericParamList *GenericParams = nullptr;
  if (P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")") ||
      P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":") ||
      parseSILType(Ty, TypeLoc, GenericEnv, GenericParams))
    return true;

  auto FTI = Ty.getAs<SILFunctionType>();
  if (!FTI) {
    P.diagnose(TypeLoc, diag::expected_sil_type_kind, "be a function");
    return true;
  }

  SubstitutionMap subs;
  if (!parsedSubs.empty()) {
    if (!GenericEnv) {
      P.diagnose(TypeLoc, diag::sil_substitutions_on_non_polymorphic_type);
      return true;
    }
    subs = getApplySubstitutionsFromParsed(*this, GenericEnv, parsedSubs);
    if (!subs)
      return true;
  }

  SILValue FnVal = getLocalValue(FnName, Ty, InstLoc, B);

  SILType FnTy = FnVal->getType();
  CanSILFunctionType substFTI = FTI;
  if (!subs.empty()) {
    auto silFnTy = FnTy.castTo<SILFunctionType>();
    substFTI =
        silFnTy->substGenericArgs(SILMod, subs, B.getTypeExpansionContext());
    FnTy = SILType::getPrimitiveObjectType(substFTI);
  }
  SILFunctionConventions substConv(substFTI, B.getModule());

  // Validate the operand count.
  if (substConv.getNumSILArguments() != ArgNames.size() &&
      Opcode != SILInstructionKind::PartialApplyInst) {
    P.diagnose(TypeLoc, diag::expected_sil_type_kind,
               "to have the same number of arg names as arg types");
    return true;
  }

  // Validate the coroutine kind.
  if (Opcode == SILInstructionKind::ApplyInst ||
      Opcode == SILInstructionKind::TryApplyInst) {
    if (FTI->getCoroutineKind() != SILCoroutineKind::None) {
      P.diagnose(TypeLoc, diag::expected_sil_type_kind,
                 "to not be a coroutine");
      return true;
    }
  } else if (Opcode == SILInstructionKind::BeginApplyInst) {
    if (FTI->getCoroutineKind() != SILCoroutineKind::YieldOnce) {
      P.diagnose(TypeLoc, diag::expected_sil_type_kind,
                 "to be a yield_once coroutine");
      return true;
    }
  } else {
    assert(Opcode == SILInstructionKind::PartialApplyInst);
    // partial_apply accepts all kinds of function
  }

  switch (Opcode) {
  default: llvm_unreachable("Unexpected case");
  case SILInstructionKind::ApplyInst : {
    if (parseSILDebugLocation(InstLoc, B))
      return true;

    unsigned ArgNo = 0;
    SmallVector<SILValue, 4> Args;
    for (auto &ArgName : ArgNames) {
      SILType expectedTy =
          substConv.getSILArgumentType(ArgNo++, B.getTypeExpansionContext());
      Args.push_back(getLocalValue(ArgName, expectedTy, InstLoc, B));
    }

    ResultVal = B.createApply(InstLoc, FnVal, subs, Args, IsNonThrowingApply);
    break;
  }
  case SILInstructionKind::BeginApplyInst: {
    if (parseSILDebugLocation(InstLoc, B))
      return true;
    
    unsigned ArgNo = 0;
    SmallVector<SILValue, 4> Args;
    for (auto &ArgName : ArgNames) {
      SILType expectedTy =
          substConv.getSILArgumentType(ArgNo++, B.getTypeExpansionContext());
      Args.push_back(getLocalValue(ArgName, expectedTy, InstLoc, B));
    }

    ResultVal =
      B.createBeginApply(InstLoc, FnVal, subs, Args, IsNonThrowingApply);
    break;
  }
  case SILInstructionKind::PartialApplyInst: {
    if (parseSILDebugLocation(InstLoc, B))
      return true;

    // Compute the result type of the partial_apply, based on which arguments
    // are getting applied.
    SmallVector<SILValue, 4> Args;
    unsigned ArgNo = substConv.getNumSILArguments() - ArgNames.size();
    for (auto &ArgName : ArgNames) {
      SILType expectedTy =
          substConv.getSILArgumentType(ArgNo++, B.getTypeExpansionContext());
      Args.push_back(getLocalValue(ArgName, expectedTy, InstLoc, B));
    }

    // FIXME: Why the arbitrary order difference in IRBuilder type argument?
    ResultVal = B.createPartialApply(
        InstLoc, FnVal, subs, Args, PartialApplyConvention,
        IsNoEscape ? PartialApplyInst::OnStackKind::OnStack
                   : PartialApplyInst::OnStackKind::NotOnStack);
    break;
  }
  case SILInstructionKind::TryApplyInst: {
    Identifier normalBBName, errorBBName;
    SourceLoc normalBBLoc, errorBBLoc;
    if (P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
        parseVerbatim("normal") ||
        parseSILIdentifier(normalBBName, normalBBLoc,
                           diag::expected_sil_block_name) ||
        P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
        parseVerbatim("error") ||
        parseSILIdentifier(errorBBName, errorBBLoc,
                           diag::expected_sil_block_name) ||
        parseSILDebugLocation(InstLoc, B))
      return true;

    unsigned argNo = 0;
    SmallVector<SILValue, 4> args;
    for (auto &argName : ArgNames) {
      SILType expectedTy =
          substConv.getSILArgumentType(argNo++, B.getTypeExpansionContext());
      args.push_back(getLocalValue(argName, expectedTy, InstLoc, B));
    }

    SILBasicBlock *normalBB = getBBForReference(normalBBName, normalBBLoc);
    SILBasicBlock *errorBB = getBBForReference(errorBBName, errorBBLoc);
    ResultVal = B.createTryApply(InstLoc, FnVal, subs, args, normalBB, errorBB);
    break;
  }
  }
  return false;
}

bool SILParser::parseSILFunctionRef(SILLocation InstLoc,
                                    SILFunction *&ResultFn) {
  Identifier Name;
  SILType Ty;
  SourceLoc Loc = P.Tok.getLoc();
  if (parseGlobalName(Name) ||
      P.parseToken(tok::colon, diag::expected_sil_colon_value_ref) ||
      parseSILType(Ty))
    return true;

  auto FnTy = Ty.getAs<SILFunctionType>();
  if (!FnTy || !Ty.isObject()) {
    P.diagnose(Loc, diag::expected_sil_function_type);
    return true;
  }
  
  ResultFn = getGlobalNameForReference(Name, FnTy, Loc);
  return false;
}

/// True if the current token sequence looks like the start of a SIL
/// instruction. This can be one of:
///
/// 1. %name
/// 2. ()
/// 3. (%name1
/// 4. identifier | keyword
///   where the identifier is not followed by a ':' or '(', or it is
///   followed by '(' and is an instruction name.  The exceptions here
///   are for recognizing block names.
bool SILParser::isStartOfSILInstruction() {
  if (P.Tok.is(tok::sil_local_name))
    return true;
  if (P.Tok.is(tok::l_paren) &&
      (P.peekToken().is(tok::sil_local_name) || P.peekToken().is(tok::r_paren)))
    return true;
  if (P.Tok.is(tok::identifier) || P.Tok.isKeyword()) {
    auto &peek = P.peekToken();
    if (peek.is(tok::l_paren))
      return getOpcodeByName(P.Tok.getText()).hasValue();
    return !peek.is(tok::colon);
  }
  return false;
}

///   sil-basic-block:
///     sil-instruction+
///     identifier sil-bb-argument-list? ':' sil-instruction+
///   sil-bb-argument-list:
///     '(' sil-typed-valueref (',' sil-typed-valueref)+ ')'
bool SILParser::parseSILBasicBlock(SILBuilder &B) {
  SILBasicBlock *BB;

  // The basic block name is optional.
  if (P.Tok.is(tok::sil_local_name)) {
    BB = getBBForDefinition(Identifier(), SourceLoc());
  } else {
    Identifier BBName;
    SourceLoc NameLoc;
    if (parseSILIdentifier(BBName, NameLoc, diag::expected_sil_block_name))
      return true;

    BB = getBBForDefinition(BBName, NameLoc);
    // For now, since we always assume that PhiArguments have
    // OwnershipKind::None, do not parse or do anything special. Eventually
    // we will parse the convention.
    bool IsEntry = BB->isEntry();

    // If there is a basic block argument list, process it.
    if (P.consumeIf(tok::l_paren)) {
      do {
        SILType Ty;
        ValueOwnershipKind OwnershipKind = OwnershipKind::None;
        SourceLoc NameLoc;
        StringRef Name = P.Tok.getText();
        if (P.parseToken(tok::sil_local_name, NameLoc,
                         diag::expected_sil_value_name) ||
            P.parseToken(tok::colon, diag::expected_sil_colon_value_ref))
          return true;

        // If SILOwnership is enabled and we are not assuming that we are
        // parsing unqualified SIL, look for printed value ownership kinds.
        if (F->hasOwnership() &&
            parseSILOwnership(OwnershipKind))
          return true;

        if (parseSILType(Ty))
          return true;

        SILArgument *Arg;
        if (IsEntry) {
          Arg = BB->createFunctionArgument(Ty);
          // Today, we construct the ownership kind straight from the function
          // type. Make sure they are in sync, otherwise bail. We want this to
          // be an exact check rather than a compatibility check since we do not
          // want incompatibilities in between @any and other types of ownership
          // to be ignored.
          if (F->hasOwnership() && Arg->getOwnershipKind() != OwnershipKind) {
            auto diagID =
                diag::silfunc_and_silarg_have_incompatible_sil_value_ownership;
            P.diagnose(NameLoc, diagID, Arg->getOwnershipKind().asString(),
                       OwnershipKind.asString());
            return true;
          }
        } else {
          Arg = BB->createPhiArgument(Ty, OwnershipKind);
        }
        setLocalValue(Arg, Name, NameLoc);
      } while (P.consumeIf(tok::comma));
      
      if (P.parseToken(tok::r_paren, diag::sil_basicblock_arg_rparen))
        return true;
    }
    
    if (P.parseToken(tok::colon, diag::expected_sil_block_colon))
      return true;
  }
  
  // Make sure the block is at the end of the function so that forward
  // references don't affect block layout.
  F->getBlocks().remove(BB);
  F->getBlocks().push_back(BB);

  B.setInsertionPoint(BB);
  do {
    if (parseSILInstruction(B))
      return true;
  } while (isStartOfSILInstruction());

  return false;
}

///   decl-sil:   [[only in SIL mode]]
///     'sil' sil-linkage '@' identifier ':' sil-type decl-sil-body?
///   decl-sil-body:
///     '{' sil-basic-block+ '}'
bool SILParserState::parseDeclSIL(Parser &P) {
  // Inform the lexer that we're lexing the body of the SIL declaration.  Do
  // this before we consume the 'sil' token so that all later tokens are
  // properly handled.
  Lexer::SILBodyRAII Tmp(*P.L);

  P.consumeToken(tok::kw_sil);

  SILParser FunctionState(P);

  Optional<SILLinkage> FnLinkage;
  Identifier FnName;
  SILType FnType;
  SourceLoc FnNameLoc;

  bool isTransparent = false;
  IsSerialized_t isSerialized = IsNotSerialized;
  bool isCanonical = false;
  IsDynamicallyReplaceable_t isDynamic = IsNotDynamic;
  IsExactSelfClass_t isExactSelfClass = IsNotExactSelfClass;
  bool hasOwnershipSSA = false;
  IsThunk_t isThunk = IsNotThunk;
  SILFunction::Purpose specialPurpose = SILFunction::Purpose::None;
  bool isWeakImported = false;
  AvailabilityContext availability = AvailabilityContext::alwaysAvailable();
  bool isWithoutActuallyEscapingThunk = false;
  Inline_t inlineStrategy = InlineDefault;
  OptimizationMode optimizationMode = OptimizationMode::NotSet;
  SmallVector<std::string, 1> Semantics;
  SmallVector<ParsedSpecAttr, 4> SpecAttrs;
  ValueDecl *ClangDecl = nullptr;
  EffectsKind MRK = EffectsKind::Unspecified;
  SILFunction *DynamicallyReplacedFunction = nullptr;
  Identifier objCReplacementFor;
  if (parseSILLinkage(FnLinkage, P) ||
      parseDeclSILOptional(
          &isTransparent, &isSerialized, &isCanonical, &hasOwnershipSSA,
          &isThunk, &isDynamic, &isExactSelfClass, &DynamicallyReplacedFunction,
          &objCReplacementFor, &specialPurpose, &inlineStrategy,
          &optimizationMode, nullptr, &isWeakImported, &availability,
          &isWithoutActuallyEscapingThunk, &Semantics,
          &SpecAttrs, &ClangDecl, &MRK, FunctionState, M) ||
      P.parseToken(tok::at_sign, diag::expected_sil_function_name) ||
      P.parseIdentifier(FnName, FnNameLoc, /*diagnoseDollarPrefix=*/false,
                        diag::expected_sil_function_name) ||
      P.parseToken(tok::colon, diag::expected_sil_type))
    return true;
  {
    // Construct a Scope for the function body so TypeAliasDecl can be added to
    // the scope.
    GenericEnvironment *GenericEnv = nullptr;
    GenericParamList *GenericParams = nullptr;
    if (FunctionState.parseSILType(FnType, GenericEnv, GenericParams,
                                   true /*IsFuncDecl*/))
      return true;
    auto SILFnType = FnType.getAs<SILFunctionType>();
    if (!SILFnType || !FnType.isObject()) {
      P.diagnose(FnNameLoc, diag::expected_sil_function_type);
      return true;
    }
  
    FunctionState.F =
      FunctionState.getGlobalNameForDefinition(FnName, SILFnType, FnNameLoc);
    FunctionState.F->setBare(IsBare);
    FunctionState.F->setTransparent(IsTransparent_t(isTransparent));
    FunctionState.F->setSerialized(IsSerialized_t(isSerialized));
    FunctionState.F->setWasDeserializedCanonical(isCanonical);
    if (!hasOwnershipSSA)
      FunctionState.F->setOwnershipEliminated();
    FunctionState.F->setThunk(IsThunk_t(isThunk));
    FunctionState.F->setIsDynamic(isDynamic);
    FunctionState.F->setIsExactSelfClass(isExactSelfClass);
    FunctionState.F->setDynamicallyReplacedFunction(
        DynamicallyReplacedFunction);
    if (!objCReplacementFor.empty())
      FunctionState.F->setObjCReplacement(objCReplacementFor);
    FunctionState.F->setSpecialPurpose(specialPurpose);
    FunctionState.F->setAlwaysWeakImported(isWeakImported);
    FunctionState.F->setAvailabilityForLinkage(availability);
    FunctionState.F->setWithoutActuallyEscapingThunk(
      isWithoutActuallyEscapingThunk);
    FunctionState.F->setInlineStrategy(inlineStrategy);
    FunctionState.F->setOptimizationMode(optimizationMode);
    FunctionState.F->setEffectsKind(MRK);
    if (ClangDecl)
      FunctionState.F->setClangNodeOwner(ClangDecl);
    for (auto &Attr : Semantics) {
      FunctionState.F->addSemanticsAttr(Attr);
    }
    // Now that we have a SILFunction parse the body, if present.

    bool isDefinition = false;
    SourceLoc LBraceLoc = P.Tok.getLoc();

    if (P.consumeIf(tok::l_brace)) {
      isDefinition = true;

      FunctionState.ContextGenericEnv = GenericEnv;
      FunctionState.ContextGenericParams = GenericParams;
      FunctionState.F->setGenericEnvironment(GenericEnv);

      if (GenericEnv && !SpecAttrs.empty()) {
        for (auto &Attr : SpecAttrs) {
          SmallVector<Requirement, 2> requirements;
          // Resolve types and convert requirements.
          FunctionState.convertRequirements(Attr.requirements, requirements);
          auto *fenv = FunctionState.F->getGenericEnvironment();
          auto genericSig = evaluateOrDefault(
              P.Context.evaluator,
              AbstractGenericSignatureRequest{
                fenv->getGenericSignature().getPointer(),
                /*addedGenericParams=*/{ },
                std::move(requirements)},
                GenericSignature());
          FunctionState.F->addSpecializeAttr(SILSpecializeAttr::create(
              FunctionState.F->getModule(), genericSig, Attr.exported,
              Attr.kind, Attr.target, Attr.spiGroupID, Attr.spiModule));
        }
      }

      // Parse the basic block list.
      SILOpenedArchetypesTracker OpenedArchetypesTracker(FunctionState.F);
      SILBuilder B(*FunctionState.F);
      // Track the archetypes just like SILGen. This
      // is required for adding typedef operands to instructions.
      B.setOpenedArchetypesTracker(&OpenedArchetypesTracker);

      // Define a callback to be invoked on the deserialized types.
      auto OldParsedTypeCallback = FunctionState.ParsedTypeCallback;
      SWIFT_DEFER {
        FunctionState.ParsedTypeCallback = OldParsedTypeCallback;
      };

      FunctionState.ParsedTypeCallback = [&OpenedArchetypesTracker](Type ty) {
        OpenedArchetypesTracker.registerUsedOpenedArchetypes(
          ty->getCanonicalType());
      };

      do {
        if (FunctionState.parseSILBasicBlock(B))
          return true;
      } while (P.Tok.isNot(tok::r_brace) && P.Tok.isNot(tok::eof));

      SourceLoc RBraceLoc;
      P.parseMatchingToken(tok::r_brace, RBraceLoc, diag::expected_sil_rbrace,
                           LBraceLoc);

      // Check that there are no unresolved forward definitions of opened
      // archetypes.
      if (OpenedArchetypesTracker.hasUnresolvedOpenedArchetypeDefinitions())
        llvm_unreachable(
            "All forward definitions of opened archetypes should be resolved");
    }

    FunctionState.F->setLinkage(resolveSILLinkage(FnLinkage, isDefinition));
  }

  if (FunctionState.diagnoseProblems())
    return true;

  // If SIL parsing succeeded, verify the generated SIL.
  if (!P.Diags.hadAnyError())
    FunctionState.F->verify();

  return false;
}

///   decl-sil-stage:   [[only in SIL mode]]
///     'sil_stage' ('raw' | 'canonical')
bool SILParserState::parseDeclSILStage(Parser &P) {
  SourceLoc stageLoc = P.consumeToken(tok::kw_sil_stage);
  if (!P.Tok.is(tok::identifier)) {
    P.diagnose(P.Tok, diag::expected_sil_stage_name);
    return true;
  }
  SILStage stage;
  if (P.Tok.isContextualKeyword("raw")) {
    stage = SILStage::Raw;
    P.consumeToken();
  } else if (P.Tok.isContextualKeyword("canonical")) {
    stage = SILStage::Canonical;
    P.consumeToken();
  } else if (P.Tok.isContextualKeyword("lowered")) {
    stage = SILStage::Lowered;
    P.consumeToken();
  } else {
    P.diagnose(P.Tok, diag::expected_sil_stage_name);
    P.consumeToken();
    return true;
  }
  
  if (DidParseSILStage) {
    P.diagnose(stageLoc, diag::multiple_sil_stage_decls);
    return false;
  }
  
  M.setStage(stage);
  DidParseSILStage = true;
  return false;
}

/// Lookup a global variable declaration from its demangled name.
///
/// A variable declaration exists for all sil_global variables defined in
/// Swift. A Swift global defined outside this module will be exposed
/// via an addressor rather than as a sil_global. Globals imported
/// from clang will produce a sil_global but will not have any corresponding
/// VarDecl.
///
/// FIXME: lookupGlobalDecl() can handle collisions between private or
/// fileprivate global variables in the same SIL Module, but the typechecker
/// will still incorrectly diagnose this as an "invalid redeclaration" and give
/// all but the first declaration an error type.
static Optional<VarDecl *> lookupGlobalDecl(Identifier GlobalName,
                                            SILLinkage GlobalLinkage,
                                            SILType GlobalType, Parser &P) {
  // Create a set of DemangleOptions to produce the global variable's
  // identifier, which is used as a search key in the declaration context.
  Demangle::DemangleOptions demangleOpts;
  demangleOpts.QualifyEntities = false;
  demangleOpts.ShowPrivateDiscriminators = false;
  demangleOpts.DisplayEntityTypes = false;
  std::string GlobalDeclName = Demangle::demangleSymbolAsString(
    GlobalName.str(), demangleOpts);

  SmallVector<ValueDecl *, 4> CurModuleResults;
  P.SF.getParentModule()->lookupValue(
      P.Context.getIdentifier(GlobalDeclName), NLKind::UnqualifiedLookup,
      CurModuleResults);
  // Bail-out on clang-imported globals.
  if (CurModuleResults.empty())
    return nullptr;

  // private and fileprivate globals of the same name may be merged into a
  // single SIL module. Find the declaration with the correct type and
  // linkage. (If multiple globals have the same type and linkage then it
  // doesn't matter which declaration we use).
  for (ValueDecl *ValDecl : CurModuleResults) {
    auto *VD = cast<VarDecl>(ValDecl);
    CanType DeclTy = VD->getType()->getCanonicalType();
    if (DeclTy == GlobalType.getASTType()
        && getDeclSILLinkage(VD) == GlobalLinkage) {
      return VD;
    }
  }
  return None;
}

/// decl-sil-global: [[only in SIL mode]]
///   'sil_global' sil-linkage @name : sil-type [external]
bool SILParserState::parseSILGlobal(Parser &P) {
  // Inform the lexer that we're lexing the body of the SIL declaration.
  Lexer::SILBodyRAII Tmp(*P.L);

  P.consumeToken(tok::kw_sil_global);
  Optional<SILLinkage> GlobalLinkage;
  Identifier GlobalName;
  SILType GlobalType;
  SourceLoc NameLoc;
  IsSerialized_t isSerialized = IsNotSerialized;
  bool isLet = false;

  SILParser State(P);
  if (parseSILLinkage(GlobalLinkage, P) ||
      parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr, nullptr,
                           nullptr, nullptr, nullptr, nullptr, nullptr,
                           nullptr, nullptr,
                           &isLet, nullptr, nullptr, nullptr, nullptr, nullptr,
                           nullptr, nullptr, State, M) ||
      P.parseToken(tok::at_sign, diag::expected_sil_value_name) ||
      P.parseIdentifier(GlobalName, NameLoc, /*diagnoseDollarPrefix=*/false,
                        diag::expected_sil_value_name) ||
      P.parseToken(tok::colon, diag::expected_sil_type))
    return true;

  if (State.parseSILType(GlobalType))
    return true;

  // Non-external global variables are definitions by default.
  if (!GlobalLinkage.hasValue())
    GlobalLinkage = SILLinkage::DefaultForDefinition;

  // Lookup the global variable declaration for this sil_global.
  auto VD =
      lookupGlobalDecl(GlobalName, GlobalLinkage.getValue(), GlobalType, P);
  if (!VD) {
    P.diagnose(NameLoc, diag::sil_global_variable_not_found, GlobalName);
    return true;
  }
  auto *GV = SILGlobalVariable::create(
      M, GlobalLinkage.getValue(), isSerialized, GlobalName.str(), GlobalType,
      RegularLocation(NameLoc), VD.getValue());

  GV->setLet(isLet);
  // Parse static initializer if exists.
  if (State.P.consumeIf(tok::equal) && State.P.consumeIf(tok::l_brace)) {
    SILBuilder B(GV);
    do {
      State.parseSILInstruction(B);
    } while (! State.P.consumeIf(tok::r_brace));
  }
  return false;
}

/// decl-sil-property: [[only in SIL mode]]
///   'sil_property' sil-decl-ref '(' sil-key-path-pattern-component ')'

bool SILParserState::parseSILProperty(Parser &P) {
  Lexer::SILBodyRAII Tmp(*P.L);

  auto loc = P.consumeToken(tok::kw_sil_property);
  auto InstLoc = RegularLocation(loc);
  SILParser SP(P);
  
  IsSerialized_t Serialized = IsNotSerialized;
  if (parseDeclSILOptional(nullptr, &Serialized, nullptr, nullptr, nullptr,
                           nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
                           nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
                           nullptr, nullptr, nullptr, SP, M))
    return true;
  
  ValueDecl *VD;
  
  if (SP.parseSILDottedPath(VD))
    return true;
  
  GenericParamList *patternParams;
  GenericEnvironment *patternEnv;
  patternParams = P.maybeParseGenericParams().getPtrOrNull();
  patternEnv = handleSILGenericParams(patternParams, &P.SF);

  if (patternEnv) {
    if (patternEnv->getGenericSignature().getCanonicalSignature() !=
        VD->getInnermostDeclContext()
            ->getGenericSignatureOfContext()
            .getCanonicalSignature()) {
      P.diagnose(loc, diag::sil_property_generic_signature_mismatch);
      return true;
    }
  } else {
    if (VD->getInnermostDeclContext()->getGenericSignatureOfContext()) {
      P.diagnose(loc, diag::sil_property_generic_signature_mismatch);
      return true;
    }
  }

  Identifier ComponentKind;
  Optional<KeyPathPatternComponent> Component;
  SourceLoc ComponentLoc;
  SmallVector<SILType, 4> OperandTypes;

  if (P.parseToken(tok::l_paren, diag::expected_tok_in_sil_instr, "("))
    return true;
  
  if (!P.consumeIf(tok::r_paren)) {
    KeyPathPatternComponent parsedComponent;
    if (P.parseIdentifier(ComponentKind, ComponentLoc,
                          /*diagnoseDollarPrefix=*/false,
                          diag::expected_tok_in_sil_instr, "component kind")
        || SP.parseKeyPathPatternComponent(parsedComponent, OperandTypes,
                 ComponentLoc, ComponentKind, InstLoc,
                 patternEnv, patternParams)
        || P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")"))
      return true;
    
    Component = std::move(parsedComponent);
  }
  
  SILProperty::create(M, Serialized,
                      cast<AbstractStorageDecl>(VD), Component);
  return false;
}

/// decl-sil-vtable: [[only in SIL mode]]
///   'sil_vtable' ClassName decl-sil-vtable-body
/// decl-sil-vtable-body:
///   '{' sil-vtable-entry* '}'
/// sil-vtable-entry:
///   SILDeclRef ':' SILFunctionName
bool SILParserState::parseSILVTable(Parser &P) {
  P.consumeToken(tok::kw_sil_vtable);
  SILParser VTableState(P);

  IsSerialized_t Serialized = IsNotSerialized;
  if (parseDeclSILOptional(nullptr, &Serialized, nullptr, nullptr, nullptr,
                           nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
                           nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
                           nullptr, nullptr, nullptr,
                           VTableState, M))
    return true;

  // Parse the class name.
  Identifier Name;
  SourceLoc Loc;
  if (VTableState.parseSILIdentifier(Name, Loc,
                                     diag::expected_sil_value_name))
    return true;

  // Find the class decl.
  llvm::PointerUnion<ValueDecl*, ModuleDecl *> Res =
    lookupTopDecl(P, Name, /*typeLookup=*/true);
  assert(Res.is<ValueDecl*>() && "Class look-up should return a Decl");
  ValueDecl *VD = Res.get<ValueDecl*>();
  if (!VD) {
    P.diagnose(Loc, diag::sil_vtable_class_not_found, Name);
    return true;
  }

  auto *theClass = dyn_cast<ClassDecl>(VD);
  if (!theClass) {
    P.diagnose(Loc, diag::sil_vtable_class_not_found, Name);
    return true;
  }

  SourceLoc LBraceLoc = P.Tok.getLoc();
  P.consumeToken(tok::l_brace);

  // We need to turn on InSILBody to parse SILDeclRef.
  Lexer::SILBodyRAII Tmp(*P.L);
  // Parse the entry list.
  std::vector<SILVTable::Entry> vtableEntries;
  if (P.Tok.isNot(tok::r_brace)) {
    do {
      SILDeclRef Ref;
      Identifier FuncName;
      SourceLoc FuncLoc;
      if (VTableState.parseSILDeclRef(Ref, true))
        return true;
      SILFunction *Func = nullptr;
      if (P.Tok.is(tok::kw_nil)) {
        P.consumeToken();
      } else {
        if (P.parseToken(tok::colon, diag::expected_sil_vtable_colon) ||
            P.parseToken(tok::at_sign, diag::expected_sil_function_name) ||
            VTableState.parseSILIdentifier(FuncName, FuncLoc,
                                           diag::expected_sil_value_name))
        return true;
        Func = M.lookUpFunction(FuncName.str());
        if (!Func) {
          P.diagnose(FuncLoc, diag::sil_vtable_func_not_found, FuncName);
          return true;
        }
      }

      auto Kind = SILVTable::Entry::Kind::Normal;
      bool NonOverridden = false;
      while (P.Tok.is(tok::l_square)) {
        P.consumeToken(tok::l_square);
        if (P.Tok.isNot(tok::identifier)) {
          P.diagnose(P.Tok.getLoc(), diag::sil_vtable_bad_entry_kind);
          return true;
        }

        if (P.Tok.getText() == "override") {
          P.consumeToken();
          Kind = SILVTable::Entry::Kind::Override;
        } else if (P.Tok.getText() == "inherited") {
          P.consumeToken();
          Kind = SILVTable::Entry::Kind::Inherited;
        } else if (P.Tok.getText() == "nonoverridden") {
          P.consumeToken();
          NonOverridden = true;
        } else {
          P.diagnose(P.Tok.getLoc(), diag::sil_vtable_bad_entry_kind);
          return true;
        }

        if (P.parseToken(tok::r_square, diag::sil_vtable_expect_rsquare))
          return true;
      }

      vtableEntries.emplace_back(Ref, Func, Kind, NonOverridden);
    } while (P.Tok.isNot(tok::r_brace) && P.Tok.isNot(tok::eof));
  }

  SourceLoc RBraceLoc;
  P.parseMatchingToken(tok::r_brace, RBraceLoc, diag::expected_sil_rbrace,
                       LBraceLoc);

  SILVTable::create(M, theClass, Serialized, vtableEntries);
  return false;
}

static ProtocolDecl *parseProtocolDecl(Parser &P, SILParser &SP) {
  Identifier DeclName;
  SourceLoc DeclLoc;
  if (SP.parseSILIdentifier(DeclName, DeclLoc, diag::expected_sil_value_name))
    return nullptr;

  // Find the protocol decl. The protocol can be imported.
  llvm::PointerUnion<ValueDecl*, ModuleDecl *> Res =
    lookupTopDecl(P, DeclName, /*typeLookup=*/true);
  assert(Res.is<ValueDecl*>() && "Protocol look-up should return a Decl");
  ValueDecl *VD = Res.get<ValueDecl*>();
  if (!VD) {
    P.diagnose(DeclLoc, diag::sil_witness_protocol_not_found, DeclName);
    return nullptr;
  }
  auto *proto = dyn_cast<ProtocolDecl>(VD);
  if (!proto)
    P.diagnose(DeclLoc, diag::sil_witness_protocol_not_found, DeclName);
  return proto;
}

static AssociatedTypeDecl *parseAssociatedTypeDecl(Parser &P, SILParser &SP,
                                                   ProtocolDecl *proto) {
  Identifier DeclName;
  SourceLoc DeclLoc;
  if (SP.parseSILIdentifier(DeclName, DeclLoc, diag::expected_sil_value_name))
    return nullptr;
  // We can return multiple decls, for now, we use the first lookup result.
  // One example is two decls when searching for Generator of Sequence:
  // one from Sequence, the other from _Sequence_Type.
  SmallVector<ValueDecl *, 4> values;
  auto VD = lookupMember(P, proto->getInterfaceType(), DeclName, DeclLoc,
                         values, true/*ExpectMultipleResults*/);
  if (!VD) {
    P.diagnose(DeclLoc, diag::sil_witness_assoc_not_found, DeclName);
    return nullptr;
  }
  return dyn_cast<AssociatedTypeDecl>(VD);
}

static bool parseAssociatedTypePath(SILParser &SP,
                                    SmallVectorImpl<Identifier> &path) {
  do {
    Identifier name;
    SourceLoc loc;
    if (SP.parseSILIdentifier(name, loc, diag::expected_sil_value_name))
      return false;
    path.push_back(name);
  } while (SP.P.consumeIf(tok::period));

  return true;
}

static bool matchesAssociatedTypePath(CanType assocType,
                                      ArrayRef<Identifier> path) {
  if (auto memberType = dyn_cast<DependentMemberType>(assocType)) {
    return (!path.empty() &&
            memberType->getName() == path.back() &&
            matchesAssociatedTypePath(memberType.getBase(), path.drop_back()));
  } else {
    assert(isa<GenericTypeParamType>(assocType));
    return path.empty();
  }
}

static CanType parseAssociatedTypePath(Parser &P, SILParser &SP,
                                       ProtocolDecl *proto) {
  SourceLoc loc = SP.P.Tok.getLoc();
  SmallVector<Identifier, 4> path;
  if (!parseAssociatedTypePath(SP, path))
    return CanType();

  // This is only used for parsing associated conformances, so we can
  // go ahead and just search the requirement signature for something that
  // matches the path.
  for (auto &reqt : proto->getRequirementSignature()) {
    if (reqt.getKind() != RequirementKind::Conformance)
      continue;
    CanType assocType = reqt.getFirstType()->getCanonicalType();
    if (matchesAssociatedTypePath(assocType, path))
      return assocType;
  }

  SmallString<128> name;
  name += path[0].str();
  for (auto elt : makeArrayRef(path).slice(1)) {
    name += '.';
    name += elt.str();
  }
  P.diagnose(loc, diag::sil_witness_assoc_conf_not_found, name);
  return CanType();
}

static ProtocolConformanceRef
parseRootProtocolConformance(Parser &P, SILParser &SP, Type ConformingTy,
                             ProtocolDecl *&proto) {
  const StringRef ModuleKeyword = "module";
  Identifier ModuleName;
  SourceLoc Loc, KeywordLoc;
  proto = parseProtocolDecl(P, SP);
  if (!proto)
    return ProtocolConformanceRef();

  if (P.parseSpecificIdentifier(
          ModuleKeyword, KeywordLoc,
          Diagnostic(diag::expected_tok_in_sil_instr, ModuleKeyword)) ||
      SP.parseSILIdentifier(ModuleName, Loc, diag::expected_sil_value_name))
    return ProtocolConformanceRef();

  // Calling lookupConformance on a BoundGenericType will return a specialized
  // conformance. We use UnboundGenericType to find the normal conformance.
  Type lookupTy = ConformingTy;
  if (auto bound = lookupTy->getAs<BoundGenericType>())
    lookupTy = bound->getDecl()->getDeclaredType();
  auto lookup = P.SF.getParentModule()->lookupConformance(lookupTy, proto);
  if (lookup.isInvalid()) {
    P.diagnose(KeywordLoc, diag::sil_witness_protocol_conformance_not_found);
    return ProtocolConformanceRef();
  }

  return lookup;
}

///  protocol-conformance ::= normal-protocol-conformance
///  protocol-conformance ::=
///    generic-parameter-list? type: 'inherit' '(' protocol-conformance ')'
///  protocol-conformance ::=
///    generic-parameter-list? type: 'specialize' '<' substitution* '>'
///    '(' protocol-conformance ')'
///  normal-protocol-conformance ::=
///    generic-parameter-list? type: protocolName module ModuleName
/// Note that generic-parameter-list is already parsed before calling this.
ProtocolConformanceRef SILParser::parseProtocolConformance(
    ProtocolDecl *&proto,
    GenericEnvironment *&genericEnv,
    GenericParamList *&genericParams) {
  // Make sure we don't leave it uninitialized in the caller
  genericEnv = nullptr;

  genericParams = P.maybeParseGenericParams().getPtrOrNull();
  if (genericParams) {
    genericEnv = handleSILGenericParams(genericParams, &P.SF);
  }

  return parseProtocolConformanceHelper(proto, genericEnv, genericParams);
}

ProtocolConformanceRef SILParser::parseProtocolConformanceHelper(
    ProtocolDecl *&proto,
    GenericEnvironment *witnessEnv,
    GenericParamList *witnessParams) {
  // Parse AST type.
  ParserResult<TypeRepr> TyR = P.parseType();
  if (TyR.isNull())
    return ProtocolConformanceRef();

  if (witnessEnv == nullptr)
    witnessEnv = ContextGenericEnv;
  if (witnessParams == nullptr)
    witnessParams = ContextGenericParams;

  const auto ConformingTy =
      performTypeResolution(TyR.get(), /*IsSILType=*/false,
                            witnessEnv, witnessParams);
  if (ConformingTy->hasError())
    return ProtocolConformanceRef();

  if (P.parseToken(tok::colon, diag::expected_sil_witness_colon))
    return ProtocolConformanceRef();

  if (P.Tok.is(tok::identifier) && P.Tok.getText() == "specialize") {
    P.consumeToken();

    // Parse substitutions for specialized conformance.
    SmallVector<ParsedSubstitution, 4> parsedSubs;
    if (parseSubstitutions(parsedSubs, witnessEnv, witnessParams))
      return ProtocolConformanceRef();

    if (P.parseToken(tok::l_paren, diag::expected_sil_witness_lparen))
      return ProtocolConformanceRef();
    ProtocolDecl *dummy;
    GenericEnvironment *specializedEnv = nullptr;
    GenericParamList *specializedParams = nullptr;
    auto genericConform =
        parseProtocolConformance(dummy, specializedEnv, specializedParams);
    if (genericConform.isInvalid() || !genericConform.isConcrete())
      return ProtocolConformanceRef();
    if (P.parseToken(tok::r_paren, diag::expected_sil_witness_rparen))
      return ProtocolConformanceRef();

    SubstitutionMap subMap =
      getApplySubstitutionsFromParsed(*this, specializedEnv, parsedSubs);
    if (!subMap)
      return ProtocolConformanceRef();

    auto result = P.Context.getSpecializedConformance(
        ConformingTy, genericConform.getConcrete(), subMap);
    return ProtocolConformanceRef(result);
  }

  if (P.Tok.is(tok::identifier) && P.Tok.getText() == "inherit") {
    P.consumeToken();

    if (P.parseToken(tok::l_paren, diag::expected_sil_witness_lparen))
      return ProtocolConformanceRef();
    auto baseConform = parseProtocolConformance();
    if (baseConform.isInvalid() || !baseConform.isConcrete())
      return ProtocolConformanceRef();
    if (P.parseToken(tok::r_paren, diag::expected_sil_witness_rparen))
      return ProtocolConformanceRef();

    auto result = P.Context.getInheritedConformance(ConformingTy,
                                                    baseConform.getConcrete());
    return ProtocolConformanceRef(result);
  }

  auto retVal =
    parseRootProtocolConformance(P, *this, ConformingTy, proto);
  return retVal;
}

/// Parser a single SIL vtable entry and add it to either \p witnessEntries
/// or \c conditionalConformances.
static bool parseSILWitnessTableEntry(
         Parser &P,
         SILModule &M,
         ProtocolDecl *proto,
         GenericEnvironment *witnessEnv,
         GenericParamList *witnessParams,
         SILParser &witnessState,
         std::vector<SILWitnessTable::Entry> &witnessEntries,
         std::vector<SILWitnessTable::ConditionalConformance>
           &conditionalConformances) {
  Identifier EntryKeyword;
  SourceLoc KeywordLoc;
  if (P.parseIdentifier(EntryKeyword, KeywordLoc,
                        /*diagnoseDollarPrefix=*/false,
                        diag::expected_tok_in_sil_instr,
                        "method, associated_type, associated_type_protocol"
                        ", base_protocol, no_default"))
    return true;

  if (EntryKeyword.str() == "no_default") {
    witnessEntries.push_back(SILDefaultWitnessTable::Entry());
    return false;
  }

  if (EntryKeyword.str() == "base_protocol") {
    ProtocolDecl *proto = parseProtocolDecl(P, witnessState);
    if (!proto)
      return true;
    if (P.parseToken(tok::colon, diag::expected_sil_witness_colon))
      return true;
    auto conform =
      witnessState.parseProtocolConformance();
    // Ignore invalid and abstract witness entries.
    if (conform.isInvalid() || !conform.isConcrete())
      return false;

    witnessEntries.push_back(
        SILWitnessTable::BaseProtocolWitness{proto, conform.getConcrete()});
    return false;
  }

  if (EntryKeyword.str() == "associated_type_protocol" ||
      EntryKeyword.str() == "conditional_conformance") {
    if (P.parseToken(tok::l_paren, diag::expected_sil_witness_lparen))
      return true;
    CanType assocOrSubject;
    if (EntryKeyword.str() == "associated_type_protocol") {
      assocOrSubject = parseAssociatedTypePath(P, witnessState, proto);
    } else {
      // Parse AST type.
      ParserResult<TypeRepr> TyR = P.parseType();
      if (TyR.isNull())
        return true;

      const auto Ty =
          swift::performTypeResolution(TyR.get(), P.Context,
                                       /*isSILMode=*/false,
                                       /*isSILType=*/false,
                                       witnessEnv,
                                       witnessParams,
                                       &P.SF);
      if (Ty->hasError())
        return true;

      assocOrSubject = Ty->getCanonicalType();
    }
    if (!assocOrSubject)
      return true;
    if (P.parseToken(tok::colon, diag::expected_sil_witness_colon))
      return true;
    ProtocolDecl *proto = parseProtocolDecl(P, witnessState);
    if (!proto)
      return true;
    if (P.parseToken(tok::r_paren, diag::expected_sil_witness_rparen) ||
        P.parseToken(tok::colon, diag::expected_sil_witness_colon))
      return true;

    ProtocolConformanceRef conformance(proto);
    if (P.Tok.getText() != "dependent") {
      auto concrete =
        witnessState.parseProtocolConformance();
      // Ignore invalid and abstract witness entries.
      if (concrete.isInvalid() || !concrete.isConcrete())
        return false;
      conformance = concrete;
    } else {
      P.consumeToken();
    }

    if (EntryKeyword.str() == "associated_type_protocol")
      witnessEntries.push_back(
          SILWitnessTable::AssociatedTypeProtocolWitness{assocOrSubject,
                                                         proto,
                                                         conformance});
    else
      conditionalConformances.push_back(
          SILWitnessTable::ConditionalConformance{assocOrSubject,
                                                  conformance});

    return false;
  }

  if (EntryKeyword.str() == "associated_type") {
    AssociatedTypeDecl *assoc = parseAssociatedTypeDecl(P, witnessState,
                                                        proto);
    if (!assoc)
      return true;
    if (P.parseToken(tok::colon, diag::expected_sil_witness_colon))
      return true;

    // Parse AST type.
    ParserResult<TypeRepr> TyR = P.parseType();
    if (TyR.isNull())
      return true;

    const auto Ty =
        swift::performTypeResolution(TyR.get(), P.Context,
                                     /*isSILMode=*/false,
                                     /*isSILType=*/false,
                                     witnessEnv, witnessParams,
                                     &P.SF);
    if (Ty->hasError())
      return true;

    witnessEntries.push_back(
        SILWitnessTable::AssociatedTypeWitness{assoc, Ty->getCanonicalType()});
    return false;
  }

  if (EntryKeyword.str() != "method") {
    P.diagnose(KeywordLoc, diag::expected_tok_in_sil_instr, "method");
    return true;
  }

  SILDeclRef Ref;


  Identifier FuncName;
  SourceLoc FuncLoc;
  if (witnessState.parseSILDeclRef(Ref, true) ||
      P.parseToken(tok::colon, diag::expected_sil_witness_colon))
    return true;

  SILFunction *Func = nullptr;
  if (P.Tok.is(tok::kw_nil)) {
    P.consumeToken();
  } else {
    if (P.parseToken(tok::at_sign, diag::expected_sil_function_name) ||
        witnessState.parseSILIdentifier(FuncName, FuncLoc,
                                        diag::expected_sil_value_name))
      return true;

    Func = M.lookUpFunction(FuncName.str());
    if (!Func) {
      P.diagnose(FuncLoc, diag::sil_witness_func_not_found, FuncName);
      return true;
    }
  }

  witnessEntries.push_back(SILWitnessTable::MethodWitness{
    Ref, Func
  });

  return false;
}

/// decl-sil-witness ::= 'sil_witness_table' sil-linkage?
///                      normal-protocol-conformance decl-sil-witness-body
/// normal-protocol-conformance ::=
///   generic-parameter-list? type: protocolName module ModuleName
/// decl-sil-witness-body:
///   '{' sil-witness-entry* '}'
/// sil-witness-entry:
///   method SILDeclRef ':' @SILFunctionName
///   associated_type AssociatedTypeDeclName: Type
///   associated_type_protocol (AssocName: ProtocolName):
///                              protocol-conformance|dependent
///   base_protocol ProtocolName: protocol-conformance
bool SILParserState::parseSILWitnessTable(Parser &P) {
  P.consumeToken(tok::kw_sil_witness_table);
  SILParser WitnessState(P);
  
  // Parse the linkage.
  Optional<SILLinkage> Linkage;
  parseSILLinkage(Linkage, P);
  
  IsSerialized_t isSerialized = IsNotSerialized;
  if (parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr, nullptr,
                           nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
                           nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
                           nullptr, nullptr, nullptr,
                           WitnessState, M))
    return true;

  // Parse the protocol conformance.
  ProtocolDecl *proto;
  GenericEnvironment *witnessEnv = nullptr;
  GenericParamList *witnessParams = nullptr;
  auto conf = WitnessState.parseProtocolConformance(proto,
                                                    witnessEnv,
                                                    witnessParams);
  WitnessState.ContextGenericEnv = witnessEnv;
  WitnessState.ContextGenericParams = witnessParams;

  // FIXME: should we really allow a specialized or inherited conformance here?
  RootProtocolConformance *theConformance = nullptr;
  if (conf.isConcrete())
    theConformance = conf.getConcrete()->getRootConformance();

  SILWitnessTable *wt = nullptr;
  if (theConformance) {
    wt = M.lookUpWitnessTable(theConformance, false);
    assert((!wt || wt->isDeclaration()) &&
           "Attempting to create duplicate witness table.");
  }

  // If we don't have an lbrace, then this witness table is a declaration.
  if (P.Tok.getKind() != tok::l_brace) {
    // Default to public external linkage.
    if (!Linkage)
      Linkage = SILLinkage::PublicExternal;
    // We ignore empty witness table without normal protocol conformance.
    if (!wt && theConformance)
      wt = SILWitnessTable::create(M, *Linkage, theConformance);
    return false;
  }

  if (!theConformance) {
    P.diagnose(P.Tok, diag::sil_witness_protocol_conformance_not_found);
    return true;
  }

  SourceLoc LBraceLoc = P.Tok.getLoc();
  P.consumeToken(tok::l_brace);

  // We need to turn on InSILBody to parse SILDeclRef.
  Lexer::SILBodyRAII Tmp(*P.L);
  // Parse the entry list.
  std::vector<SILWitnessTable::Entry> witnessEntries;
  std::vector<SILWitnessTable::ConditionalConformance> conditionalConformances;

  if (P.Tok.isNot(tok::r_brace)) {
    do {
      if (parseSILWitnessTableEntry(P, M, proto, witnessEnv, witnessParams,
                                    WitnessState, witnessEntries,
                                    conditionalConformances))
        return true;
    } while (P.Tok.isNot(tok::r_brace) && P.Tok.isNot(tok::eof));
  }

  SourceLoc RBraceLoc;
  P.parseMatchingToken(tok::r_brace, RBraceLoc, diag::expected_sil_rbrace,
                       LBraceLoc);
  
  // Default to public linkage.
  if (!Linkage)
    Linkage = SILLinkage::Public;

  if (!wt)
    wt = SILWitnessTable::create(M, *Linkage, theConformance);
  else
    wt->setLinkage(*Linkage);
  wt->convertToDefinition(witnessEntries, conditionalConformances,
                          isSerialized);
  return false;
}

/// decl-sil-default-witness ::= 'sil_default_witness_table' 
///                              sil-linkage identifier
///                              decl-sil-default-witness-body
/// decl-sil-default-witness-body:
///   '{' sil-default-witness-entry* '}'
/// sil-default-witness-entry:
///   sil-witness-entry
///   'no_default'
bool SILParserState::parseSILDefaultWitnessTable(Parser &P) {
  P.consumeToken(tok::kw_sil_default_witness_table);
  SILParser WitnessState(P);
  
  // Parse the linkage.
  Optional<SILLinkage> Linkage;
  parseSILLinkage(Linkage, P);
  
  // Parse the protocol.
  ProtocolDecl *protocol = parseProtocolDecl(P, WitnessState);
  if (!protocol)
    return true;

  WitnessState.ContextGenericEnv = protocol->getGenericEnvironment();
  WitnessState.ContextGenericParams = protocol->getGenericParams();

  // Parse the body.
  SourceLoc LBraceLoc = P.Tok.getLoc();
  P.consumeToken(tok::l_brace);

  // We need to turn on InSILBody to parse SILDeclRef.
  Lexer::SILBodyRAII Tmp(*P.L);

  // Parse the entry list.
  std::vector<SILWitnessTable::Entry> witnessEntries;
  std::vector<SILWitnessTable::ConditionalConformance> conditionalConformances;

  if (P.Tok.isNot(tok::r_brace)) {
    do {
      if (parseSILWitnessTableEntry(P, M, protocol,
                                    protocol->getGenericEnvironment(),
                                    protocol->getGenericParams(),
                                    WitnessState, witnessEntries,
                                    conditionalConformances))
        return true;
    } while (P.Tok.isNot(tok::r_brace) && P.Tok.isNot(tok::eof));
  }

  SourceLoc RBraceLoc;
  P.parseMatchingToken(tok::r_brace, RBraceLoc, diag::expected_sil_rbrace,
                       LBraceLoc);
  
  // Default to public linkage.
  if (!Linkage)
    Linkage = SILLinkage::Public;

  SILDefaultWitnessTable::create(M, *Linkage, protocol, witnessEntries);
  return false;
}

/// decl-sil-differentiability-witness ::=
///   'sil_differentiability_witness'
///   ('[' 'serialized' ']')?
///   sil-linkage?
///   sil-differentiability-witness-config-and-function
///   decl-sil-differentiability-witness-body?
///
/// decl-sil-differentiability-witness-body ::=
///   '{'
///   ('jvp' sil-function-name ':' sil-type)?
///   ('vjp' sil-function-name ':' sil-type)?
///   '}'
///
/// index-subset ::=
///   [0-9]+ (' ' [0-9]+)*
bool SILParserState::parseSILDifferentiabilityWitness(Parser &P) {
  auto loc = P.consumeToken(tok::kw_sil_differentiability_witness);
  auto silLoc = RegularLocation(loc);
  SILParser State(P);

  // Parse the linkage.
  Optional<SILLinkage> linkage;
  if (parseSILLinkage(linkage, P))
    return true;

  // Parse '[serialized]' flag (optional).
  bool isSerialized = false;
  SourceLoc serializedTokLoc;
  if (P.Tok.is(tok::l_square) && P.isIdentifier(P.peekToken(), "serialized")) {
    isSerialized = true;
    serializedTokLoc = P.Tok.getLoc();
    P.consumeToken(tok::l_square);
    P.consumeToken(tok::identifier);
    if (P.parseToken(tok::r_square, diag::sil_diff_witness_expected_token, "]"))
      return true;
  }

  // We need to turn on InSILBody to parse the function references.
  Lexer::SILBodyRAII tmp(*P.L);

  auto configAndFn =
      parseSILDifferentiabilityWitnessConfigAndFunction(P, State, silLoc);
  if (!configAndFn) {
    return true;
  }
  auto config = configAndFn->first;
  auto originalFn = configAndFn->second;

  // If this is just a declaration, create the declaration now and return.
  if (!P.Tok.is(tok::l_brace)) {
    if (isSerialized) {
      P.diagnose(serializedTokLoc,
                 diag::sil_diff_witness_serialized_declaration);
      return true;
    }

    SILDifferentiabilityWitness::createDeclaration(
        M, linkage ? *linkage : SILLinkage::DefaultForDeclaration, originalFn,
        config.parameterIndices, config.resultIndices,
        config.derivativeGenericSignature);
    return false;
  }

  // This is a definition, so parse differentiability witness body.
  SILFunction *jvp = nullptr;
  SILFunction *vjp = nullptr;
  if (P.Tok.is(tok::l_brace)) {
    // Parse '{'.
    SourceLoc lBraceLoc;
    P.consumeIf(tok::l_brace, lBraceLoc);
    // Parse JVP (optional).
    if (P.isIdentifier(P.Tok, "jvp")) {
      P.consumeToken(tok::identifier);
      if (P.parseToken(tok::colon, diag::sil_diff_witness_expected_token, ":"))
        return true;
      if (State.parseSILFunctionRef(silLoc, jvp))
        return true;
    }
    // Parse VJP (optional).
    if (P.isIdentifier(P.Tok, "vjp")) {
      P.consumeToken(tok::identifier);
      if (P.parseToken(tok::colon, diag::sil_diff_witness_expected_token, ":"))
        return true;
      if (State.parseSILFunctionRef(silLoc, vjp))
        return true;
    }
    // Parse '}'.
    SourceLoc rBraceLoc;
    if (P.parseMatchingToken(tok::r_brace, rBraceLoc, diag::expected_sil_rbrace,
                             lBraceLoc))
      return true;
  }

  SILDifferentiabilityWitness::createDefinition(
      M, linkage ? *linkage : SILLinkage::DefaultForDefinition, originalFn,
      config.parameterIndices, config.resultIndices,
      config.derivativeGenericSignature, jvp, vjp, isSerialized);
  return false;
}

llvm::Optional<llvm::coverage::Counter> SILParser::parseSILCoverageExpr(
    llvm::coverage::CounterExpressionBuilder &Builder) {
  if (P.Tok.is(tok::integer_literal)) {
    unsigned CounterId;
    if (parseInteger(CounterId, diag::sil_coverage_invalid_counter))
      return None;
    return llvm::coverage::Counter::getCounter(CounterId);
  }

  if (P.Tok.is(tok::identifier)) {
    Identifier Zero;
    SourceLoc Loc;
    if (parseSILIdentifier(Zero, Loc, diag::sil_coverage_invalid_counter))
      return None;
    if (Zero.str() != "zero") {
      P.diagnose(Loc, diag::sil_coverage_invalid_counter);
      return None;
    }
    return llvm::coverage::Counter::getZero();
  }

  if (P.Tok.is(tok::l_paren)) {
    P.consumeToken(tok::l_paren);
    auto LHS = parseSILCoverageExpr(Builder);
    if (!LHS)
      return None;
    const Identifier Operator = P.Context.getIdentifier(P.Tok.getText());
    const SourceLoc Loc = P.consumeToken();
    if (Operator.str() != "+" && Operator.str() != "-") {
      P.diagnose(Loc, diag::sil_coverage_invalid_operator);
      return None;
    }
    auto RHS = parseSILCoverageExpr(Builder);
    if (!RHS)
      return None;
    if (P.parseToken(tok::r_paren, diag::sil_coverage_expected_rparen))
      return None;

    if (Operator.str() == "+")
      return Builder.add(*LHS, *RHS);
    return Builder.subtract(*LHS, *RHS);
  }

  P.diagnose(P.Tok, diag::sil_coverage_invalid_counter);
  return None;
}

/// decl-sil-coverage-map ::= 'sil_coverage_map' CoveredName PGOFuncName CoverageHash
///                           decl-sil-coverage-body
/// decl-sil-coverage-body:
///   '{' sil-coverage-entry* '}'
/// sil-coverage-entry:
///   sil-coverage-loc ':' sil-coverage-expr
/// sil-coverage-loc:
///   StartLine ':' StartCol '->' EndLine ':' EndCol
/// sil-coverage-expr:
///   ...
bool SILParserState::parseSILCoverageMap(Parser &P) {
  P.consumeToken(tok::kw_sil_coverage_map);
  SILParser State(P);

  // Parse the filename.
  Identifier Filename;
  SourceLoc FileLoc;
  if (State.parseSILIdentifier(Filename, FileLoc,
                               diag::expected_sil_value_name))
    return true;

  // Parse the covered name.
  if (!P.Tok.is(tok::string_literal)) {
    P.diagnose(P.Tok, diag::sil_coverage_expected_quote);
    return true;
  }
  StringRef FuncName = P.Tok.getText().drop_front().drop_back();
  P.consumeToken();

  // Parse the PGO func name.
  if (!P.Tok.is(tok::string_literal)) {
    P.diagnose(P.Tok, diag::sil_coverage_expected_quote);
    return true;
  }
  StringRef PGOFuncName = P.Tok.getText().drop_front().drop_back();
  P.consumeToken();

  uint64_t Hash;
  if (State.parseInteger(Hash, diag::sil_coverage_invalid_hash))
    return true;

  if (!P.Tok.is(tok::l_brace)) {
    P.diagnose(P.Tok, diag::sil_coverage_expected_lbrace);
    return true;
  }
  SourceLoc LBraceLoc = P.Tok.getLoc();
  P.consumeToken(tok::l_brace);

  llvm::coverage::CounterExpressionBuilder Builder;
  std::vector<SILCoverageMap::MappedRegion> Regions;
  bool BodyHasError = false;
  if (P.Tok.isNot(tok::r_brace)) {
    do {
      unsigned StartLine, StartCol, EndLine, EndCol;
      if (State.parseInteger(StartLine, diag::sil_coverage_expected_loc) ||
          P.parseToken(tok::colon, diag::sil_coverage_expected_loc) ||
          State.parseInteger(StartCol, diag::sil_coverage_expected_loc) ||
          P.parseToken(tok::arrow, diag::sil_coverage_expected_arrow) ||
          State.parseInteger(EndLine, diag::sil_coverage_expected_loc) ||
          P.parseToken(tok::colon, diag::sil_coverage_expected_loc) ||
          State.parseInteger(EndCol, diag::sil_coverage_expected_loc)) {
        BodyHasError = true;
        break;
      }

      if (P.parseToken(tok::colon, diag::sil_coverage_expected_colon)) {
        BodyHasError = true;
        break;
      }

      auto Counter = State.parseSILCoverageExpr(Builder);
      if (!Counter) {
        BodyHasError = true;
        break;
      }

      Regions.emplace_back(StartLine, StartCol, EndLine, EndCol, *Counter);
    } while (P.Tok.isNot(tok::r_brace) && P.Tok.isNot(tok::eof));
  }
  if (BodyHasError)
    P.skipUntilDeclRBrace();

  SourceLoc RBraceLoc;
  P.parseMatchingToken(tok::r_brace, RBraceLoc, diag::expected_sil_rbrace,
                       LBraceLoc);

  if (!BodyHasError)
    SILCoverageMap::create(M, Filename.str(), FuncName.str(), PGOFuncName.str(),
                           Hash, Regions, Builder.getExpressions());
  return false;
}

/// sil-scope-ref ::= 'scope' [0-9]+
/// sil-scope ::= 'sil_scope' [0-9]+ '{'
///                 debug-loc
///                 'parent' scope-parent
///                 ('inlined_at' sil-scope-ref)?
///               '}'
/// scope-parent ::= sil-function-name ':' sil-type
/// scope-parent ::= sil-scope-ref
/// debug-loc ::= 'loc' string-literal ':' [0-9]+ ':' [0-9]+
bool SILParserState::parseSILScope(Parser &P) {
  P.consumeToken(tok::kw_sil_scope);
  SILParser ScopeState(P);

  SourceLoc SlotLoc = P.Tok.getLoc();
  unsigned Slot;
  if (ScopeState.parseInteger(Slot, diag::sil_invalid_scope_slot))
    return true;

  SourceLoc LBraceLoc = P.Tok.getLoc();
  P.consumeToken(tok::l_brace);

  StringRef Key = P.Tok.getText();
  RegularLocation Loc{SILLocation::DebugLoc()};
  if (Key == "loc")
    if (ScopeState.parseSILLocation(Loc))
      return true;
  ScopeState.parseVerbatim("parent");
  Identifier FnName;
  SILDebugScope *Parent = nullptr;
  SILFunction *ParentFn = nullptr;
  if (P.Tok.is(tok::integer_literal)) {
    /// scope-parent ::= sil-scope-ref
    if (ScopeState.parseScopeRef(Parent))
      return true;
  } else {
    /// scope-parent ::= sil-function-name
    SILType Ty;
    SourceLoc FnLoc = P.Tok.getLoc();
    // We need to turn on InSILBody to parse the function reference.
    Lexer::SILBodyRAII Tmp(*P.L);
    GenericEnvironment *IgnoredEnv = nullptr;
    GenericParamList *IgnoredParams = nullptr;
    if ((ScopeState.parseGlobalName(FnName)) ||
        P.parseToken(tok::colon, diag::expected_sil_colon_value_ref) ||
        ScopeState.parseSILType(Ty, IgnoredEnv, IgnoredParams, true))
      return true;

    // The function doesn't exist yet. Create a zombie forward declaration.
    auto FnTy = Ty.getAs<SILFunctionType>();
    if (!FnTy || !Ty.isObject()) {
      P.diagnose(FnLoc, diag::expected_sil_function_type);
      return true;
    }
    ParentFn = ScopeState.getGlobalNameForReference(FnName, FnTy, FnLoc, true);
    ScopeState.TUState.PotentialZombieFns.insert(ParentFn);
  }

  SILDebugScope *InlinedAt = nullptr;
  if (P.Tok.getText() == "inlined_at") {
    P.consumeToken();
    if (ScopeState.parseScopeRef(InlinedAt))
      return true;
  }

  SourceLoc RBraceLoc;
  P.parseMatchingToken(tok::r_brace, RBraceLoc, diag::expected_sil_rbrace,
                       LBraceLoc);

  auto &Scope = ScopeSlots[Slot];
  if (Scope) {
    P.diagnose(SlotLoc, diag::sil_scope_redefined, Slot);
    return true;
  }

  Scope = new (M) SILDebugScope(Loc, ParentFn, Parent, InlinedAt);
  return false;
}
