//===--- Verifier.cpp - Verification of Swift SIL Code --------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sil-verifier"
#include "VerifierPrivate.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/AnyFunctionRef.h"
#include "swift/AST/Decl.h"
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Module.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/Types.h"
#include "swift/Basic/Range.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/SIL/ApplySite.h"
#include "swift/SIL/BasicBlockUtils.h"
#include "swift/SIL/DebugUtils.h"
#include "swift/SIL/Dominance.h"
#include "swift/SIL/DynamicCasts.h"
#include "swift/SIL/MemAccessUtils.h"
#include "swift/SIL/MemoryLifetime.h"
#include "swift/SIL/OwnershipUtils.h"
#include "swift/SIL/PostOrder.h"
#include "swift/SIL/PrettyStackTrace.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILOpenedArchetypesTracker.h"
#include "swift/SIL/SILVTable.h"
#include "swift/SIL/SILVTableVisitor.h"
#include "swift/SIL/SILVisitor.h"
#include "swift/SIL/TypeLowering.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"

using namespace swift;
using namespace swift::silverifier;

using Lowering::AbstractionPattern;

// This flag controls the default behaviour when hitting a verification
// failure (abort/exit).
static llvm::cl::opt<bool> AbortOnFailure(
                              "verify-abort-on-failure",
                              llvm::cl::init(true));

static llvm::cl::opt<bool> ContinueOnFailure("verify-continue-on-failure",
                                             llvm::cl::init(false));

static llvm::cl::opt<bool> DumpModuleOnFailure("verify-dump-module-on-failure",
                                             llvm::cl::init(false));

// SWIFT_ENABLE_TENSORFLOW
// This flag is temporarily set to false because debug scope verification does
// not handle inlined call sites. This is problematic for deabstraction, which
// does performance inlining at -Onone.
// When debug scope verification handles inlined call sites, set this flag to
// true.
// Documented at SR-8114.
static llvm::cl::opt<bool> VerifyDIHoles(
                              "verify-di-holes",
                              llvm::cl::init(false));
// SWIFT_ENABLE_TENSORFLOW END

static llvm::cl::opt<bool> SkipConvertEscapeToNoescapeAttributes(
    "verify-skip-convert-escape-to-noescape-attributes", llvm::cl::init(false));

// Allow unit tests to gradually migrate toward -allow-critical-edges=false.
static llvm::cl::opt<bool> AllowCriticalEdges("allow-critical-edges",
                                              llvm::cl::init(true));

// The verifier is basically all assertions, so don't compile it with NDEBUG to
// prevent release builds from triggering spurious unused variable warnings.

//===----------------------------------------------------------------------===//
//                                SILVerifier
//===----------------------------------------------------------------------===//

/// Returns true if A is an opened existential type or is equal to an
/// archetype from F's generic context.
static bool isArchetypeValidInFunction(ArchetypeType *A, const SILFunction *F) {
  auto root = dyn_cast<PrimaryArchetypeType>(A->getRoot());
  if (!root)
    return true;
  if (isa<OpenedArchetypeType>(A->getRoot()))
    return true;
  if (isa<OpaqueTypeArchetypeType>(A->getRoot()))
    return true;

  // Ok, we have a primary archetype, make sure it is in the nested generic
  // environment of our caller.
  if (auto *genericEnv = F->getGenericEnvironment())
    if (root->getGenericEnvironment() == genericEnv)
      return true;

  return false;
}

namespace {

/// Metaprogramming-friendly base class.
template <class Impl>
class SILVerifierBase : public SILInstructionVisitor<Impl> {
public:
  // visitCLASS calls visitPARENT and checkCLASS.
  // checkCLASS does nothing by default.
#define INST(CLASS, PARENT)                                     \
  void visit##CLASS(CLASS *I) {                                 \
    static_cast<Impl*>(this)->visit##PARENT(I);                 \
    static_cast<Impl*>(this)->check##CLASS(I);                  \
  }                                                             \
  void check##CLASS(CLASS *I) {}
#include "swift/SIL/SILNodes.def"

  void visitSILInstruction(SILInstruction *I) {
    static_cast<Impl*>(this)->checkSILInstruction(I);
  }
  void checkSILInstruction(SILInstruction *I) {}
};
} // end anonymous namespace

namespace {

/// Verify invariants on a key path component.
void verifyKeyPathComponent(SILModule &M,
                            ResilienceExpansion expansion,
                            llvm::function_ref<void(bool, StringRef)> require,
                            CanType &baseTy,
                            CanType leafTy,
                            const KeyPathPatternComponent &component,
                            ArrayRef<Operand> operands,
                            CanGenericSignature patternSig,
                            SubstitutionMap patternSubs,
                            bool forPropertyDescriptor,
                            bool hasIndices) {
  auto &C = M.getASTContext();
  auto typeExpansionContext =
      TypeExpansionContext::noOpaqueTypeArchetypesSubstitution(expansion);
  auto opaque = AbstractionPattern::getOpaque();
  auto loweredBaseTy =
      M.Types.getLoweredType(opaque, baseTy, typeExpansionContext);
  auto componentTy = component.getComponentType().subst(patternSubs)
    ->getCanonicalType();
  auto loweredComponentTy =
      M.Types.getLoweredType(opaque, componentTy, typeExpansionContext);

  auto checkIndexEqualsAndHash = [&]{
    if (!component.getSubscriptIndices().empty()) {
      // Equals should be
      // <Sig...> @convention(thin) (RawPointer, RawPointer) -> Bool
      {
        auto equals = component.getSubscriptIndexEquals();
        require(equals, "key path pattern with indexes must have equals "
                        "operator");
        
        auto substEqualsType = equals->getLoweredFunctionType()
          ->substGenericArgs(M, patternSubs, TypeExpansionContext::minimal());
        
        require(substEqualsType->getParameters().size() == 2,
                "must have two arguments");
        for (unsigned i = 0; i < 2; ++i) {
          auto param = substEqualsType->getParameters()[i];
          require(param.getConvention()
                    == ParameterConvention::Direct_Unowned,
                  "indices pointer should be trivial");
          require(param.getInterfaceType()->getAnyNominal()
                    == C.getUnsafeRawPointerDecl(),
                  "indices pointer should be an UnsafeRawPointer");
        }
        
        require(substEqualsType->getResults().size() == 1,
                "must have one result");
        
        require(substEqualsType->getResults()[0].getConvention()
                  == ResultConvention::Unowned,
                "result should be unowned");
        require(substEqualsType->getResults()[0].getInterfaceType()
                               ->getAnyNominal()
                  == C.getBoolDecl(),
                "result should be Bool");
      }
      {
        // Hash should be
        // <Sig...> @convention(thin) (RawPointer) -> Int
        auto hash = component.getSubscriptIndexHash();
        require(hash, "key path pattern with indexes must have hash "
                      "operator");
        
        auto substHashType = hash->getLoweredFunctionType()
          ->substGenericArgs(M, patternSubs, TypeExpansionContext::minimal());
        
        require(substHashType->getParameters().size() == 1,
                "must have two arguments");
        auto param = substHashType->getParameters()[0];
        require(param.getConvention()
                  == ParameterConvention::Direct_Unowned,
                "indices pointer should be trivial");
        require(param.getInterfaceType()->getAnyNominal()
                  == C.getUnsafeRawPointerDecl(),
                "indices pointer should be an UnsafeRawPointer");
        
        require(substHashType->getResults().size() == 1,
                "must have one result");
        
        require(substHashType->getResults()[0].getConvention()
                  == ResultConvention::Unowned,
                "result should be unowned");
        require(substHashType->getResults()[0].getInterfaceType()
                             ->getAnyNominal()
                  == C.getIntDecl(),
                "result should be Int");
      }
    } else {
      require(!component.getSubscriptIndexEquals()
              && !component.getSubscriptIndexHash(),
              "component without indexes must not have equals/hash");
    }
  };

  switch (auto kind = component.getKind()) {
  case KeyPathPatternComponent::Kind::StoredProperty: {
    auto property = component.getStoredPropertyDecl();
    if (expansion == ResilienceExpansion::Minimal) {
      require(property->getEffectiveAccess() >= AccessLevel::Public,
              "Key path in serialized function cannot reference non-public "
              "property");
    }

    auto fieldTy = baseTy->getTypeOfMember(M.getSwiftModule(), property)
                         ->getReferenceStorageReferent()
                         ->getCanonicalType();
    require(fieldTy == componentTy,
            "property decl should be a member of the base with the same type "
            "as the component");
    require(property->hasStorage(), "property must be stored");
    require(!property->isResilient(M.getSwiftModule(), expansion),
            "cannot access storage of resilient property");
    auto propertyTy =
        loweredBaseTy.getFieldType(property, M, typeExpansionContext);
    require(propertyTy.getObjectType()
              == loweredComponentTy.getObjectType(),
            "component type should match the maximal abstraction of the "
            "formal type");
    break;
  }
    
  case KeyPathPatternComponent::Kind::GettableProperty:
  case KeyPathPatternComponent::Kind::SettableProperty: {
    if (forPropertyDescriptor) {
      require(component.getSubscriptIndices().empty()
              && !component.getSubscriptIndexEquals()
              && !component.getSubscriptIndexHash(),
              "property descriptor should not have index information");
      
      require(component.getExternalDecl() == nullptr
              && component.getExternalSubstitutions().empty(),
              "property descriptor should not refer to another external decl");
    } else {
      require(hasIndices == !component.getSubscriptIndices().empty(),
              "component for subscript should have indices");
    }
    
    auto normalArgConvention = ParameterConvention::Indirect_In_Guaranteed;
  
    // Getter should be <Sig...> @convention(thin) (@in_guaranteed Base) -> @out Result
    {
      auto getter = component.getComputedPropertyGetter();
      if (expansion == ResilienceExpansion::Minimal) {
        require(getter->hasValidLinkageForFragileRef(),
                "Key path in serialized function should not reference "
                "less visible getters");
      }

      auto substGetterType = getter->getLoweredFunctionType()->substGenericArgs(
          M, patternSubs, TypeExpansionContext::minimal());
      require(substGetterType->getRepresentation() ==
                SILFunctionTypeRepresentation::Thin,
              "getter should be a thin function");
      
      require(substGetterType->getNumParameters() == 1 + hasIndices,
              "getter should have one parameter");
      auto baseParam = substGetterType->getParameters()[0];
      require(baseParam.getConvention() == normalArgConvention,
              "getter base parameter should have normal arg convention");
      require(baseParam.getArgumentType(M, substGetterType, typeExpansionContext)
                == loweredBaseTy.getASTType(),
              "getter base parameter should match base of component");
      
      if (hasIndices) {
        auto indicesParam = substGetterType->getParameters()[1];
        require(indicesParam.getConvention()
                  == ParameterConvention::Direct_Unowned,
                "indices pointer should be trivial");
        require(
            indicesParam
                    .getArgumentType(M, substGetterType, typeExpansionContext)
                    ->getAnyNominal() == C.getUnsafeRawPointerDecl(),
            "indices pointer should be an UnsafeRawPointer");
      }

      require(substGetterType->getNumResults() == 1,
              "getter should have one result");
      auto result = substGetterType->getResults()[0];
      require(result.getConvention() == ResultConvention::Indirect,
              "getter result should be @out");
      require(
          result.getReturnValueType(M, substGetterType, typeExpansionContext) ==
              loweredComponentTy.getASTType(),
          "getter result should match the maximal abstraction of the "
          "formal component type");
    }
    
    if (kind == KeyPathPatternComponent::Kind::SettableProperty) {
      // Setter should be
      // <Sig...> @convention(thin) (@in_guaranteed Result, @in Base) -> ()
      
      auto setter = component.getComputedPropertySetter();
      if (expansion == ResilienceExpansion::Minimal) {
        require(setter->hasValidLinkageForFragileRef(),
                "Key path in serialized function should not reference "
                "less visible setters");
      }

      auto substSetterType = setter->getLoweredFunctionType()
        ->substGenericArgs(M, patternSubs, TypeExpansionContext::minimal());
      
      require(substSetterType->getRepresentation() ==
                SILFunctionTypeRepresentation::Thin,
              "setter should be a thin function");
      
      require(substSetterType->getNumParameters() == 2 + hasIndices,
              "setter should have two parameters");

      auto newValueParam = substSetterType->getParameters()[0];
      // TODO: This should probably be unconditionally +1 when we
      // can represent that.
      require(newValueParam.getConvention() == normalArgConvention,
              "setter value parameter should havee normal arg convention");

      auto baseParam = substSetterType->getParameters()[1];
      require(baseParam.getConvention() == normalArgConvention
              || baseParam.getConvention() ==
                  ParameterConvention::Indirect_Inout,
              "setter base parameter should be normal arg convention "
              "or @inout");
      
      if (hasIndices) {
        auto indicesParam = substSetterType->getParameters()[2];
        require(indicesParam.getConvention()
                  == ParameterConvention::Direct_Unowned,
                "indices pointer should be trivial");
        require(
            indicesParam
                    .getArgumentType(M, substSetterType, typeExpansionContext)
                    ->getAnyNominal() == C.getUnsafeRawPointerDecl(),
            "indices pointer should be an UnsafeRawPointer");
      }

      require(newValueParam.getArgumentType(M, substSetterType,
                                            typeExpansionContext) ==
                  loweredComponentTy.getASTType(),
              "setter value should match the maximal abstraction of the "
              "formal component type");

      require(substSetterType->getNumResults() == 0,
              "setter should have no results");
    }
    
    if (!forPropertyDescriptor) {
      for (auto &index : component.getSubscriptIndices()) {
        auto opIndex = index.Operand;
        auto contextType =
          index.LoweredType.subst(M, patternSubs);
        require(contextType == operands[opIndex].get()->getType(),
                "operand must match type required by pattern");
        SILType loweredType = index.LoweredType;
        require(
            loweredType.isLoweringOf(typeExpansionContext, M, index.FormalType),
            "pattern index formal type doesn't match lowered type");
      }

      checkIndexEqualsAndHash();
    }
    
    break;
  }
  case KeyPathPatternComponent::Kind::OptionalChain: {
    require(baseTy->getOptionalObjectType()->isEqual(componentTy),
            "chaining component should unwrap optional");
    require((bool)leafTy->getOptionalObjectType(),
            "key path with chaining component should have optional "
            "result");
    break;
  }
  case KeyPathPatternComponent::Kind::OptionalForce: {
    require(baseTy->getOptionalObjectType()->isEqual(componentTy),
            "forcing component should unwrap optional");
    break;
  }
  case KeyPathPatternComponent::Kind::OptionalWrap: {
    require(componentTy->getOptionalObjectType()->isEqual(baseTy),
            "wrapping component should wrap optional");
    break;
  }
  case KeyPathPatternComponent::Kind::TupleElement: {
    require(loweredBaseTy.is<TupleType>(),
            "invalid baseTy, should have been a TupleType");
      
    auto tupleTy = loweredBaseTy.castTo<TupleType>();
    auto eltIdx = component.getTupleIndex();
      
    require(eltIdx < tupleTy->getNumElements(),
            "invalid element index, greater than # of tuple elements");

    auto eltTy = tupleTy.getElementType(eltIdx)
      .getReferenceStorageReferent();
    
    require(eltTy == componentTy,
            "tuple element type should match the type of the component");

    break;
  }
  }
  
  baseTy = componentTy;
}

/// Check if according to the SIL language model this memory /must only/ be used
/// immutably. Today this is only applied to in_guaranteed arguments and
/// open_existential_addr. We should expand it as needed.
struct ImmutableAddressUseVerifier {
  SmallVector<Operand *, 32> worklist;

  bool isConsumingOrMutatingArgumentConvention(SILArgumentConvention conv) {
    switch (conv) {
    case SILArgumentConvention::Indirect_In_Guaranteed:
      return false;

    case SILArgumentConvention::Indirect_InoutAliasable:
      // DISCUSSION: We do not consider inout_aliasable to be "truly mutating"
      // since today it is just used as a way to mark a captured argument and
      // not that something truly has mutating semantics. The reason why this
      // is safe is that the typechecker guarantees that if our value was
      // immutable, then the use in the closure must be immutable as well.
      //
      // TODO: Remove this in favor of using Inout and In_Guaranteed.
      return false;

    case SILArgumentConvention::Indirect_Out:
    case SILArgumentConvention::Indirect_In:
    case SILArgumentConvention::Indirect_In_Constant:
    case SILArgumentConvention::Indirect_Inout:
      return true;

    case SILArgumentConvention::Direct_Unowned:
    case SILArgumentConvention::Direct_Guaranteed:
    case SILArgumentConvention::Direct_Owned:
      assert(conv.isIndirectConvention() && "Expect an indirect convention");
      return true; // return something "conservative".
    }
    llvm_unreachable("covered switch isn't covered?!");
  }

  bool isConsumingOrMutatingApplyUse(Operand *use) {
    ApplySite apply(use->getUser());
    assert(apply && "Not an apply instruction kind");
    auto conv = apply.getArgumentConvention(*use);
    return isConsumingOrMutatingArgumentConvention(conv);
  }

  bool isConsumingOrMutatingYieldUse(Operand *use) {
    // For now, just say that it is non-consuming for now.
    auto *yield = cast<YieldInst>(use->getUser());
    auto conv = yield->getArgumentConventionForOperand(*use);
    return isConsumingOrMutatingArgumentConvention(conv);
  }

  // A "copy_addr %src [take] to *" is consuming on "%src".
  // A "copy_addr * to * %dst" is mutating on "%dst".
  bool isConsumingOrMutatingCopyAddrUse(Operand *use) {
    auto *copyAddr = cast<CopyAddrInst>(use->getUser());
    if (copyAddr->getDest() == use->get())
      return true;
    if (copyAddr->getSrc() == use->get() && copyAddr->isTakeOfSrc() == IsTake)
      return true;
    return false;
  }

  bool isAddrCastToNonConsuming(SingleValueInstruction *i) {
    // Check if any of our uses are consuming. If none of them are consuming, we
    // are good to go.
    return llvm::none_of(i->getUses(), [&](Operand *use) -> bool {
      auto *inst = use->getUser();
      switch (inst->getKind()) {
      default:
        return false;
      case SILInstructionKind::ApplyInst:
      case SILInstructionKind::TryApplyInst:
      case SILInstructionKind::PartialApplyInst:
      case SILInstructionKind::BeginApplyInst:
        return isConsumingOrMutatingApplyUse(use);
      }
    });
  }

  bool isMutatingOrConsuming(SILValue address) {
    llvm::copy(address->getUses(), std::back_inserter(worklist));
    while (!worklist.empty()) {
      auto *use = worklist.pop_back_val();
      auto *inst = use->getUser();

      if (inst->isTypeDependentOperand(*use))
        continue;

      // TODO: Can this switch be restructured so break -> error, continue ->
      // next iteration, return -> return the final result.
      switch (inst->getKind()) {
      case SILInstructionKind::BuiltinInst: {
        // If we are processing a polymorphic builtin that takes an address,
        // skip the builtin. This is because the builtin must be specialized to
        // a non-memory reading builtin that works on trivial object values
        // before the diagnostic passes end (or be DCEed) or we emit a
        // diagnostic.
        if (auto builtinKind = cast<BuiltinInst>(inst)->getBuiltinKind()) {
          if (isPolymorphicBuiltin(*builtinKind)) {
            break;
          }
        }

        // Otherwise this is a builtin that we are not expecting to see, so bail
        // and assert.
        llvm::errs() << "Unhandled, unexpected builtin instruction: " << *inst;
        llvm_unreachable("invoking standard assertion failure");
        break;
      }
      case SILInstructionKind::MarkDependenceInst:
      case SILInstructionKind::LoadBorrowInst:
      case SILInstructionKind::DebugValueAddrInst:
      case SILInstructionKind::ExistentialMetatypeInst:
      case SILInstructionKind::ValueMetatypeInst:
      case SILInstructionKind::FixLifetimeInst:
      case SILInstructionKind::KeyPathInst:
      case SILInstructionKind::SwitchEnumAddrInst:
      case SILInstructionKind::SelectEnumAddrInst:
        break;
      case SILInstructionKind::AddressToPointerInst:
        // We assume that the user is attempting to do something unsafe since we
        // are converting to a raw pointer. So just ignore this use.
        //
        // TODO: Can we do better?
        break;
      case SILInstructionKind::BranchInst:
      case SILInstructionKind::CondBranchInst:
        // We do not analyze through branches and cond_br instructions and just
        // assume correctness. This is so that we can avoid having to analyze
        // through phi loops and since we want to remove address phis (meaning
        // that this eventually would never be able to happen). Once that
        // changes happens, we should remove this code and just error below.
        break;
      case SILInstructionKind::ApplyInst:
      case SILInstructionKind::TryApplyInst:
      case SILInstructionKind::PartialApplyInst:
      case SILInstructionKind::BeginApplyInst:
        if (isConsumingOrMutatingApplyUse(use))
          return true;
        break;
      case SILInstructionKind::YieldInst:
        if (isConsumingOrMutatingYieldUse(use))
          return true;
        break;
      case SILInstructionKind::BeginAccessInst:
        if (cast<BeginAccessInst>(inst)->getAccessKind() != SILAccessKind::Read)
          return true;
        break;
      case SILInstructionKind::EndAccessInst:
        break;
      case SILInstructionKind::CopyAddrInst:
        if (isConsumingOrMutatingCopyAddrUse(use))
          return true;
        else
          break;
      case SILInstructionKind::DestroyAddrInst:
        return true;
      case SILInstructionKind::UpcastInst:
      case SILInstructionKind::UncheckedAddrCastInst: {
        if (isAddrCastToNonConsuming(cast<SingleValueInstruction>(inst))) {
          break;
        }
        return true;
      }
      case SILInstructionKind::CheckedCastAddrBranchInst:
        switch (cast<CheckedCastAddrBranchInst>(inst)->getConsumptionKind()) {
        case CastConsumptionKind::BorrowAlways:
          llvm_unreachable("checked_cast_addr_br cannot have BorrowAlways");
        case CastConsumptionKind::CopyOnSuccess:
          break;
        case CastConsumptionKind::TakeAlways:
        case CastConsumptionKind::TakeOnSuccess:
          return true;
        }
        break;
      case SILInstructionKind::LoadInst:
        // A 'non-taking' value load is harmless.
        if (cast<LoadInst>(inst)->getOwnershipQualifier() ==
            LoadOwnershipQualifier::Take)
          return true;
        break;
#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...)             \
  case SILInstructionKind::Load##Name##Inst:                                   \
    if (cast<Load##Name##Inst>(inst)->isTake())                                \
      return true;                                                             \
    break;
#include "swift/AST/ReferenceStorage.def"
      case SILInstructionKind::OpenExistentialAddrInst:
        // If we have a mutable use, return true. Otherwise fallthrough since we
        // want to look through immutable uses.
        if (cast<OpenExistentialAddrInst>(inst)->getAccessKind() !=
            OpenedExistentialAccess::Immutable)
          return true;
        LLVM_FALLTHROUGH;
      case SILInstructionKind::StructElementAddrInst:
      case SILInstructionKind::TupleElementAddrInst:
      case SILInstructionKind::IndexAddrInst:
      case SILInstructionKind::TailAddrInst:
      case SILInstructionKind::IndexRawPointerInst:
        // Add these to our worklist.
        for (auto result : inst->getResults()) {
          llvm::copy(result->getUses(), std::back_inserter(worklist));
        }
        break;
      case SILInstructionKind::UncheckedTakeEnumDataAddrInst: {
        auto type =
            cast<UncheckedTakeEnumDataAddrInst>(inst)->getOperand()->getType();
        if (type.getOptionalObjectType()) {
          for (auto result : inst->getResults()) {
            llvm::copy(result->getUses(), std::back_inserter(worklist));
          }
          break;
        }
        llvm::errs() << "Unhandled, unexpected instruction: " << *inst;
        llvm_unreachable("invoking standard assertion failure");
        break;
      }
      default:
        llvm::errs() << "Unhandled, unexpected instruction: " << *inst;
        llvm_unreachable("invoking standard assertion failure");
        break;
      }
    }
    return false;
  }
};

/// The SIL verifier walks over a SIL function / basic block / instruction,
/// checking and enforcing its invariants.
class SILVerifier : public SILVerifierBase<SILVerifier> {
  ModuleDecl *M;
  const SILFunction &F;
  SILFunctionConventions fnConv;
  Lowering::TypeConverter &TC;
  SILOpenedArchetypesTracker OpenedArchetypes;
  SmallVector<StringRef, 16> DebugVars;
  const SILInstruction *CurInstruction = nullptr;
  const SILArgument *CurArgument = nullptr;
  std::unique_ptr<DominanceInfo> Dominance;

  // Used for dominance checking within a basic block.
  llvm::DenseMap<const SILInstruction *, unsigned> InstNumbers;
  
  DeadEndBlocks DEBlocks;
  LoadBorrowImmutabilityAnalysis loadBorrowImmutabilityAnalysis;
  bool SingleFunction = true;

  SILVerifier(const SILVerifier&) = delete;
  void operator=(const SILVerifier&) = delete;
public:
  bool isSILOwnershipEnabled() const {
    return F.getModule().getOptions().VerifySILOwnership;
  }

  void _require(bool condition, const Twine &complaint,
                const std::function<void()> &extraContext = nullptr) {
    if (condition) return;

    StringRef funcName;
    if (CurInstruction)
      funcName = CurInstruction->getFunction()->getName();
    else if (CurArgument)
      funcName = CurArgument->getFunction()->getName();
    if (ContinueOnFailure) {
      llvm::dbgs() << "Begin Error in function " << funcName << "\n";
    }

    llvm::dbgs() << "SIL verification failed: " << complaint << "\n";
    if (extraContext)
      extraContext();

    if (CurInstruction) {
      llvm::dbgs() << "Verifying instruction:\n";
      CurInstruction->printInContext(llvm::dbgs());
    } else if (CurArgument) {
      llvm::dbgs() << "Verifying argument:\n";
      CurArgument->printInContext(llvm::dbgs());
    }
    if (ContinueOnFailure) {
      llvm::dbgs() << "End Error in function " << funcName << "\n";
      return;
    }

    llvm::dbgs() << "In function:\n";
    F.print(llvm::dbgs());
    if (DumpModuleOnFailure) {
      // Don't do this by default because modules can be _very_ large.
      llvm::dbgs() << "In module:\n";
      F.getModule().print(llvm::dbgs());
    }

    // We abort by default because we want to always crash in
    // the debugger.
    if (AbortOnFailure)
      abort();
    else
      exit(1);
  }
#define require(condition, complaint) \
  _require(bool(condition), complaint ": " #condition)

  template <class T> typename CanTypeWrapperTraits<T>::type
  _requireObjectType(SILType type, const Twine &valueDescription,
                     const char *typeName) {
    _require(type.isObject(), valueDescription + " must be an object");
    auto result = type.getAs<T>();
    _require(bool(result), valueDescription + " must have type " + typeName);
    return result;
  }
  template <class T> typename CanTypeWrapperTraits<T>::type
  _requireObjectType(SILValue value, const Twine &valueDescription,
                     const char *typeName) {
    return _requireObjectType<T>(value->getType(), valueDescription, typeName);
  }
#define requireObjectType(type, value, valueDescription) \
  _requireObjectType<type>(value, valueDescription, #type)

  template <class T> typename CanTypeWrapperTraits<T>::type
  _requireAddressType(SILType type, const Twine &valueDescription,
                      const char *typeName) {
    _require(type.isAddress(), valueDescription + " must be an address");
    auto result = type.getAs<T>();
    _require(bool(result), valueDescription + " must have type " + typeName);
    return result;
  }
  template <class T> typename CanTypeWrapperTraits<T>::type
  _requireAddressType(SILValue value, const Twine &valueDescription,
                     const char *typeName) {
    return _requireAddressType<T>(value->getType(), valueDescription, typeName);
  }
#define requireAddressType(type, value, valueDescription) \
  _requireAddressType<type>(value, valueDescription, #type)

  template <class T>
  typename CanTypeWrapperTraits<T>::type
  _forbidObjectType(SILType type, const Twine &valueDescription,
                    const char *typeName) {
    _require(type.isObject(), valueDescription + " must be an object");
    auto result = type.getAs<T>();
    _require(!bool(result),
             valueDescription + " must not have type " + typeName);
    return result;
  }
  template <class T>
  typename CanTypeWrapperTraits<T>::type
  _forbidObjectType(SILValue value, const Twine &valueDescription,
                    const char *typeName) {
    return _forbidObjectType<T>(value->getType(), valueDescription, typeName);
  }
#define forbidObjectType(type, value, valueDescription)                        \
  _forbidObjectType<type>(value, valueDescription, #type)

  // Require that the operand is a non-optional, non-unowned reference-counted
  // type.
  void requireReferenceValue(SILValue value, const Twine &valueDescription) {
    require(value->getType().isObject(), valueDescription +" must be an object");
    require(value->getType().isReferenceCounted(F.getModule()),
            valueDescription + " must have reference semantics");
    forbidObjectType(UnownedStorageType, value, valueDescription);
  }

  // Require that the operand is a reference-counted type, or an Optional
  // thereof.
  void requireReferenceOrOptionalReferenceValue(SILValue value,
                                                const Twine &valueDescription) {
    require(value->getType().isObject(), valueDescription +" must be an object");
    
    auto objectTy = value->getType().unwrapOptionalType();
    
    require(objectTy.isReferenceCounted(F.getModule()),
            valueDescription + " must have reference semantics");
  }
  
  // Require that the operand is a type that supports reference storage
  // modifiers.
  void requireReferenceStorageCapableValue(SILValue value,
                                           const Twine &valueDescription) {
    requireReferenceOrOptionalReferenceValue(value, valueDescription);
    require(!value->getType().is<SILFunctionType>(),
            valueDescription + " cannot apply to a function type");
  }

  /// Assert that two types are equal.
  void requireSameType(Type type1, Type type2, const Twine &complaint) {
    _require(type1->isEqual(type2), complaint,
             [&] { llvm::dbgs() << "  " << type1 << "\n  " << type2 << '\n'; });
  }

  /// Assert that two types are equal.
  void requireSameType(SILType type1, SILType type2, const Twine &complaint) {
    _require(type1 == type2, complaint,
             [&] { llvm::dbgs() << "  " << type1 << "\n  " << type2 << '\n'; });
  }

  /// Require two function types to be ABI-compatible.
  void requireABICompatibleFunctionTypes(CanSILFunctionType type1,
                                         CanSILFunctionType type2,
                                         const Twine &what,
                                         SILFunction &inFunction) {
    auto complain = [=](const char *msg) -> std::function<void()> {
      return [=]{
        llvm::dbgs() << "  " << msg << '\n'
                     << "  " << type1 << "\n  " << type2 << '\n';
      };
    };
    auto complainBy = [=](std::function<void()> msg) -> std::function<void()> {
      return [=]{
        msg();
        llvm::dbgs() << '\n';
        llvm::dbgs() << "  " << type1 << "\n  " << type2 << '\n';
      };
    };

    // If we didn't have a failure, return.
    auto Result = type1->isABICompatibleWith(type2, inFunction);
    if (Result.isCompatible())
      return;

    if (!Result.hasPayload()) {
      _require(false, what, complain(Result.getMessage().data()));
    } else {
      _require(false, what, complainBy([=] {
                 llvm::dbgs() << " " << Result.getMessage().data()
                              << ".\nParameter: " << Result.getPayload();
               }));
    }
  }

  void requireSameFunctionComponents(CanSILFunctionType type1,
                                     CanSILFunctionType type2,
                                     const Twine &what) {
    require(type1->getNumResults() == type2->getNumResults(),
            "results of " + what + " do not match in count");
    for (auto i : indices(type1->getResults())) {
      require(type1->getResults()[i] == type2->getResults()[i],
              "result " + Twine(i) + " of " + what + " do not match");
    }
    require(type1->getParameters().size() ==
            type2->getParameters().size(),
            "inputs of " + what + " do not match in count");
    for (auto i : indices(type1->getParameters())) {
      require(type1->getParameters()[i] ==
              type2->getParameters()[i],
              "input " + Twine(i) + " of " + what + " do not match");
    }
  }

  static unsigned numInstsInFunction(const SILFunction &F) {
    unsigned numInsts = 0;
    for (auto &BB : F) {
      numInsts += std::distance(BB.begin(), BB.end());
    }
    return numInsts;
  }

  SILVerifier(const SILFunction &F, bool SingleFunction = true)
      : M(F.getModule().getSwiftModule()), F(F),
        fnConv(F.getConventionsInContext()), TC(F.getModule().Types),
        OpenedArchetypes(&F), Dominance(nullptr),
        InstNumbers(numInstsInFunction(F)), DEBlocks(&F),
        loadBorrowImmutabilityAnalysis(DEBlocks, &F),
        SingleFunction(SingleFunction) {
    if (F.isExternalDeclaration())
      return;
      
    // Check to make sure that all blocks are well formed.  If not, the
    // SILVerifier object will explode trying to compute dominance info.
    unsigned InstIdx = 0;
    for (auto &BB : F) {
      require(!BB.empty(), "Basic blocks cannot be empty");
      require(isa<TermInst>(BB.back()),
              "Basic blocks must end with a terminator instruction");
      for (auto &I : BB)
        InstNumbers[&I] = InstIdx++;
    }

    Dominance.reset(new DominanceInfo(const_cast<SILFunction *>(&F)));

    auto *DebugScope = F.getDebugScope();
    require(DebugScope, "All SIL functions must have a debug scope");
    require(DebugScope->Parent.get<SILFunction *>() == &F,
            "Scope of SIL function points to different function");
  }

  // Checks dominance between two instructions.
  // This does not use DominanceInfo.properlyDominates, because for large basic
  // blocks it would result in quadratic behavior.
  bool properlyDominates(SILInstruction *a, SILInstruction *b) {
    auto aBlock = a->getParent(), bBlock = b->getParent();

    // If the blocks are different, it's as easy as whether A's block
    // dominates B's block.
    if (aBlock != bBlock)
      return Dominance->properlyDominates(aBlock, bBlock);

    return InstNumbers[a] < InstNumbers[b];
  }

  // FIXME: For sanity, address-type phis should be prohibited at all SIL
  // stages. However, the optimizer currently breaks the invariant in three
  // places:
  // 1. Normal Simplify CFG during conditional branch simplification
  //    (sneaky jump threading).
  // 2. Simplify CFG via Jump Threading.
  // 3. Loop Rotation.
  //
  // BasicBlockCloner::canCloneInstruction and sinkAddressProjections is
  // designed to avoid this issue, we just need to make sure all passes use it
  // correctly.
  //
  // Minimally, we must prevent address-type phis as long as access markers are
  // preserved. A goal is to preserve access markers in OSSA.
  bool prohibitAddressPhis() {
    return F.hasOwnership();
  }

  void visitSILPhiArgument(SILPhiArgument *arg) {
    // Verify that the `isPhiArgument` property is sound:
    // - Phi arguments come from branches.
    // - Non-phi arguments have a single predecessor.
    if (arg->isPhiArgument()) {
      for (SILBasicBlock *predBB : arg->getParent()->getPredecessorBlocks()) {
        auto *TI = predBB->getTerminator();
        // FIXME: when critical edges are removed, only allow BranchInst.
        require(isa <BranchInst>(TI) || isa<CondBranchInst>(TI),
                "All phi argument inputs must be from branches.");
      }
    } else {
    }
    if (arg->isPhiArgument() && prohibitAddressPhis()) {
      // As a property of well-formed SIL, we disallow address-type
      // phis. Supporting them would prevent reliably reasoning about the
      // underlying storage of memory access. This reasoning is important for
      // diagnosing violations of memory access rules and supporting future
      // optimizations such as bitfield packing. Address-type block arguments
      // also create unnecessary complexity for SIL optimization passes that
      // need to reason about memory aliasing.
      require(!arg->getType().isAddress(),
              "Block arguments cannot be addresses");
    }
  }

  void visitSILArgument(SILArgument *arg) {
    CurArgument = arg;
    checkLegalType(arg->getFunction(), arg, nullptr);
    checkValueBaseOwnership(arg);
    if (auto *phiArg = dyn_cast<SILPhiArgument>(arg)) {
      if (phiArg->isPhiArgument())
        visitSILPhiArgument(phiArg);
      else {
        // A non-phi BlockArgument must have a single predecessor unless it is
        // unreachable.
        require(arg->getParent()->pred_empty()
                    || arg->getParent()->getSinglePredecessorBlock(),
                "Non-branch terminator must have a unique successor.");
      }
      return;
    }

    // If we are not in lowered SIL and have an in_guaranteed function argument,
    // verify that we do not mutate or consume it.
    auto *fArg = cast<SILFunctionArgument>(arg);
    if (fArg->getModule().getStage() == SILStage::Lowered ||
        !fArg->getType().isAddress() ||
        !fArg->hasConvention(SILArgumentConvention::Indirect_In_Guaranteed))
      return;

    require(!ImmutableAddressUseVerifier().isMutatingOrConsuming(fArg),
            "Found mutating or consuming use of an in_guaranteed parameter?!");
  }

  void visitSILInstruction(SILInstruction *I) {
    CurInstruction = I;
    OpenedArchetypes.registerOpenedArchetypes(I);
    checkSILInstruction(I);

    // Check the SILLLocation attached to the instruction.
    checkInstructionsSILLocation(I);

    // Check ownership and types.
    SILFunction *F = I->getFunction();
    assert(F && "Expected value base with parent function");

    for (auto result : I->getResults()) {
      checkLegalType(F, result, I);
      checkValueBaseOwnership(result);
    }
  }

  void checkValueBaseOwnership(ValueBase *V) {
    // If ownership is not enabled, bail.
    if (!isSILOwnershipEnabled())
      return;

    SILFunction *F = V->getFunction();
    assert(F && "Expected value base with parent function");
    // If we do not have qualified ownership, then do not verify value base
    // ownership.
    if (!F->hasOwnership()) {
      require(SILValue(V).getOwnershipKind() == OwnershipKind::None,
              "Once ownership is gone, all values should have none ownership");
      return;
    }
    SILValue(V).verifyOwnership(&DEBlocks);
  }

  void checkSILInstruction(SILInstruction *I) {
    const SILBasicBlock *BB = I->getParent();
    require(BB, "Instruction with null parent");

    // Check that non-terminators look ok.
    if (!isa<TermInst>(I)) {
      require(!BB->empty(), "Can't be in a parent block if it is empty");
      if (!I->isStaticInitializerInst()) {
        require(&*BB->rbegin() != I,
                "Non-terminators cannot be the last in a block");
      }
    } else {
      require(&*BB->rbegin() == I,
              "Terminator must be the last in block");
    }

    // Verify that all of our uses are in this function.
    for (auto result : I->getResults()) {
      for (Operand *use : result->getUses()) {
        auto user = use->getUser();
        require(user, "instruction user is null?");
        require(isa<SILInstruction>(user),
                "instruction used by non-instruction");
        auto userI = cast<SILInstruction>(user);
        require(userI->getParent(),
                "instruction used by unparented instruction");
        if (I->isStaticInitializerInst()) {
          require(userI->getParent() == BB,
                "instruction used by instruction not in same static initializer");
        } else {
          require(userI->getFunction() == &F,
                  "instruction used by instruction in different function");
        }

        auto operands = userI->getAllOperands();
        require(operands.begin() <= use && use <= operands.end(),
                "use doesn't actually belong to instruction it claims to");
      }
    }

    // Verify some basis structural stuff about an instruction's operands.
    for (auto &operand : I->getAllOperands()) {
      require(operand.get(), "instruction has null operand");

      if (auto *valueI = operand.get()->getDefiningInstruction()) {
        require(valueI->getParent(),
                "instruction uses value of unparented instruction");
        if (I->isStaticInitializerInst()) {
          require(valueI->getParent() == BB,
              "instruction uses value which is not in same static initializer");
        } else {
          require(valueI->getFunction() == &F,
                  "instruction uses value of instruction from another function");
          require(properlyDominates(valueI, I),
                  "instruction isn't dominated by its operand");
        }
      }
      
      if (auto *valueBBA = dyn_cast<SILArgument>(operand.get())) {
        require(!I->isStaticInitializerInst(),
                "static initializer inst cannot refer to SILArgument");
        require(valueBBA->getParent(),
                "instruction uses value of unparented instruction");
        require(valueBBA->getFunction() == &F,
                "bb argument value from another function");
        require(Dominance->dominates(valueBBA->getParent(), I->getParent()),
                "instruction isn't dominated by its bb argument operand");
      }

      require(operand.getUser() == I,
              "instruction's operand's owner isn't the instruction");
      require(isInValueUses(&operand), "operand value isn't used by operand");

      if (operand.isTypeDependent()) {
        require(isa<SILInstruction>(I),
               "opened archetype operand should refer to a SILInstruction");
      }

      // Make sure that if operand is generic that its primary archetypes match
      // the function context.
      checkLegalType(I->getFunction(), operand.get(), I);

      // If we are not in OSSA, our operand constraint should be invalid for a
      // type dependent operand (that is Optional::None) and if we have a non
      // type dependent operand then we should have a constraint of
      // OwnershipKind::Any, UseLifetimeConstraint::NonLifetimeEnding.
      if (!I->getFunction()->hasOwnership()) {
        if (operand.isTypeDependent()) {
          require(
              !operand.getOwnershipConstraint(),
              "Non Optional::None constraint for a type dependent operand?!");
        } else {
          auto constraint = operand.getOwnershipConstraint();
          require(constraint.hasValue(),
                  "All non-type dependent operands must have a "
                  "non-Optional::None constraint?!");
          require(constraint->getPreferredKind() == OwnershipKind::Any &&
                      constraint->getLifetimeConstraint() ==
                          UseLifetimeConstraint::NonLifetimeEnding,
                  "In non-ossa all non-type dependent operands must have a "
                  "constraint of Any, NonLifetimeEnding");
        }
      }
    }

    if (isa<OwnershipForwardingInst>(I)) {
      checkOwnershipForwardingInst(I);
    }
  }

  /// We are given an instruction \p fInst that forwards ownership from \p
  /// operand to one of \p fInst's results, make sure that if we have a
  /// forwarding instruction that can only accept owned or guaranteed ownership
  /// that we are following that invariant.
  void checkOwnershipForwardingInst(SILInstruction *i) {
    if (auto *o = dyn_cast<OwnedFirstArgForwardingSingleValueInst>(i)) {
      ValueOwnershipKind kind = OwnershipKind::Owned;
      require(kind.isCompatibleWith(o->getOwnershipKind()),
              "OwnedFirstArgForwardingSingleValueInst's ownership kind must be "
              "compatible with owned");
    }

    if (auto *o = dyn_cast<GuaranteedFirstArgForwardingSingleValueInst>(i)) {
      ValueOwnershipKind kind = OwnershipKind::Guaranteed;
      require(kind.isCompatibleWith(o->getOwnershipKind()),
              "GuaranteedFirstArgForwardingSingleValueInst's ownership kind "
              "must be compatible with guaranteed");
    }
  }

  void checkInstructionsSILLocation(SILInstruction *I) {
    // Check the debug scope.
    auto *DS = I->getDebugScope();
    if (DS && !maybeScopeless(*I))
      require(DS, "instruction has a location, but no scope");

    require(!DS || DS->getParentFunction() == I->getFunction(),
            "debug scope of instruction belongs to a different function");

    // Check the location kind.
    SILLocation L = I->getLoc();
    SILLocation::LocationKind LocKind = L.getKind();
    SILInstructionKind InstKind = I->getKind();

    // Check that there is at most one debug variable defined
    // for each argument slot. This catches SIL transformations
    // that accidentally remove inline information (stored in the SILDebugScope)
    // from debug-variable-carrying instructions.
    if (!DS->InlinedCallSite) {
      Optional<SILDebugVariable> VarInfo;
      if (auto *DI = dyn_cast<AllocStackInst>(I))
        VarInfo = DI->getVarInfo();
      else if (auto *DI = dyn_cast<AllocBoxInst>(I))
        VarInfo = DI->getVarInfo();
      else if (auto *DI = dyn_cast<DebugValueInst>(I))
        VarInfo = DI->getVarInfo();
      else if (auto *DI = dyn_cast<DebugValueAddrInst>(I))
        VarInfo = DI->getVarInfo();

      if (VarInfo)
        if (unsigned ArgNo = VarInfo->ArgNo) {
          // It is a function argument.
          if (ArgNo < DebugVars.size() && !DebugVars[ArgNo].empty() && !VarInfo->Name.empty()) {
            require(
                DebugVars[ArgNo] == VarInfo->Name,
                "Scope contains conflicting debug variables for one function "
                "argument");
          } else {
            // Reserve enough space.
            while (DebugVars.size() <= ArgNo) {
              DebugVars.push_back(StringRef());
            }
          }
          DebugVars[ArgNo] = VarInfo->Name;
      }
    }

    // Regular locations are allowed on all instructions.
    if (LocKind == SILLocation::RegularKind)
      return;

    if (LocKind == SILLocation::ReturnKind ||
        LocKind == SILLocation::ImplicitReturnKind)
      require(InstKind == SILInstructionKind::BranchInst ||
              InstKind == SILInstructionKind::ReturnInst ||
              InstKind == SILInstructionKind::UnreachableInst,
        "return locations are only allowed on branch and return instructions");

    if (LocKind == SILLocation::ArtificialUnreachableKind)
      require(InstKind == SILInstructionKind::UnreachableInst,
        "artificial locations are only allowed on Unreachable instructions");
  }

  /// Check that the types of this value producer are all legal in the function
  /// context in which it exists.
  void checkLegalType(SILFunction *F, ValueBase *value, SILInstruction *I) {
    SILType type = value->getType();
    if (type.is<SILTokenType>()) {
      require(isLegalSILTokenProducer(value),
              "SIL tokens can only be produced as the results of specific "
              "instructions");
      return;
    }

    checkLegalType(F, type, I);
  }

  static bool isLegalSILTokenProducer(SILValue value) {
    if (auto beginApply = dyn_cast<BeginApplyResult>(value))
      return beginApply->isTokenResult();

    // Add more token cases here as they arise.

    return false;
  }

  /// Check that the given type is a legal SIL value type.
  void checkLegalType(SILFunction *F, SILType type, SILInstruction *I) {
    checkLegalSILType(F, type.getASTType(), I);
  }

  /// Check that the given type is a legal SIL value type.
  void checkLegalSILType(SILFunction *F, CanType rvalueType, SILInstruction *I) {
    // These types should have been removed by lowering.
    require(!isa<LValueType>(rvalueType),
            "l-value types are not legal in SIL");
    require(!isa<AnyFunctionType>(rvalueType),
            "AST function types are not legal in SIL");

    // Tuples should have had their element lowered.
    if (auto tuple = dyn_cast<TupleType>(rvalueType)) {
      for (auto eltTy : tuple.getElementTypes()) {
        checkLegalSILType(F, eltTy, I);
      }
      return;
    }

    // Optionals should have had their objects lowered.
    if (auto objectType = rvalueType.getOptionalObjectType()) {
      return checkLegalSILType(F, objectType, I);
    }

    // Metatypes should have explicit representations.
    if (auto metatype = dyn_cast<AnyMetatypeType>(rvalueType)) {
      require(metatype->hasRepresentation(),
              "metatypes in SIL must have a representation");;
      // fallthrough for archetype check
    }

    rvalueType.visit([&](CanType t) {
      auto A = dyn_cast<ArchetypeType>(t);
      if (!A)
        return;
      require(isArchetypeValidInFunction(A, F),
              "Operand is of an ArchetypeType that does not exist in the "
              "Caller's generic param list.");
      if (auto OpenedA = getOpenedArchetypeOf(A)) {
        auto Def = OpenedArchetypes.getOpenedArchetypeDef(OpenedA);
        require (Def, "Opened archetype should be registered in SILFunction");
        require(I == nullptr || Def == I ||
                properlyDominates(cast<SILInstruction>(Def), I),
                "Use of an opened archetype should be dominated by a "
                "definition of this opened archetype");
      }
    });
  }

  /// Check that this operand appears in the use-chain of the value it uses.
  static bool isInValueUses(const Operand *operand) {
    for (auto use : operand->get()->getUses())
      if (use == operand)
        return true;
    return false;
  }

  /// \return True if all of the users of the AllocStack instruction \p ASI are
  /// inside the same basic block.
  static bool isSingleBlockUsage(AllocStackInst *ASI, DominanceInfo *Dominance){
    SILBasicBlock *BB = ASI->getParent();
    for (auto UI = ASI->use_begin(), E = ASI->use_end(); UI != E; ++UI)
      if (UI->getUser()->getParent() != BB &&
          Dominance->isReachableFromEntry(UI->getUser()->getParent()))
        return false;

    return true;
  }

  void checkAllocStackInst(AllocStackInst *AI) {
    require(AI->getType().isAddress(),
            "result of alloc_stack must be an address type");

    verifyOpenedArchetype(AI, AI->getElementType().getASTType());

    // There used to be a check if all uses of ASI are inside the alloc-dealloc
    // range. But apparently it can be the case that ASI has uses after the
    // dealloc_stack. This can come up if the source contains a
    // withUnsafePointer where the pointer escapes.
    // It's illegal code but the compiler should not crash on it.
  }

  void checkAllocRefBase(AllocRefInstBase *ARI) {
    requireReferenceValue(ARI, "Result of alloc_ref");
    verifyOpenedArchetype(ARI, ARI->getType().getASTType());
    auto Types = ARI->getTailAllocatedTypes();
    auto Counts = ARI->getTailAllocatedCounts();
    unsigned NumTypes = Types.size();
    require(NumTypes == Counts.size(), "Mismatching types and counts");
    require(NumTypes == 0 || !ARI->isObjC(),
            "Can't tail allocate with ObjC class");
    for (unsigned Idx = 0; Idx < NumTypes; ++Idx) {
      verifyOpenedArchetype(ARI, Types[Idx].getASTType());
      require(Counts[Idx].get()->getType().is<BuiltinIntegerType>(),
              "count needs integer type");
    }
  }

  void checkAllocRefInst(AllocRefInst *AI) {
    require(AI->isObjC() || AI->getType().getClassOrBoundGenericClass(),
            "alloc_ref must allocate class");
    checkAllocRefBase(AI);
  }

  void checkAllocRefDynamicInst(AllocRefDynamicInst *ARDI) {
    SILValue Metadata = ARDI->getMetatypeOperand();
    require(Metadata->getType().is<AnyMetatypeType>(),
            "operand of alloc_ref_dynamic must be of metatype type");
    auto metaTy = Metadata->getType().castTo<AnyMetatypeType>();
    require(metaTy->hasRepresentation(),
            "operand of alloc_ref_dynamic must have a metatype representation");
    if (ARDI->isObjC()) {
      require(metaTy->getRepresentation() == MetatypeRepresentation::ObjC,
              "alloc_ref_dynamic @objc requires operand of ObjC metatype");
    } else {
      require(metaTy->getRepresentation() == MetatypeRepresentation::Thick,
              "alloc_ref_dynamic requires operand of thick metatype");
    }
    checkAllocRefBase(ARDI);
  }

  /// Check the substitutions passed to an apply or partial_apply.
  CanSILFunctionType checkApplySubstitutions(SubstitutionMap subs,
                                             SILType calleeTy) {
    auto fnTy = requireObjectType(SILFunctionType, calleeTy, "callee operand");

    // If there are substitutions, verify them and apply them to the callee.
    if (!subs.hasAnySubstitutableParams()) {
      require(!fnTy->isPolymorphic(),
              "callee of apply without substitutions must not be polymorphic");
      return fnTy;
    }
    require(fnTy->isPolymorphic(),
            "callee of apply with substitutions must be polymorphic");

    // Each archetype occurring in the substitutions list should belong to the
    // current function.
    for (auto replacementType : subs.getReplacementTypes()) {
      replacementType->getCanonicalType().visit([&](CanType t) {
        auto A = dyn_cast<ArchetypeType>(t);
        if (!A)
          return;
        require(isArchetypeValidInFunction(A, &F),
                "Replacement type of a substitution contains an ArchetypeType "
                "that does not exist in the Caller's generic param list.");
      });
    }

    if (subs.getGenericSignature()->getCanonicalSignature() !=
          fnTy->getInvocationGenericSignature()->getCanonicalSignature()) {
      llvm::dbgs() << "substitution map's generic signature: ";
      subs.getGenericSignature()->print(llvm::dbgs());
      llvm::dbgs() << "\n";
      llvm::dbgs() << "callee's generic signature: ";
      fnTy->getInvocationGenericSignature()->print(llvm::dbgs());
      llvm::dbgs() << "\n";
      require(false,
              "Substitution map does not match callee in apply instruction");
    }
    // Apply the substitutions.
    return fnTy->substGenericArgs(F.getModule(), subs, F.getTypeExpansionContext());
  }

  /// Check that for each opened archetype or dynamic self type in substitutions
  /// or the calle type, there is a type dependent operand.
  void checkApplyTypeDependentArguments(ApplySite AS) {
    SILInstruction *AI = AS.getInstruction();

    llvm::DenseSet<ArchetypeType *> FoundOpenedArchetypes;
    unsigned hasDynamicSelf = 0;

    // Function to collect opened archetypes in FoundOpenedArchetypes and set
    // hasDynamicSelf.
    auto HandleType = [&](CanType Ty) {
      if (Ty->isOpenedExistential()) {
        auto A = cast<ArchetypeType>(Ty);
        require(isArchetypeValidInFunction(A, AI->getFunction()),
                "Archetype to be substituted must be valid in function.");
        // Collect all opened archetypes used in the substitutions list.
        FoundOpenedArchetypes.insert(A);
        // Also check that they are properly tracked inside the current
        // function.
        auto Def = OpenedArchetypes.getOpenedArchetypeDef(A);
        require(Def, "Opened archetype should be registered in SILFunction");
        require(Def == AI ||
                properlyDominates(cast<SILInstruction>(Def), AI),
                "Use of an opened archetype should be dominated by a "
                "definition of this opened archetype");
      }
      if (Ty->hasDynamicSelfType()) {
        hasDynamicSelf = 1;
      }
    };

    // Search for opened archetypes and dynamic self.
    for (auto Replacement : AS.getSubstitutionMap().getReplacementTypes()) {
      Replacement->getCanonicalType().visit(HandleType);
    }
    AS.getSubstCalleeType().visit(HandleType);

    require(FoundOpenedArchetypes.size() + hasDynamicSelf ==
                AI->getTypeDependentOperands().size(),
            "Number of opened archetypes and dynamic self in the substitutions "
            "list should match the number of type dependent operands");

    for (auto &Op : AI->getTypeDependentOperands()) {
      auto V = Op.get();
      if (isa<SILArgument>(V)) {
        require(hasDynamicSelf,
                "dynamic self operand without dynamic self type");
        require(AI->getFunction()->hasDynamicSelfMetadata(),
                "self metadata operand in function without self metadata param");
        require((ValueBase *)V == AI->getFunction()->getDynamicSelfMetadata(),
                "wrong self metadata operand");
      } else {
        require(isa<SingleValueInstruction>(V),
                "opened archetype operand should refer to a SIL instruction");
        auto Archetype = getOpenedArchetypeOf(cast<SingleValueInstruction>(V));
        require(Archetype,
                "opened archetype operand should define an opened archetype");
        require(FoundOpenedArchetypes.count(Archetype),
                "opened archetype operand does not correspond to any opened "
                "archetype from the substitutions list");
      }
    }
  }

  void checkFullApplySite(FullApplySite site) {
    checkApplyTypeDependentArguments(site);

    // Then make sure that we have a type that can be substituted for the
    // callee.
    auto substTy = checkApplySubstitutions(site.getSubstitutionMap(),
                                           site.getCallee()->getType());
    require(site.getOrigCalleeType()->getRepresentation() ==
            site.getSubstCalleeType()->getRepresentation(),
            "calling convention difference between types");

    require(!site.getSubstCalleeType()->isPolymorphic(),
            "substituted callee type should not be generic");

    requireSameType(SILType::getPrimitiveObjectType(substTy),
                    SILType::getPrimitiveObjectType(site.getSubstCalleeType()),
            "substituted callee type does not match substitutions");

    // Check that the arguments and result match.
    SILFunctionConventions substConv(substTy, F.getModule());
    //require(site.getArguments().size() == substTy->getNumSILArguments(),
    require(site.getNumArguments() == substConv.getNumSILArguments(),
            "apply doesn't have right number of arguments for function");
    for (size_t i = 0, size = site.getNumArguments(); i < size; ++i) {
      requireSameType(
          site.getArguments()[i]->getType(),
          substConv.getSILArgumentType(i, F.getTypeExpansionContext()),
          "operand of 'apply' doesn't match function input type");
    }
  }

  void checkApplyInst(ApplyInst *AI) {
    checkFullApplySite(AI);

    SILFunctionConventions calleeConv(AI->getSubstCalleeType(), F.getModule());
    requireSameType(
        AI->getType(), calleeConv.getSILResultType(F.getTypeExpansionContext()),
        "type of apply instruction doesn't match function result type");
    if (AI->isNonThrowing()) {
      require(calleeConv.funcTy->hasErrorResult(),
              "nothrow flag used for callee without error result");
    } else {
      require(!calleeConv.funcTy->hasErrorResult(),
              "apply instruction cannot call function with error result");
    }

    require(!calleeConv.funcTy->isCoroutine(),
            "cannot call coroutine with normal apply");
    require(!calleeConv.funcTy->isAsync() || AI->getFunction()->isAsync(),
            "cannot call an async function from a non async function");
  }

  void checkTryApplyInst(TryApplyInst *AI) {
    checkFullApplySite(AI);

    SILFunctionConventions calleeConv(AI->getSubstCalleeType(), F.getModule());

    require(!calleeConv.funcTy->isCoroutine(),
            "cannot call coroutine with normal apply");

    require(!calleeConv.funcTy->isAsync() || AI->getFunction()->isAsync(),
            "cannot call an async function from a non async function");

    auto normalBB = AI->getNormalBB();
    require(normalBB->args_size() == 1,
            "normal destination of try_apply must take one argument");
    requireSameType((*normalBB->args_begin())->getType(),
                    calleeConv.getSILResultType(F.getTypeExpansionContext()),
                    "normal destination of try_apply must take argument "
                    "of normal result type");

    auto errorBB = AI->getErrorBB();
    require(calleeConv.funcTy->hasErrorResult(),
            "try_apply must call function with error result");
    require(errorBB->args_size() == 1,
            "error destination of try_apply must take one argument");
    requireSameType((*errorBB->args_begin())->getType(),
                    calleeConv.getSILErrorType(F.getTypeExpansionContext()),
                    "error destination of try_apply must take argument "
                    "of error result type");
  }

  void checkBeginApplyInst(BeginApplyInst *AI) {
    checkFullApplySite(AI);

    SILFunctionConventions calleeConv(AI->getSubstCalleeType(), F.getModule());
    auto yieldResults = AI->getYieldedValues();
    auto yields = calleeConv.getYields();
    require(yields.size() == yieldResults.size(),
            "length mismatch in callee yields vs. begin_apply results");
    for (auto i : indices(yields)) {
      requireSameType(
          yieldResults[i]->getType(),
          calleeConv.getSILType(yields[i], F.getTypeExpansionContext()),
          "callee yield type does not match begin_apply result type");
    }

    if (AI->isNonThrowing()) {
      require(calleeConv.funcTy->hasErrorResult(),
              "nothrow flag used for callee without error result");
    } else {
      require(!calleeConv.funcTy->hasErrorResult(),
              "begin_apply instruction cannot call function with error result");
    }

    require(calleeConv.funcTy->getCoroutineKind() == SILCoroutineKind::YieldOnce,
            "must call yield_once coroutine with begin_apply");
    require(!calleeConv.funcTy->isAsync() || AI->getFunction()->isAsync(),
            "cannot call an async function from a non async function");
  }

  void checkAbortApplyInst(AbortApplyInst *AI) {
    require(isa<BeginApplyResult>(AI->getOperand()) &&
            cast<BeginApplyResult>(AI->getOperand())->isTokenResult(),
            "operand of abort_apply must be a begin_apply");
  }

  void checkEndApplyInst(EndApplyInst *AI) {
    require(isa<BeginApplyResult>(AI->getOperand()) &&
            cast<BeginApplyResult>(AI->getOperand())->isTokenResult(),
            "operand of end_apply must be a begin_apply");
  }

  void verifyLLVMIntrinsic(BuiltinInst *BI, llvm::Intrinsic::ID ID) {
    // Certain llvm intrinsic require constant values as their operands.
    // Consequently, these must not be phi nodes (aka. basic block arguments).
    switch (ID) {
    default:
      break;
    case llvm::Intrinsic::ctlz: // llvm.ctlz
    case llvm::Intrinsic::cttz: // llvm.cttz
      break;
    case llvm::Intrinsic::memcpy:
    case llvm::Intrinsic::memmove:
    case llvm::Intrinsic::memset:
      require(!isa<SILArgument>(BI->getArguments()[3]),
              "isvolatile argument of memory intrinsics must be an integer "
              "literal");
      break;
    case llvm::Intrinsic::lifetime_start:
    case llvm::Intrinsic::lifetime_end:
    case llvm::Intrinsic::invariant_start:
      require(!isa<SILArgument>(BI->getArguments()[0]),
              "size argument of memory use markers must be an integer literal");
      break;
    case llvm::Intrinsic::invariant_end:
      require(!isa<SILArgument>(BI->getArguments()[1]),
              "llvm.invariant.end parameter #2 must be an integer literal");
      break;
    }
  }

  void checkPartialApplyInst(PartialApplyInst *PAI) {
    if (PAI->getModule().getStage() != SILStage::Raw) {
      require(!PAI->getFunctionType()->isDifferentiable(),
              "partial_apply of differentiable funtions is only allowed "
              "in raw SIL");
    }

    auto resultInfo = requireObjectType(SILFunctionType, PAI,
                                        "result of partial_apply");
    verifySILFunctionType(resultInfo);
    require(resultInfo->getExtInfo().hasContext(),
            "result of closure cannot have a thin function type");

    checkApplyTypeDependentArguments(PAI);

    auto substTy = checkApplySubstitutions(PAI->getSubstitutionMap(),
                                        PAI->getCallee()->getType());

    require(!PAI->getSubstCalleeType()->isPolymorphic(),
            "substituted callee type should not be generic");

    requireSameType(SILType::getPrimitiveObjectType(substTy),
                    SILType::getPrimitiveObjectType(PAI->getSubstCalleeType()),
            "substituted callee type does not match substitutions");

    // The arguments must match the suffix of the original function's input
    // types.
    require(PAI->getArguments().size() +
              resultInfo->getParameters().size()
              == substTy->getParameters().size(),
            "result of partial_apply should take as many inputs as were not "
            "applied by the instruction");

    SILFunctionConventions substConv(substTy, F.getModule());
    unsigned appliedArgStartIdx =
        substConv.getNumSILArguments() - PAI->getNumArguments();
    for (unsigned i = 0, size = PAI->getArguments().size(); i < size; ++i) {
      requireSameType(
          PAI->getArguments()[i]->getType(),
          substConv.getSILArgumentType(appliedArgStartIdx + i,
                                       F.getTypeExpansionContext()),
          "applied argument types do not match suffix of function type's "
          "inputs");
    }

    // The arguments to the result function type must match the prefix of the
    // original function's input types.
    for (unsigned i = 0, size = resultInfo->getParameters().size();
         i < size; ++i) {
      require(resultInfo->getParameters()[i] ==
              substTy->getParameters()[i],
              "inputs to result function type do not match unapplied inputs "
              "of original function");
    }

    require(resultInfo->getNumResults() == substTy->getNumResults(),
            "applied results do not agree in count with function type");
    for (unsigned i = 0, size = resultInfo->getNumResults(); i < size; ++i) {
      auto originalResult = resultInfo->getResults()[i];
      auto expectedResult = substTy->getResults()[i];

      // The "returns inner pointer" convention doesn't survive through a
      // partial application, since the thunk takes responsibility for
      // lifetime-extending 'self'.
      if (expectedResult.getConvention()
            == ResultConvention::UnownedInnerPointer) {
        expectedResult = SILResultInfo(
            expectedResult.getReturnValueType(F.getModule(), substTy,
                                              F.getTypeExpansionContext()),
            ResultConvention::Unowned);
        require(originalResult == expectedResult,
                "result type of result function type for partially applied "
                "@unowned_inner_pointer function should have @unowned"
                "convention");

      // The "autoreleased" convention doesn't survive through a
      // partial application, since the thunk takes responsibility for
      // retaining the return value.
      } else if (expectedResult.getConvention()
            == ResultConvention::Autoreleased) {
        expectedResult = SILResultInfo(
            expectedResult.getReturnValueType(F.getModule(), substTy,
                                              F.getTypeExpansionContext()),
            ResultConvention::Owned);
        require(originalResult == expectedResult,
                "result type of result function type for partially applied "
                "@autoreleased function should have @owned convention");

      } else {
        require(originalResult == expectedResult,
                "result type of result function type does not match original "
                "function");
      }
    }

    // TODO: Impose additional constraints when partial_apply when the
    // -disable-sil-partial-apply flag is enabled. We want to reduce
    // partial_apply to being only a means of associating a closure invocation
    // function with its context.
    //
    // When we reach that point, we should be able to more deeply redesign
    // PartialApplyInst to simplify the representation to carry a single
    // argument.
    if (PAI->getModule().getOptions().DisableSILPartialApply) {
      // Should only be one context argument.
      require(PAI->getArguments().size() == 1,
              "partial_apply should have a single context argument");
      
      // Callee should already have the thin convention, and result should be
      // thick.
      require(resultInfo->getRepresentation() ==
                SILFunctionTypeRepresentation::Thick,
              "partial_apply result should have thick convention");
      require(PAI->getCallee()->getType().castTo<SILFunctionType>()
                ->getRepresentation() ==
              SILFunctionTypeRepresentation::Thin,
              "partial_apply callee should have thin convention");
      
      // TODO: Check that generic signature matches box's generic signature,
      // once we have boxes with generic signatures.
      require(!PAI->getCalleeFunction()->getGenericEnvironment(),
              "partial_apply context must capture generic environment for "
              "callee");
      
      // Result's callee convention should match context argument's convention.
      require(substTy->getParameters().back().getConvention()
                == resultInfo->getCalleeConvention(),
              "partial_apply context argument must have the same convention "
              "as the resulting function's callee convention");
      
      auto isSwiftRefcounted = [](SILType t) -> bool {
        if (t.is<SILBoxType>())
          return true;
        if (t.getASTType() == t.getASTContext().TheNativeObjectType)
          return true;
        if (auto clas = t.getClassOrBoundGenericClass())
          // Must be a class defined in Swift.
          return clas->hasKnownSwiftImplementation();
        return false;
      };
      
      // The context argument must be a swift-refcounted box or class.
      require(isSwiftRefcounted(PAI->getArguments().front()->getType()),
              "partial_apply context argument must be swift-refcounted");
    }
  }

  void checkBuiltinInst(BuiltinInst *BI) {
    // Check for special constraints on llvm intrinsics.
    if (BI->getIntrinsicInfo().ID != llvm::Intrinsic::not_intrinsic) {
      verifyLLVMIntrinsic(BI, BI->getIntrinsicInfo().ID);
      return;
    }

    auto builtinKind = BI->getBuiltinKind();

    // Check that 'getCurrentAsyncTask' only occurs within an async function.
    if (builtinKind == BuiltinValueKind::GetCurrentAsyncTask) {
      require(F.isAsync(),
          "getCurrentAsyncTask builtin can only be used in an async function");
      return;
    }

    if (builtinKind == BuiltinValueKind::InitializeDefaultActor ||
        builtinKind == BuiltinValueKind::DestroyDefaultActor) {
      auto arguments = BI->getArguments();
      require(arguments.size() == 1,
              "default-actor builtin can only operate on a single object");
      auto argType = arguments[0]->getType().getASTType();
      auto argClass = argType.getClassOrBoundGenericClass();
      require((argClass && argClass->isRootDefaultActor()) ||
              isa<BuiltinNativeObjectType>(argType),
              "default-actor builtin can only operate on default actors");
      return;
    }
  }

  void checkFunctionRefBaseInst(FunctionRefBaseInst *FRI) {
    auto fnType = requireObjectType(SILFunctionType, FRI,
                                    "result of function_ref");
    require(!fnType->getExtInfo().hasContext(),
            "function_ref should have a context-free function result");

    // Note: in SingleFunction mode, we relax some of these checks because
    // we may not have linked everything yet.

    SILFunction *RefF = FRI->getInitiallyReferencedFunction();

    if (isa<FunctionRefInst>(FRI))
      require(
          !RefF->isDynamicallyReplaceable(),
          "function_ref cannot reference a [dynamically_replaceable] function");
    else if (isa<PreviousDynamicFunctionRefInst>(FRI)) {
      require(!RefF->isDynamicallyReplaceable(),
              "previous_function_ref cannot reference a "
              "[dynamically_replaceable] function");
      require(RefF->getDynamicallyReplacedFunction(),
              "previous_function_ref must reference a "
              "[dynamic_replacement_for:...] function");
    } else if (isa<DynamicFunctionRefInst>(FRI))
      require(RefF->isDynamicallyReplaceable(),
              "dynamic_function_ref must reference a "
              "[dynamically_replaceable] function");

    // In canonical SIL, direct reference to a shared_external declaration
    // is an error; we should have deserialized a body. In raw SIL, including
    // the merge-modules phase, we may not have deserialized the body yet as we
    // may not have run the SILLinker pass.
    if (F.getModule().getStage() >= SILStage::Canonical) {
      if (RefF->isExternalDeclaration()) {
        require(SingleFunction ||
                !hasSharedVisibility(RefF->getLinkage()) ||
                RefF->hasForeignBody(),
                "external declarations of SILFunctions with shared visibility is "
                "not allowed");
      }
    }

    // A direct reference to a non-public or shared but not fragile function
    // from a fragile function is an error.
    if (F.isSerialized()) {
      require((SingleFunction && RefF->isExternalDeclaration()) ||
              RefF->hasValidLinkageForFragileRef(),
              "function_ref inside fragile function cannot "
              "reference a private or hidden symbol");
    }

    verifySILFunctionType(fnType);
  }

  void checkFunctionRefInst(FunctionRefInst *FRI) {
    checkFunctionRefBaseInst(FRI);
  }

  void checkDynamicFunctionRefInst(DynamicFunctionRefInst *FRI) {
    checkFunctionRefBaseInst(FRI);
  }

  void checkPreviousDynamicFunctionRefInst(PreviousDynamicFunctionRefInst *FRI) {
    checkFunctionRefBaseInst(FRI);
  }

  void checkAllocGlobalInst(AllocGlobalInst *AGI) {
    SILGlobalVariable *RefG = AGI->getReferencedGlobal();
    if (auto *VD = RefG->getDecl()) {
      require(!VD->isResilient(F.getModule().getSwiftModule(),
                               F.getResilienceExpansion()),
              "cannot access storage of resilient global");
    }
    if (F.isSerialized()) {
      require(RefG->isSerialized()
                || hasPublicVisibility(RefG->getLinkage()),
              "alloc_global inside fragile function cannot "
              "reference a private or hidden symbol");
    }
  }

  void checkGlobalAccessInst(GlobalAccessInst *GAI) {
    SILGlobalVariable *RefG = GAI->getReferencedGlobal();
    requireSameType(
        GAI->getType().getObjectType(),
        RefG->getLoweredTypeInContext(F.getTypeExpansionContext()),
        "global_addr/value must be the type of the variable it references");
    if (auto *VD = RefG->getDecl()) {
      require(!VD->isResilient(F.getModule().getSwiftModule(),
                               F.getResilienceExpansion()),
              "cannot access storage of resilient global");
    }
    if (F.isSerialized()) {
      require(RefG->isSerialized()
              || hasPublicVisibility(RefG->getLinkage()),
              "global_addr/value inside fragile function cannot "
              "reference a private or hidden symbol");
    }
  }

  void checkGlobalAddrInst(GlobalAddrInst *GAI) {
    require(GAI->getType().isAddress(),
            "global_addr must have an address result type");
    require(!GAI->getReferencedGlobal()->isInitializedObject(),
            "global_addr cannot refer to a statically initialized object");
    checkGlobalAccessInst(GAI);
  }

  void checkGlobalValueInst(GlobalValueInst *GVI) {
    require(GVI->getType().isObject(),
            "global_value must have an address result type");
    checkGlobalAccessInst(GVI);
  }

  void checkObjectInst(ObjectInst *) {
    require(false, "object instruction is only allowed in a static initializer");
  }

  void checkIntegerLiteralInst(IntegerLiteralInst *ILI) {
    require(ILI->getType().is<AnyBuiltinIntegerType>(),
            "invalid integer literal type");
  }

  void checkLoadInst(LoadInst *LI) {
    require(LI->getType().isObject(), "Result of load must be an object");
    require(!fnConv.useLoweredAddresses()
                || LI->getType().isLoadable(*LI->getFunction()),
            "Load must have a loadable type");
    require(LI->getOperand()->getType().isAddress(),
            "Load operand must be an address");
    requireSameType(LI->getOperand()->getType().getObjectType(), LI->getType(),
                    "Load operand type and result type mismatch");

    // Ownership semantic checks.
    switch (LI->getOwnershipQualifier()) {
    case LoadOwnershipQualifier::Unqualified:
      // We should not see loads with unqualified ownership when SILOwnership is
      // enabled.
      require(!F.hasOwnership(),
              "Load with unqualified ownership in a qualified function");
      break;
    case LoadOwnershipQualifier::Copy:
    case LoadOwnershipQualifier::Take:
      require(F.hasOwnership(),
              "Load with qualified ownership in an unqualified function");
      // TODO: Could probably make this a bit stricter.
      require(!LI->getType().isTrivial(*LI->getFunction()),
              "load [copy] or load [take] can only be applied to non-trivial "
              "types");
      break;
    case LoadOwnershipQualifier::Trivial:
      require(F.hasOwnership(),
              "Load with qualified ownership in an unqualified function");
      require(LI->getType().isTrivial(*LI->getFunction()),
              "A load with trivial ownership must load a trivial type");
      break;
    }
  }

  void checkLoadBorrowInst(LoadBorrowInst *LBI) {
    require(
        F.hasOwnership(),
        "Inst with qualified ownership in a function that is not qualified");
    require(LBI->getType().isObject(), "Result of load must be an object");
    require(!fnConv.useLoweredAddresses()
            || LBI->getType().isLoadable(*LBI->getFunction()),
            "Load must have a loadable type");
    require(LBI->getOperand()->getType().isAddress(),
            "Load operand must be an address");
    requireSameType(LBI->getOperand()->getType().getObjectType(),
                    LBI->getType(),
                    "Load operand type and result type mismatch");
    require(loadBorrowImmutabilityAnalysis.isImmutable(LBI),
            "Found load borrow that is invalidated by a local write?!");
  }

  void checkEndBorrowInst(EndBorrowInst *EBI) {
    require(
        F.hasOwnership(),
        "Inst with qualified ownership in a function that is not qualified");
  }

  void checkUncheckedValueCastInst(UncheckedValueCastInst *) {
    require(
        F.hasOwnership(),
        "Inst with qualified ownership in a function that is not qualified");
  }

  void checkUncheckedOwnershipConversionInst(
    UncheckedOwnershipConversionInst *uoci) {
    require(
        F.hasOwnership(),
        "Inst with qualified ownership in a function that is not qualified");
    require(!uoci->getType().isAddress(),
            "cannot convert ownership of an address");
    require(uoci->getType() == uoci->getOperand()->getType(),
            "converting ownership does not affect the type");
  }

  template <class AI>
  void checkAccessEnforcement(AI *AccessInst) {
    if (AccessInst->getModule().getStage() != SILStage::Raw) {
      require(AccessInst->getEnforcement() != SILAccessEnforcement::Unknown,
              "access must have known enforcement outside raw stage");
    }
  }

  void checkBeginAccessInst(BeginAccessInst *BAI) {
    requireSameType(BAI->getType(), BAI->getSource()->getType(),
                    "result must be same type as operand");
    require(BAI->getType().isAddress(),
            "begin_access operand must have address type");

    checkAccessEnforcement(BAI);

    switch (BAI->getAccessKind()) {
    case SILAccessKind::Init:
    case SILAccessKind::Deinit:
      require(BAI->getEnforcement() == SILAccessEnforcement::Static,
              "init/deinit accesses cannot use non-static enforcement");
      break;

    case SILAccessKind::Read:
    case SILAccessKind::Modify:
      break;
    }

    // Verify that all formal accesses patterns are recognized as part of a
    // allowlist. The presence of an unknown pattern means that analysis will
    // silently fail, and the compiler may be introducing undefined behavior
    // with no other way to detect it.
    //
    // For example, AccessEnforcementWMO runs very late in the
    // pipeline and assumes valid storage for all dynamic Read/Modify access. It
    // also requires that Unidentified access fit a allowlist on known
    // non-internal globals or class properties.
    //
    // First check that identifyFormalAccess returns without asserting. For
    // Unsafe enforcement, that is sufficient. For any other enforcement
    // level also require that it returns a valid AccessedStorage object.
    // Unsafe enforcement is used for some unrecognizable access patterns,
    // like debugger variables. The compiler never cares about the source of
    // those accesses.
    identifyFormalAccess(BAI);
    // FIXME: rdar://57291811 - the following check for valid storage will be
    // reenabled shortly. A fix is planned. In the meantime, the possiblity that
    // a real miscompilation could be caused by this failure is insignificant.
    // I will probably enable a much broader SILVerification of address-type
    // block arguments first to ensure we never hit this check again.
    /*
    AccessedStorage storage = identifyFormalAccess(BAI);
    if (BAI->getEnforcement() != SILAccessEnforcement::Unsafe)
      require(storage, "Unknown formal access pattern");
    */
  }

  void checkEndAccessInst(EndAccessInst *EAI) {
    auto BAI = dyn_cast<BeginAccessInst>(EAI->getOperand());
    require(BAI != nullptr,
            "operand of end_access must be a begin_access");

    if (EAI->isAborting()) {
      require(BAI->getAccessKind() == SILAccessKind::Init ||
              BAI->getAccessKind() == SILAccessKind::Deinit,
              "aborting access must apply to init or deinit");
    }
  }

  void checkBeginUnpairedAccessInst(BeginUnpairedAccessInst *BUAI) {
    require(BUAI->getEnforcement() != SILAccessEnforcement::Unknown,
            "unpaired access can never use unknown enforcement");
    require(BUAI->getSource()->getType().isAddress(),
            "address operand must have address type");
    requireAddressType(BuiltinUnsafeValueBufferType, BUAI->getBuffer(),
                       "scratch buffer operand");

    checkAccessEnforcement(BUAI);

    switch (BUAI->getAccessKind()) {
    case SILAccessKind::Init:
    case SILAccessKind::Deinit:
      require(BUAI->getEnforcement() == SILAccessEnforcement::Static,
              "init/deinit accesses cannot use non-static enforcement");
      break;
    case SILAccessKind::Read:
    case SILAccessKind::Modify:
      break;
    }

    // First check that identifyFormalAccess never asserts.
    AccessedStorage storage = identifyFormalAccess(BUAI);
    // Only allow Unsafe and Builtin access to have invalid storage.
    if (BUAI->getEnforcement() != SILAccessEnforcement::Unsafe
        && !BUAI->isFromBuiltin()) {
      require(storage, "Unknown formal access pattern");
    }
  }

  void checkEndUnpairedAccessInst(EndUnpairedAccessInst *I) {
    require(I->getEnforcement() != SILAccessEnforcement::Unknown,
            "unpaired access can never use unknown enforcement");
    requireAddressType(BuiltinUnsafeValueBufferType, I->getBuffer(),
                       "scratch buffer operand");

    checkAccessEnforcement(I);
  }

  void checkStoreInst(StoreInst *SI) {
    require(SI->getSrc()->getType().isObject(),
            "Can't store from an address source");
    require(!fnConv.useLoweredAddresses()
                || SI->getSrc()->getType().isLoadable(*SI->getFunction()),
            "Can't store a non loadable type");
    require(SI->getDest()->getType().isAddress(),
            "Must store to an address dest");
    requireSameType(SI->getDest()->getType().getObjectType(),
                    SI->getSrc()->getType(),
                    "Store operand type and dest type mismatch");

    // Perform ownership checks.
    switch (SI->getOwnershipQualifier()) {
    case StoreOwnershipQualifier::Unqualified:
      // We should not see loads with unqualified ownership when SILOwnership is
      // enabled.
      require(!F.hasOwnership(),
              "Qualified store in function with unqualified ownership?!");
      break;
    case StoreOwnershipQualifier::Init:
    case StoreOwnershipQualifier::Assign:
      require(
          F.hasOwnership(),
          "Inst with qualified ownership in a function that is not qualified");
      // TODO: Could probably make this a bit stricter.
      require(!SI->getSrc()->getType().isTrivial(*SI->getFunction()),
              "store [init] or store [assign] can only be applied to "
              "non-trivial types");
      break;
    case StoreOwnershipQualifier::Trivial: {
      require(
          F.hasOwnership(),
          "Inst with qualified ownership in a function that is not qualified");
      SILValue Src = SI->getSrc();
      require(Src->getType().isTrivial(*SI->getFunction()) ||
                  Src.getOwnershipKind() == OwnershipKind::None,
              "A store with trivial ownership must store a type with trivial "
              "ownership");
      break;
    }
    }
  }

  void checkAssignInst(AssignInst *AI) {
    SILValue Src = AI->getSrc(), Dest = AI->getDest();
    require(AI->getModule().getStage() == SILStage::Raw,
            "assign instruction can only exist in raw SIL");
    require(Src->getType().isObject(), "Can't assign from an address source");
    require(Dest->getType().isAddress(), "Must store to an address dest");
    requireSameType(Dest->getType().getObjectType(), Src->getType(),
                    "Store operand type and dest type mismatch");
  }

  // Usually the assign_by_wrapper initializer or setter has a single argument
  // (the value). But in case of a tuple, the initializer/setter expect the
  // tuple elements as separate arguments.
  void checkAssignByWrapperArgsRecursively(SILType ty,
                               SILFunctionConventions &conv, unsigned &argIdx) {
    if (auto tupleTy = ty.getAs<TupleType>()) {
      for (Type et : tupleTy->getElementTypes()) {
        SILType elTy = SILType::getPrimitiveType(CanType(et), ty.getCategory());
        checkAssignByWrapperArgsRecursively(elTy, conv, argIdx);
      }
      return;
    }
    require(argIdx < conv.getNumSILArguments(),
            "initializer or setter has too few arguments");
    SILType argTy =
        conv.getSILArgumentType(argIdx++, F.getTypeExpansionContext());
    if (ty.isAddress() && argTy.isObject())
      ty = ty.getObjectType();
    requireSameType(ty, argTy, "wrong argument type of initializer or setter");
  }

  void checkAssignByWrapperArgs(SILType ty, SILFunctionConventions &conv) {
    unsigned argIdx = conv.getSILArgIndexOfFirstParam();
    checkAssignByWrapperArgsRecursively(ty, conv, argIdx);
    require(argIdx == conv.getNumSILArguments(),
            "initializer or setter has too many arguments");
  }

  void checkAssignByWrapperInst(AssignByWrapperInst *AI) {
    SILValue Src = AI->getSrc(), Dest = AI->getDest();
    require(AI->getModule().getStage() == SILStage::Raw,
            "assign instruction can only exist in raw SIL");
    require(Dest->getType().isAddress(), "Must store to an address dest");

    SILValue initFn = AI->getInitializer();
    CanSILFunctionType initTy = initFn->getType().castTo<SILFunctionType>();
    SILFunctionConventions initConv(initTy, AI->getModule());
    checkAssignByWrapperArgs(Src->getType(), initConv);
    switch (initConv.getNumIndirectSILResults()) {
      case 0:
        require(initConv.getNumDirectSILResults() == 1,
                "wrong number of init function results");
        requireSameType(
            Dest->getType().getObjectType(),
            *initConv.getDirectSILResultTypes(F.getTypeExpansionContext())
                 .begin(),
            "wrong init function result type");
        break;
      case 1:
        require(initConv.getNumDirectSILResults() == 0,
                "wrong number of init function results");
        requireSameType(
            Dest->getType(),
            *initConv.getIndirectSILResultTypes(F.getTypeExpansionContext())
                 .begin(),
            "wrong indirect init function result type");
        break;
      default:
        require(false, "wrong number of indirect init function results");
    }

    SILValue setterFn = AI->getSetter();
    CanSILFunctionType setterTy = setterFn->getType().castTo<SILFunctionType>();
    SILFunctionConventions setterConv(setterTy, AI->getModule());
    require(setterConv.getNumIndirectSILResults() == 0,
            "set function has indirect results");
    checkAssignByWrapperArgs(Src->getType(), setterConv);
  }

#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...)                    \
  void checkLoad##Name##Inst(Load##Name##Inst *LWI) {                          \
    require(LWI->getType().isObject(), "Result of load must be an object");    \
    auto isOptional = bool(LWI->getType().getOptionalObjectType());            \
    auto optionality = optionalityOf(ReferenceOwnership::Name);                \
    if (optionality == ReferenceOwnershipOptionality::Required)                \
      require(isOptional, "Optionality mismatch");                             \
    if (optionality == ReferenceOwnershipOptionality::Disallowed)              \
      require(!isOptional, "Optionality mismatch");                            \
    auto PointerType = LWI->getOperand()->getType();                           \
    auto PointerRVType = PointerType.getASTType();                             \
    require(PointerType.isAddress() && PointerRVType->is<Name##StorageType>(), \
            "load_" #name " operand must be a " #name " address");             \
    requireSameType(                                                           \
        PointerRVType->getReferenceStorageReferent()->getCanonicalType(),      \
        LWI->getType().getASTType(),                                           \
        "Load operand type and result type mismatch");                         \
  }                                                                            \
  void checkStore##Name##Inst(Store##Name##Inst *SWI) {                        \
    auto SrcTy = SWI->getSrc()->getType();                                     \
    require(SrcTy.isObject(), "Can't store from an address source");           \
    auto isOptional = bool(SrcTy.getOptionalObjectType());                     \
    auto optionality = optionalityOf(ReferenceOwnership::Name);                \
    if (optionality == ReferenceOwnershipOptionality::Required)                \
      require(isOptional, "Optionality mismatch");                             \
    if (optionality == ReferenceOwnershipOptionality::Disallowed)              \
      require(!isOptional, "Optionality mismatch");                            \
    auto PointerType = SWI->getDest()->getType();                              \
    auto PointerRVType = PointerType.getASTType();                             \
    require(PointerType.isAddress() && PointerRVType->is<Name##StorageType>(), \
            "store_" #name " address operand must be a " #name " address");    \
    requireSameType(                                                           \
        PointerRVType->getReferenceStorageReferent()->getCanonicalType(),      \
        SrcTy.getASTType(), "Store operand type and dest type mismatch");      \
  }
#define LOADABLE_REF_STORAGE_HELPER(Name, name)                                \
  void checkRefTo##Name##Inst(RefTo##Name##Inst *I) {                          \
    requireReferenceStorageCapableValue(I->getOperand(),                       \
                                        "Operand of ref_to_" #name);           \
    auto operandType = I->getOperand()->getType().getASTType();                \
    auto resultType =                                                          \
        requireObjectType(Name##StorageType, I, "Result of ref_to_" #name);    \
    requireSameType(resultType.getReferentType(), operandType,                 \
                    "Result of ref_to_" #name " does not have the "            \
                    "operand's type as its referent type");                    \
  }                                                                            \
  void check##Name##ToRefInst(Name##ToRefInst *I) {                            \
    auto operandType = requireObjectType(Name##StorageType, I->getOperand(),   \
                                         "Operand of " #name "_to_ref");       \
    requireReferenceStorageCapableValue(I, "Result of " #name "_to_ref");      \
    auto resultType = I->getType().getASTType();                               \
    requireSameType(operandType.getReferentType(), resultType,                 \
                    "Operand of " #name "_to_ref does not have the "           \
                    "operand's type as its referent type");                    \
  }
#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE_HELPER(Name, name, closure)        \
  void checkStrongRetain##Name##Inst(StrongRetain##Name##Inst *RI) {           \
    auto ty = requireObjectType(Name##StorageType, RI->getOperand(),           \
                                "Operand of strong_retain_" #name);            \
    closure();                                                                 \
    (void)ty;                                                                  \
    require(!F.hasOwnership(), "strong_retain_" #name " is only in "           \
                               "functions with unqualified "                   \
                               "ownership");                                   \
  }                                                                            \
  void check##Name##RetainInst(Name##RetainInst *RI) {                         \
    auto ty = requireObjectType(Name##StorageType, RI->getOperand(),           \
                                "Operand of " #name "_retain");                \
    closure();                                                                 \
    (void)ty;                                                                  \
    require(!F.hasOwnership(),                                                 \
            #name "_retain is only in functions with unqualified ownership");  \
  }                                                                            \
  void check##Name##ReleaseInst(Name##ReleaseInst *RI) {                       \
    auto ty = requireObjectType(Name##StorageType, RI->getOperand(),           \
                                "Operand of " #name "_release");               \
    closure();                                                                 \
    (void)ty;                                                                  \
    require(!F.hasOwnership(),                                                 \
            #name "_release is only in functions with unqualified ownership"); \
  }                                                                            \
  void StrongcheckCopy##Name##ValueInst(StrongCopy##Name##ValueInst *I) {      \
    auto ty = requireObjectType(Name##StorageType, I->getOperand(),            \
                                "Operand of " #name "_retain");                \
    closure();                                                                 \
    (void)ty;                                                                  \
    /* *NOTE* We allow copy_##name##_value to be used throughout the entire */ \
    /* pipeline even though it is a higher level instruction. */               \
  }

#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \
  LOADABLE_REF_STORAGE_HELPER(Name, name) \
  ALWAYS_LOADABLE_CHECKED_REF_STORAGE_HELPER(Name, name, []{})
#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \
  LOADABLE_REF_STORAGE_HELPER(Name, name) \
  NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, "...") \
  ALWAYS_LOADABLE_CHECKED_REF_STORAGE_HELPER(Name, name, [&]{ \
    require(ty->isLoadable(ResilienceExpansion::Maximal), \
            "'" #name "' type must be loadable"); \
  })
#define UNCHECKED_REF_STORAGE(Name, name, ...)                                 \
  LOADABLE_REF_STORAGE_HELPER(Name, name)                                      \
  void checkStrongCopy##Name##ValueInst(StrongCopy##Name##ValueInst *I) {      \
    auto ty = requireObjectType(Name##StorageType, I->getOperand(),            \
                                "Operand of " #name "_retain");                \
    (void)ty;                                                                  \
    /* *NOTE* We allow copy_##name##_value to be used throughout the entire */ \
    /* pipeline even though it is a higher level instruction. */               \
  }

#include "swift/AST/ReferenceStorage.def"
#undef LOADABLE_REF_STORAGE_HELPER
#undef ALWAYS_LOADABLE_CHECKED_REF_STORAGE_HELPER

  void checkMarkUninitializedInst(MarkUninitializedInst *MU) {
    SILValue Src = MU->getOperand();
    require(MU->getModule().getStage() == SILStage::Raw,
            "mark_uninitialized instruction can only exist in raw SIL");
    require(Src->getType().isAddress() ||
            Src->getType().getClassOrBoundGenericClass() ||
            Src->getType().getAs<SILBoxType>(),
            "mark_uninitialized must be an address, class, or box type");
    requireSameType(Src->getType(), MU->getType(),
                    "operand and result type mismatch");
    // FIXME: When the work to force MUI to be on Allocations/SILArguments
    // complete, turn on this assertion.
    require(isa<AllocationInst>(Src)
            || isa<GlobalAddrInst>(Src)
            // TODO: Should we support SILUndef on mark_uninitialized? We
            // currently have a test that verifies this behavior, but it seems
            // like this would always be a bug due to the implications around
            // the code in DI. This just bakes in the current behavior.
            || isa<SILUndef>(Src)
            // We allow SILArguments to support the case of initializing
            // initializers. In such a case, the underlying case is allocated
            // outside by the allocating initializer and we pass in the to be
            // initialized value as a SILArgument.
            || isa<SILArgument>(Src)
            // FIXME: We only support pointer to address here to not break LLDB. It is
            // important that long term we get rid of this since this is a situation
            // where LLDB is breaking SILGen/DI invariants by not creating a new
            // independent stack location for the pointer to address.
            || isa<PointerToAddressInst>(Src),
            "Mark Uninitialized must be applied to a storage location");
  }

  void checkMarkFunctionEscapeInst(MarkFunctionEscapeInst *MFE) {
    require(MFE->getModule().getStage() == SILStage::Raw,
            "mark_function_escape instruction can only exist in raw SIL");
    for (auto Elt : MFE->getElements())
      require(Elt->getType().isAddress(), "MFE must refer to variable addrs");
  }

  void checkCopyAddrInst(CopyAddrInst *SI) {
    require(SI->getSrc()->getType().isAddress(),
            "Src value should be lvalue");
    require(SI->getDest()->getType().isAddress(),
            "Dest address should be lvalue");
    requireSameType(SI->getDest()->getType(), SI->getSrc()->getType(),
                    "Store operand type and dest type mismatch");
    require(F.isTypeABIAccessible(SI->getDest()->getType()),
            "cannot directly copy type with inaccessible ABI");
  }

  void checkRetainValueInst(RetainValueInst *I) {
    require(I->getOperand()->getType().isObject(),
            "Source value should be an object value");
    require(!F.hasOwnership(),
            "retain_value is only in functions with unqualified ownership");
  }

  void checkRetainValueAddrInst(RetainValueAddrInst *I) {
    require(I->getOperand()->getType().isAddress(),
            "Source value should be an address value");
    require(!F.hasOwnership(),
            "retain_value is only in functions with unqualified ownership");
  }

  void checkCopyValueInst(CopyValueInst *I) {
    require(I->getOperand()->getType().isObject(),
            "Source value should be an object value");
    require(!I->getOperand()->getType().isTrivial(*I->getFunction()),
            "Source value should be non-trivial");
    require(!fnConv.useLoweredAddresses() || F.hasOwnership(),
            "copy_value is only valid in functions with qualified "
            "ownership");
  }

  void checkDestroyValueInst(DestroyValueInst *I) {
    require(I->getOperand()->getType().isObject(),
            "Source value should be an object value");
    require(!I->getOperand()->getType().isTrivial(*I->getFunction()),
            "Source value should be non-trivial");
    require(!fnConv.useLoweredAddresses() || F.hasOwnership(),
            "destroy_value is only valid in functions with qualified "
            "ownership");
  }

  void checkReleaseValueInst(ReleaseValueInst *I) {
    require(I->getOperand()->getType().isObject(),
            "Source value should be an object value");
    require(!F.hasOwnership(),
            "release_value is only in functions with unqualified ownership");
  }

  void checkReleaseValueAddrInst(ReleaseValueAddrInst *I) {
    require(I->getOperand()->getType().isAddress(),
            "Source value should be an address value");
    require(!F.hasOwnership(),
            "release_value is only in functions with unqualified ownership");
  }

  void checkAutoreleaseValueInst(AutoreleaseValueInst *I) {
    require(I->getOperand()->getType().isObject(),
            "Source value should be an object value");
    // TODO: This instruction could in principle be generalized.
    require(I->getOperand()->getType().hasRetainablePointerRepresentation(),
            "Source value must be a reference type or optional thereof");
  }
  
  void checkSetDeallocatingInst(SetDeallocatingInst *I) {
    require(I->getOperand()->getType().isObject(),
            "Source value should be an object value");
    require(I->getOperand()->getType().hasRetainablePointerRepresentation(),
            "Source value must be a reference type");
  }
  
  void checkCopyBlockInst(CopyBlockInst *I) {
    require(I->getOperand()->getType().isBlockPointerCompatible(),
            "operand of copy_block should be a block");
    requireSameType(I->getOperand()->getType(), I->getType(),
                    "result of copy_block should be same type as operand");
  }
  void checkCopyBlockInst(CopyBlockWithoutEscapingInst *I) {
    require(I->getBlock()->getType().isBlockPointerCompatible(),
            "operand of copy_block should be a block");
    requireSameType(I->getBlock()->getType(), I->getType(),
                    "result of copy_block should be same type as operand");
    auto FnTy = requireObjectType(SILFunctionType, I->getClosure(),
                                  "copy_block_without_escaping operand");
    require(!FnTy->isNoEscape(),
            "closure parameter must not be a @noescape closure");
  }

  void checkAllocValueBufferInst(AllocValueBufferInst *I) {
    require(I->getOperand()->getType().isAddress(),
            "Operand value should be an address");
    require(I->getOperand()->getType().is<BuiltinUnsafeValueBufferType>(),
            "Operand value should be a Builtin.UnsafeValueBuffer");
    verifyOpenedArchetype(I, I->getValueType().getASTType());
  }

  void checkProjectValueBufferInst(ProjectValueBufferInst *I) {
    require(I->getOperand()->getType().isAddress(),
            "Operand value should be an address");
    require(I->getOperand()->getType().is<BuiltinUnsafeValueBufferType>(),
            "Operand value should be a Builtin.UnsafeValueBuffer");
  }

  void checkProjectBoxInst(ProjectBoxInst *I) {
    require(I->getOperand()->getType().isObject(),
            "project_box operand should be a value");
    auto boxTy = I->getOperand()->getType().getAs<SILBoxType>();
    require(boxTy, "project_box operand should be a @box type");
    requireSameType(I->getType(),
                    getSILBoxFieldType(F.getTypeExpansionContext(), boxTy,
                                       F.getModule().Types, I->getFieldIndex()),
                    "project_box result should be address of boxed type");

    // If we have a mark_uninitialized as a user, the mark_uninitialized must be
    // our only user. This is a requirement that is asserted by allocbox to
    // stack. This check just embeds the requirement into the IR.
    require(I->hasOneUse() ||
            none_of(I->getUses(),
                    [](Operand *Op) -> bool {
                      return isa<MarkUninitializedInst>(Op->getUser());
                    }),
            "project_box with more than one user when a user is a "
            "mark_uninitialized");
  }

  void checkProjectExistentialBoxInst(ProjectExistentialBoxInst *PEBI) {
    SILType operandType = PEBI->getOperand()->getType();
    require(operandType.isObject(),
            "project_existential_box operand must not be address");

    require(operandType.canUseExistentialRepresentation(
                                              ExistentialRepresentation::Boxed),
            "project_existential_box operand must be boxed existential");

    require(PEBI->getType().isAddress(),
            "project_existential_box result must be an address");

    if (auto *AEBI = dyn_cast<AllocExistentialBoxInst>(PEBI->getOperand())) {
      // The lowered type must be the properly-abstracted form of the AST type.
      SILType exType = AEBI->getExistentialType();
      auto archetype = OpenedArchetypeType::get(exType.getASTType());

      auto loweredTy = F.getLoweredType(Lowering::AbstractionPattern(archetype),
                                        AEBI->getFormalConcreteType())
                                          .getAddressType();

      requireSameType(loweredTy, PEBI->getType(),
              "project_existential_box result should be the lowered "
              "concrete type of its alloc_existential_box");
    }
  }
  
  void checkDeallocValueBufferInst(DeallocValueBufferInst *I) {
    require(I->getOperand()->getType().isAddress(),
            "Operand value should be an address");
    require(I->getOperand()->getType().is<BuiltinUnsafeValueBufferType>(),
            "Operand value should be a Builtin.UnsafeValueBuffer");
  }
  
  void checkStructInst(StructInst *SI) {
    auto *structDecl = SI->getType().getStructOrBoundGenericStruct();
    require(structDecl, "StructInst must return a struct");
    require(!structDecl->hasUnreferenceableStorage(),
            "Cannot build a struct with unreferenceable storage from elements "
            "using StructInst");
    require(!structDecl->isResilient(F.getModule().getSwiftModule(),
                                     F.getResilienceExpansion()),
            "cannot access storage of resilient struct");
    require(SI->getType().isObject(),
            "StructInst must produce an object");

    SILType structTy = SI->getType();
    auto opi = SI->getElements().begin(), opEnd = SI->getElements().end();
    for (VarDecl *field : structDecl->getStoredProperties()) {
      require(opi != opEnd,
              "number of struct operands does not match number of stored "
              "member variables of struct");

      SILType loweredType =
          structTy.getFieldType(field, F.getModule(), F.getTypeExpansionContext());
      if (SI->getModule().getStage() != SILStage::Lowered) {
        requireSameType((*opi)->getType(), loweredType,
                        "struct operand type does not match field type");
      }
      ++opi;
    }
  }

  void checkEnumInst(EnumInst *UI) {
    EnumDecl *ud = UI->getType().getEnumOrBoundGenericEnum();
    require(ud, "EnumInst must return an enum");
    require(UI->getElement()->getParentEnum() == ud,
            "EnumInst case must be a case of the result enum type");
    require(UI->getType().isObject(),
            "EnumInst must produce an object");
    require(UI->hasOperand() == UI->getElement()->hasAssociatedValues(),
            "EnumInst must take an argument iff the element does");

    if (UI->getElement()->hasAssociatedValues()) {
      require(UI->getOperand()->getType().isObject(),
              "EnumInst operand must be an object");
      SILType caseTy = UI->getType().getEnumElementType(
          UI->getElement(), F.getModule(), F.getTypeExpansionContext());
      if (UI->getModule().getStage() != SILStage::Lowered) {
        requireSameType(caseTy, UI->getOperand()->getType(),
                        "EnumInst operand type does not match type of case");
      }
    }
  }

  void checkInitEnumDataAddrInst(InitEnumDataAddrInst *UI) {
    EnumDecl *ud = UI->getOperand()->getType().getEnumOrBoundGenericEnum();
    require(ud, "InitEnumDataAddrInst must take an enum operand");
    require(UI->getElement()->getParentEnum() == ud,
            "InitEnumDataAddrInst case must be a case of the enum operand type");
    require(UI->getElement()->hasAssociatedValues(),
            "InitEnumDataAddrInst case must have a data type");
    require(UI->getOperand()->getType().isAddress(),
            "InitEnumDataAddrInst must take an address operand");
    require(UI->getType().isAddress(),
            "InitEnumDataAddrInst must produce an address");

    SILType caseTy = UI->getOperand()->getType().getEnumElementType(
        UI->getElement(), F.getModule(), F.getTypeExpansionContext());

    if (UI->getModule().getStage() != SILStage::Lowered) {
      requireSameType(
          caseTy, UI->getType(),
          "InitEnumDataAddrInst result does not match type of enum case");
    }
  }

  void checkUncheckedEnumDataInst(UncheckedEnumDataInst *UI) {
    EnumDecl *ud = UI->getOperand()->getType().getEnumOrBoundGenericEnum();
    require(ud, "UncheckedEnumData must take an enum operand");
    require(UI->getElement()->getParentEnum() == ud,
            "UncheckedEnumData case must be a case of the enum operand type");
    require(UI->getElement()->getArgumentInterfaceType(),
            "UncheckedEnumData case must have a data type");
    require(UI->getOperand()->getType().isObject(),
            "UncheckedEnumData must take an address operand");
    require(UI->getType().isObject(),
            "UncheckedEnumData must produce an address");

    SILType caseTy = UI->getOperand()->getType().getEnumElementType(
        UI->getElement(), F.getModule(), F.getTypeExpansionContext());

    if (UI->getModule().getStage() != SILStage::Lowered) {
      requireSameType(
          caseTy, UI->getType(),
          "UncheckedEnumData result does not match type of enum case");
    }
  }

  void checkUncheckedTakeEnumDataAddrInst(UncheckedTakeEnumDataAddrInst *UI) {
    EnumDecl *ud = UI->getOperand()->getType().getEnumOrBoundGenericEnum();
    require(ud, "UncheckedTakeEnumDataAddrInst must take an enum operand");
    require(UI->getElement()->getParentEnum() == ud,
            "UncheckedTakeEnumDataAddrInst case must be a case of the enum operand type");
    require(UI->getElement()->getArgumentInterfaceType(),
            "UncheckedTakeEnumDataAddrInst case must have a data type");
    require(UI->getOperand()->getType().isAddress(),
            "UncheckedTakeEnumDataAddrInst must take an address operand");
    require(UI->getType().isAddress(),
            "UncheckedTakeEnumDataAddrInst must produce an address");

    SILType caseTy = UI->getOperand()->getType().getEnumElementType(
        UI->getElement(), F.getModule(), F.getTypeExpansionContext());

    if (UI->getModule().getStage() != SILStage::Lowered) {
      requireSameType(caseTy, UI->getType(),
                      "UncheckedTakeEnumDataAddrInst result "
                      "does not match type of enum case");
    }
  }

  void checkInjectEnumAddrInst(InjectEnumAddrInst *IUAI) {
    require(IUAI->getOperand()->getType().is<EnumType>()
              || IUAI->getOperand()->getType().is<BoundGenericEnumType>(),
            "InjectEnumAddrInst must take an enum operand");
    require(IUAI->getElement()->getParentEnum()
              == IUAI->getOperand()->getType().getEnumOrBoundGenericEnum(),
            "InjectEnumAddrInst case must be a case of the enum operand type");
    require(IUAI->getOperand()->getType().isAddress(),
            "InjectEnumAddrInst must take an address operand");
  }

  void checkTupleInst(TupleInst *TI) {
    CanTupleType ResTy = requireObjectType(TupleType, TI, "Result of tuple");

    require(TI->getElements().size() == ResTy->getNumElements(),
            "Tuple field count mismatch!");

    if (TI->getModule().getStage() != SILStage::Lowered) {
      for (size_t i = 0, size = TI->getElements().size(); i < size; ++i) {
        requireSameType(TI->getElement(i)->getType().getASTType(),
                        ResTy.getElementType(i),
                        "Tuple element arguments do not match tuple type!");
      }
    }
  }

  // Is a SIL type a potential lowering of a formal type?
  bool isLoweringOf(SILType loweredType, CanType formalType) {
    return loweredType.isLoweringOf(F.getTypeExpansionContext(), F.getModule(),
                                    formalType);
  }
  
  void checkMetatypeInst(MetatypeInst *MI) {
    require(MI->getType().is<MetatypeType>(),
            "metatype instruction must be of metatype type");
    auto MetaTy = MI->getType().castTo<MetatypeType>();
    require(MetaTy->hasRepresentation(),
            "metatype instruction must have a metatype representation");
    verifyOpenedArchetype(MI, MetaTy.getInstanceType());
  }
  void checkValueMetatypeInst(ValueMetatypeInst *MI) {
    require(MI->getType().is<MetatypeType>(),
            "value_metatype instruction must be of metatype type");
    require(MI->getType().castTo<MetatypeType>()->hasRepresentation(),
            "value_metatype instruction must have a metatype representation");
    auto formalInstanceTy
      = MI->getType().castTo<MetatypeType>().getInstanceType();
    require(isLoweringOf(MI->getOperand()->getType(), formalInstanceTy),
            "value_metatype result must be formal metatype of "
            "lowered operand type");
  }
  void checkExistentialMetatypeInst(ExistentialMetatypeInst *MI) {
    require(MI->getType().is<ExistentialMetatypeType>(),
            "existential_metatype instruction must be of metatype type");
    require(MI->getType().castTo<ExistentialMetatypeType>()->hasRepresentation(),
            "value_metatype instruction must have a metatype representation");
    require(MI->getOperand()->getType().isAnyExistentialType(),
            "existential_metatype operand must be of protocol type");
    auto formalInstanceTy
      = MI->getType().castTo<ExistentialMetatypeType>().getInstanceType();
    require(isLoweringOf(MI->getOperand()->getType(), formalInstanceTy),
            "existential_metatype result must be formal metatype of "
            "lowered operand type");
  }

  void checkStrongRetainInst(StrongRetainInst *RI) {
    requireReferenceValue(RI->getOperand(), "Operand of strong_retain");
    require(!F.hasOwnership(),
            "strong_retain is only in functions with unqualified ownership");
  }
  void checkStrongReleaseInst(StrongReleaseInst *RI) {
    requireReferenceValue(RI->getOperand(), "Operand of release");
    require(!F.hasOwnership(),
            "strong_release is only in functions with unqualified ownership");
  }

  void checkDeallocStackInst(DeallocStackInst *DI) {
    require(isa<SILUndef>(DI->getOperand()) ||
                isa<AllocStackInst>(DI->getOperand()) ||
                (isa<PartialApplyInst>(DI->getOperand()) &&
                 cast<PartialApplyInst>(DI->getOperand())->isOnStack()),
            "Operand of dealloc_stack must be an alloc_stack or partial_apply "
            "[stack]");
  }
  void checkDeallocRefInst(DeallocRefInst *DI) {
    require(DI->getOperand()->getType().isObject(),
            "Operand of dealloc_ref must be object");
    auto *cd = DI->getOperand()->getType().getClassOrBoundGenericClass();
    require(cd, "Operand of dealloc_ref must be of class type");

    if (!DI->canAllocOnStack()) {
      require(!cd->isResilient(F.getModule().getSwiftModule(),
                              F.getResilienceExpansion()),
              "cannot directly deallocate resilient class");
    }
  }
  void checkDeallocPartialRefInst(DeallocPartialRefInst *DPRI) {
    require(DPRI->getInstance()->getType().isObject(),
            "First operand of dealloc_partial_ref must be object");
    auto class1 = DPRI->getInstance()->getType().getClassOrBoundGenericClass();
    require(class1,
            "First operand of dealloc_partial_ref must be of class type");
    require(DPRI->getMetatype()->getType().is<MetatypeType>(),
            "Second operand of dealloc_partial_ref must be a metatype");
    auto class2 = DPRI->getMetatype()->getType().castTo<MetatypeType>()
        ->getInstanceType()->getClassOrBoundGenericClass();
    require(class2,
            "Second operand of dealloc_partial_ref must be a class metatype");
    require(class2->isSuperclassOf(class1),
            "First operand not superclass of second instance type");
  }

  void checkAllocBoxInst(AllocBoxInst *AI) {
    auto boxTy = AI->getType().getAs<SILBoxType>();
    require(boxTy, "alloc_box must have a @box type");

    require(AI->getType().isObject(),
            "result of alloc_box must be an object");
    for (unsigned field : indices(AI->getBoxType()->getLayout()->getFields())) {
      verifyOpenedArchetype(AI, getSILBoxFieldLoweredType(
                                    F.getTypeExpansionContext(), AI->getBoxType(),
                                    F.getModule().Types, field));
    }

    // An alloc_box with a mark_uninitialized user can not have any other users.
    require(none_of(AI->getUses(),
                    [](Operand *Op) -> bool {
                      return isa<MarkUninitializedInst>(Op->getUser());
                    }) ||
                AI->hasOneUse(),
            "An alloc_box with a mark_uninitialized user can not have any "
            "other users.");
  }

  void checkDeallocBoxInst(DeallocBoxInst *DI) {
    auto boxTy = DI->getOperand()->getType().getAs<SILBoxType>();
    require(boxTy, "operand must be a @box type");
    require(DI->getOperand()->getType().isObject(),
            "operand must be an object");
  }

  void checkDestroyAddrInst(DestroyAddrInst *DI) {
    require(DI->getOperand()->getType().isAddress(),
            "Operand of destroy_addr must be address");
    require(F.isTypeABIAccessible(DI->getOperand()->getType()),
            "cannot directly destroy type with inaccessible ABI");
  }

  void checkBindMemoryInst(BindMemoryInst *BI) {
    require(BI->getBoundType(), "BI must have a bound type");
    require(BI->getBase()->getType().is<BuiltinRawPointerType>(),
            "bind_memory base be a RawPointer");
    requireSameType(BI->getIndex()->getType(),
                    SILType::getBuiltinWordType(F.getASTContext()),
                    "bind_memory index must be a Word");
  }

  void checkIndexAddrInst(IndexAddrInst *IAI) {
    require(IAI->getType().isAddress(), "index_addr must produce an address");
    requireSameType(
        IAI->getType(), IAI->getBase()->getType(),
        "index_addr must produce an address of the same type as its base");
    require(IAI->getIndex()->getType().is<BuiltinIntegerType>(),
            "index_addr index must be of a builtin integer type");
  }

  void checkTailAddrInst(TailAddrInst *IAI) {
    require(IAI->getType().isAddress(), "tail_addr must produce an address");
    require(IAI->getIndex()->getType().is<BuiltinIntegerType>(),
            "tail_addr index must be of a builtin integer type");
  }

  void checkIndexRawPointerInst(IndexRawPointerInst *IAI) {
    require(IAI->getType().is<BuiltinRawPointerType>(),
            "index_raw_pointer must produce a RawPointer");
    require(IAI->getBase()->getType().is<BuiltinRawPointerType>(),
            "index_raw_pointer base must be a RawPointer");
    require(IAI->getIndex()->getType().is<BuiltinIntegerType>(),
            "index_raw_pointer index must be of a builtin integer type");
  }

  void checkTupleExtractInst(TupleExtractInst *EI) {
    CanTupleType operandTy = requireObjectType(TupleType, EI->getOperand(),
                                               "Operand of tuple_extract");
    require(EI->getType().isObject(),
            "result of tuple_extract must be object");

    require(EI->getFieldIndex() < operandTy->getNumElements(),
            "invalid field index for tuple_extract instruction");
    if (EI->getModule().getStage() != SILStage::Lowered) {
      requireSameType(EI->getType().getASTType(),
                      operandTy.getElementType(EI->getFieldIndex()),
                      "type of tuple_extract does not match type of element");
    }
  }

  void checkStructExtractInst(StructExtractInst *EI) {
    SILType operandTy = EI->getOperand()->getType();
    require(operandTy.isObject(),
            "cannot struct_extract from address");
    require(EI->getType().isObject(),
            "result of struct_extract cannot be address");
    StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
    require(sd, "must struct_extract from struct");
    require(!sd->isResilient(F.getModule().getSwiftModule(),
                             F.getResilienceExpansion()),
            "cannot access storage of resilient struct");
    require(!EI->getField()->isStatic(),
            "cannot get address of static property with struct_element_addr");
    require(EI->getField()->hasStorage(),
            "cannot load computed property with struct_extract");

    require(EI->getField()->getDeclContext() == sd,
            "struct_extract field is not a member of the struct");

    if (EI->getModule().getStage() != SILStage::Lowered) {
      SILType loweredFieldTy = operandTy.getFieldType(
          EI->getField(), F.getModule(), F.getTypeExpansionContext());
      requireSameType(loweredFieldTy, EI->getType(),
                      "result of struct_extract does not match type of field");
    }
  }

  void checkTupleElementAddrInst(TupleElementAddrInst *EI) {
    SILType operandTy = EI->getOperand()->getType();
    require(operandTy.isAddress(),
            "must derive element_addr from address");
    require(EI->getType().isAddress(),
            "result of tuple_element_addr must be address");
    require(operandTy.is<TupleType>(),
            "must derive tuple_element_addr from tuple");

    ArrayRef<TupleTypeElt> fields = operandTy.castTo<TupleType>()->getElements();
    require(EI->getFieldIndex() < fields.size(),
            "invalid field index for element_addr instruction");
    if (EI->getModule().getStage() != SILStage::Lowered) {
      requireSameType(
          EI->getType().getASTType(),
          CanType(fields[EI->getFieldIndex()].getType()),
          "type of tuple_element_addr does not match type of element");
    }
  }

  void checkStructElementAddrInst(StructElementAddrInst *EI) {
    SILType operandTy = EI->getOperand()->getType();
    require(operandTy.isAddress(),
            "must derive struct_element_addr from address");
    StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
    require(sd, "struct_element_addr operand must be struct address");
    require(!sd->isResilient(F.getModule().getSwiftModule(),
                             F.getResilienceExpansion()),
            "cannot access storage of resilient struct");
    require(EI->getType().isAddress(),
            "result of struct_element_addr must be address");
    require(!EI->getField()->isStatic(),
            "cannot get address of static property with struct_element_addr");
    require(EI->getField()->hasStorage(),
            "cannot get address of computed property with struct_element_addr");

    require(EI->getField()->getDeclContext() == sd,
            "struct_element_addr field is not a member of the struct");

    if (EI->getModule().getStage() != SILStage::Lowered) {
      SILType loweredFieldTy = operandTy.getFieldType(
          EI->getField(), F.getModule(), F.getTypeExpansionContext());
      requireSameType(
          loweredFieldTy, EI->getType(),
          "result of struct_element_addr does not match type of field");
    }
  }

  void checkRefElementAddrInst(RefElementAddrInst *EI) {
    requireReferenceValue(EI->getOperand(), "Operand of ref_element_addr");
    require(EI->getType().isAddress(),
            "result of ref_element_addr must be lvalue");
    require(!EI->getField()->isStatic(),
            "cannot get address of static property with struct_element_addr");
    require(EI->getField()->hasStorage(),
            "cannot get address of computed property with ref_element_addr");
    SILType operandTy = EI->getOperand()->getType();
    ClassDecl *cd = operandTy.getClassOrBoundGenericClass();
    require(cd, "ref_element_addr operand must be a class instance");
    require(!cd->isResilient(F.getModule().getSwiftModule(),
                             F.getResilienceExpansion()),
            "cannot access storage of resilient class");

    require(EI->getField()->getDeclContext() == cd,
            "ref_element_addr field must be a member of the class");

    if (EI->getModule().getStage() != SILStage::Lowered) {
      SILType loweredFieldTy = operandTy.getFieldType(
          EI->getField(), F.getModule(), F.getTypeExpansionContext());
      requireSameType(
          loweredFieldTy, EI->getType(),
          "result of ref_element_addr does not match type of field");
    }
    EI->getFieldIndex();  // Make sure we can access the field without crashing.
  }

  void checkRefTailAddrInst(RefTailAddrInst *RTAI) {
    requireReferenceValue(RTAI->getOperand(), "Operand of ref_tail_addr");
    require(RTAI->getType().isAddress(),
            "result of ref_tail_addr must be lvalue");
    SILType operandTy = RTAI->getOperand()->getType();
    ClassDecl *cd = operandTy.getClassOrBoundGenericClass();
    require(cd, "ref_tail_addr operand must be a class instance");
    require(!cd->isResilient(F.getModule().getSwiftModule(),
                             F.getResilienceExpansion()),
            "cannot access storage of resilient class");
    require(cd, "ref_tail_addr operand must be a class instance");
  }

  void checkDestructureStructInst(DestructureStructInst *DSI) {
    SILType operandTy = DSI->getOperand()->getType();
    StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
    require(sd, "must struct_extract from struct");
    require(!sd->isResilient(F.getModule().getSwiftModule(),
                             F.getResilienceExpansion()),
            "cannot access storage of resilient struct");
    if (F.hasOwnership()) {
      // Make sure that all of our destructure results ownership kinds are
      // compatible with our destructure_struct's ownership kind /and/ that if
      // our destructure ownership kind is non-trivial then all non-trivial
      // results must have the same ownership kind as our operand.
      auto parentKind = DSI->getOwnershipKind();
      for (const DestructureStructResult &result : DSI->getAllResultsBuffer()) {
        require(parentKind.isCompatibleWith(result.getOwnershipKind()),
                "destructure result with ownership that is incompatible with "
                "parent forwarding ownership kind");
        require(parentKind != OwnershipKind::None ||
                    result.getOwnershipKind() == OwnershipKind::None,
                "destructure with none ownership kind operand and non-none "
                "ownership kind result?!");
      }
    }
  }

  void checkDestructureTupleInst(DestructureTupleInst *dti) {
    if (F.hasOwnership()) {
      // Make sure that all of our destructure results ownership kinds are
      // compatible with our destructure_struct's ownership kind /and/ that if
      // our destructure ownership kind is non-trivial then all non-trivial
      // results must have the same ownership kind as our operand.
      auto parentKind = dti->getOwnershipKind();
      for (const auto &result : dti->getAllResultsBuffer()) {
        require(parentKind.isCompatibleWith(result.getOwnershipKind()),
                "destructure result with ownership that is incompatible with "
                "parent forwarding ownership kind");
        require(parentKind != OwnershipKind::None ||
                    result.getOwnershipKind() == OwnershipKind::None,
                "destructure with none ownership kind operand and non-none "
                "ownership kind result?!");
      }
    }
  }

  SILType getMethodSelfType(CanSILFunctionType ft) {
    return fnConv.getSILType(ft->getParameters().back(),
                             F.getTypeExpansionContext());
  }

  void checkWitnessMethodInst(WitnessMethodInst *AMI) {
    auto methodType = requireObjectType(SILFunctionType, AMI,
                                        "result of witness_method");

    auto *protocol
      = dyn_cast<ProtocolDecl>(AMI->getMember().getDecl()->getDeclContext());
    require(protocol,
            "witness_method method must be a protocol method");

    require(methodType->getRepresentation()
              == F.getModule().Types.getProtocolWitnessRepresentation(protocol),
            "result of witness_method must have correct representation for protocol");

    require(methodType->isPolymorphic(),
            "result of witness_method must be polymorphic");

    auto genericSig = methodType->getInvocationGenericSignature();

    auto selfGenericParam = genericSig->getGenericParams()[0];
    require(selfGenericParam->getDepth() == 0
            && selfGenericParam->getIndex() == 0,
            "method should be polymorphic on Self parameter at depth 0 index 0");
    Optional<Requirement> selfRequirement;
    for (auto req : genericSig->getRequirements()) {
      if (req.getKind() != RequirementKind::SameType) {
        selfRequirement = req;
        break;
      }
    }

    require(selfRequirement &&
            selfRequirement->getKind() == RequirementKind::Conformance,
            "first non-same-typerequirement should be conformance requirement");
    const auto protos = genericSig->getRequiredProtocols(selfGenericParam);
    require(std::find(protos.begin(), protos.end(), protocol) != protos.end(),
            "requirement Self parameter must conform to called protocol");

    auto lookupType = AMI->getLookupType();
    if (getOpenedArchetypeOf(lookupType) || isa<DynamicSelfType>(lookupType)) {
      require(AMI->getTypeDependentOperands().size() == 1,
              "Must have a type dependent operand for the opened archetype");
      verifyOpenedArchetype(AMI, lookupType);
    } else {
      require(AMI->getTypeDependentOperands().empty(),
              "Should not have an operand for the opened existential");
    }
    if (!isa<ArchetypeType>(lookupType) && !isa<DynamicSelfType>(lookupType)) {
      require(AMI->getConformance().isConcrete(),
              "concrete type lookup requires concrete conformance");
      auto conformance = AMI->getConformance().getConcrete();
      requireSameType(
          conformance->getType(), AMI->getLookupType(),
          "concrete type lookup requires conformance that matches type");
    }

    require(AMI->getMember().requiresNewWitnessTableEntry(),
            "method does not have a witness table entry");
  }

  // Get the expected type of a dynamic method reference.
  SILType getDynamicMethodType(SILType selfType, SILDeclRef method) {
    auto &C = F.getASTContext();

    // The type of the dynamic method must match the usual type of the method,
    // but with the more opaque Self type.
    auto constantInfo =
        F.getModule().Types.getConstantInfo(F.getTypeExpansionContext(), method);
    auto methodTy = constantInfo.SILFnType;

    assert(!methodTy->isCoroutine());

    // Map interface types to archetypes.
    if (auto *env = F.getModule().Types.getConstantGenericEnvironment(method)) {
      auto subs = env->getForwardingSubstitutionMap();
      methodTy = methodTy->substGenericArgs(F.getModule(), subs,
                                            F.getTypeExpansionContext());
    }
    assert(!methodTy->isPolymorphic());

    // Replace Self parameter with type of 'self' at the call site.
    auto params = methodTy->getParameters();
    SmallVector<SILParameterInfo, 4>
      dynParams(params.begin(), params.end() - 1);
    dynParams.push_back(SILParameterInfo(selfType.getASTType(),
                                         params.back().getConvention()));

    auto results = methodTy->getResults();
    SmallVector<SILResultInfo, 4> dynResults(results.begin(), results.end());    

    // If the method returns Self, substitute AnyObject for the result type.
    if (auto fnDecl = dyn_cast<FuncDecl>(method.getDecl())) {
      if (fnDecl->hasDynamicSelfResult()) {
        auto anyObjectTy = C.getAnyObjectType();
        for (auto &dynResult : dynResults) {
          auto newResultTy =
              dynResult
                  .getReturnValueType(F.getModule(), methodTy,
                                      F.getTypeExpansionContext())
                  ->replaceCovariantResultType(anyObjectTy, 0);
          dynResult = SILResultInfo(newResultTy->getCanonicalType(),
                                    dynResult.getConvention());
        }
      }
    }

    auto fnTy = SILFunctionType::get(nullptr,
                                     methodTy->getExtInfo(),
                                     methodTy->getCoroutineKind(),
                                     methodTy->getCalleeConvention(),
                                     dynParams,
                                     methodTy->getYields(),
                                     dynResults,
                                     methodTy->getOptionalErrorResult(),
                                     SubstitutionMap(), SubstitutionMap(),
                                     F.getASTContext());
    return SILType::getPrimitiveObjectType(fnTy);
  }

  /// Visitor class that checks whether a given decl ref has an entry in the
  /// class's vtable.
  class VerifyClassMethodVisitor
      : public SILVTableVisitor<VerifyClassMethodVisitor>
  {
  public:
    SILDeclRef Method;
    bool Seen = false;

    VerifyClassMethodVisitor(SILDeclRef method)
      : Method(method.getOverriddenVTableEntry()) {
      auto *theClass = cast<ClassDecl>(Method.getDecl()->getDeclContext());
      addVTableEntries(theClass);
    }

    void addMethod(SILDeclRef method) {
      if (Seen)
        return;
      if (method == Method)
        Seen = true;
    }

    void addMethodOverride(SILDeclRef base, SILDeclRef derived) {}

    void addPlaceholder(MissingMemberDecl *) {}
  };

  void checkClassMethodInst(ClassMethodInst *CMI) {
    auto member = CMI->getMember();
    auto overrideTy =
        TC.getConstantOverrideType(F.getTypeExpansionContext(), member);
    if (CMI->getModule().getStage() != SILStage::Lowered) {
      requireSameType(
          CMI->getType(), SILType::getPrimitiveObjectType(overrideTy),
          "result type of class_method must match abstracted type of method");
    }
    auto methodType = requireObjectType(SILFunctionType, CMI,
                                        "result of class_method");
    require(!methodType->getExtInfo().hasContext(),
            "result method must be of a context-free function type");

    SILType operandType = CMI->getOperand()->getType();
    require(operandType.isClassOrClassMetatype(),
            "operand must be of a class type");
    require(getMethodSelfType(methodType).isClassOrClassMetatype(),
            "result must be a method of a class");
    
    require(!member.isForeign,
            "foreign method cannot be dispatched natively");
    require(!isa<ExtensionDecl>(member.getDecl()->getDeclContext()),
            "extension method cannot be dispatched natively");
    
    // The method ought to appear in the class vtable.
    require(VerifyClassMethodVisitor(member).Seen,
            "method does not appear in the class's vtable");
  }

  void checkSuperMethodInst(SuperMethodInst *CMI) {
    auto member = CMI->getMember();
    auto overrideTy =
        TC.getConstantOverrideType(F.getTypeExpansionContext(), member);
    if (CMI->getModule().getStage() != SILStage::Lowered) {
      requireSameType(
          CMI->getType(), SILType::getPrimitiveObjectType(overrideTy),
          "result type of super_method must match abstracted type of method");
    }
    auto methodType = requireObjectType(SILFunctionType, CMI,
                                        "result of super_method");
    require(!methodType->getExtInfo().hasContext(),
            "result method must be of a context-free function type");
    SILType operandType = CMI->getOperand()->getType();
    require(operandType.isClassOrClassMetatype(),
            "operand must be of a class type");
    require(getMethodSelfType(methodType).isClassOrClassMetatype(),
            "result must be a method of a class");

    require(!member.isForeign,
            "foreign method cannot be dispatched natively");
    require(!isa<ExtensionDecl>(member.getDecl()->getDeclContext()),
            "extension method cannot be dispatched natively");

    auto decl = CMI->getMember().getDecl();
    auto methodClass = decl->getDeclContext()->getDeclaredInterfaceType();

    require(methodClass->getClassOrBoundGenericClass(),
            "super_method must look up a class method");

    // The method ought to appear in the class vtable.
    require(VerifyClassMethodVisitor(member).Seen,
            "method does not appear in the class's vtable");    
  }

  void checkObjCMethodInst(ObjCMethodInst *OMI) {
    auto member = OMI->getMember();
    require(member.isForeign,
            "native method cannot be dispatched via objc");

    auto methodType = requireObjectType(SILFunctionType, OMI,
                                        "result of objc_method");
    require(!methodType->getExtInfo().hasContext(),
            "result method must be of a context-free function type");
    require(methodType->getRepresentation()
            == SILFunctionTypeRepresentation::ObjCMethod,
            "wrong function type representation");

    auto operandType = OMI->getOperand()->getType();
    auto operandInstanceType = operandType.getASTType();
    if (auto metatypeType = dyn_cast<MetatypeType>(operandInstanceType))
      operandInstanceType = metatypeType.getInstanceType();

    if (operandInstanceType.getClassOrBoundGenericClass()) {
      auto overrideTy =
          TC.getConstantOverrideType(F.getTypeExpansionContext(), member);
      requireSameType(
          OMI->getType(), SILType::getPrimitiveObjectType(overrideTy),
          "result type of objc_method must match abstracted type of method");
    } else {
      require(isa<ArchetypeType>(operandInstanceType) ||
              operandInstanceType->isObjCExistentialType(),
              "operand type must be an archetype or self-conforming existential");
      verifyOpenedArchetype(OMI, OMI->getType().getASTType());
    }

    // TODO: We should enforce that ObjC methods are dispatched on ObjC
    // metatypes, but IRGen appears not to care right now.
#if 0
    if (auto metaTy = operandType.getAs<AnyMetatypeType>()) {
      bool objcMetatype
        = metaTy->getRepresentation() == MetatypeRepresentation::ObjC;
      require(objcMetatype,
              "objc class methods must be invoked on objc metatypes");
    }
#endif
  }

  void checkObjCSuperMethodInst(ObjCSuperMethodInst *OMI) {
    auto member = OMI->getMember();
    auto overrideTy =
        TC.getConstantOverrideType(F.getTypeExpansionContext(), member);
    if (OMI->getModule().getStage() != SILStage::Lowered) {
      requireSameType(
          OMI->getType(), SILType::getPrimitiveObjectType(overrideTy),
          "result type of super_method must match abstracted type of method");
    }
    auto methodType = requireObjectType(SILFunctionType, OMI,
                                        "result of objc_super_method");
    require(!methodType->getExtInfo().hasContext(),
            "result method must be of a context-free function type");
    SILType operandType = OMI->getOperand()->getType();
    require(operandType.isClassOrClassMetatype(),
            "operand must be of a class type");
    require(getMethodSelfType(methodType).isClassOrClassMetatype(),
            "result must be a method of a class");

    require(member.isForeign,
            "native method cannot be dispatched via objc");

    auto decl = member.getDecl();
    auto methodClass = decl->getDeclContext()->getDeclaredInterfaceType();

    require(methodClass->getClassOrBoundGenericClass(),
            "objc_super_method must look up a class method");
  }

  void checkOpenExistentialAddrInst(OpenExistentialAddrInst *OEI) {
    SILType operandType = OEI->getOperand()->getType();
    require(operandType.isAddress(),
            "open_existential_addr must be applied to address");
    require(operandType.canUseExistentialRepresentation(
                                        ExistentialRepresentation::Opaque),
           "open_existential_addr must be applied to opaque existential");

    require(OEI->getType().isAddress(),
            "open_existential_addr result must be an address");

    auto archetype = getOpenedArchetypeOf(OEI->getType().getASTType());
    require(archetype,
        "open_existential_addr result must be an opened existential archetype");
    require(OpenedArchetypes.getOpenedArchetypeDef(archetype) == OEI,
            "Archetype opened by open_existential_addr should be registered in "
            "SILFunction");

    // Check all the uses. Consuming or mutating uses must have mutable access
    // to the opened value.
    auto allowedAccessKind = OEI->getAccessKind();
    if (allowedAccessKind == OpenedExistentialAccess::Mutable)
      return;

    require(allowedAccessKind == OpenedExistentialAccess::Mutable ||
                !ImmutableAddressUseVerifier().isMutatingOrConsuming(OEI),
            "open_existential_addr uses that consumes or mutates but is not "
            "opened for mutation");
  }

  void checkOpenExistentialRefInst(OpenExistentialRefInst *OEI) {
    SILType operandType = OEI->getOperand()->getType();
    require(operandType.isObject(),
            "open_existential_ref operand must not be address");

    require(operandType.canUseExistentialRepresentation(
                                              ExistentialRepresentation::Class),
            "open_existential_ref operand must be class existential");

    CanType resultInstanceTy = OEI->getType().getASTType();

    require(OEI->getType().isObject(),
            "open_existential_ref result must be an address");

    auto archetype = getOpenedArchetypeOf(resultInstanceTy);
    require(archetype,
        "open_existential_ref result must be an opened existential archetype");
    require(OpenedArchetypes.getOpenedArchetypeDef(archetype) == OEI,
            "Archetype opened by open_existential_ref should be registered in "
            "SILFunction");
  }

  void checkOpenExistentialBoxInst(OpenExistentialBoxInst *OEI) {
    SILType operandType = OEI->getOperand()->getType();
    require(operandType.isObject(),
            "open_existential_box operand must not be address");

    require(operandType.canUseExistentialRepresentation(
                                              ExistentialRepresentation::Boxed),
            "open_existential_box operand must be boxed existential");

    CanType resultInstanceTy = OEI->getType().getASTType();

    require(OEI->getType().isAddress(),
            "open_existential_box result must be an address");

    auto archetype = getOpenedArchetypeOf(resultInstanceTy);
    require(archetype,
        "open_existential_box result must be an opened existential archetype");
    require(OpenedArchetypes.getOpenedArchetypeDef(archetype) == OEI,
            "Archetype opened by open_existential_box should be registered in "
            "SILFunction");
  }

  void checkOpenExistentialBoxValueInst(OpenExistentialBoxValueInst *OEI) {
    SILType operandType = OEI->getOperand()->getType();
    require(operandType.isObject(),
            "open_existential_box operand must not be address");

    require(operandType.canUseExistentialRepresentation(
                                              ExistentialRepresentation::Boxed),
            "open_existential_box operand must be boxed existential");

    CanType resultInstanceTy = OEI->getType().getASTType();

    require(!OEI->getType().isAddress(),
            "open_existential_box_value result must not be an address");

    auto archetype = getOpenedArchetypeOf(resultInstanceTy);
    require(archetype,
        "open_existential_box_value result not an opened existential archetype");
    require(OpenedArchetypes.getOpenedArchetypeDef(archetype) == OEI,
            "Archetype opened by open_existential_box_value should be "
            "registered in SILFunction");
  }

  void checkOpenExistentialMetatypeInst(OpenExistentialMetatypeInst *I) {
    SILType operandType = I->getOperand()->getType();
    require(operandType.isObject(),
            "open_existential_metatype operand must not be address");
    require(operandType.is<ExistentialMetatypeType>(),
            "open_existential_metatype operand must be existential metatype");
    require(operandType.castTo<ExistentialMetatypeType>()->hasRepresentation(),
            "open_existential_metatype operand must have a representation");

    SILType resultType = I->getType();
    require(resultType.isObject(),
            "open_existential_metatype result must not be address");
    require(resultType.is<MetatypeType>(),
            "open_existential_metatype result must be metatype");
    require(resultType.castTo<MetatypeType>()->hasRepresentation(),
            "open_existential_metatype result must have a representation");
    require(operandType.castTo<ExistentialMetatypeType>()->getRepresentation()
              == resultType.castTo<MetatypeType>()->getRepresentation(),
            "open_existential_metatype result must match representation of "
            "operand");

    CanType operandInstTy =
      operandType.castTo<ExistentialMetatypeType>().getInstanceType();
    CanType resultInstTy = 
      resultType.castTo<MetatypeType>().getInstanceType();

    while (auto operandMetatype =
             dyn_cast<ExistentialMetatypeType>(operandInstTy)) {
      require(isa<MetatypeType>(resultInstTy),
              "metatype depth mismatch in open_existential_metatype result");
      operandInstTy = operandMetatype.getInstanceType();
      resultInstTy = cast<MetatypeType>(resultInstTy).getInstanceType();
    }

    require(operandInstTy.isExistentialType(),
            "ill-formed existential metatype in open_existential_metatype "
            "operand");
    auto archetype = getOpenedArchetypeOf(resultInstTy);
    require(archetype, "open_existential_metatype result must be an opened "
                       "existential metatype");
    require(
        OpenedArchetypes.getOpenedArchetypeDef(archetype) == I,
        "Archetype opened by open_existential_metatype should be registered in "
        "SILFunction");
  }

  void checkOpenExistentialValueInst(OpenExistentialValueInst *OEI) {
    SILType operandType = OEI->getOperand()->getType();
    require(!operandType.isAddress(),
            "open_existential_value must not be applied to address");
    require(operandType.canUseExistentialRepresentation(
                ExistentialRepresentation::Opaque),
            "open_existential_value must be applied to opaque existential");

    require(!OEI->getType().isAddress(),
            "open_existential_value result must not be an address");

    auto archetype = getOpenedArchetypeOf(OEI->getType().getASTType());
    require(archetype, "open_existential_value result must be an opened "
                       "existential archetype");
    require(OpenedArchetypes.getOpenedArchetypeDef(archetype) == OEI,
            "Archetype opened by open_existential should be registered in "
            "SILFunction");
  }

  void checkAllocExistentialBoxInst(AllocExistentialBoxInst *AEBI) {
    SILType exType = AEBI->getExistentialType();
    require(exType.isObject(),
            "alloc_existential_box #0 result should be a value");
    require(exType.canUseExistentialRepresentation(
                                             ExistentialRepresentation::Boxed,
                                             AEBI->getFormalConcreteType()),
            "alloc_existential_box must be used with a boxed existential "
            "type");
    
    checkExistentialProtocolConformances(exType.getASTType(),
                                         AEBI->getFormalConcreteType(),
                                         AEBI->getConformances());
    verifyOpenedArchetype(AEBI, AEBI->getFormalConcreteType());
  }

  void checkInitExistentialAddrInst(InitExistentialAddrInst *AEI) {
    SILType exType = AEI->getOperand()->getType();
    require(exType.isAddress(),
            "init_existential_addr must be applied to an address");
    require(exType.canUseExistentialRepresentation(
                                       ExistentialRepresentation::Opaque,
                                       AEI->getFormalConcreteType()),
            "init_existential_addr must be used with an opaque "
            "existential type");
    
    // The lowered type must be the properly-abstracted form of the AST type.
    auto archetype = OpenedArchetypeType::get(exType.getASTType());
    
    auto loweredTy = F.getLoweredType(Lowering::AbstractionPattern(archetype),
                                      AEI->getFormalConcreteType())
                      .getAddressType();
    
    requireSameType(loweredTy, AEI->getLoweredConcreteType(),
                    "init_existential_addr result type must be the lowered "
                    "concrete type at the right abstraction level");

    require(isLoweringOf(AEI->getLoweredConcreteType(),
                         AEI->getFormalConcreteType()),
            "init_existential_addr payload must be a lowering of the formal "
            "concrete type");
    
    checkExistentialProtocolConformances(exType.getASTType(),
                                         AEI->getFormalConcreteType(),
                                         AEI->getConformances());
    verifyOpenedArchetype(AEI, AEI->getFormalConcreteType());
  }

  void checkInitExistentialValueInst(InitExistentialValueInst *IEI) {
    SILType concreteType = IEI->getOperand()->getType();
    require(!concreteType.isAddress(),
            "init_existential_value must not be used on addresses");
    require(!IEI->getType().isAddress(),
            "init_existential_value result must not be an address");
    // The operand must be at the right abstraction level for the existential.
    SILType exType = IEI->getType();
    auto archetype = OpenedArchetypeType::get(exType.getASTType());
    auto loweredTy = F.getLoweredType(Lowering::AbstractionPattern(archetype),
                                      IEI->getFormalConcreteType());
    requireSameType(
        concreteType, loweredTy,
        "init_existential_value operand must be lowered to the right "
        "abstraction level for the existential");

    require(isLoweringOf(IEI->getOperand()->getType(),
                         IEI->getFormalConcreteType()),
            "init_existential_value operand must be a lowering of the formal "
            "concrete type");

    checkExistentialProtocolConformances(exType.getASTType(),
                                         IEI->getFormalConcreteType(),
                                         IEI->getConformances());
    verifyOpenedArchetype(IEI, IEI->getFormalConcreteType());
  }

  void checkInitExistentialRefInst(InitExistentialRefInst *IEI) {
    SILType concreteType = IEI->getOperand()->getType();
    require(concreteType.getASTType()->isBridgeableObjectType(),
            "init_existential_ref operand must be a class instance");
    require(IEI->getType().canUseExistentialRepresentation(
                                     ExistentialRepresentation::Class,
                                     IEI->getFormalConcreteType()),
            "init_existential_ref must be used with a class existential type");
    require(IEI->getType().isObject(),
            "init_existential_ref result must not be an address");
    
    // The operand must be at the right abstraction level for the existential.
    SILType exType = IEI->getType();
    auto archetype = OpenedArchetypeType::get(exType.getASTType());
    auto loweredTy = F.getLoweredType(Lowering::AbstractionPattern(archetype),
                                      IEI->getFormalConcreteType());
    requireSameType(concreteType, loweredTy,
                    "init_existential_ref operand must be lowered to the right "
                    "abstraction level for the existential");
    
    require(isLoweringOf(IEI->getOperand()->getType(),
                         IEI->getFormalConcreteType()),
            "init_existential_ref operand must be a lowering of the formal "
            "concrete type");
    
    checkExistentialProtocolConformances(exType.getASTType(),
                                         IEI->getFormalConcreteType(),
                                         IEI->getConformances());
    verifyOpenedArchetype(IEI, IEI->getFormalConcreteType());
  }

  void checkDeinitExistentialAddrInst(DeinitExistentialAddrInst *DEI) {
    SILType exType = DEI->getOperand()->getType();
    require(exType.isAddress(),
            "deinit_existential_addr must be applied to an address");
    require(exType.canUseExistentialRepresentation(
                ExistentialRepresentation::Opaque),
            "deinit_existential_addr must be applied to an opaque existential");
  }

  void checkDeinitExistentialValueInst(DeinitExistentialValueInst *DEI) {
    SILType exType = DEI->getOperand()->getType();
    require(!exType.isAddress(),
            "deinit_existential_value must not be applied to an address");
    require(
        exType.canUseExistentialRepresentation(
            ExistentialRepresentation::Opaque),
        "deinit_existential_value must be applied to an opaque existential");
  }
  
  void checkDeallocExistentialBoxInst(DeallocExistentialBoxInst *DEBI) {
    SILType exType = DEBI->getOperand()->getType();
    require(exType.isObject(),
            "dealloc_existential_box must be applied to a value");
    require(exType.canUseExistentialRepresentation(
                                       ExistentialRepresentation::Boxed),
            "dealloc_existential_box must be applied to a boxed "
            "existential");
  }

  void checkInitExistentialMetatypeInst(InitExistentialMetatypeInst *I) {
    SILType operandType = I->getOperand()->getType();
    require(operandType.isObject(),
            "init_existential_metatype operand must not be an address");
    require(operandType.is<MetatypeType>(),
            "init_existential_metatype operand must be a metatype");
    require(operandType.castTo<MetatypeType>()->hasRepresentation(),
            "init_existential_metatype operand must have a representation");

    SILType resultType = I->getType();
    require(resultType.is<ExistentialMetatypeType>(),
            "init_existential_metatype result must be an existential metatype");
    auto MetaTy = resultType.castTo<ExistentialMetatypeType>();
    require(resultType.isObject(),
            "init_existential_metatype result must not be an address");
    require(MetaTy->hasRepresentation(),
            "init_existential_metatype result must have a representation");
    require(MetaTy->getRepresentation()
              == operandType.castTo<MetatypeType>()->getRepresentation(),
            "init_existential_metatype result must match representation of "
            "operand");

    auto resultInstanceType = resultType.getASTType();
    auto operandInstanceType = operandType.getASTType();
    while (isa<ExistentialMetatypeType>(resultInstanceType)) {
      resultInstanceType =
          cast<ExistentialMetatypeType>(resultInstanceType).getInstanceType();
      operandInstanceType =
          cast<MetatypeType>(operandInstanceType).getInstanceType();
    }

    checkExistentialProtocolConformances(resultInstanceType,
                                         operandInstanceType,
                                         I->getConformances());
    verifyOpenedArchetype(I, MetaTy.getInstanceType());
  }

  void checkExistentialProtocolConformances(CanType resultType,
                                            CanType concreteType,
                                ArrayRef<ProtocolConformanceRef> conformances) {
    auto layout = resultType.getExistentialLayout();
    auto protocols = layout.getProtocols();

    require(conformances.size() == protocols.size(),
            "init_existential instruction must have the "
            "right number of conformances");

    if (layout.requiresClass()) {
      require(concreteType->mayHaveSuperclass() ||
              (concreteType.isExistentialType() &&
               concreteType.getExistentialLayout().requiresClass()),
              "init_existential of class existential with non-class type");
    }

    if (auto superclass = layout.getSuperclass()) {
      require(superclass->isExactSuperclassOf(concreteType),
              "init_existential of subclass existential with wrong type");
    }

    for (auto i : indices(conformances)) {
      require(conformances[i].getRequirement() == protocols[i]->getDecl(),
              "init_existential instruction must have conformances in "
              "proper order");
    }
  }

  void verifyCheckedCast(bool isExact, SILType fromTy, SILType toTy,
                         bool isOpaque = false) {
    // Verify common invariants.
    require(fromTy.isObject() && toTy.isObject(),
            "value checked cast src and dest must be objects");

    auto fromCanTy = fromTy.getASTType();
    auto toCanTy = toTy.getASTType();

    require(isOpaque || canUseScalarCheckedCastInstructions(F.getModule(),
                                                            fromCanTy, toCanTy),
            "invalid value checked cast src or dest types");

    // Peel off metatypes. If two types are checked-cast-able, so are their
    // metatypes.
    unsigned MetatyLevel = 0;
    while (isa<AnyMetatypeType>(fromCanTy) && isa<AnyMetatypeType>(toCanTy)) {
      auto fromMetaty = cast<AnyMetatypeType>(fromCanTy);
      auto toMetaty = cast<AnyMetatypeType>(toCanTy);
      
      // Check representations only for the top-level metatypes as only
      // those are SIL-lowered.
      if (!MetatyLevel) {
        // The representations must match.
        require(fromMetaty->getRepresentation() == toMetaty->getRepresentation(),
                "metatype checked cast cannot change metatype representation");

        // We can't handle the 'thin' case yet, but it shouldn't really even be
        // interesting.
        require(fromMetaty->getRepresentation() != MetatypeRepresentation::Thin,
                "metatype checked cast cannot check thin metatypes");
      }

      fromCanTy = fromMetaty.getInstanceType();
      toCanTy = toMetaty.getInstanceType();
      ++MetatyLevel;
    }

    if (isExact) {
      require(fromCanTy.getClassOrBoundGenericClass(),
              "downcast operand must be a class type");
      require(toCanTy.getClassOrBoundGenericClass(),
              "downcast must convert to a class type");
      require(fromCanTy->isBindableToSuperclassOf(toCanTy),
              "downcast must convert to a subclass");
    }
  }

  void checkUnconditionalCheckedCastInst(UnconditionalCheckedCastInst *CI) {
    verifyCheckedCast(/*exact*/ false,
                      CI->getOperand()->getType(),
                      CI->getType());
    verifyOpenedArchetype(CI, CI->getType().getASTType());
  }

  void checkUnconditionalCheckedCastValueInst(
      UnconditionalCheckedCastValueInst *CI) {
    verifyCheckedCast(/*exact*/ false, CI->getOperand()->getType(),
                      CI->getType(), true);
    verifyOpenedArchetype(CI, CI->getType().getASTType());
  }

  // Make sure that opcodes handled by isRCIdentityPreservingCast cannot cast
  // from a trivial to a reference type. Such a cast may dynamically
  // instantiate a new reference-counted object.
  void checkNoTrivialToReferenceCast(SingleValueInstruction *svi) {
    require(!svi->getOperand(0)->getType().isTrivial(*svi->getFunction())
            || svi->getType().isTrivial(*svi->getFunction()),
            "Unexpected trivial-to-reference conversion: ");
  }

  /// Verify if a given type is or contains an opened archetype or dynamic self.
  /// If this is the case, verify that the provided instruction has a type
  /// dependent operand for it.
  void verifyOpenedArchetype(SILInstruction *I, CanType Ty) {
    if (!Ty)
      return;
    // Check the type and all of its contained types.
    Ty.visit([&](CanType t) {
      SILValue Def;
      if (t->isOpenedExistential()) {
        auto archetypeTy = cast<ArchetypeType>(t);
        Def = OpenedArchetypes.getOpenedArchetypeDef(archetypeTy);
        require(Def, "Opened archetype should be registered in SILFunction");
      } else if (t->hasDynamicSelfType()) {
        require(I->getFunction()->hasSelfParam() ||
                I->getFunction()->hasDynamicSelfMetadata(),
              "Function containing dynamic self type must have self parameter");
        if (I->getFunction()->hasDynamicSelfMetadata())
          Def = I->getFunction()->getDynamicSelfMetadata();
        else
          Def = I->getFunction()->getSelfArgument();
      } else {
        return;
      }
      for (auto &TypeDefOp : I->getTypeDependentOperands()) {
        if (TypeDefOp.get() == Def)
          return;
      }
      require(false, "Instruction should contain a type dependent operand for "
                     "every used open archetype or dynamic self");
    });
  }

  void checkCheckedCastBranchInst(CheckedCastBranchInst *CBI) {
    verifyCheckedCast(CBI->isExact(),
                      CBI->getSourceLoweredType(),
                      CBI->getTargetLoweredType());
    verifyOpenedArchetype(CBI, CBI->getTargetFormalType());

    require(CBI->getSuccessBB()->args_size() == 1,
            "success dest of checked_cast_br must take one argument");
    requireSameType(
        CBI->getSuccessBB()->args_begin()[0]->getType(),
        CBI->getTargetLoweredType(),
        "success dest block argument of checked_cast_br must match type of "
        "cast");
    if (F.hasOwnership()) {
      require(CBI->getFailureBB()->args_size() == 1,
              "failure dest of checked_cast_br must take one argument in "
              "ownership qualified sil");
      requireSameType(
          CBI->getFailureBB()->args_begin()[0]->getType(),
          CBI->getOperand()->getType(),
          "failure dest block argument must match type of original type in "
          "ownership qualified sil");
      auto succOwnershipKind =
          CBI->getSuccessBB()->args_begin()[0]->getOwnershipKind();
      require(succOwnershipKind.isCompatibleWith(
                  CBI->getOperand().getOwnershipKind()),
              "succ dest block argument must have ownership compatible with "
              "the checked_cast_br operand");
      auto failOwnershipKind =
          CBI->getFailureBB()->args_begin()[0]->getOwnershipKind();
      require(failOwnershipKind.isCompatibleWith(
                  CBI->getOperand().getOwnershipKind()),
              "failure dest block argument must have ownership compatible with "
              "the checked_cast_br operand");
    } else {
      require(CBI->getFailureBB()->args_empty(),
              "Failure dest of checked_cast_br must not take any argument in "
              "non-ownership qualified sil");
    }
  }

  void checkCheckedCastValueBranchInst(CheckedCastValueBranchInst *CBI) {
    verifyCheckedCast(false,
                      CBI->getSourceLoweredType(),
                      CBI->getTargetLoweredType(),
                      true);
    verifyOpenedArchetype(CBI, CBI->getTargetFormalType());

    require(CBI->getSuccessBB()->args_size() == 1,
            "success dest of checked_cast_value_br must take one argument");
    requireSameType(
        CBI->getSuccessBB()->args_begin()[0]->getType(),
        CBI->getTargetLoweredType(),
        "success dest block argument of checked_cast_value_br must match "
        "type of cast");
    require(F.hasOwnership() || CBI->getFailureBB()->args_empty(),
            "failure dest of checked_cast_value_br in unqualified ownership "
            "sil must take no arguments");
  }

  void checkCheckedCastAddrBranchInst(CheckedCastAddrBranchInst *CCABI) {
    require(CCABI->getSrc()->getType().isAddress(),
            "checked_cast_addr_br src must be an address");
    require(CCABI->getDest()->getType().isAddress(),
            "checked_cast_addr_br dest must be an address");

    require(
        CCABI->getSuccessBB()->args_size() == 0,
        "success dest block of checked_cast_addr_br must not take an argument");
    require(
        CCABI->getFailureBB()->args_size() == 0,
        "failure dest block of checked_cast_addr_br must not take an argument");
  }

  void checkThinToThickFunctionInst(ThinToThickFunctionInst *TTFI) {
    auto opFTy = requireObjectType(SILFunctionType, TTFI->getOperand(),
                                   "thin_to_thick_function operand");
    auto resFTy = requireObjectType(SILFunctionType, TTFI,
                                    "thin_to_thick_function result");
    require(opFTy->isPolymorphic() == resFTy->isPolymorphic(),
            "thin_to_thick_function operand and result type must differ only "
            " in thinness");
    requireSameFunctionComponents(opFTy, resFTy,
                                  "thin_to_thick_function operand and result");

    require(opFTy->getRepresentation() == SILFunctionType::Representation::Thin,
            "operand of thin_to_thick_function must be thin");
    require(resFTy->getRepresentation() == SILFunctionType::Representation::Thick,
            "result of thin_to_thick_function must be thick");

    auto adjustedOperandExtInfo =
        opFTy->getExtInfo()
            .intoBuilder()
            .withRepresentation(SILFunctionType::Representation::Thick)
            .withNoEscape(resFTy->isNoEscape())
            .build();
    require(adjustedOperandExtInfo.isEqualTo(resFTy->getExtInfo(),
                                             useClangTypes(opFTy)),
            "operand and result of thin_to_think_function must agree in "
            "particulars");
  }

  void checkThickToObjCMetatypeInst(ThickToObjCMetatypeInst *TTOCI) {
    auto opTy = requireObjectType(AnyMetatypeType, TTOCI->getOperand(),
                                  "thick_to_objc_metatype operand");
    auto resTy = requireObjectType(AnyMetatypeType, TTOCI,
                                   "thick_to_objc_metatype result");

    require(TTOCI->getOperand()->getType().is<MetatypeType>() ==
            TTOCI->getType().is<MetatypeType>(),
            "thick_to_objc_metatype cannot change metatype kinds");
    require(opTy->getRepresentation() == MetatypeRepresentation::Thick,
            "operand of thick_to_objc_metatype must be thick");
    require(resTy->getRepresentation() == MetatypeRepresentation::ObjC,
            "operand of thick_to_objc_metatype must be ObjC");

    requireSameType(opTy->getInstanceType(), resTy->getInstanceType(),
                    "thick_to_objc_metatype instance types do not match");
  }

  void checkObjCToThickMetatypeInst(ObjCToThickMetatypeInst *OCTTI) {
    auto opTy = requireObjectType(AnyMetatypeType, OCTTI->getOperand(),
                                  "objc_to_thick_metatype operand");
    auto resTy = requireObjectType(AnyMetatypeType, OCTTI,
                                   "objc_to_thick_metatype result");

    require(OCTTI->getOperand()->getType().is<MetatypeType>() ==
            OCTTI->getType().is<MetatypeType>(),
            "objc_to_thick_metatype cannot change metatype kinds");
    require(opTy->getRepresentation() == MetatypeRepresentation::ObjC,
            "operand of objc_to_thick_metatype must be ObjC");
    require(resTy->getRepresentation() == MetatypeRepresentation::Thick,
            "operand of objc_to_thick_metatype must be thick");

    requireSameType(opTy->getInstanceType(), resTy->getInstanceType(),
                    "objc_to_thick_metatype instance types do not match");
  }

  void checkUpcastInst(UpcastInst *UI) {
    require(UI->getType() != UI->getOperand()->getType(),
            "can't upcast to same type");
    checkNoTrivialToReferenceCast(UI);
    if (UI->getType().is<MetatypeType>()) {
      CanType instTy(UI->getType().castTo<MetatypeType>()->getInstanceType());
      require(UI->getOperand()->getType().is<MetatypeType>(),
              "upcast operand must be a class or class metatype instance");
      CanType opInstTy(UI->getOperand()->getType().castTo<MetatypeType>()
                         ->getInstanceType());
      auto instClass = instTy->getClassOrBoundGenericClass();
      require(instClass,
              "upcast must convert a class metatype to a class metatype");
      
      if (instClass->usesObjCGenericsModel()) {
        require(instClass->getDeclaredTypeInContext()
                  ->isBindableToSuperclassOf(opInstTy),
                "upcast must cast to a superclass or an existential metatype");
      } else {
        require(instTy->isExactSuperclassOf(opInstTy),
                "upcast must cast to a superclass or an existential metatype");
      }
      return;
    }

    require(UI->getType().getCategory() ==
            UI->getOperand()->getType().getCategory(),
            "Upcast can only upcast in between types of the same "
            "SILValueCategory. This prevents address types from being cast to "
            "object types or vis-a-versa");

    auto ToTy = UI->getType();
    auto FromTy = UI->getOperand()->getType();

    // Upcast from Optional<B> to Optional<A> is legal as long as B is a
    // subclass of A.
    if (ToTy.getASTType().getOptionalObjectType() &&
        FromTy.getASTType().getOptionalObjectType()) {
      ToTy = SILType::getPrimitiveObjectType(
          ToTy.getASTType().getOptionalObjectType());
      FromTy = SILType::getPrimitiveObjectType(
          FromTy.getASTType().getOptionalObjectType());
    }

    auto ToClass = ToTy.getClassOrBoundGenericClass();
    require(ToClass,
            "upcast must convert a class instance to a class type");
      if (ToClass->usesObjCGenericsModel()) {
        require(ToClass->getDeclaredTypeInContext()
                  ->isBindableToSuperclassOf(FromTy.getASTType()),
                "upcast must cast to a superclass or an existential metatype");
      } else {
        require(ToTy.isExactSuperclassOf(FromTy),
                "upcast must cast to a superclass or an existential metatype");
      }
  }

  void checkAddressToPointerInst(AddressToPointerInst *AI) {
    require(AI->getOperand()->getType().isAddress(),
            "address-to-pointer operand must be an address");
    require(AI->getType().getASTType()->isEqual(
                              AI->getType().getASTContext().TheRawPointerType),
            "address-to-pointer result type must be RawPointer");
  }
  
  void checkUncheckedRefCastInst(UncheckedRefCastInst *AI) {
    verifyOpenedArchetype(AI, AI->getType().getASTType());
    require(AI->getOperand()->getType().isObject(),
            "unchecked_ref_cast operand must be a value");
    require(AI->getType().isObject(),
            "unchecked_ref_cast result must be an object");
    require(SILType::canRefCast(AI->getOperand()->getType(), AI->getType(),
                                AI->getModule()),
            "unchecked_ref_cast requires a heap object reference type");
  }

  void checkUncheckedRefCastAddrInst(UncheckedRefCastAddrInst *AI) {
    auto srcTy = AI->getSrc()->getType();
    auto destTy = AI->getDest()->getType();
    require(srcTy.isAddress(),
            "unchecked_ref_cast_addr operand must be an address");
    require(destTy.isAddress(),
            "unchecked_ref_cast_addr result must be an address");
    // The static src/dest types cannot be checked here even if they are
    // loadable. unchecked_ref_cast_addr may accept nonreference static types
    // (as a result of specialization). These cases will never be promoted to
    // value bitcast, thus will cause the subsequent runtime cast to fail.
  }
  
  void checkUncheckedAddrCastInst(UncheckedAddrCastInst *AI) {
    verifyOpenedArchetype(AI, AI->getType().getASTType());

    require(AI->getOperand()->getType().isAddress(),
            "unchecked_addr_cast operand must be an address");
    require(AI->getType().isAddress(),
            "unchecked_addr_cast result must be an address");
  }
  
  void checkUncheckedTrivialBitCastInst(UncheckedTrivialBitCastInst *BI) {
    verifyOpenedArchetype(BI, BI->getType().getASTType());
    require(BI->getOperand()->getType().isObject(),
            "unchecked_trivial_bit_cast must operate on a value");
    require(BI->getType().isObject(),
            "unchecked_trivial_bit_cast must produce a value");
    require(BI->getType().isTrivial(F),
            "unchecked_trivial_bit_cast must produce a value of trivial type");
  }

  void checkUncheckedBitwiseCastInst(UncheckedBitwiseCastInst *BI) {
    verifyOpenedArchetype(BI, BI->getType().getASTType());
    require(BI->getOperand()->getType().isObject(),
            "unchecked_bitwise_cast must operate on a value");
    require(BI->getType().isObject(),
            "unchecked_bitwise_cast must produce a value");
  }

  void checkRefToRawPointerInst(RefToRawPointerInst *AI) {
    require(AI->getOperand()->getType().isAnyClassReferenceType(),
            "ref-to-raw-pointer operand must be a class reference or"
            " NativeObject");
    requireSameType(AI->getType().getASTType(),
                    AI->getType().getASTContext().TheRawPointerType,
                    "ref-to-raw-pointer result must be RawPointer");
  }

  void checkRawPointerToRefInst(RawPointerToRefInst *AI) {
    verifyOpenedArchetype(AI, AI->getType().getASTType());
    require(AI->getType()
              .getASTType()->isBridgeableObjectType()
            || AI->getType().getASTType()->isEqual(
                             AI->getType().getASTContext().TheNativeObjectType),
        "raw-pointer-to-ref result must be a class reference or NativeObject");
    requireSameType(AI->getOperand()->getType().getASTType(),
                    AI->getType().getASTContext().TheRawPointerType,
                    "raw-pointer-to-ref operand must be NativeObject");
  }
  
  void checkRefToBridgeObjectInst(RefToBridgeObjectInst *RI) {
    require(RI->getConverted()->getType().isObject(),
            "ref_to_bridge_object must convert from a value");
    require(RI->getConverted()->getType().getASTType()
              ->isBridgeableObjectType(),
            "ref_to_bridge_object must convert from a heap object ref");
    requireSameType(
        RI->getBitsOperand()->getType(),
        SILType::getBuiltinWordType(F.getASTContext()),
        "ref_to_bridge_object must take a Builtin.Word bits operand");
    requireSameType(RI->getType(),
                    SILType::getBridgeObjectType(F.getASTContext()),
                    "ref_to_bridge_object must produce a BridgeObject");
  }
  
  void checkBridgeObjectToRefInst(BridgeObjectToRefInst *RI) {
    verifyOpenedArchetype(RI, RI->getType().getASTType());
    requireSameType(RI->getConverted()->getType(),
                    SILType::getBridgeObjectType(F.getASTContext()),
                    "bridge_object_to_ref must take a BridgeObject");
    require(RI->getType().isObject(),
            "bridge_object_to_ref must produce a value");
    require(RI->getType().getASTType()->isBridgeableObjectType(),
            "bridge_object_to_ref must produce a heap object reference");
  }
  void checkBridgeObjectToWordInst(BridgeObjectToWordInst *RI) {
    requireSameType(RI->getConverted()->getType(),
                    SILType::getBridgeObjectType(F.getASTContext()),
                    "bridge_object_to_word must take a BridgeObject");
    require(RI->getType().isObject(),
            "bridge_object_to_word must produce a value");
    requireSameType(RI->getType(),
                    SILType::getBuiltinWordType(F.getASTContext()),
                    "bridge_object_to_word must produce a Word");
  }

  void checkConvertFunctionInst(ConvertFunctionInst *ICI) {
    auto opTI = requireObjectType(SILFunctionType, ICI->getOperand(),
                                  "convert_function operand");
    auto resTI = requireObjectType(SILFunctionType, ICI,
                                   "convert_function result");

    // convert_function is required to be an ABI-compatible conversion.
    requireABICompatibleFunctionTypes(
        opTI, resTI, "convert_function cannot change function ABI",
        *ICI->getFunction());
  }

  void checkConvertEscapeToNoEscapeInst(ConvertEscapeToNoEscapeInst *ICI) {
    auto opTI = requireObjectType(SILFunctionType, ICI->getOperand(),
                                  "convert_escape_to_noescape operand");
    auto resTI = ICI->getType().castTo<SILFunctionType>();

    // FIXME: Not yet, to be enabled when this is true.
    // require(resTI->isTrivial(F.getModule()),
    //         "convert_escape_to_noescape should produce a trivial result type");

    // convert_escape_to_noescape is required to be an ABI-compatible
    // conversion once escapability is the same on both sides.
    requireABICompatibleFunctionTypes(
        opTI, resTI->getWithExtInfo(resTI->getExtInfo().withNoEscape(false)),
        "convert_escape_to_noescape cannot change function ABI",
        *ICI->getFunction());

    // After mandatory passes convert_escape_to_noescape should not have the
    // '[not_guaranteed]' or '[escaped]' attributes.
    if (!SkipConvertEscapeToNoescapeAttributes &&
        F.getModule().getStage() != SILStage::Raw) {
      require(ICI->isLifetimeGuaranteed(),
              "convert_escape_to_noescape [not_guaranteed] not "
              "allowed after mandatory passes");
    }
  }

  void checkThinFunctionToPointerInst(ThinFunctionToPointerInst *CI) {
    auto opTI = requireObjectType(SILFunctionType, CI->getOperand(),
                                  "thin_function_to_pointer operand");
    requireObjectType(BuiltinRawPointerType, CI,
                      "thin_function_to_pointer result");

    auto rep = opTI->getRepresentation();
    require(rep == SILFunctionTypeRepresentation::Thin ||
            rep == SILFunctionTypeRepresentation::Method ||
            rep == SILFunctionTypeRepresentation::WitnessMethod,
            "thin_function_to_pointer only works on thin, method or "
            "witness_method functions");
  }

  void checkPointerToThinFunctionInst(PointerToThinFunctionInst *CI) {
    auto resultTI = requireObjectType(SILFunctionType, CI,
                                      "pointer_to_thin_function result");
    requireObjectType(BuiltinRawPointerType, CI->getOperand(),
                      "pointer_to_thin_function operand");

    auto rep = resultTI->getRepresentation();
    require(rep == SILFunctionTypeRepresentation::Thin ||
            rep == SILFunctionTypeRepresentation::Method ||
            rep == SILFunctionTypeRepresentation::WitnessMethod,
            "pointer_to_thin_function only works on thin, method or "
            "witness_method functions");
  }

  void checkCondFailInst(CondFailInst *CFI) {
    requireSameType(CFI->getOperand()->getType(),
                    SILType::getBuiltinIntegerType(1, F.getASTContext()),
                    "cond_fail operand must be a Builtin.Int1");
  }

  void checkReturnInst(ReturnInst *RI) {
    LLVM_DEBUG(RI->print(llvm::dbgs()));

    SILType functionResultType =
        F.getLoweredType(F.mapTypeIntoContext(fnConv.getSILResultType(
                                                  F.getTypeExpansionContext()))
                             .getASTType())
            .getCategoryType(
                fnConv.getSILResultType(F.getTypeExpansionContext())
                    .getCategory());
    SILType instResultType = RI->getOperand()->getType();
    LLVM_DEBUG(llvm::dbgs() << "function return type: ";
               functionResultType.dump();
               llvm::dbgs() << "return inst type: ";
               instResultType.dump(););
    requireSameType(functionResultType, instResultType,
                    "return value type does not match return type of function");
  }

  void checkThrowInst(ThrowInst *TI) {
    LLVM_DEBUG(TI->print(llvm::dbgs()));

    require(fnConv.funcTy->hasErrorResult(),
            "throw in function that doesn't have an error result");

    SILType functionResultType =
        F.getLoweredType(F.mapTypeIntoContext(fnConv.getSILErrorType(
                                                  F.getTypeExpansionContext()))
                             .getASTType())
            .getCategoryType(fnConv.getSILErrorType(F.getTypeExpansionContext())
                                 .getCategory());
    SILType instResultType = TI->getOperand()->getType();
    LLVM_DEBUG(llvm::dbgs() << "function error result type: ";
               functionResultType.dump();
               llvm::dbgs() << "throw operand type: ";
               instResultType.dump(););
    requireSameType(
        functionResultType, instResultType,
        "throw operand type does not match error result type of function");
  }
  
  void checkUnwindInst(UnwindInst *UI) {
    require(F.getLoweredFunctionType()->isCoroutine(),
            "unwind in non-coroutine function");
  }

  void checkYieldInst(YieldInst *YI) {
    require(fnConv.funcTy->isCoroutine(),
            "yield in non-coroutine function");

    auto yieldedValues = YI->getYieldedValues();
    auto yieldInfos = fnConv.funcTy->getYields();
    require(yieldedValues.size() == yieldInfos.size(),
            "wrong number of yielded values for function");
    for (auto i : indices(yieldedValues)) {
      SILType yieldType = F.mapTypeIntoContext(
          fnConv.getSILType(yieldInfos[i], F.getTypeExpansionContext()));
      requireSameType(yieldedValues[i]->getType(), yieldType,
                      "yielded value does not match yield type of coroutine");
    }

    // We require the resume and unwind destinations to be unique in order
    // to prevent either edge from becoming critical.
    require(YI->getResumeBB()->getSinglePredecessorBlock(),
            "resume dest of 'yield' must be uniquely used");
    require(YI->getUnwindBB()->getSinglePredecessorBlock(),
            "unwind dest of 'yield' must be uniquely used");
  }

  void checkSelectEnumCases(SelectEnumInstBase *I) {
    EnumDecl *eDecl = I->getEnumOperand()->getType().getEnumOrBoundGenericEnum();
    require(eDecl, "select_enum operand must be an enum");

    // Find the set of enum elements for the type so we can verify
    // exhaustiveness.
    llvm::DenseSet<EnumElementDecl*> unswitchedElts;
    eDecl->getAllElements(unswitchedElts);

    // Verify the set of enum cases we dispatch on.
    for (unsigned i = 0, e = I->getNumCases(); i < e; ++i) {
      EnumElementDecl *elt;
      SILValue result;
      std::tie(elt, result) = I->getCase(i);

      require(elt->getDeclContext() == eDecl,
              "select_enum dispatches on enum element that is not part of "
              "its type");
      require(unswitchedElts.count(elt),
              "select_enum dispatches on same enum element more than once");
      unswitchedElts.erase(elt);

      // The result value must match the type of the instruction.
      requireSameType(result->getType(), I->getType(),
                    "select_enum case operand must match type of instruction");
    }

    // If the select is non-exhaustive, we require a default.
    bool isExhaustive =
        eDecl->isEffectivelyExhaustive(F.getModule().getSwiftModule(),
                                       F.getResilienceExpansion());
    require((isExhaustive && unswitchedElts.empty()) || I->hasDefault(),
            "nonexhaustive select_enum must have a default destination");
    if (I->hasDefault()) {
      requireSameType(I->getDefaultResult()->getType(),
                  I->getType(),
                  "select_enum default operand must match type of instruction");
    }
  }

  void checkSelectEnumInst(SelectEnumInst *SEI) {
    require(SEI->getEnumOperand()->getType().isObject(),
            "select_enum operand must be an object");
    
    checkSelectEnumCases(SEI);
  }
  void checkSelectEnumAddrInst(SelectEnumAddrInst *SEI) {
    require(SEI->getEnumOperand()->getType().isAddress(),
            "select_enum_addr operand must be an address");
    
    checkSelectEnumCases(SEI);
  }

  void checkSwitchValueInst(SwitchValueInst *SVI) {
    // TODO: Type should be either integer or function
    auto Ty = SVI->getOperand()->getType();
    require(Ty.is<BuiltinIntegerType>() || Ty.is<SILFunctionType>(),
            "switch_value operand should be either of an integer "
            "or function type");

    auto ult = [](const SILValue &a, const SILValue &b) { 
      return a == b || a < b; 
    };

    std::set<SILValue, decltype(ult)> cases(ult);

    for (unsigned i = 0, e = SVI->getNumCases(); i < e; ++i) {
      SILValue value;
      SILBasicBlock *dest;
      std::tie(value, dest) = SVI->getCase(i);

      requireSameType(
          value->getType(), Ty,
          "switch_value case value should have the same type as its operand");

      require(!cases.count(value),
              "multiple switch_value cases for same value");
      cases.insert(value);

      require(dest->args_empty(),
              "switch_value case destination cannot take arguments");
    }

    if (SVI->hasDefault())
      require(SVI->getDefaultBB()->args_empty(),
              "switch_value default destination cannot take arguments");
  }

  void checkSelectValueCases(SelectValueInst *I) {
    struct APIntCmp {
      bool operator()(const APInt &a, const APInt &b) const {
        return a.ult(b);
      };
    };

    llvm::SmallSet<APInt, 16, APIntCmp> seenCaseValues;

    // Verify the set of cases we dispatch on.
    for (unsigned i = 0, e = I->getNumCases(); i < e; ++i) {
      SILValue casevalue;
      SILValue result;
      std::tie(casevalue, result) = I->getCase(i);
      
      if (!isa<SILUndef>(casevalue)) {
        auto  *il = dyn_cast<IntegerLiteralInst>(casevalue);
        require(il,
                "select_value case operands should refer to integer literals");
        APInt elt = il->getValue();

        require(!seenCaseValues.count(elt),
                "select_value dispatches on same case value more than once");

        seenCaseValues.insert(elt);
      }

      requireSameType(I->getOperand()->getType(), casevalue->getType(),
                      "select_value case value must match type of operand");

      // The result value must match the type of the instruction.
      requireSameType(result->getType(), I->getType(),
                    "select_value case result must match type of instruction");
    }

    require(I->hasDefault(),
            "select_value should always have a default");
    requireSameType(I->getDefaultResult()->getType(),
                  I->getType(),
                  "select_value default operand must match type of instruction");
  }

  void checkSelectValueInst(SelectValueInst *SVI) {
    require(SVI->getOperand()->getType().isObject(),
            "select_value operand must be an object");

    checkSelectValueCases(SVI);
  }

  void checkSwitchEnumInst(SwitchEnumInst *SOI) {
    require(SOI->getOperand()->getType().isObject(),
            "switch_enum operand must be an object");

    SILType uTy = SOI->getOperand()->getType();
    EnumDecl *uDecl = uTy.getEnumOrBoundGenericEnum();
    require(uDecl, "switch_enum operand is not an enum");

    // Find the set of enum elements for the type so we can verify
    // exhaustiveness.
    llvm::DenseSet<EnumElementDecl*> unswitchedElts;
    uDecl->getAllElements(unswitchedElts);

    // Verify the set of enum cases we dispatch on.
    for (unsigned i = 0, e = SOI->getNumCases(); i < e; ++i) {
      EnumElementDecl *elt;
      SILBasicBlock *dest;
      std::tie(elt, dest) = SOI->getCase(i);

      require(elt->getDeclContext() == uDecl,
              "switch_enum dispatches on enum element that is not part of "
              "its type");
      require(unswitchedElts.count(elt),
              "switch_enum dispatches on same enum element more than once");
      unswitchedElts.erase(elt);

      // The destination BB can take the argument payload, if any, as a BB
      // arguments, or it can ignore it and take no arguments.
      if (elt->hasAssociatedValues()) {
        if (isSILOwnershipEnabled() && F.hasOwnership()) {
          require(dest->getArguments().size() == 1,
                  "switch_enum destination for case w/ args must take 1 "
                  "argument");
          if (!dest->getArgument(0)->getType().isTrivial(*SOI->getFunction())) {
            require(
                dest->getArgument(0)->getOwnershipKind().isCompatibleWith(
                    SOI->getOwnershipKind()),
                "Switch enum non-trivial destination arg must have ownership "
                "kind that is compatible with the switch_enum's operand");
          }
        } else {
          require(dest->getArguments().empty() ||
                      dest->getArguments().size() == 1,
                  "switch_enum destination for case w/ args must take 0 or 1 "
                  "arguments");
        }

        if (dest->getArguments().size() == 1) {
          SILType eltArgTy = uTy.getEnumElementType(elt, F.getModule(),
                                                    F.getTypeExpansionContext());
          SILType bbArgTy = dest->getArguments()[0]->getType();
          if (F.getModule().getStage() != SILStage::Lowered) {
            // During the lowered stage, a function type might have different
            // signature
            require(eltArgTy == bbArgTy,
                    "switch_enum destination bbarg must match case arg type");
          }
          require(!dest->getArguments()[0]->getType().isAddress(),
                  "switch_enum destination bbarg type must not be an address");
        }

      } else {
        require(dest->getArguments().empty(),
                "switch_enum destination for no-argument case must take no "
                "arguments");
      }
    }

    // If the switch is non-exhaustive, we require a default.
    bool isExhaustive =
        uDecl->isEffectivelyExhaustive(F.getModule().getSwiftModule(),
                                       F.getResilienceExpansion());
    require((isExhaustive && unswitchedElts.empty()) || SOI->hasDefault(),
            "nonexhaustive switch_enum must have a default destination");
    if (SOI->hasDefault()) {
      // When SIL ownership is enabled, we require all default branches to take
      // an @owned original version of the enum.
      //
      // When SIL ownership is disabled, we no longer support this.
      if (isSILOwnershipEnabled() && F.hasOwnership()) {
        require(SOI->getDefaultBB()->getNumArguments() == 1,
                "Switch enum default block should have one argument");
        requireSameType(
            SOI->getDefaultBB()->getArgument(0)->getType(),
            SOI->getOperand()->getType(),
            "Switch enum default block should have one argument that is "
            "the same as the input type");
        auto defaultKind =
            SOI->getDefaultBB()->getArgument(0)->getOwnershipKind();
        require(
            defaultKind.isCompatibleWith(SOI->getOperand().getOwnershipKind()),
            "Switch enum default block arg must have same ownership kind "
            "as operand");
      } else if (!F.hasOwnership()) {
        require(SOI->getDefaultBB()->args_empty(),
                "switch_enum default destination must take no arguments");
      }
    }
  }

  void checkSwitchEnumAddrInst(SwitchEnumAddrInst *SOI) {
    require(SOI->getOperand()->getType().isAddress(),
            "switch_enum_addr operand must be an address");

    SILType uTy = SOI->getOperand()->getType();
    EnumDecl *uDecl = uTy.getEnumOrBoundGenericEnum();
    require(uDecl, "switch_enum_addr operand must be an enum");

    // Find the set of enum elements for the type so we can verify
    // exhaustiveness.
    llvm::DenseSet<EnumElementDecl*> unswitchedElts;
    uDecl->getAllElements(unswitchedElts);

    // Verify the set of enum cases we dispatch on.
    for (unsigned i = 0, e = SOI->getNumCases(); i < e; ++i) {
      EnumElementDecl *elt;
      SILBasicBlock *dest;
      std::tie(elt, dest) = SOI->getCase(i);

      require(elt->getDeclContext() == uDecl,
              "switch_enum_addr dispatches on enum element that "
              "is not part of its type");
      require(unswitchedElts.count(elt),
              "switch_enum_addr dispatches on same enum element "
              "more than once");
      unswitchedElts.erase(elt);

      // The destination BB must not have BB arguments.
      require(dest->getArguments().empty(),
              "switch_enum_addr destination must take no BB args");
    }

    // If the switch is non-exhaustive, we require a default.
    bool isExhaustive =
        uDecl->isEffectivelyExhaustive(F.getModule().getSwiftModule(),
                                       F.getResilienceExpansion());
    require((isExhaustive && unswitchedElts.empty()) || SOI->hasDefault(),
            "nonexhaustive switch_enum_addr must have a default destination");

    if (SOI->hasDefault())
      require(SOI->getDefaultBB()->args_empty(),
              "switch_enum_addr default destination must take "
              "no arguments");
  }

  bool verifyBranchArgs(SILValue branchArg, SILArgument *bbArg) {
    // NOTE: IRGen currently does not support the following method_inst
    // variants as branch arguments.
    // Once this is supported, the check can be removed.
    require(!(isa<MethodInst>(branchArg) &&
              cast<MethodInst>(branchArg)->getMember().isForeign),
        "branch argument cannot be a witness_method or an objc method_inst");
    require(!(branchArg->getType().is<SILFunctionType>() &&
              branchArg->getType()
                      .castTo<SILFunctionType>()
                      ->getExtInfo()
                      .getRepresentation() ==
                  SILFunctionTypeRepresentation::ObjCMethod),
            "branch argument cannot be a objective-c method");
    return branchArg->getType() == bbArg->getType();
  }

  void checkBranchInst(BranchInst *BI) {
    require(BI->getArgs().size() == BI->getDestBB()->args_size(),
            "branch has wrong number of arguments for dest bb");
    require(std::equal(BI->getArgs().begin(), BI->getArgs().end(),
                       BI->getDestBB()->args_begin(),
                       [&](SILValue branchArg, SILArgument *bbArg) {
                         return verifyBranchArgs(branchArg, bbArg);
                       }),
            "branch argument types do not match arguments for dest bb");
  }

  void checkCondBranchInst(CondBranchInst *cbi) {
    // It is important that cond_br keeps an i1 type. ARC Sequence Opts assumes
    // that cond_br does not use reference counted values or decrement reference
    // counted values under the assumption that the instruction that computes
    // the i1 is the use/decrement that ARC cares about and that after that
    // instruction is evaluated, the scalar i1 has a different identity and the
    // object can be deallocated.
    requireSameType(cbi->getCondition()->getType(),
                    SILType::getBuiltinIntegerType(
                        1, cbi->getCondition()->getType().getASTContext()),
                    "condition of conditional branch must have Int1 type");

    require(cbi->getTrueArgs().size() == cbi->getTrueBB()->args_size(),
            "true branch has wrong number of arguments for dest bb");
    require(cbi->getTrueBB() != cbi->getFalseBB(), "identical destinations");
    require(std::equal(cbi->getTrueArgs().begin(), cbi->getTrueArgs().end(),
                       cbi->getTrueBB()->args_begin(),
                       [&](SILValue branchArg, SILArgument *bbArg) {
                         return verifyBranchArgs(branchArg, bbArg);
                       }),
            "true branch argument types do not match arguments for dest bb");

    require(cbi->getFalseArgs().size() == cbi->getFalseBB()->args_size(),
            "false branch has wrong number of arguments for dest bb");
    require(std::equal(cbi->getFalseArgs().begin(), cbi->getFalseArgs().end(),
                       cbi->getFalseBB()->args_begin(),
                       [&](SILValue branchArg, SILArgument *bbArg) {
                         return verifyBranchArgs(branchArg, bbArg);
                       }),
            "false branch argument types do not match arguments for dest bb");
    // When we are in ossa, cond_br can not have any arguments that are
    // non-trivial.
    if (!F.hasOwnership())
      return;

    require(llvm::all_of(cbi->getOperandValues(),
                         [&](SILValue v) -> bool {
                           return v->getType().isTrivial(*cbi->getFunction());
                         }),
            "cond_br must not have a non-trivial value in ossa.");
  }

  void checkDynamicMethodBranchInst(DynamicMethodBranchInst *DMBI) {
    SILType operandType = DMBI->getOperand()->getType();

    require(DMBI->getMember().getDecl()->isObjC(), "method must be @objc");
    if (!DMBI->getMember().getDecl()->isInstanceMember()) {
      require(operandType.is<MetatypeType>(),
              "operand must have metatype type");
      require(operandType.castTo<MetatypeType>()
                ->getInstanceType()->mayHaveSuperclass(),
              "operand must have metatype of class or class-bound type");
    }

    // Check that the branch argument is of the expected dynamic method type.
    require(DMBI->getHasMethodBB()->args_size() == 1,
            "true bb for dynamic_method_br must take an argument");

    auto bbArgTy = DMBI->getHasMethodBB()->args_begin()[0]->getType();
    require(getDynamicMethodType(operandType, DMBI->getMember())
              .getASTType()
              ->isBindableTo(bbArgTy.getASTType()),
            "bb argument for dynamic_method_br must be of the method's type");
  }

  void checkProjectBlockStorageInst(ProjectBlockStorageInst *PBSI) {
    require(PBSI->getOperand()->getType().isAddress(),
            "operand must be an address");
    auto storageTy = PBSI->getOperand()->getType().getAs<SILBlockStorageType>();
    require(storageTy, "operand must be a @block_storage type");
    
    require(PBSI->getType().isAddress(),
            "result must be an address");
    auto captureTy = PBSI->getType().getASTType();
    requireSameType(
        storageTy->getCaptureType(), captureTy,
        "result must be the capture type of the @block_storage type");
  }
  
  void checkInitBlockStorageHeaderInst(InitBlockStorageHeaderInst *IBSHI) {
    auto storage = IBSHI->getBlockStorage();
    require(storage->getType().isAddress(),
            "block storage operand must be an address");

    auto storageTy = storage->getType().getAs<SILBlockStorageType>();
    require(storageTy, "block storage operand must be a @block_storage type");

    auto captureTy = storageTy->getCaptureType();
    if (auto capturedFnTy = captureTy->getAs<SILFunctionType>()) {
      if (capturedFnTy->isNoEscape()) {
        // If the capture is a noescape function then it must be possible to
        // locally determine the value stored to initialize the storage for the
        // capture. This is required to diagnose static exclusivity violations
        // when a noescape closure is converted to a noescape block that
        // is then passed to a function.
        auto *storageProjection =
           storage->getSingleUserOfType<ProjectBlockStorageInst>();
        require(storageProjection,
                "block storage operand with noescape capture must have "
                "projection from block");

        auto *storeInst = storageProjection->getSingleUserOfType<StoreInst>();
        require(storeInst,
                "block storage operand with noescape capture must have "
                "store to projection");
      }
    }

    require(IBSHI->getInvokeFunction()->getType().isObject(),
            "invoke function operand must be a value");
    auto invokeTy
      = IBSHI->getInvokeFunction()->getType().getAs<SILFunctionType>();
    require(invokeTy, "invoke function operand must be a function");
    require(invokeTy->getRepresentation()
              == SILFunctionType::Representation::CFunctionPointer,
            "invoke function operand must be a c function");
    require(invokeTy->getParameters().size() >= 1,
            "invoke function must take at least one parameter");
    require(!invokeTy->getInvocationGenericSignature() ||
            invokeTy->getExtInfo().isPseudogeneric(),
            "invoke function must not take reified generic parameters");
    
    invokeTy = checkApplySubstitutions(IBSHI->getSubstitutions(),
                                    SILType::getPrimitiveObjectType(invokeTy));
    
    auto storageParam = invokeTy->getParameters()[0];
    require(storageParam.getConvention() ==
            ParameterConvention::Indirect_InoutAliasable,
            "invoke function must take block storage as @inout_aliasable "
            "parameter");
    requireSameType(
        storageParam.getArgumentType(F.getModule(), invokeTy,
                                     F.getTypeExpansionContext()),
        storageTy,
        "invoke function must take block storage type as first parameter");

    require(IBSHI->getType().isObject(), "result must be a value");
    auto blockTy = IBSHI->getType().getAs<SILFunctionType>();
    require(blockTy, "result must be a function");
    require(blockTy->getRepresentation() == SILFunctionType::Representation::Block,
            "result must be a cdecl block function");
    require(blockTy->getResults() == invokeTy->getResults(),
            "result must have same results as invoke function");

    require(blockTy->getParameters().size() + 1
              == invokeTy->getParameters().size(),
          "result must match all parameters of invoke function but the first");
    auto blockParams = blockTy->getParameters();
    auto invokeBlockParams = invokeTy->getParameters().slice(1);
    for (unsigned i : indices(blockParams)) {
      require(blockParams[i] == invokeBlockParams[i],
          "result must match all parameters of invoke function but the first");
    }
  }
  
  void checkObjCProtocolInst(ObjCProtocolInst *OPI) {
    require(OPI->getProtocol()->isObjC(),
            "objc_protocol must be applied to an @objc protocol");
    auto classTy = OPI->getType();
    require(classTy.isObject(), "objc_protocol must produce a value");
    auto classDecl = classTy.getClassOrBoundGenericClass();
    require(classDecl, "objc_protocol must produce a class instance");
    require(classDecl->getName() == F.getASTContext().Id_Protocol,
            "objc_protocol must produce an instance of ObjectiveC.Protocol class");
    require(classDecl->getModuleContext()->getName() == F.getASTContext().Id_ObjectiveC,
            "objc_protocol must produce an instance of ObjectiveC.Protocol class");
  }
  
  void checkObjCMetatypeToObjectInst(ObjCMetatypeToObjectInst *OMOI) {
    require(OMOI->getOperand()->getType().isObject(),
            "objc_metatype_to_object must take a value");
    auto fromMetaTy = OMOI->getOperand()->getType().getAs<MetatypeType>();
    require(fromMetaTy, "objc_metatype_to_object must take an @objc metatype value");
    require(fromMetaTy->getRepresentation() == MetatypeRepresentation::ObjC,
            "objc_metatype_to_object must take an @objc metatype value");
    require(OMOI->getType().isObject(),
            "objc_metatype_to_object must produce a value");
    require(OMOI->getType().getASTType()->isAnyObject(),
            "objc_metatype_to_object must produce an AnyObject value");
  }

  void checkObjCExistentialMetatypeToObjectInst(
                                    ObjCExistentialMetatypeToObjectInst *OMOI) {
    require(OMOI->getOperand()->getType().isObject(),
            "objc_metatype_to_object must take a value");
    auto fromMetaTy = OMOI->getOperand()->getType()
      .getAs<ExistentialMetatypeType>();
    require(fromMetaTy, "objc_metatype_to_object must take an @objc existential metatype value");
    require(fromMetaTy->getRepresentation() == MetatypeRepresentation::ObjC,
            "objc_metatype_to_object must take an @objc existential metatype value");
    require(OMOI->getType().isObject(),
            "objc_metatype_to_object must produce a value");
    require(OMOI->getType().getASTType()->isAnyObject(),
            "objc_metatype_to_object must produce an AnyObject value");
  }
  
  void checkKeyPathInst(KeyPathInst *KPI) {
    auto kpTy = KPI->getType();
    
    require(kpTy.isObject(), "keypath result must be an object type");
    
    auto kpBGT = kpTy.getAs<BoundGenericType>();
    require(kpBGT, "keypath result must be a generic type");
    auto &C = F.getASTContext();
    require(kpBGT->getDecl() == C.getKeyPathDecl()
            || kpBGT->getDecl() == C.getWritableKeyPathDecl()
            || kpBGT->getDecl() == C.getReferenceWritableKeyPathDecl(),
            "keypath result must be a key path type");
    
    auto baseTy = CanType(kpBGT->getGenericArgs()[0]);
    auto pattern = KPI->getPattern();
    SubstitutionMap patternSubs = KPI->getSubstitutions();
    requireSameType(
        baseTy, pattern->getRootType().subst(patternSubs)->getCanonicalType(),
        "keypath root type should match root type of keypath pattern");

    auto leafTy = CanType(kpBGT->getGenericArgs()[1]);
    requireSameType(
        leafTy, pattern->getValueType().subst(patternSubs)->getCanonicalType(),
        "keypath value type should match value type of keypath pattern");

    {
      for (auto &component : pattern->getComponents()) {
        bool hasIndices;
        switch (component.getKind()) {
        case KeyPathPatternComponent::Kind::GettableProperty:
        case KeyPathPatternComponent::Kind::SettableProperty:
          hasIndices = !component.getSubscriptIndices().empty();
          break;
        
        case KeyPathPatternComponent::Kind::StoredProperty:
        case KeyPathPatternComponent::Kind::OptionalChain:
        case KeyPathPatternComponent::Kind::OptionalWrap:
        case KeyPathPatternComponent::Kind::OptionalForce:
        case KeyPathPatternComponent::Kind::TupleElement:
          hasIndices = false;
          break;
        }
      
        verifyKeyPathComponent(F.getModule(), F.getResilienceExpansion(),
          [&](bool reqt, StringRef message) { _require(reqt, message); },
          baseTy,
          leafTy,
          component,
          KPI->getAllOperands(),
          KPI->getPattern()->getGenericSignature(),
          KPI->getSubstitutions(),
          /*property descriptor*/false,
          hasIndices);
      }
    }
    requireSameType(
        CanType(baseTy), CanType(leafTy),
        "final component should match leaf value type of key path type");
  }

  void checkIsEscapingClosureInst(IsEscapingClosureInst *IEC) {
    // The closure operand is allowed to be an optional closure.
    auto operandType = IEC->getOperand()->getType();
    if (operandType.getOptionalObjectType())
      operandType = operandType.getOptionalObjectType();

    auto fnType = operandType.getAs<SILFunctionType>();
    require(fnType && fnType->getExtInfo().hasContext() &&
                !fnType->isNoEscape() &&
                fnType->getExtInfo().getRepresentation() ==
                    SILFunctionTypeRepresentation::Thick,
            "is_escaping_closure must have a thick "
            "function operand");
    require(IEC->getVerificationType() == IsEscapingClosureInst::ObjCEscaping ||
                IEC->getVerificationType() ==
                    IsEscapingClosureInst::WithoutActuallyEscaping,
            "unknown verfication type");
  }

  void checkDifferentiableFunctionInst(DifferentiableFunctionInst *dfi) {
    // FIXME(TF-1197): Re-enable verification after substituted SIL function
    // types.
    return;
#if 0
    auto origTy =
        dfi->getOriginalFunction()->getType().getAs<SILFunctionType>();
    require(origTy, "The original function must have a function type");
    require(!origTy->isDifferentiable(),
            "The original function must not be @differentiable");
    // Skip verification in lowered SIL: LoadableByAddress changes
    // parameter/result conventions.
    // TODO: Check that derivative function types match excluding
    // parameter/result conventions in lowered SIL.
    if (F.getModule().getStage() == SILStage::Lowered)
      return;
    if (dfi->hasDerivativeFunctions()) {
      auto jvp = dfi->getJVPFunction();
      auto jvpType = jvp->getType().getAs<SILFunctionType>();
      require(jvpType, "The JVP function must have a function type");
      require(!jvpType->isDifferentiable(),
              "The JVP function must not be @differentiable");
      auto expectedJVPType = origTy->getAutoDiffDerivativeFunctionType(
          dfi->getParameterIndices(), dfi->getResultIndices(),
          AutoDiffDerivativeFunctionKind::JVP, TC,
          LookUpConformanceInModule(M));
      requireSameType(SILType::getPrimitiveObjectType(jvpType),
                      SILType::getPrimitiveObjectType(expectedJVPType),
                      "JVP type does not match expected JVP type");
      auto vjp = dfi->getVJPFunction();
      auto vjpType = vjp->getType().getAs<SILFunctionType>();
      require(vjpType, "The VJP function must have a function type");
      require(!vjpType->isDifferentiable(),
              "The VJP function must not be @differentiable");
      auto expectedVJPType = origTy->getAutoDiffDerivativeFunctionType(
          dfi->getParameterIndices(), dfi->getResultIndices(),
          AutoDiffDerivativeFunctionKind::VJP, TC,
          LookUpConformanceInModule(M));
      requireSameType(SILType::getPrimitiveObjectType(vjpType),
                      SILType::getPrimitiveObjectType(expectedVJPType),
                      "VJP type does not match expected VJP type");
    }
#endif
  }

  void checkLinearFunctionInst(LinearFunctionInst *lfi) {
    auto origTy =
        lfi->getOriginalFunction()->getType().getAs<SILFunctionType>();
    require(origTy, "The original function must have a function type");
    require(!origTy->isDifferentiable(),
            "The original function must not be differentiable");
    // Skip lowered SIL: LoadableByAddress changes parameter/result conventions.
    // TODO: Check that transpose function type matches excluding
    // parameter/result conventions in lowered SIL.
    if (F.getModule().getStage() == SILStage::Lowered)
      return;
    if (lfi->hasTransposeFunction()) {
      auto transpose = lfi->getTransposeFunction();
      auto transposeType = transpose->getType().getAs<SILFunctionType>();
      require(transposeType,
              "The transpose function must have a function type");
      require(!transposeType->isDifferentiable(),
              "The transpose function must not be differentiable");
      auto expectedTransposeType = origTy->getAutoDiffTransposeFunctionType(
          lfi->getParameterIndices(), TC, LookUpConformanceInModule(M));
      // TODO: Consider tightening verification. This requires changes to
      // `SILFunctionType::getAutoDiffTransposeFunctionType`.
      requireSameType(
          SILType::getPrimitiveObjectType(
              transposeType->getUnsubstitutedType(F.getModule())),
          SILType::getPrimitiveObjectType(
              expectedTransposeType->getUnsubstitutedType(F.getModule())),
          "Transpose type does not match expected transpose type");
    }
  }

  void checkDifferentiableFunctionExtractInst(
      DifferentiableFunctionExtractInst *dfei) {
    auto fnTy = dfei->getOperand()->getType().getAs<SILFunctionType>();
    require(fnTy, "The function operand must have a function type");
    require(fnTy->getDifferentiabilityKind() == DifferentiabilityKind::Normal,
            "The function operand must be a '@differentiable' function");
  }

  void checkLinearFunctionExtractInst(LinearFunctionExtractInst *lfei) {
    auto fnTy = lfei->getOperand()->getType().getAs<SILFunctionType>();
    require(fnTy, "The function operand must have a function type");
    require(fnTy->getDifferentiabilityKind() == DifferentiabilityKind::Linear,
            "The function operand must be a '@differentiable(linear)' "
            "function");
  }

  void checkDifferentiabilityWitnessFunctionInst(
      DifferentiabilityWitnessFunctionInst *dwfi) {
    auto witnessFnTy = dwfi->getType().castTo<SILFunctionType>();
    auto *witness = dwfi->getWitness();
    // `DifferentiabilityWitnessFunctionInst` constructor asserts that
    // `witness` is non-null.
    auto witnessKind = dwfi->getWitnessKind();
    // Return if not witnessing a derivative function.
    auto derivKind = witnessKind.getAsDerivativeFunctionKind();
    if (!derivKind)
      return;
    // Return if witness does not define the referenced derivative.
    auto *derivativeFn = witness->getDerivative(*derivKind);
    if (!derivativeFn)
      return;
    auto derivativeFnTy = derivativeFn->getLoweredFunctionType();
    requireSameType(SILType::getPrimitiveObjectType(witnessFnTy),
                    SILType::getPrimitiveObjectType(derivativeFnTy),
                    "Type of witness instruction does not match actual type of "
                    "witnessed function");
  }
  
  void checkGetAsyncContinuationInstBase(GetAsyncContinuationInstBase *GACI) {
    auto resultTy = GACI->getType();
    require(resultTy.is<BuiltinRawUnsafeContinuationType>(),
            "Instruction type must be a continuation type");
  }
  
  void checkGetAsyncContinuationInst(GetAsyncContinuationInst *GACI) {
    checkGetAsyncContinuationInstBase(GACI);
  }
  
  void checkGetAsyncContinuationAddrInst(GetAsyncContinuationAddrInst *GACI) {
    checkGetAsyncContinuationInstBase(GACI);

    requireSameType(GACI->getOperand()->getType(),
                    GACI->getLoweredResumeType().getAddressType(),
                    "Operand type must match continuation resume type");
  }
  
  void checkAwaitAsyncContinuationInst(AwaitAsyncContinuationInst *AACI) {
    // The operand must be a GetAsyncContinuation* instruction.
    auto cont = dyn_cast<GetAsyncContinuationInstBase>(AACI->getOperand());
    require(cont, "can only await the result of a get_async_continuation instruction");
    bool isAddressForm = isa<GetAsyncContinuationAddrInst>(cont);

    auto &C = cont->getType().getASTContext();
    
    // The shape of the successors depends on the continuation instruction being
    // awaited.
    require((bool)AACI->getErrorBB() == cont->throws(),
            "must have an error successor if and only if the continuation is throwing");
    if (cont->throws()) {
      require(AACI->getErrorBB()->getNumArguments() == 1,
              "error successor must take one argument");
      auto arg = AACI->getErrorBB()->getArgument(0);
      auto errorType = C.getErrorDecl()->getDeclaredType()->getCanonicalType();
      requireSameType(arg->getType(),
                      SILType::getPrimitiveObjectType(errorType),
              "error successor argument must have Error type");
      
      if (AACI->getFunction()->hasOwnership()) {
        require(arg->getOwnershipKind() == OwnershipKind::Owned,
                "error successor argument must be owned");
      }
    }
    if (isAddressForm) {
      require(AACI->getResumeBB()->getNumArguments() == 0,
              "resume successor must take no arguments for get_async_continuation_addr");
    } else {
      require(AACI->getResumeBB()->getNumArguments() == 1,
              "resume successor must take one argument for get_async_continuation");
      auto arg = AACI->getResumeBB()->getArgument(0);

      requireSameType(arg->getType(), cont->getLoweredResumeType(),
                      "resume successor must take an argument of the continuation resume type");
      if (AACI->getFunction()->hasOwnership()) {
        require(arg->getOwnershipKind() == OwnershipKind::Owned,
                "resume successor argument must be owned");
      }
    }
  }

  // This verifies that the entry block of a SIL function doesn't have
  // any predecessors and also verifies the entry point arguments.
  void verifyEntryBlock(SILBasicBlock *entry) {
    require(entry->pred_empty(), "entry block cannot have predecessors");

    LLVM_DEBUG(
        llvm::dbgs() << "Argument types for entry point BB:\n";
        for (auto *arg
             : make_range(entry->args_begin(), entry->args_end()))
            arg->getType()
                .dump();
        llvm::dbgs() << "Input types for SIL function type ";
        F.getLoweredFunctionType()->print(llvm::dbgs()); llvm::dbgs() << ":\n";
        for (auto paramTy
             : fnConv.getParameterSILTypes(F.getTypeExpansionContext())) {
          paramTy.dump();
        });

    require(entry->args_size() == (fnConv.getNumIndirectSILResults()
                                   + fnConv.getNumParameters()),
            "entry point has wrong number of arguments");

    bool matched = true;
    auto argI = entry->args_begin();

    auto check = [&](const char *what, SILType ty) {
      auto mappedTy = F.mapTypeIntoContext(ty);
      SILArgument *bbarg = *argI;
      ++argI;
      if (bbarg->getType() != mappedTy &&
          bbarg->getType() != F.getLoweredType(mappedTy.getASTType())
                                  .getCategoryType(mappedTy.getCategory())) {
        llvm::errs() << what << " type mismatch!\n";
        llvm::errs() << "  argument: "; bbarg->dump();
        llvm::errs() << "  expected: "; mappedTy.dump();
        matched = false;
      }

      // If we do not have qualified ownership, do not check ownership.
      if (!F.hasOwnership()) {
        return;
      }

      auto ownershipkind = ValueOwnershipKind(
          F, mappedTy, fnConv.getSILArgumentConvention(bbarg->getIndex()));

      if (bbarg->getOwnershipKind() != ownershipkind) {
        llvm::errs() << what << " ownership kind mismatch!\n";
        llvm::errs() << "  argument: " << bbarg->getOwnershipKind() << '\n';
        llvm::errs() << "  expected: " << ownershipkind << '\n';
        matched = false;
      }
    };

    for (auto result : fnConv.getIndirectSILResults()) {
      assert(fnConv.isSILIndirect(result));
      check("indirect result",
            fnConv.getSILType(result, F.getTypeExpansionContext()));
    }
    for (auto param : F.getLoweredFunctionType()->getParameters()) {
      check("parameter", fnConv.getSILType(param, F.getTypeExpansionContext()));
    }

    require(matched, "entry point argument types do not match function type");

    // TBAA requirement for all address arguments.
    require(std::equal(entry->args_begin() + fnConv.getNumIndirectSILResults(),
                       entry->args_end(),
                       fnConv.funcTy->getParameters().begin(),
                       [&](SILArgument *bbarg, SILParameterInfo paramInfo) {
                         if (!bbarg->getType().isAddress())
                           return true;
                         switch (paramInfo.getConvention()) {
                         default:
                           return false;
                         case ParameterConvention::Indirect_In:
                         case ParameterConvention::Indirect_In_Constant:
                         case ParameterConvention::Indirect_Inout:
                         case ParameterConvention::Indirect_InoutAliasable:
                         case ParameterConvention::Indirect_In_Guaranteed:
                           return true;
                         }
                       }),
            "entry point address argument must have an indirect calling "
            "convention");
  }

  void verifyEpilogBlocks(SILFunction *F) {
    bool FoundReturnBlock = false;
    bool FoundThrowBlock = false;
    bool FoundUnwindBlock = false;
    for (auto &BB : *F) {
      if (isa<ReturnInst>(BB.getTerminator())) {
        require(!FoundReturnBlock,
                "more than one return block in function");
        FoundReturnBlock = true;
      } else if (isa<ThrowInst>(BB.getTerminator())) {
        require(!FoundThrowBlock,
                "more than one throw block in function");
        FoundThrowBlock = true;
      } else if (isa<UnwindInst>(BB.getTerminator())) {
        require(!FoundUnwindBlock,
                "more than one unwind block in function");
        FoundUnwindBlock = true;
      } else {
        assert(!BB.getTerminator()->isFunctionExiting());
      }
    }
  }

  bool isUnreachableAlongAllPathsStartingAt(
      SILBasicBlock *StartBlock, SmallPtrSetImpl<SILBasicBlock *> &Visited) {
    if (isa<UnreachableInst>(StartBlock->getTerminator()))
      return true;
    else if (isa<ReturnInst>(StartBlock->getTerminator()))
      return false;
    else if (isa<ThrowInst>(StartBlock->getTerminator()))
      return false;

    // Recursively check all successors.
    for (auto *SuccBB : StartBlock->getSuccessorBlocks())
      if (!Visited.insert(SuccBB).second)
        if (!isUnreachableAlongAllPathsStartingAt(SuccBB, Visited))
          return false;

    return true;
  }

  void verifySILFunctionType(CanSILFunctionType FTy) {
    // Make sure that if FTy's calling convention implies that it must have a
    // self parameter.
    require(!FTy->hasSelfParam() || !FTy->getParameters().empty(),
            "Functions with a calling convention with self parameter must "
            "have at least one argument for self.");
  }

  struct VerifyFlowSensitiveRulesDetails {
    enum CFGState {
      /// No special rules are in play.
      Normal,
      /// We've followed the resume edge of a yield in a yield_once coroutine.
      YieldOnceResume,
      /// We've followed the unwind edge of a yield.
      YieldUnwind
    };

    struct BBState {
      std::vector<SingleValueInstruction*> Stack;

      /// Contents: BeginAccessInst*, BeginApplyInst*.
      std::set<SILInstruction*> ActiveOps;

      CFGState CFG = Normal;
      
      GetAsyncContinuationInstBase *GotAsyncContinuation = nullptr;
    };
  };

  /// Verify the various control-flow-sensitive rules of SIL:
  ///
  /// - stack allocations and deallocations must obey a stack discipline
  /// - accesses must be uniquely ended
  /// - async continuations must be awaited before getting the continuation again, suspending
  ///  the task, or exiting the function
  /// - flow-sensitive states must be equivalent on all paths into a block
  void verifyFlowSensitiveRules(SILFunction *F) {
    // Do a traversal of the basic blocks.
    // Note that we intentionally don't verify these properties in blocks
    // that can't be reached from the entry block.
    llvm::DenseMap<SILBasicBlock*, VerifyFlowSensitiveRulesDetails::BBState> visitedBBs;
    SmallVector<SILBasicBlock*, 16> Worklist;
    visitedBBs.try_emplace(&*F->begin());
    Worklist.push_back(&*F->begin());
    while (!Worklist.empty()) {
      SILBasicBlock *BB = Worklist.pop_back_val();
      VerifyFlowSensitiveRulesDetails::BBState state = visitedBBs[BB];
      for (SILInstruction &i : *BB) {
        CurInstruction = &i;

        if (i.maySuspend()) {
          // Instructions that may suspend an async context must not happen
          // while the continuation is being accessed, with the exception of
          // the AwaitAsyncContinuationInst that completes suspending the task.
          if (auto aaci = dyn_cast<AwaitAsyncContinuationInst>(&i)) {
            require(state.GotAsyncContinuation == aaci->getOperand(),
                    "encountered await_async_continuation that doesn't match active gotten continuation");
            state.GotAsyncContinuation = nullptr;
          } else {
            require(!state.GotAsyncContinuation,
                    "cannot suspend async task while unawaited continuation is active");
          }
        }
          
        if (i.isAllocatingStack()) {
          state.Stack.push_back(cast<SingleValueInstruction>(&i));

        } else if (i.isDeallocatingStack()) {
          SILValue op = i.getOperand(0);
          require(!state.Stack.empty(),
                  "stack dealloc with empty stack");
          if (op != state.Stack.back()) {
            llvm::errs() << "Recent stack alloc: " << *state.Stack.back();
            require(op == state.Stack.back(),
                    "stack dealloc does not match most recent stack alloc");
          }
          state.Stack.pop_back();

        } else if (isa<BeginAccessInst>(i) || isa<BeginApplyInst>(i)) {
          bool notAlreadyPresent = state.ActiveOps.insert(&i).second;
          require(notAlreadyPresent,
                  "operation was not ended before re-beginning it");

        } else if (isa<EndAccessInst>(i) || isa<AbortApplyInst>(i) ||
                   isa<EndApplyInst>(i)) {
          if (auto beginOp = i.getOperand(0)->getDefiningInstruction()) {
            bool present = state.ActiveOps.erase(beginOp);
            require(present, "operation has already been ended");
          }
        } else if (auto gaci = dyn_cast<GetAsyncContinuationInstBase>(&i)) {
          require(!state.GotAsyncContinuation,
                  "get_async_continuation while unawaited continuation is already active");
          state.GotAsyncContinuation = gaci;
        } else if (auto term = dyn_cast<TermInst>(&i)) {
          if (term->isFunctionExiting()) {
            require(state.Stack.empty(),
                    "return with stack allocs that haven't been deallocated");
            require(state.ActiveOps.empty(),
                    "return with operations still active");
            require(!state.GotAsyncContinuation,
                    "return with unawaited async continuation");

            if (isa<UnwindInst>(term)) {
              require(state.CFG == VerifyFlowSensitiveRulesDetails::YieldUnwind,
                      "encountered 'unwind' when not on unwind path");
            } else {
              require(state.CFG != VerifyFlowSensitiveRulesDetails::YieldUnwind,
                      "encountered 'return' or 'throw' when on unwind path");
              if (isa<ReturnInst>(term) &&
                  F->getLoweredFunctionType()->getCoroutineKind() ==
                    SILCoroutineKind::YieldOnce &&
                  F->getModule().getStage() != SILStage::Raw) {
                require(state.CFG == VerifyFlowSensitiveRulesDetails::YieldOnceResume,
                        "encountered 'return' before yielding a value in "
                        "yield_once coroutine");
              }
            }
          }
          
          if (isa<YieldInst>(term)) {
            require(state.CFG != VerifyFlowSensitiveRulesDetails::YieldOnceResume,
                    "encountered multiple 'yield's along single path");
            require(state.CFG == VerifyFlowSensitiveRulesDetails::Normal,
                    "encountered 'yield' on abnormal CFG path");
            require(!state.GotAsyncContinuation,
                    "encountered 'yield' while an unawaited continuation is active");
          }

          auto successors = term->getSuccessors();
          for (auto i : indices(successors)) {
            SILBasicBlock *succBB = successors[i].getBB();

            // Optimistically try to set our current state as the state
            // of the successor.  We can use a move on the final successor;
            // note that if the insertion fails, the move won't actually
            // happen, which is important because we'll still need it
            // to compare against the already-recorded state for the block.
            auto insertResult =
              i + 1 == successors.size()
                ? visitedBBs.try_emplace(succBB, std::move(state))
                : visitedBBs.try_emplace(succBB, state);

            // If the insertion was successful, add the successor to the
            // worklist and continue.
            if (insertResult.second) {
              Worklist.push_back(succBB);

              // If we're following a 'yield', update the CFG state:
              if (isa<YieldInst>(term)) {
                // Enforce that the unwind logic is segregated in all stages.
                if (i == 1) {
                  insertResult.first->second.CFG = VerifyFlowSensitiveRulesDetails::YieldUnwind;

                // We check the yield_once rule in the mandatory analyses,
                // so we can't assert it yet in the raw stage.
                } else if (F->getLoweredFunctionType()->getCoroutineKind()
                             == SILCoroutineKind::YieldOnce && 
                           F->getModule().getStage() != SILStage::Raw) {
                  insertResult.first->second.CFG = VerifyFlowSensitiveRulesDetails::YieldOnceResume;
                }
              }

              continue;
            }

            // This rule is checked elsewhere, but we'd want to assert it
            // here anyway.
            require(!isa<YieldInst>(term),
                    "successor of 'yield' should not be encountered twice");

            // Check that the stack height is consistent coming from all entry
            // points into this BB. We only care about consistency if there is
            // a possible return from this function along the path starting at
            // this successor bb.  (FIXME: Why? Infinite loops should still
            // preserve consistency...)
            auto isUnreachable = [&] {
              SmallPtrSet<SILBasicBlock *, 16> visited;
              return isUnreachableAlongAllPathsStartingAt(succBB, visited);
            };
            
            const auto &foundState = insertResult.first->second;
            require(state.Stack == foundState.Stack || isUnreachable(),
                    "inconsistent stack heights entering basic block");
            require(state.ActiveOps == foundState.ActiveOps || isUnreachable(),
                    "inconsistent active-operations sets entering basic block");
            require(state.CFG == foundState.CFG,
                    "inconsistent coroutine states entering basic block");
            require(state.GotAsyncContinuation == foundState.GotAsyncContinuation,
                    "inconsistent active async continuations entering basic block");
          }
        }
      }
    }
  }

  void verifyBranches(const SILFunction *F) {
    // Verify no critical edge.
    auto requireNonCriticalSucc = [this](const TermInst *termInst,
                                         const Twine &message) {
      // A critical edge has more than one outgoing edges from the source
      // block.
      auto succBlocks = termInst->getSuccessorBlocks();
      if (succBlocks.size() <= 1)
        return;

      for (const SILBasicBlock *destBB : succBlocks) {
        // And its destination block has more than one predecessor.
        _require(destBB->getSinglePredecessorBlock(), message);
      }
    };

    for (auto &bb : *F) {
      const TermInst *termInst = bb.getTerminator();
      CurInstruction = termInst;

      if (isSILOwnershipEnabled() && F->hasOwnership()) {
        requireNonCriticalSucc(termInst, "critical edges not allowed in OSSA");
      }
      // In Lowered SIL, they are allowed on conditional branches only.
      if (!AllowCriticalEdges && !isa<CondBranchInst>(termInst)) {
        requireNonCriticalSucc(termInst, "only cond_br critical edges allowed");
      }
    }
  }

  void verifyOpenedArchetypes(SILFunction *F) {
    require(OpenedArchetypes.getFunction() == F,
           "Wrong SILFunction provided to verifyOpenedArchetypes");
    // Check that definitions of all opened archetypes from
    // OpenedArchetypesDefs are existing instructions
    // belonging to the function F.
    for (auto KV: OpenedArchetypes.getOpenedArchetypeDefs()) {
      require(getOpenedArchetypeOf(CanType(KV.first)),
              "Only opened archetypes should be registered in SILFunction");
      auto Def = cast<SILInstruction>(KV.second);
      require(Def->getFunction() == F, 
              "Definition of every registered opened archetype should be an"
              " existing instruction in a current SILFunction");
    }
  }

  /// This pass verifies that there are no hole in debug scopes at -Onone.
  void verifyDebugScopeHoles(SILBasicBlock *BB) {
    if (!VerifyDIHoles)
      return;

    // This check only makes sense at -Onone. Optimizations,
    // e.g. inlining, can move scopes around.
    llvm::DenseSet<const SILDebugScope *> AlreadySeenScopes;
    if (BB->getParent()->getEffectiveOptimizationMode() !=
        OptimizationMode::NoOptimization)
      return;

    // Exit early if this BB is empty.
    if (BB->empty())
      return;

    const SILDebugScope *LastSeenScope = nullptr;
    for (SILInstruction &SI : *BB) {
      if (SI.isMetaInstruction())
        continue;
      LastSeenScope = SI.getDebugScope();
      AlreadySeenScopes.insert(LastSeenScope);
      break;
    }
    for (SILInstruction &SI : *BB) {
      if (SI.isMetaInstruction())
        continue;

      // If we haven't seen this debug scope yet, update the
      // map and go on.
      auto *DS = SI.getDebugScope();
      assert(DS && "Each instruction should have a debug scope");
      if (!AlreadySeenScopes.count(DS)) {
        AlreadySeenScopes.insert(DS);
        LastSeenScope = DS;
        continue;
      }

      // Otherwise, we're allowed to re-enter a scope only if
      // the scope is an ancestor of the scope we're currently leaving.
      auto isAncestorScope = [](const SILDebugScope *Cur,
                                const SILDebugScope *Previous) {
        const SILDebugScope *Tmp = Previous;
        assert(Tmp && "scope can't be null");
        while (Tmp) {
          PointerUnion<const SILDebugScope *, SILFunction *> Parent =
              Tmp->Parent;
          auto *ParentScope = Parent.dyn_cast<const SILDebugScope *>();
          if (!ParentScope)
            break;
          if (ParentScope == Cur)
            return true;
          Tmp = ParentScope;
        }
        return false;
      };

      if (isAncestorScope(DS, LastSeenScope)) {
        LastSeenScope = DS;
        continue;
      }
      if (DS != LastSeenScope) {
        LLVM_DEBUG(llvm::dbgs() << "Broken instruction!\n"; SI.dump());
        LLVM_DEBUG(llvm::dbgs() << "Please report a bug on bugs.swift.org\n");
        LLVM_DEBUG(llvm::dbgs() <<
          "Pass -Xllvm -verify-di-holes=false to disable the verification\n");
        require(
            DS == LastSeenScope,
            "Basic block contains a non-contiguous lexical scope at -Onone");
      }
    }
  }

  void visitSILBasicBlock(SILBasicBlock *BB) {
    // Make sure that each of the successors/predecessors of this basic block
    // have this basic block in its predecessor/successor list.
    for (const auto *SuccBB : BB->getSuccessorBlocks()) {
      require(SuccBB->isPredecessorBlock(BB),
              "Must be a predecessor of each successor.");
    }

    for (const SILBasicBlock *PredBB : BB->getPredecessorBlocks()) {
      require(PredBB->isSuccessorBlock(BB),
              "Must be a successor of each predecessor.");
    }
    
    SILInstructionVisitor::visitSILBasicBlock(BB);
    verifyDebugScopeHoles(BB);
  }

  void visitBasicBlockArguments(SILBasicBlock *BB) {
    CurInstruction = nullptr;
    for (auto argI = BB->args_begin(), argEnd = BB->args_end(); argI != argEnd;
         ++argI)
      visitSILArgument(*argI);
  }

  void visitSILBasicBlocks(SILFunction *F) {
    // Visit all basic blocks in the RPOT order.
    // This ensures that any open_existential instructions, which
    // open archetypes, are seen before the uses of these archetypes.
    llvm::ReversePostOrderTraversal<SILFunction *> RPOT(F);
    llvm::DenseSet<SILBasicBlock *> VisitedBBs;
    for (auto Iter = RPOT.begin(), E = RPOT.end(); Iter != E; ++Iter) {
      auto *BB = *Iter;
      VisitedBBs.insert(BB);
      visitSILBasicBlock(BB);
    }

    // Visit all basic blocks that were not visited during the RPOT traversal,
    // e.g. unreachable basic blocks.
    for (auto &BB : *F) {
      if (VisitedBBs.count(&BB))
        continue;
      visitSILBasicBlock(&BB);
    }
  }

  void visitSILFunction(SILFunction *F) {
    PrettyStackTraceSILFunction stackTrace("verifying", F);

    CanSILFunctionType FTy = F->getLoweredFunctionType();
    verifySILFunctionType(FTy);

    // Don't verify functions that were skipped. We are likely to see them in
    // FunctionBodySkipping::NonInlinableWithoutTypes mode.
    auto Ctx = F->getDeclContext();
    if (Ctx) {
      if (auto AFD = dyn_cast<AbstractFunctionDecl>(Ctx)) {
        if (AFD->isBodySkipped())
          return;
      }
    }

    if (F->isExternalDeclaration()) {
      if (F->hasForeignBody())
        return;

      require(F->isAvailableExternally(),
              "external declaration of internal SILFunction not allowed");
      // If F is an external declaration, there is nothing further to do,
      // return.
      return;
    }

    assert(!F->hasForeignBody());

    // Make sure that our SILFunction only has context generic params if our
    // SILFunctionType is non-polymorphic.
    if (F->getGenericEnvironment()) {
      require(FTy->isPolymorphic(),
              "non-generic function definitions cannot have a "
              "generic environment");
    } else {
      require(!FTy->isPolymorphic(),
              "generic function definition must have a generic environment");
    }

    // Otherwise, verify the body of the function.
    verifyEntryBlock(&*F->getBlocks().begin());
    verifyEpilogBlocks(F);
    verifyFlowSensitiveRules(F);
    verifyBranches(F);

    visitSILBasicBlocks(F);

    // Verify archetypes after all basic blocks are visited,
    // because we build the map of archetypes as we visit the
    // instructions.
    verifyOpenedArchetypes(F);

    if (F->hasOwnership() && F->shouldVerifyOwnership() &&
        !F->getModule().getASTContext().hadError()) {
      verifyMemoryLifetime(F);
    }
  }

  void verify() {
    visitSILFunction(const_cast<SILFunction*>(&F));
  }
};
} // end anonymous namespace

#undef require
#undef requireObjectType

//===----------------------------------------------------------------------===//
//                     Out of Line Verifier Run Functions
//===----------------------------------------------------------------------===//

static bool verificationEnabled(const SILModule &M) {
#ifdef NDEBUG
  if (!M.getOptions().VerifyAll)
    return false;
#endif
  return !M.getOptions().VerifyNone;
}

/// verify - Run the SIL verifier to make sure that the SILFunction follows
/// invariants.
void SILFunction::verify(bool SingleFunction) const {
  if (!verificationEnabled(getModule()))
    return;

  // Please put all checks in visitSILFunction in SILVerifier, not here. This
  // ensures that the pretty stack trace in the verifier is included with the
  // back trace when the verifier crashes.
  SILVerifier(*this, SingleFunction).verify();
}

void SILFunction::verifyCriticalEdges() const {
  if (!verificationEnabled(getModule()))
    return;

  SILVerifier(*this, /*SingleFunction=*/true).verifyBranches(this);
}

/// Verify that a property descriptor follows invariants.
void SILProperty::verify(const SILModule &M) const {
  if (!verificationEnabled(M))
    return;

  auto *decl = getDecl();
  auto *dc = decl->getInnermostDeclContext();
  
  // TODO: base type for global/static descriptors
  auto sig = dc->getGenericSignatureOfContext();
  auto baseTy = dc->getInnermostTypeContext()->getSelfInterfaceType()
                  ->getCanonicalType(sig);
  auto leafTy = decl->getValueInterfaceType()->getCanonicalType(sig);
  SubstitutionMap subs;
  if (sig) {
    auto env = dc->getGenericEnvironmentOfContext();
    subs = env->getForwardingSubstitutionMap();
    baseTy = env->mapTypeIntoContext(baseTy)->getCanonicalType();
    leafTy = env->mapTypeIntoContext(leafTy)->getCanonicalType();
  }
  bool hasIndices = false;
  if (auto subscript = dyn_cast<SubscriptDecl>(decl)) {
    hasIndices = subscript->getIndices()->size() != 0;
  }

  auto canSig = sig.getCanonicalSignature();

  auto require = [&](bool reqt, StringRef message) {
      if (!reqt) {
        llvm::errs() << message << "\n";
        assert(false && "invoking standard assertion failure");
      }
    };

  if (auto &component = getComponent()) {
    verifyKeyPathComponent(const_cast<SILModule&>(M),
                           ResilienceExpansion::Maximal,
                           require,
                           baseTy,
                           leafTy,
                           *component,
                           {},
                           canSig,
                           subs,
                           /*property descriptor*/true,
                           hasIndices);
    // verifyKeyPathComponent updates baseTy to be the projected type of the
    // component, which should be the same as the type of the declared storage
    require(baseTy == leafTy,
            "component type of property descriptor should match type of storage");
  }
}

/// Verify that a vtable follows invariants.
void SILVTable::verify(const SILModule &M) const {
  if (!verificationEnabled(M))
    return;
  
  // Compare against the base class vtable if there is one.
  const SILVTable *superVTable = nullptr;
  auto superclass = getClass()->getSuperclassDecl();
  if (superclass) {
    for (auto &vt : M.getVTables()) {
      if (vt->getClass() == superclass) {
        superVTable = vt;
        break;
      }
    }
  }
  
  for (unsigned i : indices(getEntries())) {
    auto &entry = getEntries()[i];
    
    // Make sure the module's lookup cache is consistent.
    assert(entry == *getEntry(const_cast<SILModule &>(M), entry.getMethod())
           && "vtable entry is out of sync with method's vtable cache");
    
    // All vtable entries must be decls in a class context.
    assert(entry.getMethod().hasDecl() && "vtable entry is not a decl");
    auto baseInfo = M.Types.getConstantInfo(TypeExpansionContext::minimal(),
                                            entry.getMethod());
    ValueDecl *decl = entry.getMethod().getDecl();

    assert((!isa<AccessorDecl>(decl)
            || !cast<AccessorDecl>(decl)->isObservingAccessor())
           && "observing accessors shouldn't have vtable entries");

    // For ivar destroyers, the decl is the class itself.
    ClassDecl *theClass;
    if (entry.getMethod().kind == SILDeclRef::Kind::IVarDestroyer)
      theClass = dyn_cast<ClassDecl>(decl);
    else
      theClass = dyn_cast<ClassDecl>(decl->getDeclContext());

    assert(theClass && "vtable entry must refer to a class member");

    // The class context must be the vtable's class, or a superclass thereof.
    assert(theClass->isSuperclassOf(getClass()) &&
           "vtable entry must refer to a member of the vtable's class");

    // Foreign entry points shouldn't appear in vtables.
    assert(!entry.getMethod().isForeign && "vtable entry must not be foreign");

    // The vtable entry must be ABI-compatible with the overridden vtable slot.
    SmallString<32> baseName;
    {
      llvm::raw_svector_ostream os(baseName);
      entry.getMethod().print(os);
    }

    if (M.getStage() != SILStage::Lowered) {
      SILVerifier(*entry.getImplementation())
          .requireABICompatibleFunctionTypes(
              baseInfo.getSILType().castTo<SILFunctionType>(),
              entry.getImplementation()->getLoweredFunctionType(),
              "vtable entry for " + baseName + " must be ABI-compatible",
              *entry.getImplementation());
    }
    
    // Validate the entry against its superclass vtable.
    if (!superclass) {
      // Root methods should not have inherited or overridden entries.
      bool validKind;
      switch (entry.getKind()) {
      case Entry::Normal:
        validKind = true;
        break;
        
      case Entry::Inherited:
      case Entry::Override:
        validKind = false;
        break;
      }
      assert(validKind && "vtable entry in root class must not be inherited or override");
    } else if (superVTable) {
      // Validate the entry against the matching entry from the superclass
      // vtable.

      const Entry *superEntry = nullptr;
      for (auto &se : superVTable->getEntries()) {
        if (se.getMethod().getOverriddenVTableEntry() ==
            entry.getMethod().getOverriddenVTableEntry()) {
          superEntry = &se;
          break;
        }
      }

      switch (entry.getKind()) {
      case Entry::Normal:
        assert(!superEntry && "non-root vtable entry must be inherited or override");
        break;

      case Entry::Inherited:
        if (!superEntry)
          break;

        assert(entry.isNonOverridden() == superEntry->isNonOverridden()
               && "inherited vtable entry must share overridden-ness of superclass entry");
        break;
          
      case Entry::Override:
        assert(!entry.isNonOverridden()
               && "override entry can't claim to be nonoverridden");
        if (!superEntry)
          break;

        // The superclass entry must not prohibit overrides.
        assert(!superEntry->isNonOverridden()
               && "vtable entry overrides an entry that claims to have no overrides");
        // TODO: Check the root vtable entry for the method too.
        break;
      }
    }
  }
}

/// Verify that a witness table follows invariants.
void SILWitnessTable::verify(const SILModule &M) const {
  if (!verificationEnabled(M))
    return;

  if (isDeclaration())
    assert(getEntries().empty() &&
           "A witness table declaration should not have any entries.");

  for (const Entry &E : getEntries())
    if (E.getKind() == SILWitnessTable::WitnessKind::Method) {
      SILFunction *F = E.getMethodWitness().Witness;
      if (F) {
        // If a SILWitnessTable is going to be serialized, it must only
        // reference public or serializable functions.
        if (isSerialized()) {
          assert(F->hasValidLinkageForFragileRef() &&
                 "Fragile witness tables should not reference "
                 "less visible functions.");
        }

        assert(F->getLoweredFunctionType()->getRepresentation() ==
               SILFunctionTypeRepresentation::WitnessMethod &&
               "Witnesses must have witness_method representation.");
      }
    }
}

/// Verify that a default witness table follows invariants.
void SILDefaultWitnessTable::verify(const SILModule &M) const {
#ifndef NDEBUG
  for (const Entry &E : getEntries()) {
    // FIXME: associated type witnesses.
    if (!E.isValid() || E.getKind() != SILWitnessTable::Method)
      continue;

    SILFunction *F = E.getMethodWitness().Witness;

#if 0
    // FIXME: For now, all default witnesses are private.
    assert(F->hasValidLinkageForFragileRef() &&
           "Default witness tables should not reference "
           "less visible functions.");
#endif

    assert(F->getLoweredFunctionType()->getRepresentation() ==
           SILFunctionTypeRepresentation::WitnessMethod &&
           "Default witnesses must have witness_method representation.");
  }
#endif
}

/// Verify that a global variable follows invariants.
void SILGlobalVariable::verify() const {
  if (!verificationEnabled(getModule()))
    return;

  assert(getLoweredType().isObject()
         && "global variable cannot have address type");

  // Verify the static initializer.
  for (const SILInstruction &I : StaticInitializerBlock) {
    assert(isValidStaticInitializerInst(&I, getModule()) &&
           "illegal static initializer");
    auto init = cast<SingleValueInstruction>(&I);
    if (init == &StaticInitializerBlock.back()) {
      assert(init->use_empty() && "Init value must not have another use");
    } else {
      assert(!init->use_empty() && "dead instruction in static initializer");
      assert(!isa<ObjectInst>(init) &&
             "object instruction is only allowed for final initial value");
    }
    assert(I.getParent() == &StaticInitializerBlock);
  }
}

// SWIFT_ENABLE_TENSORFLOW
/// Verify that a differentiability witness follows invariants.
void SILDifferentiabilityWitness::verify(const SILModule &M) const {
  // FIXME(TF-1197): Re-enable verification after substituted SIL function
  // types.
  return;
#if 0
#ifdef NDEBUG
  if (!M.getOptions().VerifyAll)
    return;
#endif
  // Skip lowered SIL: LoadableByAddress changes parameter/result conventions.
  // TODO: Check that derivative function types match excluding
  // parameter/result conventions in lowered SIL.
  if (M.getStage() == SILStage::Lowered)
    return;
  auto *origFn = getOriginalFunction();
  auto origFnType = origFn->getLoweredFunctionType();
  bool origIsReabstractionThunk = origFn->isThunk() == IsReabstractionThunk;
  CanGenericSignature derivativeCanGenSig;
  if (auto derivativeGenSig = getDerivativeGenericSignature())
    derivativeCanGenSig = derivativeGenSig->getCanonicalSignature();
  auto requireSameType =
      [&](CanSILFunctionType type1, CanSILFunctionType type2,
          const Twine &complaint) {
    if (type1 == type2)
      return;
    llvm::dbgs() << "SIL verification failed: " << complaint << "\n";
    llvm::dbgs() << "  " << type1 << "\n  " << type2 << "\n\n";
    llvm::dbgs() << "In differentiability witness:\n";
    print(llvm::dbgs());
    // We abort by default because we want to always crash in
    // the debugger.
    if (AbortOnFailure)
      abort();
    else
      exit(1);
  };
  if (auto *jvp = getJVP()) {
    // TODO(TF-893): Change `SILFunctionType::getAutoDiffDerivativeFunctionType`
    // to accept result indices.
    auto expectedJVPType = origFnType->getAutoDiffDerivativeFunctionType(
        getParameterIndices(), /*resultIndex*/ *getResultIndices()->begin(),
        AutoDiffDerivativeFunctionKind::JVP, M.Types,
        LookUpConformanceInModule(M.getSwiftModule()), derivativeCanGenSig,
        origIsReabstractionThunk);
    requireSameType(jvp->getLoweredFunctionType(), expectedJVPType,
                    "JVP type does not match expected JVP type");
  }
  if (auto *vjp = getVJP()) {
    // TODO(TF-893): Change `SILFunctionType::getAutoDiffDerivativeFunctionType`
    // to result indices.
    auto expectedVJPType = origFnType->getAutoDiffDerivativeFunctionType(
        getParameterIndices(), /*resultIndex*/ *getResultIndices()->begin(),
        AutoDiffDerivativeFunctionKind::VJP, M.Types,
        LookUpConformanceInModule(M.getSwiftModule()), derivativeCanGenSig,
        origIsReabstractionThunk);
    requireSameType(vjp->getLoweredFunctionType(), expectedVJPType,
                    "VJP type does not match expected VJP type");
  }
#endif
}
// SWIFT_ENABLE_TENSORFLOW END

/// Verify the module.
void SILModule::verify() const {
  if (!verificationEnabled(*this))
    return;

  checkForLeaks();

  // Uniquing set to catch symbol name collisions.
  llvm::DenseSet<StringRef> symbolNames;

  // Check all functions.
  for (const SILFunction &f : *this) {
    if (!symbolNames.insert(f.getName()).second) {
      llvm::errs() << "Symbol redefined: " << f.getName() << "!\n";
      assert(false && "triggering standard assertion failure routine");
    }
    f.verify(/*singleFunction*/ false);
  }

  // Check all globals.
  for (const SILGlobalVariable &g : getSILGlobals()) {
    if (!symbolNames.insert(g.getName()).second) {
      llvm::errs() << "Symbol redefined: " << g.getName() << "!\n";
      assert(false && "triggering standard assertion failure routine");
    }
    g.verify();
  }

  // Check all vtables and the vtable cache.
  llvm::DenseSet<ClassDecl*> vtableClasses;
  unsigned EntriesSZ = 0;
  for (const auto &vt : getVTables()) {
    if (!vtableClasses.insert(vt->getClass()).second) {
      llvm::errs() << "Vtable redefined: " << vt->getClass()->getName() << "!\n";
      assert(false && "triggering standard assertion failure routine");
    }
    vt->verify(*this);
    // Check if there is a cache entry for each vtable entry
    for (auto entry : vt->getEntries()) {
      if (VTableEntryCache.find({vt, entry.getMethod()}) ==
          VTableEntryCache.end()) {
        llvm::errs() << "Vtable entry for function: "
                     << entry.getImplementation()->getName()
                     << "not in cache!\n";
        assert(false && "triggering standard assertion failure routine");
      }
      ++EntriesSZ;
    }
  }
  assert(EntriesSZ == VTableEntryCache.size() &&
         "Cache size is not equal to true number of VTable entries");

  // Check all witness tables.
  LLVM_DEBUG(llvm::dbgs() <<"*** Checking witness tables for duplicates ***\n");
  llvm::DenseSet<RootProtocolConformance*> wtableConformances;
  for (const SILWitnessTable &wt : getWitnessTables()) {
    LLVM_DEBUG(llvm::dbgs() << "Witness Table:\n"; wt.dump());
    auto conformance = wt.getConformance();
    if (!wtableConformances.insert(conformance).second) {
      llvm::errs() << "Witness table redefined: ";
      conformance->printName(llvm::errs());
      assert(false && "triggering standard assertion failure routine");
    }
    wt.verify(*this);
  }

  // Check all default witness tables.
  LLVM_DEBUG(llvm::dbgs() << "*** Checking default witness tables for "
             "duplicates ***\n");
  llvm::DenseSet<const ProtocolDecl *> defaultWitnessTables;
  for (const SILDefaultWitnessTable &wt : getDefaultWitnessTables()) {
    LLVM_DEBUG(llvm::dbgs() << "Default Witness Table:\n"; wt.dump());
    if (!defaultWitnessTables.insert(wt.getProtocol()).second) {
      llvm::errs() << "Default witness table redefined: ";
      wt.dump();
      assert(false && "triggering standard assertion failure routine");
    }
    wt.verify(*this);
  }

  // SWIFT_ENABLE_TENSORFLOW
  // Check all differentiability witnesses.
  LLVM_DEBUG(llvm::dbgs() <<
             "*** Checking differentiability witnesses for duplicates ***\n");
  llvm::DenseSet<SILDifferentiabilityWitnessKey> diffWitnesses;
  for (auto &dw : getDifferentiabilityWitnesses()) {
    LLVM_DEBUG(llvm::dbgs() << "Differentiability Witness:\n"; dw.dump());
    if (!diffWitnesses.insert(dw.getKey()).second) {
      llvm::errs() << "Differentiability witness redefined: ";
      dw.dump();
      assert(false && "triggering standard assertion failure routine");
    }
    dw.verify(*this);
  }
  // SWIFT_ENABLE_TENSORFLOW END
  
  // Check property descriptors.
  LLVM_DEBUG(llvm::dbgs() << "*** Checking property descriptors ***\n");
  for (auto &prop : getPropertyList()) {
    prop.verify(*this);
  }
}
