//===--- IRGenDebugInfo.cpp - Debug Info Support --------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
//  This file implements IR debug info generation for Swift.
//
//===----------------------------------------------------------------------===//

#include "IRGenDebugInfo.h"
#include "GenEnum.h"
#include "GenOpaque.h"
#include "GenStruct.h"
#include "GenTuple.h"
#include "GenType.h"
#include "IRBuilder.h"
#include "swift/AST/ASTDemangler.h"
#include "swift/AST/ASTMangler.h"
#include "swift/AST/Attr.h"
#include "swift/AST/Decl.h"
#include "swift/AST/DeclContext.h"
#include "swift/AST/Expr.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/Module.h"
#include "swift/AST/ModuleLoader.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/TypeDifferenceVisitor.h"
#include "swift/AST/TypeWalker.h"
#include "swift/AST/Types.h"
#include "swift/Basic/Assertions.h"
#include "swift/Basic/Compiler.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Basic/Version.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/Demangling/ManglingMacros.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILBasicBlock.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILModule.h"
#include "swift/Serialization/SerializedModuleLoader.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Serialization/ASTReader.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Config/config.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/WindowsDriver/MSVCPaths.h"

#define DEBUG_TYPE "debug-info"

using namespace swift;
using namespace irgen;

llvm::cl::opt<bool> VerifyLineTable(
    "verify-linetable", llvm::cl::init(false),
    llvm::cl::desc(
        "Verify that the debug locations within one scope are contiguous."));

namespace {
using TrackingDIRefMap =
    llvm::DenseMap<const llvm::MDString *, llvm::TrackingMDNodeRef>;

class EqualUpToClangTypes
    : public CanTypeDifferenceVisitor<EqualUpToClangTypes> {
public:
  bool visitDifferentTypeStructure(CanType t1, CanType t2) {
#define COMPARE_UPTO_CLANG_TYPE(CLASS)                                         \
  if (auto f1 = dyn_cast<CLASS>(t1)) {                                         \
    auto f2 = cast<CLASS>(t2);                                                 \
    return !f1->getExtInfo().isEqualTo(f2->getExtInfo(),                       \
                                       /*useClangTypes*/ false);               \
  }
    COMPARE_UPTO_CLANG_TYPE(FunctionType);
    COMPARE_UPTO_CLANG_TYPE(SILFunctionType);
#undef COMPARE_UPTO_CLANG_TYPE
    return true;
  }
  bool check(Type t1, Type t2) {
    return !visit(t1->getCanonicalType(), t2->getCanonicalType());
  };
};

/// FIXME: This should be removed in favor of fixing ASTDemangler to wrap types in
/// ExistentialType where appropriate.
static bool equalWithoutExistentialTypes(Type t1, Type t2) {
  static Type (*withoutExistentialTypes)(Type) = [](Type type) -> Type {
    return type.transformRec([](TypeBase *type) -> std::optional<Type> {
      if (auto existential = dyn_cast<ExistentialType>(type)) {
        return withoutExistentialTypes(existential->getConstraintType());
      }
      return std::nullopt;
    });
  };

  return withoutExistentialTypes(t1)
      ->isEqual(withoutExistentialTypes(t2));
}

class IRGenDebugInfoImpl : public IRGenDebugInfo {
  const IRGenOptions &Opts;
  ClangImporter &CI;
  SourceManager &SM;
  llvm::Module &M;
  llvm::DIBuilder DBuilder;
  IRGenModule &IGM;
  const PathRemapper &DebugPrefixMap;

  struct FileAndLocation {
    unsigned Line = 0;
    uint16_t Column = 0;
    llvm::DIFile *File = nullptr;
    StringRef getFilename() const { return File ? File->getFilename() : ""; }
    bool operator==(const FileAndLocation &other) const {
      return Line == other.Line && Column == other.Column && File == other.File;
    }
  };

  /// Various caches.
  /// \{
  llvm::StringSet<> VarNames;
  using VarID = std::tuple<llvm::MDNode *, llvm::StringRef, unsigned, uint16_t>;
  llvm::DenseMap<VarID, llvm::TrackingMDNodeRef> LocalVarCache;
  llvm::DenseMap<const SILDebugScope *, llvm::TrackingMDNodeRef> ScopeCache;
  llvm::DenseMap<const SILDebugScope *, llvm::TrackingMDNodeRef> InlinedAtCache;
  llvm::DenseMap<const void *, FileAndLocation> FileAndLocationCache;
  llvm::DenseMap<TypeBase *, llvm::TrackingMDNodeRef> DITypeCache;
  llvm::DenseMap<const void *, llvm::TrackingMDNodeRef> DIModuleCache;
  llvm::StringMap<llvm::TrackingMDNodeRef> DIFileCache;
  llvm::StringMap<llvm::TrackingMDNodeRef> RuntimeErrorFnCache;
  llvm::StringSet<> OriginallyDefinedInTypes;
  llvm::StringSet<> AnchoredTypeAliases;
  TrackingDIRefMap DIRefMap;
  TrackingDIRefMap InnerTypeCache;
  TrackingDIRefMap ExistentialTypeAliasMap;
  /// \}

  /// A list of replaceable fwddecls that need to be RAUWed at the end.
  std::vector<std::pair<StringRef, llvm::TrackingMDRef>> FwdDeclTypes;
  /// The set of imported modules.
  llvm::DenseSet<ModuleDecl *> ImportedModules;

  llvm::BumpPtrAllocator DebugInfoNames;
  /// The current working directory.
  StringRef CWDName;
  /// User-provided -D macro definitions.
  SmallString<0> ConfigMacros;
  /// The current compilation unit.
  llvm::DICompileUnit *TheCU = nullptr;
  /// The main file.
  llvm::DIFile *MainFile = nullptr;
  /// The default file for compiler-generated code.
  llvm::DIFile *CompilerGeneratedFile = nullptr;
  /// The current module.
  llvm::DIModule *MainModule = nullptr;
  /// Scope of entry point function (main by default).
  llvm::DIScope *EntryPointFn = nullptr;
  /// The artificial type decls for named archetypes.
  llvm::StringMap<TypeAliasDecl *> MetadataTypeDeclCache;
  /// Catch-all type for opaque internal types.
  llvm::DIType *InternalType = nullptr;

  /// The last location that was emitted.
  FileAndLocation LastFileAndLocation;
  /// The scope of that last location.
  const SILDebugScope *LastScope = nullptr;

  /// Used by pushLoc.
  SmallVector<std::pair<FileAndLocation, const SILDebugScope *>, 8>
      LocationStack;

#ifndef NDEBUG
  using UUFTuple = std::pair<std::pair<unsigned, unsigned>, llvm::DIFile *>;
  struct FileAndLocationKey : public UUFTuple {
    FileAndLocationKey(FileAndLocation DL)
        : UUFTuple({{DL.Line, DL.Column}, DL.File}) {}
    inline bool operator==(const FileAndLocation &DL) const {
      return first.first == DL.Line && first.second == DL.Column &&
             second == DL.File;
    }
  };
  llvm::DenseSet<UUFTuple> PreviousLineEntries;
  FileAndLocation PreviousFileAndLocation;
#endif

public:
  IRGenDebugInfoImpl(const IRGenOptions &Opts, ClangImporter &CI,
                     IRGenModule &IGM, llvm::Module &M,
                     StringRef MainOutputFilenameForDebugInfo,
                     StringRef PrivateDiscriminator,
                     StringRef CacheKeyForJob);
  ~IRGenDebugInfoImpl() {
    // FIXME: SILPassManager sometimes creates an IGM and doesn't finalize it.
    if (!FwdDeclTypes.empty())
      finalize();
    assert(FwdDeclTypes.empty() && "finalize() was not called");
  }
  void finalize();

  void setCurrentLoc(IRBuilder &Builder, const SILDebugScope *DS,
                     SILLocation Loc);

  void addFailureMessageToCurrentLoc(IRBuilder &Builder, StringRef failureMsg);

  void clearLoc(IRBuilder &Builder);
  void pushLoc();
  void popLoc();
  void setInlinedTrapLocation(IRBuilder &Builder, const SILDebugScope *Scope);
  void setEntryPointLoc(IRBuilder &Builder);
  llvm::DIScope *getEntryPointFn();
  llvm::DIScope *getOrCreateScope(const SILDebugScope *DS);
  void emitImport(ImportDecl *D);
  llvm::DISubprogram *emitFunction(const SILDebugScope *DS, llvm::Function *Fn,
                                   SILFunctionTypeRepresentation Rep,
                                   SILType Ty, DeclContext *DeclCtx = nullptr,
                                   StringRef outlinedFromName = StringRef());
  llvm::DISubprogram *emitFunction(SILFunction &SILFn, llvm::Function *Fn);
  void emitArtificialFunction(IRBuilder &Builder, llvm::Function *Fn,
                              SILType SILTy);
  void emitOutlinedFunction(IRBuilder &Builder,
                            llvm::Function *Fn,
                            StringRef outlinedFromName);

  /// Return false if we fail to create the right DW_OP_LLVM_fragment operand.
  bool handleFragmentDIExpr(const SILDIExprOperand &CurDIExprOp,
                            llvm::DIExpression::FragmentInfo &Fragment);
  /// Return false if we fail to create the right DW_OP_LLVM_fragment operand.
  bool handleTupleFragmentDIExpr(const SILDIExprOperand &CurDIExprOp,
                                 llvm::DIExpression::FragmentInfo &Fragment);
  /// Return false if we fail to create the desired !DIExpression.
  bool buildDebugInfoExpression(const SILDebugVariable &VarInfo,
                                SmallVectorImpl<uint64_t> &Operands,
                                llvm::DIExpression::FragmentInfo &Fragment);

  /// Emit a dbg.declare at the current insertion point in Builder.
  void emitVariableDeclaration(IRBuilder &Builder,
                               ArrayRef<llvm::Value *> Storage,
                               DebugTypeInfo Ty, const SILDebugScope *DS,
                               std::optional<SILLocation> VarLoc,
                               SILDebugVariable VarInfo,
                               bool InCoroContext = false,
                               ArtificialKind = RealValue,
                               AddrDbgInstrKind = AddrDbgInstrKind::DbgDeclare);

  void emitDbgIntrinsic(IRBuilder &Builder, llvm::Value *Storage,
                        llvm::DILocalVariable *Var, llvm::DIExpression *Expr,
                        unsigned Line, unsigned Col, llvm::DILocalScope *Scope,
                        const SILDebugScope *DS, bool InCoroContext,
                        AddrDbgInstrKind = AddrDbgInstrKind::DbgDeclare);

  void emitGlobalVariableDeclaration(llvm::GlobalVariable *Storage,
                                     StringRef Name, StringRef LinkageName,
                                     DebugTypeInfo DebugType,
                                     bool IsLocalToUnit,
                                     std::optional<SILLocation> Loc);
  void emitTypeMetadata(IRGenFunction &IGF, llvm::Value *Metadata,
                        unsigned Depth, unsigned Index, StringRef Name);
  void emitPackCountParameter(IRGenFunction &IGF, llvm::Value *Metadata,
                              SILDebugVariable VarInfo);

  void emitExistentialPayloadType(swift::Type Ty) {
    if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::ASTTypes)
      return;
    if (!Ty || Ty->hasTypeParameter() || Ty->hasArchetype())
      return;

    auto DbgTy = DebugTypeInfo::getFromTypeInfo(
        Ty, IGM.getTypeInfoForUnlowered(Ty), IGM);
    anchorType(getOrCreateType(DbgTy));
  }

  /// Return flags which enable debug info emission for call sites, provided
  /// that it is supported and enabled.
  llvm::DINode::DIFlags getCallSiteRelatedAttrs() const;

  /// Return the DIBuilder.
  llvm::DIBuilder &getBuilder() { return DBuilder; }

  /// Decode (and cache) a SourceLoc.
  FileAndLocation decodeSourceLoc(SourceLoc SL) {
    auto &Cached = FileAndLocationCache[SL.getOpaquePointerValue()];
    if (Cached.File)
      return Cached;

    if (!SL.isValid()) {
      Cached.File = CompilerGeneratedFile;
      return Cached;
    }

    // If the source buffer is a macro, extract its full text.
    std::optional<StringRef> Source;
    bool ForceGeneratedSourceToDisk = Opts.DWARFVersion < 5;
    if (!ForceGeneratedSourceToDisk) {
      auto BufferID = SM.findBufferContainingLoc(SL);
      if (auto generatedInfo = SM.getGeneratedSourceInfo(BufferID)) {
        // We only care about macro expansion buffers,
        // so skip everything else.
        if (generatedInfo->kind != GeneratedSourceInfo::ReplacedFunctionBody &&
            generatedInfo->kind != GeneratedSourceInfo::PrettyPrinted &&
            generatedInfo->kind != GeneratedSourceInfo::DefaultArgument &&
            generatedInfo->kind != GeneratedSourceInfo::AttributeFromClang)
          if (auto *MemBuf = SM.getLLVMSourceMgr().getMemoryBuffer(BufferID)) {
            Source = MemBuf->getBuffer();
            // This is copying the buffer twice, but Xcode depends on this
            // comment in the file.
            auto origRange = generatedInfo->originalSourceRange;
            if (origRange.isValid()) {
              std::string s;
              {
                llvm::raw_string_ostream buffer(s);
                buffer << MemBuf->getBuffer() << "\n";
                auto originalFilename =
                    SM.getDisplayNameForLoc(origRange.getStart(), true);
                unsigned startLine, startColumn, endLine, endColumn;
                std::tie(startLine, startColumn) =
                    SM.getPresumedLineAndColumnForLoc(origRange.getStart());
                std::tie(endLine, endColumn) =
                    SM.getPresumedLineAndColumnForLoc(origRange.getEnd());
                buffer << "// original-source-range: "
                       << DebugPrefixMap.remapPath(originalFilename) << ":"
                       << startLine << ":" << startColumn << "-" << endLine
                       << ":" << endColumn << "\n";
              }
              Source = BumpAllocatedString(s);
            }
          }
      }
    }
    Cached.File = getOrCreateFile(
        SM.getDisplayNameForLoc(SL, ForceGeneratedSourceToDisk), Source);
    std::tie(Cached.Line, Cached.Column) =
        SM.getPresumedLineAndColumnForLoc(SL);
    // When WinDbg finds two locations with the same line but different
    // columns, the user must select an address when they break on that
    // line. Also, clang does not emit column locations in CodeView for C++.
    if (Opts.DebugInfoFormat == IRGenDebugInfoFormat::CodeView)
      Cached.Column = 0;
    return Cached;
  }

  IRGenDebugInfoFormat getDebugInfoFormat() { return Opts.DebugInfoFormat; }

private:
  /// Convert a SILLocation into the corresponding LLVM Loc.
  FileAndLocation computeLLVMLoc(const SILDebugScope *DS, SILLocation Loc);

  /// Compute the LLVM DebugLoc when targeting CodeView. In CodeView, zero is
  /// not an artificial line location; attempt to avoid those line locations near
  /// user code to reduce the number of breaks in the linetables.
  FileAndLocation computeLLVMLocCodeView(const SILDebugScope *DS,
                                         SILLocation Loc);

  static StringRef getFilenameFromDC(const DeclContext *DC) {
    if (auto *LF = dyn_cast<LoadedFile>(DC))
      return LF->getFilename();
    if (auto *SF = dyn_cast<SourceFile>(DC))
      return SF->getFilename();
    if (auto *M = dyn_cast<ModuleDecl>(DC))
      return M->getModuleFilename();
    return {};
  }

  FileAndLocation getDeserializedLoc(Pattern *) { return {}; }
  FileAndLocation getDeserializedLoc(Expr *) { return {}; }
  FileAndLocation getDeserializedLoc(Decl *D) {
    FileAndLocation L;
    const DeclContext *DC = D->getDeclContext()->getModuleScopeContext();
    StringRef Filename = getFilenameFromDC(DC);
    if (!Filename.empty())
      L.File = getOrCreateFile(Filename, {});
    return L;
  }

  FileAndLocation
  getFileAndLocation(const SILLocation::FilenameAndLocation &FL) {
    // When WinDbg finds two locations with the same line but different
    // columns, the user must select an address when they break on that
    // line. Also, clang does not emit column locations in CodeView for C++.
    bool CodeView = Opts.DebugInfoFormat == IRGenDebugInfoFormat::CodeView;
    return {FL.line, CodeView ? (uint16_t)0 : FL.column,
            getOrCreateFile(FL.filename, {})};
  }

  /// Use the Swift SM to figure out the actual line/column of a SourceLoc.
  template <typename WithLoc>
  FileAndLocation getSwiftFileAndLocation(WithLoc *ASTNode, bool End) {
    if (!ASTNode)
      return {};

    SourceLoc Loc = End ? ASTNode->getEndLoc() : ASTNode->getStartLoc();
    if (Loc.isInvalid())
      // This may be a deserialized or clang-imported decl. And modules
      // don't come with SourceLocs right now. Get at least the name of
      // the module.
      return getDeserializedLoc(ASTNode);

    return decodeSourceLoc(Loc);
  }

  FileAndLocation getFileAndLocation(Pattern *P, bool End = false) {
    return getSwiftFileAndLocation(P, End);
  }
  FileAndLocation getFileAndLocation(Expr *E, bool End = false) {
    return getSwiftFileAndLocation(E, End);
  }
  FileAndLocation getFileAndLocation(Decl *D, bool End = false) {
    FileAndLocation L;
    if (!D)
      return L;

    if (auto *ClangDecl = D->getClangDecl()) {
      clang::SourceLocation ClangSrcLoc = ClangDecl->getBeginLoc();
      clang::SourceManager &ClangSM =
          CI.getClangASTContext().getSourceManager();
      clang::PresumedLoc PresumedLoc = ClangSM.getPresumedLoc(ClangSrcLoc);
      if (!PresumedLoc.isValid())
        return L;
      L.Line = PresumedLoc.getLine();
      L.Column = PresumedLoc.getColumn();
      L.File = getOrCreateFile(PresumedLoc.getFilename(), {});
      return L;
    }
    return getSwiftFileAndLocation(D, End);
  }

  FileAndLocation getStartLocation(std::optional<SILLocation> OptLoc) {
    if (!OptLoc)
      return {};
    if (OptLoc->isFilenameAndLocation())
      return getFileAndLocation(*OptLoc->getFilenameAndLocation());
    return decodeSourceLoc(OptLoc->getStartSourceLoc());
  }

  FileAndLocation decodeFileAndLocation(SILLocation Loc) {
    if (Loc.isFilenameAndLocation())
      return getFileAndLocation(*Loc.getFilenameAndLocation());
    return decodeSourceLoc(Loc.getSourceLocForDebugging());
  }

  /// Strdup a raw char array using the bump pointer.
  StringRef BumpAllocatedString(const char *Data, size_t Length) {
    char *Ptr = DebugInfoNames.Allocate<char>(Length + 1);
    memcpy(Ptr, Data, Length);
    *(Ptr + Length) = 0;
    return StringRef(Ptr, Length);
  }

  /// Strdup S using the bump pointer.
  StringRef BumpAllocatedString(std::string S) {
    if (S.empty())
      return {};
    return BumpAllocatedString(S.c_str(), S.length());
  }

  /// Strdup StringRef S using the bump pointer.
  StringRef BumpAllocatedString(StringRef S) {
    if (S.empty())
      return {};
    return BumpAllocatedString(S.data(), S.size());
  }

  /// Return the size reported by a type.
  static unsigned getSizeInBits(llvm::DIType *Ty) {
    if (!Ty)
      return 0;
    // Follow derived types until we reach a type that
    // reports back a size.
    while (isa<llvm::DIDerivedType>(Ty) && !Ty->getSizeInBits()) {
      auto *DT = cast<llvm::DIDerivedType>(Ty);
      Ty = DT->getBaseType();
      if (!Ty)
        return 0;
    }
    return Ty->getSizeInBits();
  }

#ifndef NDEBUG

  /// Return the size reported by the variable's type.
  static unsigned getSizeInBits(const llvm::DILocalVariable *Var) {
    llvm::DIType *Ty = Var->getType();
    return getSizeInBits(Ty);
  }

#endif

  /// Determine whether this debug scope belongs to an explicit closure.
  static bool isExplicitClosure(const SILFunction *SILFn) {
    if (SILFn && SILFn->hasLocation())
      if (Expr *E = SILFn->getLocation().getAsASTNode<Expr>())
        if (isa<ClosureExpr>(E))
          return true;
    return false;
  }

public:
  llvm::MDNode *createInlinedAt(const SILDebugScope *DS) {
    auto *CS = DS->InlinedCallSite;
    if (!CS)
      return nullptr;

    auto CachedInlinedAt = InlinedAtCache.find(CS);
    if (CachedInlinedAt != InlinedAtCache.end())
      return cast<llvm::MDNode>(CachedInlinedAt->second);

    auto L = decodeFileAndLocation(CS->Loc);
    auto Scope = getOrCreateScope(CS->Parent.dyn_cast<const SILDebugScope *>());
    if (auto *Fn = CS->Parent.dyn_cast<SILFunction *>())
      Scope = getOrCreateScope(Fn->getDebugScope());
    // Pretend transparent functions don't exist.
    if (!Scope)
      return createInlinedAt(CS);
    auto InlinedAt = llvm::DILocation::getDistinct(
        IGM.getLLVMContext(), L.Line, L.Column, Scope, createInlinedAt(CS));
    InlinedAtCache.insert({CS, llvm::TrackingMDNodeRef(InlinedAt)});
    return InlinedAt;
  }

private:

#ifndef NDEBUG
  /// Perform a couple of soundness checks on scopes.
  static bool parentScopesAreSane(const SILDebugScope *DS) {
    auto *Parent = DS;
    while ((Parent = Parent->Parent.dyn_cast<const SILDebugScope *>())) {
      if (!DS->InlinedCallSite)
        assert(!Parent->InlinedCallSite &&
               "non-inlined scope has an inlined parent");
    }
    return true;
  }

  /// Assert that within one lexical block, each location is only visited once.
  bool lineEntryIsSane(FileAndLocation DL, const SILDebugScope *DS);

#endif

  llvm::DIFile *getOrCreateFile(StringRef Filename,
                                std::optional<StringRef> Source) {
    if (Filename.empty())
      Filename = SILLocation::getCompilerGeneratedLoc()->filename;

    // Look in the cache first.
    auto CachedFile = DIFileCache.find(Filename);
    if (CachedFile != DIFileCache.end()) {
      // Verify that the information still exists.
      if (llvm::Metadata *V = CachedFile->second)
        return cast<llvm::DIFile>(V);
    }

    // Detect the main file.
    StringRef MainFileName = MainFile->getFilename();
    if (MainFile && Filename.ends_with(MainFileName)) {
      SmallString<256> AbsThisFile, AbsMainFile;
      AbsThisFile = Filename;
      llvm::sys::fs::make_absolute(AbsThisFile);
      if (llvm::sys::path::is_absolute(MainFileName))
        AbsMainFile = MainFileName;
      else
        llvm::sys::path::append(AbsMainFile, MainFile->getDirectory(),
                                MainFileName);
      if (AbsThisFile == DebugPrefixMap.remapPath(AbsMainFile)) {
        DIFileCache[Filename] = llvm::TrackingMDNodeRef(MainFile);
        return MainFile;
      }
    }

    return createFile(Filename, std::nullopt, Source);
  }

  /// This is effectively \p clang::CGDebugInfo::createFile().
  llvm::DIFile *
  createFile(StringRef FileName,
             std::optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo,
             std::optional<StringRef> Source) {
    StringRef File, Dir;
    StringRef CurDir = Opts.DebugCompilationDir;
    SmallString<128> NormalizedFile(FileName);
    SmallString<128> FileBuf, DirBuf;
    llvm::sys::path::remove_dots(NormalizedFile);
    if (llvm::sys::path::is_absolute(NormalizedFile) &&
        llvm::sys::path::is_absolute(CurDir)) {
      // Strip the common prefix (if it is more than just "/") from current
      // directory and FileName for a more space-efficient encoding.
      auto FileIt = llvm::sys::path::begin(NormalizedFile);
      auto FileE = llvm::sys::path::end(NormalizedFile);
      auto CurDirIt = llvm::sys::path::begin(CurDir);
      auto CurDirE = llvm::sys::path::end(CurDir);
      for (; CurDirIt != CurDirE && *CurDirIt == *FileIt; ++CurDirIt, ++FileIt)
        llvm::sys::path::append(DirBuf, *CurDirIt);
      if (std::distance(llvm::sys::path::begin(CurDir), CurDirIt) == 1) {
        // Don't strip the common prefix if it is only the root "/"
        // since that would make LLVM diagnostic locations confusing.
        Dir = {};
        File = NormalizedFile;
      } else {
        for (; FileIt != FileE; ++FileIt)
          llvm::sys::path::append(FileBuf, *FileIt);
        Dir = DirBuf;
        File = FileBuf;
      }
    } else {
      File = NormalizedFile;
      // Leave <compiler-generated> & friends as is, without directory.
      if (!(File.starts_with("<") && File.ends_with(">")))
        Dir = CurDir;
      else
        Dir = llvm::sys::path::root_directory(CurDir);
    }
    llvm::DIFile *F =
        DBuilder.createFile(DebugPrefixMap.remapPath(File),
                            DebugPrefixMap.remapPath(Dir), CSInfo, Source);
    DIFileCache[FileName].reset(F);
    return F;
  }

  StringRef getName(const FuncDecl &FD) {
    // Getters and Setters are anonymous functions, so we forge a name
    // using its parent declaration.
    if (auto accessor = dyn_cast<AccessorDecl>(&FD))
      if (ValueDecl *VD = accessor->getStorage()) {
        const char *Kind;
        switch (accessor->getAccessorKind()) {
        case AccessorKind::Get:
          Kind = ".get";
          break;
        case AccessorKind::DistributedGet:
          Kind = "._distributed_get";
          break;
        case AccessorKind::Set:
          Kind = ".set";
          break;
        case AccessorKind::WillSet:
          Kind = ".willset";
          break;
        case AccessorKind::DidSet:
          Kind = ".didset";
          break;
        case AccessorKind::Address:
          Kind = ".addressor";
          break;
        case AccessorKind::MutableAddress:
          Kind = ".mutableAddressor";
          break;
        case AccessorKind::Read:
          Kind = ".read";
          break;
        case AccessorKind::Modify:
          Kind = ".modify";
          break;
        case AccessorKind::Init:
          Kind = ".init";
          break;
        case AccessorKind::YieldingMutate:
          Kind = ".yielding_mutate";
          break;
        case AccessorKind::YieldingBorrow:
          Kind = ".yielding_borrow";
          break;
        case AccessorKind::Borrow:
          Kind = ".borrow";
          break;
        case AccessorKind::Mutate:
          Kind = ".mutate";
          break;
        }

        SmallVector<char, 64> Buf;
        StringRef Name =
            (VD->getBaseName().userFacingName() + Twine(Kind)).toStringRef(Buf);
        return BumpAllocatedString(Name);
      }

    if (FD.hasName())
      return FD.getBaseIdentifier().str();

    return StringRef();
  }

  StringRef getName(SILLocation L) {
    if (L.isNull())
      return StringRef();

    if (FuncDecl *FD = L.getAsASTNode<FuncDecl>())
      return getName(*FD);

    if (ValueDecl *D = L.getAsASTNode<ValueDecl>())
      return D->getBaseName().userFacingName();

    if (auto *D = L.getAsASTNode<MacroExpansionDecl>())
      return D->getMacroName().getBaseIdentifier().str();

    if (auto *E = L.getAsASTNode<MacroExpansionExpr>())
      return E->getMacroName().getBaseIdentifier().str();

    return StringRef();
  }

  static CanSILFunctionType getFunctionType(SILType SILTy) {
    if (!SILTy)
      return CanSILFunctionType();

    auto FnTy = SILTy.getAs<SILFunctionType>();
    if (!FnTy) {
      LLVM_DEBUG(llvm::dbgs() << "Unexpected function type: ";
                 SILTy.print(llvm::dbgs()); llvm::dbgs() << "\n");
      return CanSILFunctionType();
    }

    return FnTy;
  }

  llvm::DIScope *getOrCreateContext(DeclContext *DC) {
    if (!DC)
      return TheCU;

    auto createContext = [&](NominalTypeDecl &NTD) {
      GenericContextScope scope(
          IGM, NTD.getGenericSignature().getCanonicalSignature());

      auto Ty = NTD.getDeclaredInterfaceType();
      // Create a Forward-declared type.
      auto DbgTy = DebugTypeInfo::getForwardDecl(Ty);
      return getOrCreateType(DbgTy);
    };

    if (isa<FuncDecl>(DC))
      if (auto *Decl = IGM.getSILModule().lookUpFunction(SILDeclRef(
              cast<AbstractFunctionDecl>(DC), SILDeclRef::Kind::Func)))
        return getOrCreateScope(Decl->getDebugScope());

    switch (DC->getContextKind()) {
    // The interesting cases are already handled above.
    case DeclContextKind::AbstractFunctionDecl:
    case DeclContextKind::AbstractClosureExpr:
    case DeclContextKind::SerializedAbstractClosure:

    // We don't model these in DWARF.
    case DeclContextKind::Initializer:
    case DeclContextKind::SubscriptDecl:
    case DeclContextKind::EnumElementDecl:
    case DeclContextKind::TopLevelCodeDecl:
    case DeclContextKind::SerializedTopLevelCodeDecl:
      return getOrCreateContext(DC->getParent());

    case DeclContextKind::Package: {
      auto *pkg = cast<PackageUnit>(DC);
      return getOrCreateContext(pkg);
    }
    case DeclContextKind::Module:
      return getOrCreateModule(
          {ImportPath::Access(), cast<ModuleDecl>(DC)});
    case DeclContextKind::FileUnit:
      // A module may contain multiple files.
      return getOrCreateContext(DC->getParent());
    case DeclContextKind::MacroDecl:
      return getOrCreateContext(DC->getParent());
    case DeclContextKind::ExtensionDecl: {
      auto *ED = cast<ExtensionDecl>(DC);
      if (auto *NTD = ED->getExtendedNominal())
        return createContext(*NTD);
      return getOrCreateContext(DC->getParent());
    }
    case DeclContextKind::GenericTypeDecl: {
      // The generic signature of this nominal type has no relation to the
      // current function's generic signature.
      auto *NTD = cast<NominalTypeDecl>(DC);
      return createContext(*NTD);
    }
    }
    return TheCU;
  }

  void createParameterType(llvm::SmallVectorImpl<llvm::Metadata *> &Parameters,
                           SILType type) {
    auto RealType = type.getASTType();
    auto DbgTy = DebugTypeInfo::getForwardDecl(RealType);
    Parameters.push_back(getOrCreateType(DbgTy));
  }

  // This is different from SILFunctionType::getAllResultsType() in some subtle
  // ways.
  static SILType getResultTypeForDebugInfo(IRGenModule &IGM,
                                           CanSILFunctionType fnTy) {
    if (fnTy->getNumResults() == 1) {
      return fnTy->getResults()[0].getSILStorageType(
          IGM.getSILModule(), fnTy, IGM.getMaximalTypeExpansionContext());
    } else if (!fnTy->getNumIndirectFormalResults()) {
      return fnTy->getDirectFormalResultsType(
          IGM.getSILModule(), IGM.getMaximalTypeExpansionContext(),
          /*loweredAddresses=*/true);
    } else {
      SmallVector<TupleTypeElt, 4> eltTys;
      for (auto &result : fnTy->getResults()) {
        eltTys.push_back(result.getReturnValueType(
            IGM.getSILModule(), fnTy, IGM.getMaximalTypeExpansionContext()));
      }
      return SILType::getPrimitiveAddressType(
          CanType(TupleType::get(eltTys, fnTy->getASTContext())));
    }
  }

  llvm::DITypeArray createParameterTypes(SILType SILTy) {
    if (!SILTy)
      return nullptr;
    return createParameterTypes(SILTy.castTo<SILFunctionType>());
  }

  llvm::DITypeArray createParameterTypes(CanSILFunctionType FnTy) {
    SmallVector<llvm::Metadata *, 16> Parameters;

    GenericContextScope scope(IGM, FnTy->getInvocationGenericSignature());

    // The function return type is the first element in the list.
    createParameterType(Parameters, getResultTypeForDebugInfo(IGM, FnTy));

    for (auto &Param : FnTy->getParameters())
      createParameterType(
          Parameters, IGM.silConv.getSILType(
                          Param, FnTy, IGM.getMaximalTypeExpansionContext()));

    return DBuilder.getOrCreateTypeArray(Parameters);
  }

  /// FIXME: replace this condition with something more sound.
  static bool isAllocatingConstructor(SILFunctionTypeRepresentation Rep,
                                      DeclContext *DeclCtx) {
    return Rep != SILFunctionTypeRepresentation::Method && DeclCtx &&
           isa<ConstructorDecl>(DeclCtx);
  }

  void createImportedModule(llvm::DIScope *Context,
                            ImportedModule M, llvm::DIFile *File,
                            unsigned Line) {
    // For overlays of Clang modules also emit an import of the underlying Clang
    // module. The helps the debugger resolve types that are present only in the
    // underlying module.
    if (const clang::Module *UnderlyingClangModule =
            M.importedModule->findUnderlyingClangModule()) {
      DBuilder.createImportedModule(
          Context,
          getOrCreateModule(
              {*const_cast<clang::Module *>(UnderlyingClangModule)},
              UnderlyingClangModule),
          File, 0);
    }
    DBuilder.createImportedModule(Context, getOrCreateModule(M), File, Line);
  }

  llvm::DIModule *getOrCreateModule(const void *Key, llvm::DIScope *Parent,
                                    StringRef Name, StringRef IncludePath,
                                    uint64_t Signature = ~1ULL,
                                    StringRef ASTFile = {}) {
    // Look in the cache first.
    auto Val = DIModuleCache.find(Key);
    if (Val != DIModuleCache.end())
      return cast<llvm::DIModule>(Val->second);

    std::string RemappedIncludePath = DebugPrefixMap.remapPath(IncludePath);
    std::string RemappedASTFile = DebugPrefixMap.remapPath(ASTFile);

    // For Clang modules / PCH, create a Skeleton CU pointing to the PCM/PCH.
    if (!Opts.DisableClangModuleSkeletonCUs) {
      bool CreateSkeletonCU = !ASTFile.empty();
      bool IsRootModule = !Parent;
      if (CreateSkeletonCU && IsRootModule) {
        llvm::DIBuilder DIB(M);
        DIB.createCompileUnit(IGM.ObjCInterop ? llvm::dwarf::DW_LANG_ObjC
                                              : llvm::dwarf::DW_LANG_C99,
                              DIB.createFile(Name, RemappedIncludePath),
                              TheCU->getProducer(), true, StringRef(), 0,
                              RemappedASTFile, llvm::DICompileUnit::FullDebug,
                              Signature);
        // NOTE: not setting DebugInfoForProfiling here
        DIB.finalize();
      }
    }

    llvm::DIModule *M =
        DBuilder.createModule(Parent, Name, ConfigMacros, RemappedIncludePath);
    DIModuleCache.insert({Key, llvm::TrackingMDNodeRef(M)});
    return M;
  }

  using ASTSourceDescriptor = clang::ASTSourceDescriptor;
  /// Create a DIModule from a clang module or PCH.
  /// The clang::Module pointer is passed separately because the recursive case
  /// needs to fudge the AST descriptor.
  llvm::DIModule *getOrCreateModule(ASTSourceDescriptor Desc,
                                    const clang::Module *ClangModule) {
    // PCH files don't have a signature field in the control block,
    // but LLVM detects skeleton CUs by looking for a non-zero DWO id.
    // We use the lower 64 bits for debug info.
    uint64_t Signature =
      Desc.getSignature() ? Desc.getSignature().truncatedValue() : ~1ULL;

    // Clang modules using fmodule-file-home-is-cwd should have their
    // include path set to the working directory.
    auto &HSI =
        CI.getClangPreprocessor().getHeaderSearchInfo().getHeaderSearchOpts();
    StringRef IncludePath =
        HSI.ModuleFileHomeIsCwd ? Opts.DebugCompilationDir : Desc.getPath();
    StringRef ASTFile =
        Desc.getCASID().empty() ? Desc.getASTFile() : Desc.getCASID();

    // Handle Clang modules.
    if (ClangModule) {
      llvm::DIModule *Parent = nullptr;
      if (ClangModule->Parent) {
        // The loading of additional modules by Sema may trigger an out-of-date
        // PCM rebuild in the Clang module dependencies of the additional
        // module. A PCM rebuild causes the ModuleManager to unload previously
        // loaded ASTFiles. For this reason we must use the cached ASTFile
        // information here instead of the potentially dangling pointer to the
        // ASTFile that is stored in the clang::Module object.
        //
        // Note: The implementation here assumes that all clang submodules
        //       belong to the same PCM file.
        ASTSourceDescriptor ParentDescriptor(*ClangModule->Parent);
        Parent = getOrCreateModule(
            {ParentDescriptor.getModuleName(), ParentDescriptor.getPath(),
             Desc.getASTFile(), Desc.getSignature(), Desc.getCASID()},
            ClangModule->Parent);
      }
      return getOrCreateModule(ClangModule, Parent, Desc.getModuleName(),
                               IncludePath, Signature, ASTFile);
    }
    // Handle PCH.
    return getOrCreateModule(Desc.getASTFile().bytes_begin(), nullptr,
                             Desc.getModuleName(), IncludePath, Signature,
                             ASTFile);
  };

  static std::optional<ASTSourceDescriptor>
  getClangModule(const ModuleDecl &M) {
    for (auto *FU : M.getFiles())
      if (auto *CMU = dyn_cast_or_null<ClangModuleUnit>(FU))
        if (auto Desc = CMU->getASTSourceDescriptor())
          return Desc;
    return std::nullopt;
  }

  llvm::DIModule *getOrCreateModule(ImportedModule IM) {
    ModuleDecl *M = IM.importedModule;
    if (std::optional<ASTSourceDescriptor> ModuleDesc = getClangModule(*M))
      return getOrCreateModule(*ModuleDesc, ModuleDesc->getModuleOrNull());
    StringRef Path = getFilenameFromDC(M);
    // Use the module 'real' name, which can be different from the name if module
    // aliasing was used (swift modules only). For example, if a source file has
    // 'import Foo', and '-module-alias Foo=Bar' was passed in, the real name of
    // the module on disk is Bar (.swiftmodule or .swiftinterface), and is used
    // for loading and mangling.
    StringRef Name = M->getRealName().str();
    // Handle bridging header imports. If there is a cache key, use cache key as
    // path if debug module path is specified.
    if (Name == CLANG_HEADER_MODULE_NAME && !Opts.BridgingPCHCacheKey.empty())
      Path = Opts.BridgingPCHCacheKey;
    return getOrCreateModule(M, TheCU, Name, Path);
  }

  TypeAliasDecl *getMetadataType(StringRef ArchetypeName) {
    TypeAliasDecl *&Entry = MetadataTypeDeclCache[ArchetypeName];
    if (Entry)
      return Entry;

    SourceLoc NoLoc;
    Entry = new (IGM.Context) TypeAliasDecl(
        NoLoc, NoLoc, IGM.Context.getIdentifier(ArchetypeName), NoLoc,
        /*genericparams*/ nullptr, IGM.Context.TheBuiltinModule);
    Entry->setUnderlyingType(IGM.Context.TheRawPointerType);
    return Entry;
  }

  /// Return the DIFile that is the ancestor of Scope.
  llvm::DIFile *getFile(llvm::DIScope *Scope) {
    while (!isa<llvm::DIFile>(Scope)) {
      switch (Scope->getTag()) {
      case llvm::dwarf::DW_TAG_lexical_block:
        Scope = cast<llvm::DILexicalBlock>(Scope)->getScope();
        break;
      case llvm::dwarf::DW_TAG_subprogram:
        Scope = cast<llvm::DISubprogram>(Scope)->getFile();
        break;
      default:
        return MainFile;
      }
      if (Scope)
        return MainFile;
    }
    if (Scope)
      return cast<llvm::DIFile>(Scope);

    return MainFile;
  }

  static unsigned getStorageSizeInBits(const llvm::DataLayout &DL,
                                       ArrayRef<llvm::Value *> Storage) {
    unsigned SizeInBits = 0;
    for (llvm::Value *Piece : Storage)
      SizeInBits += DL.getTypeSizeInBits(Piece->getType());
    return SizeInBits;
  }

  struct MangledNames {
    StringRef Sugared, Canonical;
  };
  MangledNames getMangledName(DebugTypeInfo DbgTy) {
    if (DbgTy.isMetadataType())
      return {{},
              MetadataTypeDeclCache.find(DbgTy.getDecl()->getName().str())
                  ->getKey()};

    // This is a bit of a hack. We need a generic signature to use for mangling.
    // If we started with an interface type, just use IGM.getCurGenericContext(),
    // since callers that use interface types typically push a signature that way.
    //
    // Otherwise, if we have a contextual type, find an archetype and ask it for
    // it's generic signature. The context generic signature from the IRGenModule
    // is unlikely to be useful here.
    GenericSignature Sig;
    Type Ty = DbgTy.getType();
    if (Ty->hasArchetype()) {
      Ty.findIf([&](Type t) -> bool {
        if (auto *archetypeTy = t->getAs<PrimaryArchetypeType>()) {
          Sig = archetypeTy->getGenericEnvironment()->getGenericSignature();
          return true;
        }

        if (auto *archetypeTy = t->getAs<PackArchetypeType>()) {
          Sig = archetypeTy->getGenericEnvironment()->getGenericSignature();
          return true;
        }

        return false;
      });

      Ty = Ty->mapTypeOutOfEnvironment();
    } else {
      Sig = IGM.getCurGenericContext();
    }

    // Strip off top level of type sugar (except for type aliases).
    // We don't want Optional<T> and T? to get different debug types.
    while (true) {
      if (auto *SugarTy = dyn_cast<SyntaxSugarType>(Ty.getPointer())) {
        Ty = SugarTy->getSinglyDesugaredType();
        continue;
      }

      break;
    }

    // TODO: Eliminate substitutions in SILFunctionTypes for now.
    // On platforms where the substitutions affect representation, we will need
    // to preserve this info and teach type reconstruction about it.
    Ty = Ty->replaceSubstitutedSILFunctionTypesWithUnsubstituted(
        IGM.getSILModule());

    Mangle::ASTMangler Mangler(IGM.Context);
    std::string SugaredName, CanonicalName;
    SugaredName = Mangler.mangleTypeForDebugger(Ty, Sig);

    CanType CanTy = Ty->getCanonicalType();
    if (CanTy.getPointer() != Ty.getPointer()) {
      CanonicalName = Mangler.mangleTypeForDebugger(CanTy, Sig);
      if (SugaredName == CanonicalName)
        CanonicalName.clear();
    }

    bool IsTypeOriginallyDefinedIn = containsOriginallyDefinedIn(DbgTy.getType());
    bool IsCxxType = containsCxxType(DbgTy.getType());
    // TODO: ASTDemangler drops LifetimeDependenceInfo (see ASTDemangler.cpp's
    // "Handle LifetimeDependenceInfo here" TODO); until that TODO is closed,
    // types containing function types with lifetime dependencies cannot
    // round-trip. This exclusion is intentionally transitive.
    bool ContainsLifetimeDependencies =
        containsFunctionTypeWithLifetimeDependencies(DbgTy.getType());
    // There's no way to round trip when respecting @_originallyDefinedIn for a type.
    // TODO(https://github.com/apple/swift/issues/57699): We currently cannot round trip some C++ types.
    if (!Opts.DisableRoundTripDebugTypes && !IsTypeOriginallyDefinedIn &&
        !IsCxxType && !ContainsLifetimeDependencies) {
      // Make sure we can reconstruct mangled types for the debugger.
      auto &Ctx = Ty->getASTContext();
      Type Reconstructed = Demangle::getTypeForMangling(Ctx, SugaredName, Sig);
      if (!Reconstructed) {
        ABORT([&](auto &out) {
          out << "Failed to reconstruct type for " << SugaredName << "\n";
          out << "Original type:\n";
          Ty->dump(out);
          if (Sig)
            out << "Generic signature: " << Sig << "\n";
          out << SWIFT_CRASH_BUG_REPORT_MESSAGE << "\n"
              << "Pass '-Xfrontend -disable-round-trip-debug-types' to disable "
                 "this assertion.";
        });
      } else if (!Reconstructed->isEqual(Ty) &&
                 // FIXME: Some existential types are reconstructed without
                 // an explicit ExistentialType wrapping the constraint.
                 !equalWithoutExistentialTypes(Reconstructed, Ty) &&
                 !EqualUpToClangTypes().check(Reconstructed, Ty)) {
        // [FIXME: Include-Clang-type-in-mangling] Remove second check
        ABORT([&](auto &out) {
          out << "Incorrect reconstructed type for " << SugaredName << "\n";
          out << "Original type:\n";
          Ty->dump(out);
          out << "Reconstructed type:\n";
          Reconstructed->dump(out);
          if (Sig)
            out << "Generic signature: " << Sig << "\n";
          out << SWIFT_CRASH_BUG_REPORT_MESSAGE << "\n"
              << "Pass '-Xfrontend -disable-round-trip-debug-types' to disable "
                 "this assertion.";
        });
      }
    }

    // Only return a dedicated sugared name if it's different from the canonical
    // one.
    if (CanonicalName.empty())
      std::swap(SugaredName, CanonicalName);
    return {BumpAllocatedString(SugaredName),
            BumpAllocatedString(CanonicalName)};
  }

  llvm::DIDerivedType *
  createMemberType(llvm::DIType *DITy, StringRef Name, unsigned &OffsetInBits,
                   unsigned AlignInBits, llvm::DIScope *Scope,
                   llvm::DIFile *File, llvm::DINode::DIFlags Flags) {
    auto SizeInBits = getSizeInBits(DITy);
    llvm::DIDerivedType *DIMemberTy = DBuilder.createMemberType(
        Scope, Name, File, 0, SizeInBits, 0, OffsetInBits, Flags, DITy);
    OffsetInBits += SizeInBits;
    if (AlignInBits)
      OffsetInBits = llvm::alignTo(OffsetInBits, AlignInBits);
    return DIMemberTy;
  }

  /// Creates a temporary replaceable forward decl to protect against recursion.
  llvm::TempDIType createTemporaryReplaceableForwardDecl(
      TypeBase *Type, llvm::DIScope *Scope, llvm::DIFile *File, unsigned Line,
      unsigned SizeInBits, unsigned AlignInBits, llvm::DINode::DIFlags Flags,
      StringRef MangledName, StringRef Name) {
#ifndef NDEBUG
    {
      if (MangledName.empty())
        assert(!Name.empty() &&
               "no mangled name and no human readable name given");
      else
        assert(swift::Demangle::isMangledName(MangledName) &&
               "UID is not a mangled name");
      auto UID = llvm::MDString::get(IGM.getLLVMContext(), MangledName);
      assert(DIRefMap.count(UID) == 0 && "type is already cached");
    }
#endif
    auto ReplaceableType = DBuilder.createReplaceableCompositeType(
        llvm::dwarf::DW_TAG_structure_type, "", Scope, File, Line,
        llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
        MangledName);
    auto FwdDecl = llvm::TempDIType(ReplaceableType);

    auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
    DITypeCache[Type] = TH;
    if (auto UID = ReplaceableType->getRawIdentifier())
      DIRefMap[UID] = llvm::TrackingMDNodeRef(TH);

    return FwdDecl;
  }

  using TrackingDIType = llvm::TypedTrackingMDRef<llvm::DIType>;
  struct MemberDIType {
    StringRef Name;
    unsigned AlignInBits;
    TrackingDIType DIType;
    MemberDIType(StringRef Name, unsigned AlignInBits, llvm::DIType *DIType)
        : Name(Name), AlignInBits(AlignInBits), DIType(DIType) {}
  };

  unsigned getByteSize() { return CI.getTargetInfo().getCharWidth(); }

  /// The alignment to record in the debug info for \p DbgTy, in bits, or 0 to
  /// record none. The DWARF emitter checks for a 0 and omits DW_AT_alignment 
  /// in that case.
  unsigned getAlignInBits(DebugTypeInfo DbgTy) {
    if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::ASTTypes)
      return 0;
    return DbgTy.getAlignInBits(getByteSize());
  }

  llvm::DICompositeType *createStructType(
      NominalOrBoundGenericNominalType *Type, NominalTypeDecl *Decl,
      llvm::DIScope *Scope, llvm::DIFile *File, unsigned Line,
      unsigned SizeInBits, unsigned AlignInBits, llvm::DINode::DIFlags Flags,
      StringRef MangledName, llvm::DIType *SpecificationOf = nullptr) {
    StringRef Name = Decl->getName().str();
    auto FwdDecl = createTemporaryReplaceableForwardDecl(
        Type, Scope, File, Line, SizeInBits, AlignInBits, Flags, MangledName,
        Name);
    // Collect the members.
    SmallVector<MemberDIType, 16> MemberTypes;
    if (!IGM.isResilient(Decl, ResilienceExpansion::Maximal)) {
      for (VarDecl *VD : Decl->getStoredProperties()) {
        auto memberTy = Type->getTypeOfMember(VD);
        if (auto DbgTy = CompletedDebugTypeInfo::getFromTypeInfo(
                memberTy,
                IGM.getTypeInfoForUnlowered(
                    IGM.getSILTypes().getAbstractionPattern(VD), memberTy),
                IGM)) {
          MemberTypes.emplace_back(VD->getName().str(),
                                   getAlignInBits(*DbgTy),
                                   getOrCreateType(*DbgTy));
          anchorTypeAliasesIn(memberTy);
        } else {
          // Without complete type info we can only create a forward decl.
          return DBuilder.createForwardDecl(
              llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, File, Line,
              llvm::dwarf::DW_LANG_Swift, SizeInBits, 0);
        }
      }
    }

    SmallVector<llvm::Metadata *, 16> Members;
    unsigned OffsetInBits = 0;
    for (auto &Member : MemberTypes)
      Members.push_back(createMemberType(Member.DIType, Member.Name,
                                         OffsetInBits, Member.AlignInBits,
                                         Scope, File, Flags));

    llvm::DINodeArray BoundParams = collectGenericParams(Type);
    llvm::DICompositeType *DITy = createStruct(
        Scope, Name, File, Line, SizeInBits, AlignInBits, Flags, MangledName,
        DBuilder.getOrCreateArray(Members), BoundParams, SpecificationOf,
        /*Annotations=*/nullptr);
    return DBuilder.replaceTemporary(std::move(FwdDecl), DITy);
  }

  /// Creates debug info for a generic struct or class with archetypes (e.g.:
  /// Pair<τ_0_0, τ_0_1>). For types with unsubstituted generic type parameters,
  /// debug info generation doesn't attempt to emit the size and aligment of the
  /// type, as in the general case those are all dependent on substituting the
  /// type parameters in (some exceptions exist, like generic types that are
  /// class constrained). It also doesn't attempt to emit the members for the
  /// same reason.
  llvm::DICompositeType *createUnsubstitutedGenericStructOrClassType(
      DebugTypeInfo DbgTy, NominalTypeDecl *Decl, Type UnsubstitutedType,
      llvm::DIScope *Scope, llvm::DIFile *File, unsigned Line,
      llvm::DINode::DIFlags Flags, llvm::DIType *DerivedFrom,
      unsigned RuntimeLang, StringRef UniqueID) {
    // FIXME: ideally, we'd like to emit this type with no size and alignment at
    // all (instead of emitting them as 0). Fix this by changing DIBuilder to
    // allow for struct types that have optional size and alignment.
    unsigned SizeInBits = 0;
    unsigned AlignInBits = 0;
    StringRef Name = Decl->getName().str();
    auto FwdDecl = createTemporaryReplaceableForwardDecl(
        DbgTy.getType(), Scope, File, Line, SizeInBits, AlignInBits, Flags,
        UniqueID, Name);
    // Collect the members.
    SmallVector<MemberDIType, 16> MemberTypes;

    if (!IGM.isResilient(Decl, ResilienceExpansion::Maximal)) {
      for (VarDecl *VD : Decl->getStoredProperties()) {
        Type memberTy = UnsubstitutedType->getTypeOfMember(VD);
        auto DbgTy = DebugTypeInfo::getFromTypeInfo(
            memberTy,
            IGM.getTypeInfoForUnlowered(
                IGM.getSILTypes().getAbstractionPattern(VD), memberTy),
            IGM);
        MemberTypes.emplace_back(VD->getName().str(),
                                 getAlignInBits(DbgTy),
                                 getOrCreateType(DbgTy));
        anchorTypeAliasesIn(memberTy);
      }
    }

    SmallVector<llvm::Metadata *, 16> Members;
    for (auto &Member : MemberTypes) {
      unsigned OffsetInBits = 0;
      auto *member = createMemberType(Member.DIType, Member.Name,
                                         OffsetInBits, Member.AlignInBits,
                                      Scope, File, Flags);
      Members.push_back(member);
    }

    llvm::DICompositeType *DITy = DBuilder.createStructType(
        Scope, Name, File, Line, SizeInBits, AlignInBits, Flags, DerivedFrom,
        DBuilder.getOrCreateArray(Members), RuntimeLang, nullptr, UniqueID);

    if (auto SuperClassTy = UnsubstitutedType->getSuperclass()) {
      auto SuperClassDbgTy = DebugTypeInfo::getFromTypeInfo(
          SuperClassTy, IGM.getTypeInfoForUnlowered(SuperClassTy), IGM);
      if (llvm::DIType *SuperClassDITy = getOrCreateType(SuperClassDbgTy)) {
        DBuilder.retainType(DBuilder.createInheritance(
            DITy, SuperClassDITy, 0, 0, llvm::DINode::FlagZero));
      }
    }
    return DBuilder.replaceTemporary(std::move(FwdDecl), DITy);
  }

  std::pair<bool, Type> getUnsubstitutedType(Type Ty, StringRef MangledName) {
    if (!Ty)
      return {false,{}};
    // Go from Pair<Int, Double> to Pair<T, U>.
    auto *Decl = Ty->getNominalOrBoundGenericNominal();
    if (!Decl)
      return {false, {}};
    // Go from Pair<Int, Double> to Pair<T, U>.
    Type InterfaceTy = Decl->getDeclaredInterfaceType();
    Type UnsubstitutedTy = Decl->mapTypeIntoEnvironment(InterfaceTy);

    Mangle::ASTMangler Mangler(IGM.Context);
    std::string DeclTypeMangledName = Mangler.mangleTypeForDebugger(
        UnsubstitutedTy->mapTypeOutOfEnvironment(), {});
    bool IsUnsubstituted = (DeclTypeMangledName == MangledName);
    return {IsUnsubstituted, UnsubstitutedTy};
  }

  llvm::DIType *
  createSpecializedEnumType(NominalOrBoundGenericNominalType *EnumTy,
                            EnumDecl *Decl, StringRef MangledName,
                            unsigned SizeInBits, unsigned AlignInBits,
                            llvm::DIScope *Scope, llvm::DIFile *File,
                            unsigned Line, llvm::DINode::DIFlags Flags) {
    auto [IsUnsubstituted, UnsubstitutedTy] =
        getUnsubstitutedType(EnumTy, MangledName);
    auto UnsubstitutedDbgTy = DebugTypeInfo::getFromTypeInfo(
        UnsubstitutedTy, IGM.getTypeInfoForUnlowered(UnsubstitutedTy), IGM);
    if (IsUnsubstituted)
      return createUnsubstitutedVariantType(UnsubstitutedDbgTy, Decl,
                                            MangledName, Scope, File, 0, Flags);

    StringRef Name = Decl->getName().str();
    auto FwdDecl = createTemporaryReplaceableForwardDecl(
        EnumTy, Scope, File, Line, SizeInBits, AlignInBits, Flags, MangledName,
        Name);
    // Force the creation of the unsubstituted type, don't create it
    // directly so it goes through all the caching/verification logic.
    auto UnsubstitutedDITy = getOrCreateType(UnsubstitutedDbgTy);
    llvm::DICompositeType *DIType = createOpaqueStruct(
        Scope, "", File, 0, SizeInBits, AlignInBits, Flags, MangledName,
        collectGenericParams(EnumTy), UnsubstitutedDITy);
    return DBuilder.replaceTemporary(std::move(FwdDecl), DIType);
  }

  /// Create a DICompositeType from a specialized struct. A specialized type
  /// is a generic type, or a child type whose parent is generic.
  llvm::DIType *createSpecializedStructOrClassType(
      NominalOrBoundGenericNominalType *Type,
      llvm::DIScope *Scope, llvm::DIFile *File, unsigned Line,
      unsigned SizeInBits, unsigned AlignInBits, llvm::DINode::DIFlags Flags,
      StringRef MangledName, bool IsClass = false) {
    // To emit debug info of the DwarfTypes level for generic types, the
    // strategy is to emit a description of all the fields for the type with
    // archetypes, and still the same debug info as the ASTTypes level for the
    // specialized type. For example, given: struct Pair<T, U> {
    //   let t: T
    //   let u: U
    // }
    // When emitting debug information for a type such as Pair<Int, Double>,
    // emit a description of all the fields for Pair<T, U>, and emit the regular
    // debug information for Pair<Int, Double>.
    auto *Decl = Type->getNominalOrBoundGenericNominal();
    if (!Decl)
      return nullptr;

    auto [IsUnsubstitued, UnsubstitutedType] =
        getUnsubstitutedType(Type, MangledName);
    auto UnsubstitutedDbgTy = DebugTypeInfo::getFromTypeInfo(
        UnsubstitutedType, IGM.getTypeInfoForUnlowered(UnsubstitutedType), IGM);
    if (IsUnsubstitued) {
      return createUnsubstitutedGenericStructOrClassType(
          UnsubstitutedDbgTy, Decl, UnsubstitutedType, Scope, File, Line, Flags,
          nullptr, llvm::dwarf::DW_LANG_Swift, MangledName);
    }

    // Force the creation of the unsubstituted type, don't create it
    // directly so it goes through all the caching/verification logic.
    auto UnsubstitutedDITy = getOrCreateType(UnsubstitutedDbgTy);

    if (auto *ClassTy = llvm::dyn_cast<BoundGenericClassType>(Type)) {
      auto SuperClassTy = ClassTy->getSuperclass();
      if (SuperClassTy) {
        auto SuperClassDbgTy = DebugTypeInfo::getFromTypeInfo(
            SuperClassTy, IGM.getTypeInfoForUnlowered(SuperClassTy), IGM);

        llvm::DIType *SuperClassDITy = getOrCreateType(SuperClassDbgTy);
        assert(SuperClassDITy && "getOrCreateType should never return null!");
        DBuilder.createInheritance(UnsubstitutedDITy, SuperClassDITy, 0, 0,
                                   llvm::DINode::FlagZero);
      }
    }

    // Generally, we don't emit members of a specialized bound generic, because
    // these can be reconstructed by substituting the "template parameters" in
    // the unspecialized type. We make an exception for inline arrays, because
    // DWARF has special support for arrays.
    if ((Type->isInlineArray() || Type->is_InlineArray()) &&
	!Type->hasTypeParameter() &&
        !Type->hasPrimaryArchetype())
      // Create the substituted type.
      return createStructType(Type, Decl, Scope, File, Line, SizeInBits,
                              AlignInBits, Flags, MangledName,
                              UnsubstitutedDITy);

    // Create the substituted type (without members).
    llvm::DIType *SpecializedDITy = createOpaqueStructWithSizedContainer(
        Scope, Decl ? Decl->getNameStr() : "", File, Line, SizeInBits,
        AlignInBits, Flags, MangledName, collectGenericParams(Type),
        UnsubstitutedDITy);
    return SpecializedDITy;
  }

  /// Create debug information for an enum with a raw type (enum E : Int {}).
  llvm::DICompositeType *createRawEnumType(CompletedDebugTypeInfo DbgTy,
                                           EnumDecl *Decl,
                                           StringRef MangledName,
                                           llvm::DIScope *Scope,
                                           llvm::DIFile *File, unsigned Line,
                                           llvm::DINode::DIFlags Flags) {
    assert(
        Decl->hasRawType() &&
        "Trying to create a raw enum debug info from enum with no raw type!");

    StringRef Name = Decl->getName().str();
    unsigned SizeInBits = DbgTy.getSizeInBits();
    // Default, since Swift doesn't allow specifying a custom alignment.
    unsigned AlignInBits = 0;

    auto FwdDecl = createTemporaryReplaceableForwardDecl(
        DbgTy.getType(), Scope, File, Line, SizeInBits, AlignInBits, Flags,
        MangledName, Name);

    auto RawType = Decl->getRawType();
    auto &TI = IGM.getTypeInfoForUnlowered(RawType);
    std::optional<CompletedDebugTypeInfo> ElemDbgTy =
        CompletedDebugTypeInfo::getFromTypeInfo(RawType, TI, IGM);
    if (!ElemDbgTy)
      // Without complete type info we can only create a forward decl.
      return DBuilder.createForwardDecl(
          llvm::dwarf::DW_TAG_enumeration_type, Name, Scope, File, Line,
          llvm::dwarf::DW_LANG_Swift, SizeInBits, 0, MangledName);

    SmallVector<llvm::Metadata *, 16> Elements;
    for (auto *ElemDecl : Decl->getAllElements()) {
      // TODO: add the option to emit an enumerator with no value, and use that
      // instead of emitting a 0.
      auto MTy =
          DBuilder.createEnumerator(ElemDecl->getBaseIdentifier().str(), 0);
      Elements.push_back(MTy);
    }

    auto EnumType = getOrCreateType(*ElemDbgTy);
    llvm::DICompositeType *DITy = DBuilder.createEnumerationType(
        Scope, Name, File, Line, SizeInBits, AlignInBits,
        DBuilder.getOrCreateArray(Elements), EnumType,
        llvm::dwarf::DW_LANG_Swift, MangledName, false);

    return DBuilder.replaceTemporary(std::move(FwdDecl), DITy);
  }

  /// If the enum case is indirect, wrap the payload debug type in a
  /// DW_TAG_reference_type to indicate the case stores a pointer to a
  /// heap-allocated box rather than the payload directly.
  llvm::DIType *wrapInReferenceTypeIfIndirect(llvm::DIType *PayloadDITy,
                                              EnumElementDecl *ElemDecl,
                                              EnumDecl *Decl) {
    if (ElemDecl->isIndirect() || Decl->isIndirect()) {
      unsigned PtrSizeInBits =
          CI.getTargetInfo().getPointerWidth(clang::LangAS::Default);
      return DBuilder.createReferenceType(llvm::dwarf::DW_TAG_reference_type,
                                          PayloadDITy, PtrSizeInBits);
    }
    return PayloadDITy;
  }

  /// Create debug information for an enum with no raw type.
  llvm::DICompositeType *createVariantType(CompletedDebugTypeInfo DbgTy,
                                           EnumDecl *Decl,
                                           StringRef MangledName,
                                           unsigned AlignInBits,
                                           llvm::DIScope *Scope,
                                           llvm::DIFile *File, unsigned Line,
                                           llvm::DINode::DIFlags Flags) {
    assert(!Decl->getRawType() &&
           "Attempting to create variant debug info from raw enum!");;

    StringRef Name = Decl->getName().str();
    unsigned SizeInBits = DbgTy.getSizeInBits();
    auto NumExtraInhabitants = DbgTy.getNumExtraInhabitants();

    // A variant part should actually be a child to a DW_TAG_structure_type
    // according to the DWARF spec.

    auto FwdDecl = createTemporaryReplaceableForwardDecl(
        DbgTy.getType(), Scope, File, Line, SizeInBits, AlignInBits, Flags,
        MangledName, Name);

    SmallVector<MemberDIType, 16> MemberTypes;
    for (auto *ElemDecl : Decl->getAllElements()) {
      std::optional<CompletedDebugTypeInfo> ElemDbgTy;
      if (auto PayloadTy = ElemDecl->getPayloadInterfaceType()) {
        // A variant case which carries a payload.
        PayloadTy = ElemDecl->getParentEnum()->mapTypeIntoEnvironment(PayloadTy);
        auto &TI = IGM.getTypeInfoForUnlowered(PayloadTy);
        ElemDbgTy = CompletedDebugTypeInfo::getFromTypeInfo(PayloadTy, TI, IGM);
        // FIXME: This is not correct, but seems to be the only way to emit
        // children for opaque-sized payload-carrying enums.
        if (!ElemDbgTy)
          ElemDbgTy =
              CompletedDebugTypeInfo::getFromTypeInfo(PayloadTy, TI, IGM, 0);
        if (!ElemDbgTy) {
          // Without complete type info we can only create a forward decl.
          return DBuilder.createForwardDecl(
              llvm::dwarf::DW_TAG_structure_type, Name, Scope, File, Line,
              llvm::dwarf::DW_LANG_Swift, SizeInBits, 0, MangledName);
        }
        llvm::DIType *PayloadDITy = getOrCreateType(*ElemDbgTy);
        PayloadDITy =
            wrapInReferenceTypeIfIndirect(PayloadDITy, ElemDecl, Decl);

        MemberTypes.emplace_back(ElemDecl->getBaseIdentifier().str(),
                                 getAlignInBits(*ElemDbgTy),
                                 TrackingDIType(PayloadDITy));
        anchorTypeAliasesIn(PayloadTy);
      } else {
        // A variant with no payload.
        MemberTypes.emplace_back(ElemDecl->getBaseIdentifier().str(), 0,
                                 nullptr);
      }
    }
    SmallVector<llvm::Metadata *, 16> Members;
    for (auto &Member : MemberTypes) {
      unsigned Offset = 0;
      Members.push_back(createMemberType(Member.DIType, Member.Name, Offset,
                                         Member.AlignInBits, Scope, File,
                                         Flags));
    }

    auto VPTy = DBuilder.createVariantPart(
        Scope, {}, File, Line, SizeInBits, AlignInBits, Flags, nullptr,
        DBuilder.getOrCreateArray(Members), /*UniqueIdentifier=*/"");

    llvm::DICompositeType *DITy = DBuilder.createStructType(
        Scope, Name, File, Line, SizeInBits, AlignInBits, Flags, nullptr,
        DBuilder.getOrCreateArray(VPTy), llvm::dwarf::DW_LANG_Swift, nullptr,
        MangledName, nullptr, NumExtraInhabitants ? *NumExtraInhabitants : 0);
    return DBuilder.replaceTemporary(std::move(FwdDecl), DITy);
  }

  // Create debug information for an enum with no raw type.
  llvm::DICompositeType *
  createUnsubstitutedVariantType(DebugTypeInfo DbgTy, EnumDecl *Decl,
                                 StringRef MangledName,
                                 llvm::DIScope *Scope, llvm::DIFile *File,
                                 unsigned Line, llvm::DINode::DIFlags Flags) {
    assert(!Decl->getRawType() &&
           "Attempting to create variant debug info from raw enum!");

    StringRef Name = Decl->getName().str();
    auto NumExtraInhabitants = DbgTy.getNumExtraInhabitants();

    unsigned SizeInBits = 0;
    unsigned AlignInBits = 0;
    // A variant part should actually be a child to a DW_TAG_structure_type
    // according to the DWARF spec.
    auto FwdDecl = createTemporaryReplaceableForwardDecl(
        DbgTy.getType(), Scope, File, Line, SizeInBits, AlignInBits, Flags,
        MangledName, Name);

    SmallVector<MemberDIType, 16> MemberTypes;
    for (auto *ElemDecl : Decl->getAllElements()) {
      std::optional<DebugTypeInfo> ElemDbgTy;
      if (auto PayloadTy = ElemDecl->getPayloadInterfaceType()) {
        // A variant case which carries a payload.
        PayloadTy = ElemDecl->getParentEnum()->mapTypeIntoEnvironment(PayloadTy);
        ElemDbgTy = DebugTypeInfo::getFromTypeInfo(
            PayloadTy, IGM.getTypeInfoForUnlowered(PayloadTy), IGM);
        llvm::DIType *PayloadDITy = getOrCreateType(*ElemDbgTy);
        PayloadDITy =
            wrapInReferenceTypeIfIndirect(PayloadDITy, ElemDecl, Decl);

        MemberTypes.emplace_back(ElemDecl->getBaseIdentifier().str(),
                                 getAlignInBits(*ElemDbgTy),
                                 TrackingDIType(PayloadDITy));
        anchorTypeAliasesIn(PayloadTy);
      } else {
        // A variant with no payload.
        MemberTypes.emplace_back(ElemDecl->getBaseIdentifier().str(), 0,
                                 nullptr);
      }
    }
    SmallVector<llvm::Metadata *, 16> Members;
    for (auto &Member : MemberTypes) {
      unsigned Offset = 0;
      Members.push_back(createMemberType(Member.DIType, Member.Name, Offset,
                                         Member.AlignInBits, Scope, File,
                                         Flags));
    }

    auto VPTy = DBuilder.createVariantPart(Scope, {}, File, Line, SizeInBits,
                                           AlignInBits, Flags, nullptr,
                                           DBuilder.getOrCreateArray(Members));

    llvm::DICompositeType *DITy = DBuilder.createStructType(
        Scope, Name, File, Line, SizeInBits, AlignInBits, Flags, nullptr,
        DBuilder.getOrCreateArray(VPTy), llvm::dwarf::DW_LANG_Swift, nullptr,
        MangledName, nullptr, NumExtraInhabitants.value_or(0));
    return DBuilder.replaceTemporary(std::move(FwdDecl), DITy);
  }

  llvm::DICompositeType *createEnumType(CompletedDebugTypeInfo DbgTy,
                                        EnumDecl *Decl, StringRef MangledName,
                                        unsigned AlignInBits,
                                        llvm::DIScope *Scope,
                                        llvm::DIFile *File, unsigned Line,
                                        llvm::DINode::DIFlags Flags) {
    if (Decl->hasRawType())
      return createRawEnumType(DbgTy, Decl, MangledName, Scope, File, Line,
                               Flags);
    return createVariantType(DbgTy, Decl, MangledName, AlignInBits, Scope, File,
                             Line, Flags);
  }

  llvm::DIType *getOrCreateDesugaredType(Type Ty, DebugTypeInfo DbgTy) {
    DebugTypeInfo BlandDbgTy(Ty, DbgTy.getAlignment(), false,
                             DbgTy.isFixedBuffer(),
                             DbgTy.getNumExtraInhabitants());
    return getOrCreateType(BlandDbgTy);
  }

  uint64_t getSizeOfBasicType(CompletedDebugTypeInfo DbgTy) {
    uint64_t BitWidth = DbgTy.getSizeInBits();
    return BitWidth;
  }

  /// Collect the type parameters of a bound generic type. This is needed to
  /// anchor any typedefs that may appear in parameters so they can be
  /// resolved in the debugger without needing to query the Swift module.
  llvm::DINodeArray collectGenericParams(NominalOrBoundGenericNominalType *BGT,
                                         bool AsForwardDeclarations = false) {

    // Collect the generic args from the type and its parent.
    std::vector<Type> GenericArgs;
    Type CurrentType = BGT;
    while (CurrentType && CurrentType->getAnyNominal()) {
      if (auto *BGT = CurrentType->getAs<BoundGenericType>())
        GenericArgs.insert(GenericArgs.end(), BGT->getGenericArgs().begin(),
                           BGT->getGenericArgs().end());
      CurrentType = CurrentType->getNominalParent();
    }

    SmallVector<llvm::Metadata *, 16> TemplateParams;
    for (auto Arg : GenericArgs) {
      DebugTypeInfo ParamDebugType;
      if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes &&
          !AsForwardDeclarations) {
        if (Arg->is<IntegerType>()) {
          ParamDebugType = DebugTypeInfo(Arg);
        } else {
          // For the DwarfTypes level don't generate just a forward declaration
          // for the generic type parameters.
          ParamDebugType = DebugTypeInfo::getFromTypeInfo(
              Arg, IGM.getTypeInfoForUnlowered(Arg), IGM);
        }
      } else {
        ParamDebugType = DebugTypeInfo::getForwardDecl(Arg);
      }

      TemplateParams.push_back(DBuilder.createTemplateTypeParameter(
          TheCU, "", getOrCreateType(ParamDebugType), false));
    }
    return DBuilder.getOrCreateArray(TemplateParams);
  }

  /// Create a sized container for a sizeless type. Used to represent
  /// BoundGenericEnums that may have different sizes depending on what they are
  /// bound to, but still share a mangled name.
  llvm::DIType *createOpaqueStructWithSizedContainer(
      llvm::DIScope *Scope, StringRef Name, llvm::DIFile *File, unsigned Line,
      unsigned SizeInBits, unsigned AlignInBits, llvm::DINode::DIFlags Flags,
      StringRef MangledName, llvm::DINodeArray BoundParams,
      llvm::DIType *SpecificationOf = nullptr) {
    // This uses a separate cache and not DIRefMap for the inner type to avoid
    // associating the anonymous container (which is specific to the
    // variable/storage and not the type) with the MangledName.
    llvm::DICompositeType *UniqueType = nullptr;
    auto *UID = llvm::MDString::get(IGM.getLLVMContext(), MangledName);
    if (llvm::Metadata *V = InnerTypeCache.lookup(UID))
      UniqueType = cast<llvm::DICompositeType>(V);
    else {
      UniqueType = DBuilder.createForwardDecl(
          llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, File, Line,
          llvm::dwarf::DW_LANG_Swift, 0, 0);
      if (BoundParams)
        DBuilder.replaceArrays(UniqueType, nullptr, BoundParams);
      InnerTypeCache[UID] = llvm::TrackingMDNodeRef(UniqueType);
    }

    // CodeView drops empty unnamed members, so we need to give the inner struct
    // member a name so it survives.
    StringRef MemberName = Opts.isDebugInfoCodeView() ? MangledName : "";
    llvm::Metadata *Elements[] = {DBuilder.createMemberType(
        Scope, MemberName, File, 0, SizeInBits, AlignInBits, 0, Flags,
        UniqueType)};
    // FIXME: It's a limitation of LLVM that a forward declaration cannot have a
    // specificationOf, so this attritbute is put on the sized container type
    // instead. This is confusing consumers, and LLDB has to go out of its way
    // to parse these confusing types as intended.
    return DBuilder.createStructType(
        Scope, "", File, Line, SizeInBits, AlignInBits, Flags,
        /* DerivedFrom */ nullptr, DBuilder.getOrCreateArray(Elements),
        llvm::dwarf::DW_LANG_Swift, nullptr, "", SpecificationOf, 0);
  }

  llvm::DIType *
  createPointerSizedStruct(llvm::DIScope *Scope, StringRef Name,
                           llvm::DIFile *File, unsigned Line,
                           llvm::DINode::DIFlags Flags, StringRef MangledName,
                           llvm::DIType *SpecificationOf = nullptr) {
    if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
      auto FwdDecl = DBuilder.createForwardDecl(
          llvm::dwarf::DW_TAG_structure_type, Name, Scope, File, Line,
          llvm::dwarf::DW_LANG_Swift, 0, 0);
      return createPointerSizedStruct(Scope, Name, FwdDecl, File, Line, Flags,
                                      MangledName, SpecificationOf);
    } else {
      unsigned SizeInBits = CI.getTargetInfo().getPointerWidth(clang::LangAS::Default);
      return createOpaqueStruct(Scope, Name, File, Line, SizeInBits, 0, Flags,
                                MangledName);
    }
  }

  llvm::DIType *createPointerSizedStruct(
      llvm::DIScope *Scope, StringRef Name, llvm::DIType *PointeeTy,
      llvm::DIFile *File, unsigned Line, llvm::DINode::DIFlags Flags,
      StringRef MangledName, llvm::DIType *SpecificationOf = nullptr,
      uint32_t NumExtraInhabitants = 0) {
    unsigned PtrSize =
        CI.getTargetInfo().getPointerWidth(clang::LangAS::Default);
    auto PtrTy = DBuilder.createPointerType(PointeeTy, PtrSize, 0);
    llvm::Metadata *Elements[] = {DBuilder.createMemberType(
        Scope, "ptr", File, 0, PtrSize, 0, 0, Flags, PtrTy)};
    return DBuilder.createStructType(
        Scope, Name, File, Line, PtrSize, 0, Flags,
        /* DerivedFrom */ nullptr, DBuilder.getOrCreateArray(Elements),
        llvm::dwarf::DW_LANG_Swift, nullptr, MangledName, SpecificationOf,
        NumExtraInhabitants);
  }

  llvm::DIType *createDoublePointerSizedStruct(
      llvm::DIScope *Scope, StringRef Name, llvm::DIType *PointeeTy,
      llvm::DIFile *File, unsigned Line, llvm::DINode::DIFlags Flags,
      StringRef MangledName, uint32_t NumExtraInhabitants = 0) {
    unsigned PtrSize = CI.getTargetInfo().getPointerWidth(clang::LangAS::Default);
    llvm::Metadata *Elements[] = {
        DBuilder.createMemberType(
            Scope, "ptr", File, 0, PtrSize, 0, 0, Flags,
            DBuilder.createPointerType(PointeeTy, PtrSize, 0)),
        DBuilder.createMemberType(
            Scope, "_", File, 0, PtrSize, 0, 0, Flags,
            DBuilder.createPointerType(nullptr, PtrSize, 0))};
    return DBuilder.createStructType(
        Scope, Name, File, Line, 2 * PtrSize, 0, Flags,
        /* DerivedFrom */ nullptr, DBuilder.getOrCreateArray(Elements),
        llvm::dwarf::DW_LANG_Swift, nullptr, MangledName,
        /*Specification=*/nullptr, NumExtraInhabitants);
  }

  llvm::DIType *createFixedValueBufferStruct(llvm::DIType *PointeeTy) {
    unsigned Line = 0;
    unsigned PtrSize = CI.getTargetInfo().getPointerWidth(clang::LangAS::Default);
    llvm::DINode::DIFlags Flags = llvm::DINode::FlagArtificial;
    llvm::DIFile *File = MainFile;
    llvm::DIScope *Scope = TheCU;
    llvm::Metadata *Elements[] = {DBuilder.createMemberType(
        Scope, "contents", File, 0, PtrSize, 0, 0, Flags, PointeeTy)};
    return DBuilder.createStructType(
        Scope, "$swift.fixedbuffer", File, Line, 3 * PtrSize, 0, Flags,
        /* DerivedFrom */ nullptr, DBuilder.getOrCreateArray(Elements),
        llvm::dwarf::DW_LANG_Swift, nullptr);
  }

  /// Create struct with a single member, used for Swift types that do not yet
  /// have specialized DIDerivedTypes.
  llvm::DIType *createSingleMemberStruct(
      llvm::DIScope *Scope, StringRef Name, llvm::DIFile *File, unsigned Line,
      unsigned SizeInBits, unsigned AlignInBits, llvm::DINode::DIFlags Flags,
      StringRef MangledName, StringRef MemberName, llvm::DIType *MemberType) {
    llvm::Metadata *Elements[] = {
        DBuilder.createMemberType(Scope, MemberName, File, 0, SizeInBits,
                                  AlignInBits, 0, Flags, MemberType)};
    return DBuilder.createStructType(
        Scope, Name, File, Line, SizeInBits, AlignInBits, Flags,
        /* DerivedFrom */ nullptr, DBuilder.getOrCreateArray(Elements),
        llvm::dwarf::DW_LANG_Swift, nullptr, MangledName, nullptr, 0);
  }

  llvm::DIType *createFunctionPointer(DebugTypeInfo DbgTy, llvm::DIScope *Scope,
                                      unsigned SizeInBits, unsigned AlignInBits,
                                      llvm::DINode::DIFlags Flags,
                                      StringRef MangledName,
                                      uint32_t NumExtraInhabitants) {
    auto FwdDecl = createTemporaryReplaceableForwardDecl(
        DbgTy.getType(), Scope, MainFile, 0, SizeInBits, AlignInBits, Flags,
        MangledName, MangledName);

    CanSILFunctionType FunTy;
    TypeBase *BaseTy = DbgTy.getType();
    if (auto *SILFnTy = dyn_cast<SILFunctionType>(BaseTy))
      FunTy = CanSILFunctionType(SILFnTy);
    // FIXME: Handling of generic parameters in SIL type lowering is in flux.
    // DebugInfo doesn't appear to care about the generic context, so just
    // throw it away before lowering.
    else if (isa<GenericFunctionType>(BaseTy)) {
      auto *fTy = cast<AnyFunctionType>(BaseTy);
      auto *nongenericTy = FunctionType::get(fTy->getParams(), fTy->getResult(),
                                             fTy->getExtInfo());

      FunTy = IGM.getLoweredType(nongenericTy).castTo<SILFunctionType>();
    } else
      FunTy = IGM.getLoweredType(BaseTy).castTo<SILFunctionType>();
    auto Params = createParameterTypes(FunTy);

    auto FnTy = DBuilder.createSubroutineType(Params, Flags);
    llvm::DIType *DITy;
    if (FunTy->getRepresentation() == SILFunctionType::Representation::Thick) {
      if (SizeInBits == 2 * CI.getTargetInfo().getPointerWidth(clang::LangAS::Default))
        // This is a FunctionPairTy: { i8*, %swift.refcounted* }.
        DITy = createDoublePointerSizedStruct(Scope, MangledName, FnTy,
                                              MainFile, 0, Flags, MangledName,
                                              NumExtraInhabitants);
      else
        // This is a generic function as noted above.
        DITy = createOpaqueStruct(Scope, MangledName, MainFile, 0, SizeInBits,
                                  AlignInBits, Flags, MangledName, {}, nullptr,
                                  nullptr, NumExtraInhabitants);
    } else {
      assert(SizeInBits == CI.getTargetInfo().getPointerWidth(clang::LangAS::Default));
      DITy = createPointerSizedStruct(
          Scope, MangledName, FnTy, MainFile, 0, Flags, MangledName,
          /*SpecificationOf=*/nullptr, NumExtraInhabitants);
    }
    return DBuilder.replaceTemporary(std::move(FwdDecl), DITy);
  }

  llvm::DIType *createTuple(DebugTypeInfo DbgTy, llvm::DIScope *Scope,
                            unsigned SizeInBits, unsigned AlignInBits,
                            llvm::DINode::DIFlags Flags,
                            StringRef MangledName) {
    auto FwdDecl = createTemporaryReplaceableForwardDecl(
        DbgTy.getType(), Scope, MainFile, 0, SizeInBits, AlignInBits, Flags,
        MangledName, MangledName);

    TypeBase *BaseTy = DbgTy.getType();
    auto *TupleTy = BaseTy->castTo<TupleType>();

    SmallVector<MemberDIType, 16> MemberTypes;
    auto genericSig = IGM.getCurGenericContext();
    for (auto ElemTy : TupleTy->getElementTypes()) {
      auto &elemTI = IGM.getTypeInfoForUnlowered(
          AbstractionPattern(genericSig, ElemTy->getCanonicalType()), ElemTy);
      auto DbgTy =
            DebugTypeInfo::getFromTypeInfo(ElemTy, elemTI, IGM);
      MemberTypes.emplace_back("", getAlignInBits(DbgTy),
                               getOrCreateType(DbgTy));
    }
    SmallVector<llvm::Metadata *, 16> Members;
    unsigned OffsetInBits = 0;
    for (auto &Member : MemberTypes)
      Members.emplace_back(createMemberType(Member.DIType, Member.Name,
                                            OffsetInBits, Member.AlignInBits,
                                            Scope, MainFile, Flags));
    // FIXME: assert that SizeInBits == OffsetInBits.

    llvm::DICompositeType *DITy = DBuilder.createStructType(
        Scope, MangledName, MainFile, 0, SizeInBits, AlignInBits, Flags,
        nullptr, // DerivedFrom
        DBuilder.getOrCreateArray(Members), llvm::dwarf::DW_LANG_Swift, nullptr,
        MangledName);

    return DBuilder.replaceTemporary(std::move(FwdDecl), DITy);
  }

  llvm::DICompositeType *
  createStruct(llvm::DIScope *Scope, StringRef Name, llvm::DIFile *File,
               unsigned Line, unsigned SizeInBits, unsigned AlignInBits,
               llvm::DINode::DIFlags Flags, StringRef MangledName,
               llvm::DINodeArray Elements, llvm::DINodeArray BoundParams,
               llvm::DIType *SpecificationOf, llvm::DINodeArray Annotations,
               uint32_t NumExtraInhabitants = 0) {

    auto StructType = DBuilder.createStructType(
        Scope, Name, File, Line, SizeInBits, AlignInBits, Flags,
        /* DerivedFrom */ nullptr, Elements, llvm::dwarf::DW_LANG_Swift,
        nullptr, MangledName, SpecificationOf, NumExtraInhabitants,
        Annotations);

    if (BoundParams)
      DBuilder.replaceArrays(StructType, nullptr, BoundParams);
    return StructType;
  }

  llvm::DICompositeType *
  createOpaqueStruct(llvm::DIScope *Scope, StringRef Name, llvm::DIFile *File,
                     unsigned Line, unsigned SizeInBits, unsigned AlignInBits,
                     llvm::DINode::DIFlags Flags, StringRef MangledName,
                     llvm::DINodeArray BoundParams = {},
                     llvm::DIType *SpecificationOf = nullptr,
                     llvm::DINodeArray Annotations = nullptr,
                     uint32_t NumExtraInhabitants = 0) {
    return createStruct(Scope, Name, File, Line, SizeInBits, AlignInBits, Flags,
                        MangledName, {}, BoundParams, SpecificationOf,
                        Annotations, NumExtraInhabitants);
  }

  bool shouldCacheDIType(llvm::DIType *DITy, DebugTypeInfo &DbgTy) {
    // Don't cache a type alias to a forward declaration either.
    if (DbgTy.isFixedBuffer() || DITy->isForwardDecl())
      return false;

    if (auto Ty = DbgTy.getType())
      // FIXME: Primary archetypes carry all sorts of auxiliary information
      // that isn't contained in their mangled name.  See also
      // getMangledName().
      return Ty->getKind() != swift::TypeKind::PrimaryArchetype;
    return true;
  }

  std::optional<CompletedDebugTypeInfo> completeType(DebugTypeInfo DbgTy) {
    if (!DbgTy.getType() || DbgTy.getType()->hasTypeParameter() ||
        isa<IntegerType>(DbgTy.getType()))
      return {};
    return CompletedDebugTypeInfo::getFromTypeInfo(
        DbgTy.getType(), IGM.getTypeInfoForUnlowered(DbgTy.getType()), IGM);
  }

  llvm::DIType *createType(DebugTypeInfo DbgTy, StringRef MangledName,
                           llvm::DIScope *Scope, llvm::DIFile *File) {
    // FIXME: For SizeInBits, clang uses the actual size of the type on
    // the target machine instead of the storage size that is alloca'd
    // in the LLVM IR. For all types that are boxed in a struct, we are
    // emitting the storage size of the struct, but it may be necessary
    // to emit the (target!) size of the underlying basic type.
    std::optional<CompletedDebugTypeInfo> CompletedDbgTy = completeType(DbgTy);
    std::optional<uint64_t> SizeInBitsOrNull;
    if (CompletedDbgTy)
      SizeInBitsOrNull = CompletedDbgTy->getSizeInBits();

    uint64_t SizeInBits = SizeInBitsOrNull.value_or(0);
    unsigned AlignInBits = getAlignInBits(DbgTy);
    unsigned Encoding = 0;
    uint32_t NumExtraInhabitants = DbgTy.getNumExtraInhabitants().value_or(0);

    llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;

    TypeBase *BaseTy = DbgTy.getType();
    if (!BaseTy) {
      LLVM_DEBUG(llvm::dbgs() << "Type without TypeBase: ";
                 DbgTy.getType()->dump(llvm::dbgs()); llvm::dbgs() << "\n");
      if (!InternalType) {
        StringRef Name = "<internal>";
        InternalType = DBuilder.createForwardDecl(
            llvm::dwarf::DW_TAG_structure_type, Name, Scope, File,
            /*Line*/ 0, llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits,
            MangledName);
      }
      return InternalType;
    }

    llvm::DIType *SpecificationOf = nullptr;

    // Here goes!
    switch (BaseTy->getKind()) {
    case TypeKind::LValue:
    case TypeKind::TypeVariable:
    case TypeKind::ErrorUnion:
    case TypeKind::Placeholder:
    case TypeKind::Join:
    case TypeKind::Meet:
    case TypeKind::Module:
    case TypeKind::BuiltinUnboundGeneric:
    case TypeKind::BuiltinBorrow:
      ABORT([&](llvm::raw_ostream &out) {
        out << "Don't know how to emit debug info for type:\n";
        BaseTy->dump(out);
      });

    case TypeKind::Hidden: {
      unsigned FwdDeclLine = 0;
      return createOpaqueStruct(Scope, MangledName, MainFile, FwdDeclLine,
                                SizeInBits, AlignInBits, Flags, MangledName);
    }

    case TypeKind::BuiltinFixedArray: {
      if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
        auto *FixedArray = llvm::cast<swift::BuiltinFixedArrayType>(BaseTy);
        llvm::DIType *ElementTy = getOrCreateType(FixedArray->getElementType());
        llvm::SmallVector<llvm::Metadata *, 2> Subscripts;
        if (auto NumElts = FixedArray->getFixedInhabitedSize()) {
          auto *NumEltsNode = llvm::ConstantAsMetadata::get(
              llvm::ConstantInt::get(IGM.Int64Ty, *NumElts));
          Subscripts.push_back(DBuilder.getOrCreateSubrange(
              NumEltsNode /*count*/, nullptr /*lowerBound*/,
              nullptr /*upperBound*/, nullptr /*stride*/));
        }
        return DBuilder.createArrayType(SizeInBits, AlignInBits, ElementTy,
                                        DBuilder.getOrCreateArray(Subscripts));
      }
      unsigned FwdDeclLine = 0;
      return createOpaqueStruct(Scope, "Builtin.FixedArray", MainFile,
                                FwdDeclLine, SizeInBits, AlignInBits, Flags,
                                MangledName);
    }

    case TypeKind::BuiltinPackIndex:
    case TypeKind::BuiltinInteger: {
      Encoding = llvm::dwarf::DW_ATE_unsigned;
      if (CompletedDbgTy)
        SizeInBits = getSizeOfBasicType(*CompletedDbgTy);
      break;
    }

    case TypeKind::BuiltinIntegerLiteral: {
      Encoding = llvm::dwarf::DW_ATE_unsigned; // ?
      if (CompletedDbgTy)
        SizeInBits = getSizeOfBasicType(*CompletedDbgTy);
      break;
    }

    case TypeKind::BuiltinFloat: {
      auto *FloatTy = BaseTy->castTo<BuiltinFloatType>();
      // Assuming that the bitwidth and FloatTy->getFPKind() are identical.
      SizeInBits = FloatTy->getBitWidth();
      Encoding = llvm::dwarf::DW_ATE_float;
      break;
    }

    case TypeKind::BuiltinNativeObject:
    case TypeKind::BuiltinBridgeObject:
    case TypeKind::BuiltinRawPointer:
    case TypeKind::BuiltinRawUnsafeContinuation:
    case TypeKind::BuiltinJob: {
      unsigned PtrSize =
          CI.getTargetInfo().getPointerWidth(clang::LangAS::Default);
      if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
        Flags |= llvm::DINode::FlagArtificial;
        llvm::DICompositeType *PTy = DBuilder.createStructType(
            Scope, MangledName, File, 0, PtrSize, 0, Flags, nullptr, nullptr,
            llvm::dwarf::DW_LANG_Swift, nullptr, {}, nullptr,
            NumExtraInhabitants);
        return PTy;
      }
      llvm::DIDerivedType *PTy = DBuilder.createPointerType(
          nullptr, PtrSize, 0,
          /* DWARFAddressSpace */ std::nullopt, MangledName);

      // FIXME: Set DIFlagObjectPointer and make sure it is only set for `self`.
      return PTy;
    }
    case TypeKind::BuiltinExecutor: {
      return createDoublePointerSizedStruct(
          Scope, "Builtin.Executor", nullptr, MainFile, 0,
          llvm::DINode::FlagArtificial, MangledName);
    }

    case TypeKind::BuiltinImplicitActor: {
      return createDoublePointerSizedStruct(
          Scope, "Builtin.ImplicitActor", nullptr, MainFile, 0,
          llvm::DINode::FlagArtificial, MangledName);
    }

    case TypeKind::DynamicSelf: {
      // Self. We don't have a way to represent instancetype in DWARF,
      // so we emit the static type instead. This is similar to what we
      // do with instancetype in Objective-C.
      auto *DynamicSelfTy = BaseTy->castTo<DynamicSelfType>();
      auto SelfTy =
          getOrCreateDesugaredType(DynamicSelfTy->getSelfType(), DbgTy);
      return DBuilder.createTypedef(SelfTy, MangledName, File, 0, File);
    }

    // Even builtin swift types usually come boxed in a struct.
    case TypeKind::Struct: {
      auto *StructTy = BaseTy->castTo<StructType>();
      auto *Decl = StructTy->getDecl();
      auto L = getFileAndLocation(Decl);
      // No line numbers are attached to type forward declarations.  This is
      // intentional: It interferes with the efficacy of incremental builds.
      // We don't want a whitespace change to an secondary file trigger a
      // recompilation of the debug info of a primary source file.
      unsigned FwdDeclLine = 0;
      if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
        if (StructTy->isSpecialized())
          return createSpecializedStructOrClassType(
              StructTy, Scope, L.File, L.Line, SizeInBits, AlignInBits,
              Flags, MangledName);
        return createStructType(StructTy, Decl, Scope, L.File, L.Line,
                                SizeInBits, AlignInBits, Flags, MangledName);
      }
      StringRef Name = Decl->getName().str();
      if (!SizeInBitsOrNull)
        return DBuilder.createForwardDecl(
            llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, L.File,
            FwdDeclLine, llvm::dwarf::DW_LANG_Swift, 0, AlignInBits);
      if (DbgTy.isFixedBuffer())
        return DBuilder.createForwardDecl(
            llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, L.File,
            FwdDeclLine, llvm::dwarf::DW_LANG_Swift, 0, AlignInBits);
      return createOpaqueStruct(Scope, Name, L.File, FwdDeclLine, SizeInBits,
                                AlignInBits, Flags, MangledName, {},
                                SpecificationOf);
    }

    case TypeKind::Class: {
      // Classes are represented as DW_TAG_structure_type. This way the
      // DW_AT_APPLE_runtime_class(DW_LANG_Swift) attribute can be
      // used to differentiate them from C++ and ObjC classes.
      auto *ClassTy = BaseTy->castTo<ClassType>();
      auto *Decl = ClassTy->getDecl();
      auto L = getFileAndLocation(Decl);
      unsigned FwdDeclLine = 0;
      assert(SizeInBits ==
             CI.getTargetInfo().getPointerWidth(clang::LangAS::Default));
      if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
        if (ClassTy->isSpecialized())
          return createSpecializedStructOrClassType(
              ClassTy, Scope, L.File, L.Line, SizeInBits, AlignInBits,
              Flags, MangledName);

        auto *DIType =
            createStructType(ClassTy, Decl, Scope, File, L.Line, SizeInBits,
                             AlignInBits, Flags, MangledName);
        assert(DIType && "Unexpected null DIType!");
        assert(DIType && "createStructType should never return null!");
        auto SuperClassTy = ClassTy->getSuperclass();
        if (SuperClassTy) {
          auto SuperClassDbgTy = DebugTypeInfo::getFromTypeInfo(
              SuperClassTy, IGM.getTypeInfoForUnlowered(SuperClassTy), IGM);

          llvm::DIType *SuperClassDITy = getOrCreateType(SuperClassDbgTy);
          assert(SuperClassDITy && "getOrCreateType should never return null!");
          DBuilder.retainType(DBuilder.createInheritance(
              DIType, SuperClassDITy, 0, 0, llvm::DINode::FlagZero));
        }
        return DIType;
      }
      return createPointerSizedStruct(Scope, Decl->getNameStr(), L.File,
                                      FwdDeclLine, Flags, MangledName,
                                      SpecificationOf);
    }

    case TypeKind::Existential: {
      auto *ExistentialTy = BaseTy->castTo<ExistentialType>();
      Type ConstraintTy = ExistentialTy->getConstraintType();
      TypeBase *TyPtr = ConstraintTy.getPointer();
      if (!isa<ProtocolType>(TyPtr) && !isa<ProtocolCompositionType>(TyPtr) &&
          !isa<ParameterizedProtocolType>(TyPtr)) {
        // This could be an alias type, which we need to anchor in DWARF.
        auto *Decl = DbgTy.getDecl();
        auto L = getFileAndLocation(Decl);
        unsigned FwdDeclLine = 0;
        return createSingleMemberStruct(
            Scope, Decl ? Decl->getNameStr() : MangledName, L.File, FwdDeclLine,
            SizeInBits, AlignInBits, Flags, MangledName, "$swift.constraint",
            getOrCreateType(ConstraintTy));
      }
      // If the existential is just a protocol type it shares its mangled name
      // with it, so we can just represent it directly as a protocol.
      auto ProtoDbgTy = DebugTypeInfo::getFromTypeInfo(
          TyPtr, IGM.getTypeInfoForUnlowered(TyPtr), IGM);
      return getOrCreateType(ProtoDbgTy);
    }

    case TypeKind::ProtocolComposition: {
      auto *CompTy = BaseTy->castTo<ProtocolCompositionType>();

      // A composition's mangled name will always be that of the canonical
      // composition type. This means that a composition can be canonicalized
      // into a single protocol type. For example, given:
      //
      // protocol P {}
      // typealias P2 = P
      // func f(param: (any P & P2)) {}
      //
      // The canonical type of "param" is simply P. To make sure we don't have
      // two conflicting types with the same mangled name (one being the
      // protocol composition, the other being only the protocol), In that case,
      // emit debug info as only the protocol type.
      auto CanTy = BaseTy->getCanonicalType();
      if (!isa<ProtocolCompositionType>(CanTy)) {
        return getOrCreateDesugaredType(CanTy, DbgTy);
      }

      llvm::TempDICompositeType FwdDecl(DBuilder.createReplaceableCompositeType(
          llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, nullptr, 0,
          llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags));

      SmallVector<llvm::Metadata *, 4> Members;
      for (const Type MemberTy : CompTy->getMembers()) {
        auto MemberDbgTy = DebugTypeInfo::getFromTypeInfo(
            MemberTy, IGM.getTypeInfoForUnlowered(MemberTy), IGM);
        auto *MemberDITy = getOrCreateType(MemberDbgTy);
        Members.push_back(
            DBuilder.createInheritance(FwdDecl.get(), MemberDITy, 0, 0, Flags));
      }

      auto *DITy = DBuilder.createStructType(
          Scope, MangledName, nullptr, 0, SizeInBits, AlignInBits, Flags,
          nullptr, DBuilder.getOrCreateArray(Members),
          llvm::dwarf::DW_LANG_Swift, /*VTableHolder=*/nullptr, MangledName);

      return DBuilder.replaceTemporary(std::move(FwdDecl), DITy);
    }

    // FIXME: (LLVM branch) This should probably be a DW_TAG_interface_type.
    case TypeKind::Protocol:
    case TypeKind::ParameterizedProtocol: {
      auto *Decl = DbgTy.getDecl();
      auto L = getFileAndLocation(Decl);
      unsigned FwdDeclLine = 0;

      llvm::DINodeArray Annotations = nullptr;
      if (auto *PD = dyn_cast_or_null<ProtocolDecl>(Decl)) {
        SmallVector<llvm::Metadata *, 2> Annots;
        auto addFlag = [&](StringRef Name) {
          llvm::Metadata *Ops[2] = {
              llvm::MDString::get(IGM.getLLVMContext(), Name),
              llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
                  llvm::Type::getInt1Ty(IGM.getLLVMContext()), true))};
          Annots.push_back(llvm::MDNode::get(IGM.getLLVMContext(), Ops));
        };

        if (PD->isMarkerProtocol())
          addFlag("swift.MarkerProtocol");

        if (PD->isObjC())
          addFlag("swift.ObjCProtocol");
        else if (PD->requiresClass())
          addFlag("swift.ClassConstrainedProtocol");

        if (!Annots.empty())
          Annotations = DBuilder.getOrCreateArray(Annots);
      }

      return createOpaqueStruct(Scope, Decl ? Decl->getNameStr() : MangledName,
                                L.File, FwdDeclLine, SizeInBits, AlignInBits,
                                Flags, MangledName, /*BoundParams=*/{},
                                /*SpecificationOf=*/nullptr, Annotations);
    }

    case TypeKind::UnboundGeneric: {
      auto *UnboundTy = BaseTy->castTo<UnboundGenericType>();
      auto *Decl = UnboundTy->getDecl();
      auto L = getFileAndLocation(Decl);
      unsigned FwdDeclLine = 0;
      assert(SizeInBits ==
             CI.getTargetInfo().getPointerWidth(clang::LangAS::Default));
      return createPointerSizedStruct(Scope,
                                      Decl ? Decl->getNameStr() : MangledName,
                                      L.File, FwdDeclLine, Flags, MangledName);
    }

    case TypeKind::BoundGenericStruct: {
      auto *StructTy = BaseTy->castTo<BoundGenericStructType>();
      auto *Decl = StructTy->getDecl();
      auto L = getFileAndLocation(Decl);
      unsigned FwdDeclLine = 0;
      if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
        return createSpecializedStructOrClassType(
            StructTy, Scope, L.File, L.Line, SizeInBits, AlignInBits,
            Flags, MangledName);

      return createOpaqueStructWithSizedContainer(
          Scope, Decl ? Decl->getNameStr() : "", L.File, FwdDeclLine,
          SizeInBits, AlignInBits, Flags, MangledName,
          collectGenericParams(StructTy), SpecificationOf);
    }

    case TypeKind::BoundGenericClass: {
      auto *ClassTy = BaseTy->castTo<BoundGenericClassType>();
      auto *Decl = ClassTy->getDecl();
      auto L = getFileAndLocation(Decl);
      return createSpecializedStructOrClassType(ClassTy, Scope, L.File,
                                                L.Line, SizeInBits, AlignInBits,
                                                Flags, MangledName);
    }

    case TypeKind::Pack:
    case TypeKind::PackElement:
    case TypeKind::SILPack:
    case TypeKind::PackExpansion:
      // assert(SizeInBits == CI.getTargetInfo().getPointerWidth(0));
      return createPointerSizedStruct(Scope, MangledName, MainFile, 0, Flags,
                                      MangledName);

    case TypeKind::BuiltinTuple:
      llvm_unreachable("BuiltinTupleType should not show up here");

    case TypeKind::Tuple: {
      // Tuples are also represented as structs.  Since tuples are ephemeral
      // (not nominal) they don't have a source location.
      if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
        return createTuple(DbgTy, Scope, SizeInBits, AlignInBits, Flags,
                           MangledName);
      else
        return createOpaqueStruct(Scope, MangledName, MainFile, 0, SizeInBits,
                                  AlignInBits, Flags, MangledName);
    }

    case TypeKind::InOut:
      break;

    case TypeKind::OpaqueTypeArchetype:
    case TypeKind::PrimaryArchetype:
    case TypeKind::ExistentialArchetype:
    case TypeKind::ElementArchetype:
    case TypeKind::PackArchetype: {
      auto *Archetype = BaseTy->castTo<ArchetypeType>();
      AssociatedTypeDecl *assocType = nullptr;
      if (auto depMemTy =
              Archetype->getInterfaceType()->getAs<DependentMemberType>())
        assocType = depMemTy->getAssocType();
      auto L = getFileAndLocation(assocType);
      if (!L.File)
        L.File = CompilerGeneratedFile;
      unsigned FwdDeclLine = 0;
      auto Superclass = Archetype->getSuperclass();
      auto DerivedFrom = Superclass.isNull()
                             ? nullptr
                             : getOrCreateDesugaredType(Superclass, DbgTy);
      llvm::TempDICompositeType FwdDecl(DBuilder.createReplaceableCompositeType(
          llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, L.File,
          FwdDeclLine, llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits,
          Flags));

      // Emit the protocols the archetypes conform to.
      SmallVector<llvm::Metadata *, 4> Protocols;
      for (auto *ProtocolDecl : Archetype->getConformsTo()) {
        // Skip marker protocols, as they are not available at runtime.
        if (ProtocolDecl->isMarkerProtocol())
          continue;

        auto PTy =
            IGM.getLoweredType(ProtocolDecl->getInterfaceType()).getASTType();
        auto PDbgTy =
            DebugTypeInfo::getFromTypeInfo(ProtocolDecl->getInterfaceType(),
                                           IGM.getTypeInfoForLowered(PTy), IGM);
        auto PDITy = getOrCreateType(PDbgTy);
        Protocols.push_back(
            DBuilder.createInheritance(FwdDecl.get(), PDITy, 0, 0, Flags));
      }
      llvm::DICompositeType *DITy = DBuilder.createStructType(
          Scope, MangledName, L.File, FwdDeclLine, SizeInBits, AlignInBits,
          Flags, DerivedFrom, DBuilder.getOrCreateArray(Protocols),
          llvm::dwarf::DW_LANG_Swift, nullptr);

      return DBuilder.replaceTemporary(std::move(FwdDecl), DITy);
    }

    case TypeKind::ExistentialMetatype:
    case TypeKind::Metatype: {
      // Metatypes are (mostly) singleton type descriptors, often without
      // storage.
      Flags |= llvm::DINode::FlagArtificial;
      auto L = getFileAndLocation(DbgTy.getDecl());
      unsigned FwdDeclLine = 0;

      return DBuilder.createStructType(
          Scope, MangledName, L.File, FwdDeclLine, SizeInBits, AlignInBits,
          Flags, nullptr, nullptr, llvm::dwarf::DW_LANG_Swift, nullptr,
          MangledName, /*Specification=*/nullptr, NumExtraInhabitants);
    }

    case TypeKind::SILFunction:
    case TypeKind::Function:
    case TypeKind::GenericFunction: {
      if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
        return createFunctionPointer(DbgTy, Scope, SizeInBits, AlignInBits,
                                     Flags, MangledName, NumExtraInhabitants);
      else
        return createOpaqueStruct(Scope, MangledName, MainFile, 0, SizeInBits,
                                  AlignInBits, Flags, MangledName, {}, nullptr,
                                  nullptr, NumExtraInhabitants);
    }

    case TypeKind::Enum: {
      auto *EnumTy = BaseTy->castTo<EnumType>();
      auto *Decl = EnumTy->getDecl();
      auto L = getFileAndLocation(Decl);
      unsigned FwdDeclLine = 0;
      if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
        if (EnumTy->isSpecialized() && !Decl->hasRawType())
          return createSpecializedEnumType(EnumTy, Decl, MangledName,
                                           SizeInBits, AlignInBits, Scope, File,
                                           FwdDeclLine, Flags);

        if (CompletedDbgTy)
          return createEnumType(*CompletedDbgTy, Decl, MangledName, AlignInBits,
                                Scope, L.File, L.Line, Flags);
      }
      return createOpaqueStruct(Scope, Decl->getName().str(), L.File,
                                FwdDeclLine, SizeInBits, AlignInBits, Flags,
                                MangledName, {}, SpecificationOf);
    }

    case TypeKind::BoundGenericEnum: {
      auto *EnumTy = BaseTy->castTo<BoundGenericEnumType>();
      auto *Decl = EnumTy->getDecl();
      auto L = getFileAndLocation(Decl);
      unsigned FwdDeclLine = 0;

      if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
        if (EnumTy->isSpecialized() && !EnumTy->hasTypeParameter() &&
            !EnumTy->hasPrimaryArchetype())
          return createSpecializedEnumType(EnumTy, Decl, MangledName,
                                           SizeInBits, AlignInBits, Scope, File,
                                           FwdDeclLine, Flags);
        // If we do not know the size of this type, pass a size of 0.
        // FIXME: createEnumType should not require a sized debug info type.
        if (!CompletedDbgTy)
          CompletedDbgTy = CompletedDebugTypeInfo::get(DbgTy, 0);
        return createEnumType(*CompletedDbgTy, Decl, MangledName, AlignInBits,
                              Scope, L.File, L.Line, Flags);
      }
      return createOpaqueStructWithSizedContainer(
          Scope, Decl->getName().str(), L.File, FwdDeclLine, SizeInBits,
          AlignInBits, Flags, MangledName, collectGenericParams(EnumTy),
          SpecificationOf);
    }

    case TypeKind::BuiltinVector: {
      // FIXME: Emit the name somewhere.
      (void)MangledName;
      auto *BuiltinVectorTy = BaseTy->castTo<BuiltinVectorType>();
      auto ElemTy = BuiltinVectorTy->getElementType();
      auto ElemDbgTy = DebugTypeInfo::getFromTypeInfo(
          ElemTy, IGM.getTypeInfoForUnlowered(ElemTy), IGM);
      unsigned Count = BuiltinVectorTy->getNumElements();
      auto Subscript = DBuilder.getOrCreateSubrange(0, Count ? Count : -1);
      return DBuilder.createVectorType(SizeInBits, AlignInBits,
                                       getOrCreateType(ElemDbgTy),
                                       DBuilder.getOrCreateArray(Subscript));
    }

    // Reference storage types.
#define REF_STORAGE(Name, ...) case TypeKind::Name##Storage:
#include "swift/AST/ReferenceStorage.def"
      {
        auto *ReferenceTy = cast<ReferenceStorageType>(BaseTy);
        auto CanTy = ReferenceTy->getReferentType();
        auto L = getFileAndLocation(DbgTy.getDecl());
        unsigned CompilerGeneratedLine = 0;

        return DBuilder.createTypedef(getOrCreateDesugaredType(CanTy, DbgTy),
                                      MangledName, L.File,
                                      CompilerGeneratedLine, File);
      }

      // Sugared types.

    case TypeKind::TypeAlias: {
      auto *TypeAliasTy = cast<TypeAliasType>(BaseTy);
      auto *Decl = TypeAliasTy->getDecl();
      auto L = getFileAndLocation(Decl);
      auto AliasedTy = TypeAliasTy->getSinglyDesugaredType();

      // For TypeAlias types, the DeclContext for the aliased type is
      // in the decl of the alias type.
      DebugTypeInfo AliasedDbgTy(AliasedTy, DbgTy.getAlignment(),
                                 /* IsMetadataType = */ false,
                                 DbgTy.isFixedBuffer(),
                                 DbgTy.getNumExtraInhabitants());
      auto *TypeDef = DBuilder.createTypedef(getOrCreateType(AliasedDbgTy),
                                             MangledName, L.File, 0, Scope);
      // Bound generic types don't reference their type parameters in ASTTypes
      // mode, so we need to artificially keep typealiases alive, since they can
      // appear in reflection metadata.
      if (Opts.DebugInfoLevel < IRGenDebugInfoLevel::DwarfTypes)
        DBuilder.retainType(TypeDef);
      return TypeDef;
    }

    case TypeKind::Locatable: {
      auto *Sugar = cast<LocatableType>(BaseTy);
      auto *CanTy = Sugar->getSinglyDesugaredType();
      return getOrCreateDesugaredType(CanTy, DbgTy);
    }

    // SyntaxSugarType derivations.
    case TypeKind::Dictionary:
    case TypeKind::ArraySlice:
    case TypeKind::InlineArray:
    case TypeKind::Optional:
    case TypeKind::VariadicSequence: {
      auto *SyntaxSugarTy = cast<SyntaxSugarType>(BaseTy);
      auto *CanTy = SyntaxSugarTy->getSinglyDesugaredType();
      return getOrCreateDesugaredType(CanTy, DbgTy);
    }

    // SILBox should appear only inside of coroutine contexts.
    case TypeKind::SILBox:
    case TypeKind::DependentMember:
    case TypeKind::GenericTypeParam: {
      // FIXME: Provide a more meaningful debug type.
      return DBuilder.createStructType(
          Scope, MangledName, File, 0, SizeInBits, AlignInBits, Flags, nullptr,
          nullptr, llvm::dwarf::DW_LANG_Swift, nullptr, MangledName);
    }

    // A special stdlib builtin type, which the debugger looks up by mangled
    // name, so it must not be renamed to "<unknown>" below.
    case TypeKind::BuiltinUnsafeValueBuffer:
      break;

    // The following types exist primarily for internal use by the type
    // checker.
    case TypeKind::Error:
    case TypeKind::SILBlockStorage:
    case TypeKind::SILToken:
    case TypeKind::BuiltinDefaultActorStorage:
    case TypeKind::BuiltinNonDefaultDistributedActorStorage:
    case TypeKind::SILMoveOnlyWrapped:
    case TypeKind::Integer:
      LLVM_DEBUG(llvm::dbgs() << "Unhandled type: ";
                 DbgTy.getType()->dump(llvm::dbgs()); llvm::dbgs() << "\n");
      MangledName = "<unknown>";
    }
    return DBuilder.createBasicType(MangledName, SizeInBits, Encoding,
                                    llvm::DINode::FlagZero,
                                    NumExtraInhabitants);
  }

  /// Determine if there exists a name mangling for the given type.
  static bool canMangle(TypeBase *Ty) {
    switch (Ty->getKind()) {
    case TypeKind::GenericFunction: // Not yet supported.
    case TypeKind::SILBlockStorage: // Not supported at all.
      return false;
    default:
      return true;
    }
  }

  llvm::DIType *getTypeOrNull(TypeBase *Ty) {
    auto CachedType = DITypeCache.find(Ty);
    if (CachedType != DITypeCache.end()) {
      // Verify that the information still exists.
      if (llvm::Metadata *Val = CachedType->second) {
        auto DITy = cast<llvm::DIType>(Val);
        return DITy;
      }
    }
    return nullptr;
  }

  /// The private discriminator is represented as an inline namespace.
  llvm::DIScope *getFilePrivateScope(llvm::DIScope *Parent, TypeDecl *Decl) {
    // Retrieve the private discriminator.
    auto *MSC = Decl->getDeclContext()->getModuleScopeContext();
    auto *FU = cast<FileUnit>(MSC);
    Identifier PD = FU->getDiscriminatorForPrivateDecl(Decl);
    bool ExportSymbols = true;
    return DBuilder.createNameSpace(Parent, PD.str(), ExportSymbols);
  }

#ifndef NDEBUG
  /// Verify that the size of this type matches the one of the cached type.
  bool sanityCheckCachedType(DebugTypeInfo DbgTy, llvm::DIType *CachedType) {
    // If this is a temporary, we're in the middle of creating a recursive type,
    // so skip the sanity check.
    if (CachedType->isTemporary())
      return true;
    if (!isa<llvm::DICompositeType>(CachedType))
      return true;
    bool IsUnsubstituted =
        getUnsubstitutedType(DbgTy.getType(), getMangledName(DbgTy).Canonical)
            .first;
    std::optional<uint64_t> SizeInBits;
    if (!IsUnsubstituted)
      if (auto CompletedDbgTy = completeType(DbgTy))
        SizeInBits = CompletedDbgTy->getSizeInBits();

    unsigned CachedSizeInBits = getSizeInBits(CachedType);
    if (SizeInBits && CachedSizeInBits != *SizeInBits) {
      // Note that CachedSizeInBits && !SizeInBits may happen and is benign,
      // because the cached copy would win. When the sizeless type is generated
      // it should be emitted as a forward declaration and thus never make it
      // into the cache.

      // In some situation a specialized type is emitted with size 0, even if
      // the real type has a size.
      if (DbgTy.getType()->isSpecialized() && SizeInBits && *SizeInBits > 0 &&
          CachedSizeInBits == 0)
        return true;

      CachedType->dump();
      DbgTy.dump();
      llvm::errs() << "SizeInBits = " << SizeInBits << "\n";
      llvm::errs() << "CachedSizeInBits = " << CachedSizeInBits << "\n";
      return false;
    }
    return true;
  }
#endif

  /// Emits the special builtin types into the debug info. These types are the
  /// ones that are unconditionally emitted into the stdlib's metadata and are
  /// needed to correctly calculate the layout of more complex types built on
  /// top of them.
  void createSpecialStlibBuiltinTypes() {
    if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::ASTTypes)
      return;
    for (auto BuiltinType : IGM.getOrCreateSpecialStlibBuiltinTypes()) {
      auto DbgTy = DebugTypeInfo::getFromTypeInfo(
          BuiltinType, IGM.getTypeInfoForUnlowered(BuiltinType), IGM);
      anchorType(getOrCreateType(DbgTy));

      // The reflection metadata emits AnyObject as the old
      // Builtin.UnknownObject for ABI compatibility (see
      // FixedTypeMetadataBuilder::layout()), so emit a second DIE under that
      // name.
      if (!BuiltinType->isAnyObject())
        continue;
      if (auto CompletedDbgTy = completeType(DbgTy)) {
        StringRef Prefix = IGM.Context.LangOpts.hasFeature(Feature::Embedded)
                               ? MANGLING_PREFIX_EMBEDDED_STR
                               : MANGLING_PREFIX_STR;
        anchorType(DBuilder.createBasicType(
            BumpAllocatedString((Twine(Prefix) + "BOD").str()),
            CompletedDbgTy->getSizeInBits(), /*Encoding=*/0,
            llvm::DINode::FlagZero,
            CompletedDbgTy->getNumExtraInhabitants().value_or(0)));
      }
    }
  }

  /// Retain \p DITy, and keep dsymutil from stripping it as unused.
  void anchorType(llvm::DIType *DITy) {
    if (!DITy)
      return;
    DBuilder.retainType(DITy);
    DBuilder.createImportedDeclaration(TheCU, DITy, MainFile, 0);
  }

  /// Anchor DW_TAG_typedef DIEs for the stdlib C-interop typealiases (CChar,
  /// CInt, CDouble, CWideChar, ...). LLDB can encounter these via DWARF
  /// references on fields of clang-imported types, even when the Swift source
  /// never names them. Most Swift programs use most of these types, so it's
  /// not worth trying to figure out a minimal required set; just emit them all.
  void anchorClangInteropTypeAliases() {
    if (Opts.DebugInfoLevel < IRGenDebugInfoLevel::ASTTypes)
      return;

    SmallVector<ImportedModule, 8> ModuleWideImports;
    IGM.getSwiftModule()->getImportedModules(
        ModuleWideImports, ModuleDecl::getImportFilterLocal());
    const bool importsAnyClangModule =
        llvm::any_of(ModuleWideImports, [](ImportedModule M) {
          return M.importedModule->findUnderlyingClangModule() != nullptr;
        });
    if (!importsAnyClangModule)
      return;

    ASTContext &Ctx = IGM.Context;
    ModuleDecl *Stdlib = Ctx.getStdlibModule();
    if (!Stdlib)
      return;

    auto anchorAlias = [&](StringRef Name) {
      SmallVector<ValueDecl *, 1> Results;
      Stdlib->lookupMember(Results, Stdlib, Ctx.getIdentifier(Name),
                           Identifier());
      if (Results.size() != 1)
        return;
      auto *AliasDecl = cast<TypeAliasDecl>(Results.front());
      Type Underlying = AliasDecl->getUnderlyingType();
      auto *AliasTy = TypeAliasType::get(AliasDecl, /*parent=*/Type(),
                                         /*genericArgs=*/{}, Underlying);
      auto AliasDbgTy = DebugTypeInfo::getFromTypeInfo(
          AliasTy, IGM.getTypeInfoForUnlowered(AliasTy), IGM);
      anchorType(getOrCreateType(AliasDbgTy));
    };
#define MAP_BUILTIN_TYPE(CLANG, SWIFT) anchorAlias(#SWIFT);
#include "swift/ClangImporter/BuiltinMappedTypes.def"
#undef MAP_BUILTIN_TYPE
  }

  /// Forward-declared composite types may still refer refer to a type alias by
  /// name in their mangled name. We need to make sure they are emitted in
  /// DWARF.
  void anchorTypeAliasesIn(Type Ty) {
    if (!Ty || Opts.DebugInfoLevel < IRGenDebugInfoLevel::ASTTypes)
      return;
    Ty.findIf([&](Type T) -> bool {
      auto *Alias = llvm::dyn_cast<TypeAliasType>(T.getPointer());
      if (!Alias)
        return false;
      DebugTypeInfo AliasDbgTy = DebugTypeInfo::getForwardDecl(Alias);
      // Dedup by the alias's mangled name.
      auto Mangled = getMangledName(AliasDbgTy);
      if (Mangled.Sugared.empty() ||
          !AnchoredTypeAliases.insert(Mangled.Sugared).second)
        return false;
      if (llvm::DIType *TypeDef = getOrCreateType(AliasDbgTy)) {
        DBuilder.retainType(TypeDef);
        // Keep dsymutil from stripping the typedef as unused.
        DBuilder.createImportedDeclaration(TheCU, TypeDef, MainFile, 0);
      }
      return false;
    });
  }

  /// A TypeWalker that finds if a given type's mangling is affected by an
  /// @_originallyDefinedIn annotation.
  struct OriginallyDefinedInFinder : public TypeWalker {
    bool visitedOriginallyDefinedIn = false;

    TypeWalker::Action walkToTypePre(Type T) override {
      if (visitedOriginallyDefinedIn)
        return TypeWalker::Action::Stop;

      DeclContext *D = nullptr;
      if (auto *TAT = llvm::dyn_cast<TypeAliasType>(T.getPointer()))
        D = TAT->getDecl()->getDeclContext();
      else if (auto *NT = llvm::dyn_cast<NominalOrBoundGenericNominalType>(
                   T.getPointer()))
        D = NT->getDecl()->getDeclContext();

      // A type inside a function uses that function's signature as part of
      // its mangling, so check if any types in the generic signature are
      // annotated with @_originallyDefinedIn.
      if (auto AFD = llvm::dyn_cast_or_null<AbstractFunctionDecl>(D)) {
        OriginallyDefinedInFinder InnerWalker;
        AFD->getInterfaceType().walk(InnerWalker);
        if (InnerWalker.visitedOriginallyDefinedIn) {
          visitedOriginallyDefinedIn = true;
          return TypeWalker::Action::Stop;
        }
      }

      auto *TypeDecl = T->getNominalOrBoundGenericNominal();
      if (!TypeDecl)
        return TypeWalker::Action::Continue;

      NominalTypeDecl *ParentDecl = TypeDecl;
      while (llvm::isa_and_nonnull<NominalTypeDecl>(ParentDecl->getParent()))
        ParentDecl = llvm::cast<NominalTypeDecl>(ParentDecl->getParent());

      if (ParentDecl->getAttrs().hasAttribute<OriginallyDefinedInAttr>()) {
        visitedOriginallyDefinedIn = true;
        return TypeWalker::Action::Stop;
      }

      return TypeWalker::Action::Continue;
    }
  };

  /// Returns true if the type's mangled name is affected by an
  /// @_originallyDefinedIn annotation. This annotation can be on the type
  /// itself, one of its generic arguments, etc.
  bool containsOriginallyDefinedIn(Type T) {
    OriginallyDefinedInFinder Walker;
    T.walk(Walker);
    return Walker.visitedOriginallyDefinedIn;
  }

  /// Returns true if the type contains an imported C++ type. Due to
  /// various unimplemented features these cannot round-trip through
  /// the ASTDemangler.
  ///
  /// FIXME: Get these cases working with the ASTDemangler instead.
  bool containsCxxType(Type T) {
    return T.findIf([&](Type t) -> bool {
      if (auto *decl = t->getAnyNominal()) {
        if (auto *clangDecl = decl->getClangDecl()) {
          // Lookup of template instantiations is not implemented.
          if (isa<clang::ClassTemplateSpecializationDecl>(clangDecl))
            return true;

          // Lookup of types in weird contexts is not implemented.
          if (isa<clang::EnumDecl>(clangDecl) ||
              isa<clang::CXXRecordDecl>(clangDecl)) {
            auto *dc = clangDecl->getDeclContext();
            while (!isa<clang::TranslationUnitDecl>(dc)) {
              // ... in namespaces,
              if (isa<clang::NamespaceDecl>(dc))
                return true;

              // ... or inside other types.
              if (isa<clang::CXXRecordDecl>(dc))
                return true;

              dc = dc->getParent();
            }
          }
        }
      }

      return false;
    });
  }

  /// Returns true if the type contains a function type with lifetime
  /// dependencies. ASTDemangler drops LifetimeDependenceInfo (see the
  /// "Handle LifetimeDependenceInfo here" TODO in ASTDemangler.cpp), so
  /// such types cannot round-trip through the demangler. Covers both
  /// inferred and explicit dependencies via hasLifetimeDependencies(),
  /// and both AST-level (AnyFunctionType) and SIL-level (SILFunctionType)
  /// function type hierarchies.
  bool containsFunctionTypeWithLifetimeDependencies(Type T) {
    return T.findIf([](Type t) -> bool {
      if (auto *fn = t->getAs<AnyFunctionType>())
        return fn->hasLifetimeDependencies();
      if (auto *silFn = t->getAs<SILFunctionType>())
        return silFn->hasLifetimeDependencies();
      return false;
    });
  }

  /// Returns the decl of the type's parent chain annotated by
  /// @_originallyDefinedIn. Returns null if no type is annotated.
  NominalTypeDecl *getDeclAnnotatedByOriginallyDefinedIn(DebugTypeInfo DbgTy) {
    auto Type = DbgTy.getType();
    auto *TypeDecl = Type->getNominalOrBoundGenericNominal();
    if (!TypeDecl)
      return nullptr;

    // Find the outermost type, since only those can have @_originallyDefinedIn
    // attached to them.
    NominalTypeDecl *ParentDecl = TypeDecl;
    while (llvm::isa_and_nonnull<NominalTypeDecl>(ParentDecl->getParent()))
      ParentDecl = llvm::cast<NominalTypeDecl>(ParentDecl->getParent());

    if (ParentDecl->getAttrs().hasAttribute<OriginallyDefinedInAttr>())
      return ParentDecl;;

    return nullptr;
  }

  /// If this is a nominal type that has the @_originallyDefinedIn
  /// attribute, IRGenDebugInfo emits an imported declaration of the type as
  /// a child of the real module. We do this so LLDB has enough
  /// information to both find the type in reflection metadata (the module name
  /// in the type's mangled name), and find it in the swiftmodule (the type's
  /// imported declaration's parent module name).
  void handleOriginallyDefinedIn(DebugTypeInfo DbgTy, llvm::DIType *DITy,
                                 StringRef MangledName, llvm::DIFile *File) {
    if (OriginallyDefinedInTypes.contains(MangledName))
      return;

    // Force the generation of the generic type parameters as forward
    // declarations, as those types might be annotated with
    // @_originallyDefinedIn.
    if (auto *BoundDecl = llvm::dyn_cast<BoundGenericType>(DbgTy.getType()))
      collectGenericParams(BoundDecl, /*AsForwardDeclarations=*/true);

    NominalTypeDecl *OriginallyDefinedInDecl = getDeclAnnotatedByOriginallyDefinedIn(DbgTy);
    if (!OriginallyDefinedInDecl)
      return;

    // Emit the imported declaration under the real swiftmodule the type lives on.
    auto RealModule = getOrCreateContext(OriginallyDefinedInDecl->getParent());
    DBuilder.createImportedDeclaration(RealModule, DITy, File, 0, MangledName);
    OriginallyDefinedInTypes.insert(MangledName);
  }

  /// Retrieve the context of the type, as opposed to the DeclContext
  /// of the variable.
  ///
  /// FIXME: Builtin and qualified types in LLVM have no parent
  /// scope. TODO: This can be fixed by extending DIBuilder.
  /// Make sure to retrieve the context of the type alias, not the pointee.
  llvm::DIScope *updateScope(llvm::DIScope *Scope, DebugTypeInfo DbgTy) {
    DeclContext *Context = nullptr;
    const Decl *TypeDecl = nullptr;
    const clang::Decl *ClangDecl = nullptr;
    if (auto Alias = dyn_cast<TypeAliasType>(DbgTy.getType())) {
      TypeAliasDecl *AliasDecl = Alias->getDecl();
      TypeDecl = AliasDecl;
      Context = AliasDecl->getParent();
      ClangDecl = AliasDecl->getClangDecl();
    } else if (auto *ND = DbgTy.getType()->getNominalOrBoundGenericNominal()) {
      TypeDecl = ND;
      // If this is an originally defined in type, we want to emit this type's
      // scope to be the ABI module.
      if (auto Attribute =
              ND->getAttrs().getAttribute<OriginallyDefinedInAttr>()) {
        auto Identifier = IGM.getSILModule().getASTContext().getIdentifier(
            Attribute->getManglingModuleName());
        void *Key = (void *)Identifier.get();
        Scope =
            getOrCreateModule(Key, TheCU, Attribute->getManglingModuleName(), {});
      } else {
        Context = ND->getParent();
      }
      ClangDecl = ND->getClangDecl();
    } else if (auto BNO = dyn_cast<BuiltinType>(DbgTy.getType())) {
      Context = BNO->getASTContext().TheBuiltinModule;
    }
    if (ClangDecl) {
      clang::ASTReader &Reader = *CI.getClangInstance().getASTReader();
      auto Idx = ClangDecl->getOwningModuleID();
      auto SubModuleDesc = Reader.getSourceDescriptor(Idx);
      auto TopLevelModuleDesc = getClangModule(*TypeDecl->getModuleContext());
      if (SubModuleDesc) {
        if (TopLevelModuleDesc)
          // Describe the submodule, but substitute the cached ASTFile from
          // the toplevel module. The ASTFile pointer in SubModule may be
          // dangling and cant be trusted.
          Scope = getOrCreateModule({SubModuleDesc->getModuleName(),
                                     SubModuleDesc->getPath(),
                                     TopLevelModuleDesc->getASTFile(),
                                     TopLevelModuleDesc->getSignature(),
                                     TopLevelModuleDesc->getCASID()},
                                    SubModuleDesc->getModuleOrNull());
        else if (SubModuleDesc->getModuleOrNull() == nullptr)
          // This is (bridging header) PCH.
          Scope = getOrCreateModule(*SubModuleDesc, nullptr);
      }
    }
    if (!Scope)
      Scope = getOrCreateContext(Context);

    // Scope outermost fileprivate decls in an inline private discriminator
    // namespace.
    //
    // We need to don't do this for decls imported from Clang modules because
    // the scopes of C/C++ symbols are not restricted to a particular file unit.
    if (auto *Decl = DbgTy.getDecl())
      if (Decl->isOutermostPrivateOrFilePrivateScope() &&
          !isa<ClangModuleUnit>(
              Decl->getDeclContext()->getModuleScopeContext()))
        Scope = getFilePrivateScope(Scope, Decl);

    return Scope;
  }

  static bool isExistentialTypeAlias(DebugTypeInfo DbgTy) {
    TypeBase *BaseTy = DbgTy.getType();
    auto *ExistentialTy = BaseTy->getAs<ExistentialType>();
    if (!ExistentialTy)
      return false;
    Type ConstraintTy = ExistentialTy->getConstraintType();
    TypeBase *TyPtr = ConstraintTy.getPointer();
    return isa<TypeAliasType>(TyPtr);
  }

  llvm::DIType *getOrCreateType(DebugTypeInfo DbgTy,
                                llvm::DIScope *Scope = nullptr) {
    // Is this an empty type?
    if (DbgTy.isNull())
      // We can't use the empty type as an index into DenseMap.
      return createType(DbgTy, "", TheCU, MainFile);

    // Look in the cache first.
    if (auto *DITy = getTypeOrNull(DbgTy.getType())) {
      assert(sanityCheckCachedType(DbgTy, DITy));
      return DITy;
    }

    // Use a separate DIRefMap cache for existential typealiases
    // because they have identical mangled names as their inner
    // protocol types and cause conflicts in the cache. For example,
    // protocol P<Value> {
    //    associatedtype Value
    // }
    // actor A<Value> {
    //    public typealias T = P<Value>
    //    let t: any T
    //    ...
    // }
    // "any T" (existential type) and "P<Value>" (parameterized protocol type)
    // have the same mangled name but distinct DI types.
    TrackingDIRefMap &RefMap =
        isExistentialTypeAlias(DbgTy) ? ExistentialTypeAliasMap : DIRefMap;

    // Second line of defense: Look up the mangled name. TypeBase*'s are
    // not necessarily unique, but name mangling is too expensive to do
    // every time.
    MangledNames Mangled;
    llvm::MDString *UID = nullptr;
    if (canMangle(DbgTy.getType())) {
      Mangled = getMangledName(DbgTy);
      if (!Mangled.Sugared.empty()) {
        UID = llvm::MDString::get(IGM.getLLVMContext(), Mangled.Sugared);
        if (llvm::Metadata *CachedTy = RefMap.lookup(UID))
          return cast<llvm::DIType>(CachedTy);

        if (DbgTy.getType()->getKind() != swift::TypeKind::TypeAlias) {
          // A type with the same canonical type already exists, emit a typedef.
          // This extra step is necessary to break out of loops: We don't
          // canoncialize types before mangling to preserve sugared types. But
          // some types can also have different equivalent non-canonical
          // representations with no sugar involved, for example a type
          // recursively that appears iniside itself. To deal with the latter we
          // directly emit a type alias to the canonical type.
          UID = llvm::MDString::get(IGM.getLLVMContext(), Mangled.Canonical);
          if (llvm::Metadata *CachedTy = RefMap.lookup(UID)) {
            Scope = updateScope(Scope, DbgTy);
            llvm::DIType *DITy = cast<llvm::DIType>(CachedTy);
            llvm::DIType *TypeDef = DBuilder.createTypedef(
                DITy, Mangled.Sugared, MainFile, 0, Scope);
            return TypeDef;
          }
          UID = llvm::MDString::get(IGM.getLLVMContext(), Mangled.Sugared);
        }
        // Fall through and create the sugared type.
      } else if (auto *AliasTy =
                     llvm::dyn_cast<TypeAliasType>(DbgTy.getType())) {
        // An alias type, but the mangler failed to produce a sugared type, just
        // return the desugared type.
        llvm::DIType *Desugared =
            getOrCreateDesugaredType(AliasTy->getSinglyDesugaredType(), DbgTy);
        StringRef Name;
        if (auto *AliasDecl = AliasTy->getDecl())
          Name = AliasDecl->getName().str();
        if (!Name.empty())
          return DBuilder.createTypedef(Desugared, Name, MainFile, 0,
                                        updateScope(Scope, DbgTy));
        return Desugared;
      } else if (llvm::Metadata *CachedTy = RefMap.lookup(UID)) {
        auto *DITy = cast<llvm::DIType>(CachedTy);
        assert(sanityCheckCachedType(DbgTy, DITy));
        return DITy;
      } else {
        UID = llvm::MDString::get(IGM.getLLVMContext(), Mangled.Canonical);
        if (llvm::Metadata *CachedTy = RefMap.lookup(UID))
          return cast<llvm::DIType>(CachedTy);
      }
    }

    Scope = updateScope(Scope, DbgTy);
    StringRef MangledName =
        !Mangled.Sugared.empty() ? Mangled.Sugared : Mangled.Canonical;

    StringRef Name = MangledName;
    if (auto *Decl = DbgTy.getDecl())
      Name = Decl->getName().str();

    // If this type can have a definition that provides us with its layout/size,
    // then only emit a forward declaration.
    // TODO: This check can probably be simplified and generalized.
    const bool RequiresSize = !isa<PrimaryArchetypeType>(DbgTy.getType()) &&
                              !DbgTy.getType()->hasArchetype() &&
                              !isa<TypeAliasType>(DbgTy.getType());
    const bool HasNoFixedSize =
        DbgTy.isForwardDecl() || DbgTy.isFixedBuffer() || !completeType(DbgTy);
    if (RequiresSize && HasNoFixedSize) {
      // In LTO type uniquing is performed based on the UID. Forward
      // declarations may not have a unique ID to avoid a forward declaration
      // winning over a full definition.
      auto *FwdDecl = DBuilder.createReplaceableCompositeType(
          llvm::dwarf::DW_TAG_structure_type, Name, Scope, 0, 0,
          llvm::dwarf::DW_LANG_Swift, 0, 0, llvm::DINode::FlagFwdDecl,
          MangledName);
      FwdDeclTypes.emplace_back(
          std::piecewise_construct, std::make_tuple(MangledName),
          std::make_tuple(static_cast<llvm::Metadata *>(FwdDecl)));

      handleOriginallyDefinedIn(DbgTy, FwdDecl, MangledName, getFile(Scope));
      return FwdDecl;
    }
    llvm::DIType *DITy = createType(DbgTy, MangledName, Scope, getFile(Scope));

    if (!shouldCacheDIType(DITy, DbgTy))
      return DITy;

    // Incrementally build the DIRefMap.
    if (auto *CTy = dyn_cast<llvm::DICompositeType>(DITy)) {
#ifndef NDEBUG
      // Soundness check.
      if (llvm::Metadata *V = RefMap.lookup(UID)) {
        auto *CachedTy = cast<llvm::DIType>(V);
        assert(CachedTy == DITy && "conflicting types for one UID");
      }
#endif
      // If this type supports a UID, enter it to the cache.
      if (auto UID = CTy->getRawIdentifier()) {
        assert(UID->getString() == MangledName &&
               "Unique identifier is different from mangled name ");
        RefMap[UID] = llvm::TrackingMDNodeRef(DITy);
      }
    }

    // Store it in the cache.
    DITypeCache.insert({DbgTy.getType(), llvm::TrackingMDNodeRef(DITy)});

    handleOriginallyDefinedIn(DbgTy, DITy, MangledName, getFile(Scope));
    return DITy;
  }
};

IRGenDebugInfoImpl::IRGenDebugInfoImpl(const IRGenOptions &Opts,
                                       ClangImporter &CI, IRGenModule &IGM,
                                       llvm::Module &M,
                                       StringRef MainOutputFilenameForDebugInfo,
                                       StringRef PD,
                                       StringRef CacheKeyForJob)
    : Opts(Opts), CI(CI), SM(IGM.Context.SourceMgr), M(M), DBuilder(M),
      IGM(IGM), DebugPrefixMap(Opts.DebugPrefixMap) {
  assert(Opts.DebugInfoLevel > IRGenDebugInfoLevel::None &&
         "no debug info should be generated");
  llvm::SmallString<256> SourcePath;
  if (MainOutputFilenameForDebugInfo.empty())
    SourcePath = "<unknown>";
  else
    SourcePath = MainOutputFilenameForDebugInfo;

  unsigned Lang = llvm::dwarf::DW_LANG_Swift;
  std::string Producer = version::getSwiftFullVersion(
      IGM.Context.LangOpts.EffectiveLanguageVersion);
  unsigned Major, Minor;
  std::tie(Major, Minor) = version::getSwiftNumericVersion();
  unsigned MajorRuntimeVersion = Major;

  // No split DWARF on Darwin.
  StringRef SplitName = StringRef();
  // Note that File + Dir need not result in a valid path.
  // The directory part of the main file is the current working directory.
  std::string RemappedFile = DebugPrefixMap.remapPath(SourcePath);
  std::string RemappedDir = DebugPrefixMap.remapPath(Opts.DebugCompilationDir);
  bool RelFile = llvm::sys::path::is_relative(RemappedFile);
  bool RelDir = llvm::sys::path::is_relative(RemappedDir);
  MainFile = (RelFile && RelDir)
                 ? createFile(SourcePath, {}, {})
                 : DBuilder.createFile(RemappedFile, RemappedDir);
  CompilerGeneratedFile = getOrCreateFile("", {});

  StringRef Sysroot = IGM.Context.SearchPathOpts.getSDKPath();
  StringRef SDK;
  {
    auto B = llvm::sys::path::rbegin(Sysroot);
    auto E = llvm::sys::path::rend(Sysroot);
    auto It = std::find_if(B, E, [](auto SDK) { return SDK.ends_with(".sdk"); });
    if (It != E)
      SDK = *It;
  }

  bool EnableCXXInterop =
      IGM.getSILModule().getASTContext().LangOpts.EnableCXXInterop;
  bool EnableEmbeddedSwift =
      IGM.getSILModule().getASTContext().LangOpts.hasFeature(Feature::Embedded);
  TheCU = DBuilder.createCompileUnit(
      Lang, MainFile, Producer, Opts.shouldOptimize(),
      Opts.getDebugFlags(PD, EnableCXXInterop, EnableEmbeddedSwift),
      MajorRuntimeVersion, SplitName,
      Opts.DebugInfoLevel > IRGenDebugInfoLevel::LineTables
          ? llvm::DICompileUnit::FullDebug
          : llvm::DICompileUnit::LineTablesOnly,
      /* DWOId */ 0, /* SplitDebugInlining */ true,
      /* DebugInfoForProfiling */ Opts.DebugInfoForProfiling,
      llvm::DICompileUnit::DebugNameTableKind::Default,
      /* RangesBaseAddress */ false, DebugPrefixMap.remapPath(Sysroot), SDK);

  // Because the swift compiler relies on Clang to setup the Module,
  // the clang CU is always created first.  Several dwarf-reading
  // tools (older versions of ld64, and lldb) can get confused if the
  // first CU in an object is empty, so ensure that the Swift CU comes
  // first by rearranging the list of CUs in the LLVM module.
  llvm::NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu");
  SmallVector<llvm::DICompileUnit *, 2> CUs;
  for (auto *N : CU_Nodes->operands())
    CUs.push_back(cast<llvm::DICompileUnit>(N));
  CU_Nodes->dropAllReferences();
  for (auto CU = CUs.rbegin(), CE = CUs.rend(); CU != CE; ++CU)
    CU_Nodes->addOperand(*CU);

  // Create a module for the current compile unit.
  auto *MDecl = IGM.getSwiftModule();
  StringRef Path = Opts.DebugModulePath;
  if (Opts.DebugModuleSelfKey)
    Path = CacheKeyForJob;

  if (Path.empty()) {
    llvm::sys::path::remove_filename(SourcePath);
    Path = SourcePath;
  }
  MainModule = getOrCreateModule(MDecl, TheCU, Opts.ModuleName, Path);
  DBuilder.createImportedModule(MainFile, MainModule, MainFile, 0);

  // Macro definitions that were defined by the user with "-Xcc -D" on the
  // command line. This does not include any macros defined by ClangImporter.
  llvm::raw_svector_ostream OS(ConfigMacros);
  unsigned I = 0;
  // Translate the macro definitions back into a command line.
  for (auto &Macro : Opts.ClangDefines) {
    if (++I > 1)
      OS << ' ';
    OS << '"';
    for (char c : Macro)
      switch (c) {
      case '\\':
        OS << "\\\\";
        break;
      case '"':
        OS << "\\\"";
        break;
      default:
        OS << c;
      }
    OS << '"';
  }
  createSpecialStlibBuiltinTypes();
  anchorClangInteropTypeAliases();
}

void IRGenDebugInfoImpl::finalize() {
  assert(LocationStack.empty() && "Mismatch of pushLoc() and popLoc().");

  // Get the list of imported modules (which may actually be different
  // from all ImportDecls).
  SmallVector<ImportedModule, 8> ModuleWideImports;
  IGM.getSwiftModule()->getImportedModules(ModuleWideImports,
                                           ModuleDecl::getImportFilterLocal());
  for (auto M : ModuleWideImports)
    if (!ImportedModules.count(M.importedModule))
      createImportedModule(MainFile, M, MainFile, 0);

  // Finalize all replaceable forward declarations.
  auto finalize = [&](llvm::MDNode *FwdDeclType, llvm::MDNode *FullType,
                      llvm::MDString *UID = nullptr) {
    llvm::TempDICompositeType FwdDecl(cast<llvm::DICompositeType>(FwdDeclType));
    llvm::Metadata *Replacement = FullType ? FullType : FwdDeclType;
    llvm::Metadata *Replaced = DBuilder.replaceTemporary(
        std::move(FwdDecl), cast<llvm::MDNode>(Replacement));

    // Unique all identical forward declarations.
    if (UID && !FullType)
      DIRefMap[UID] = llvm::TrackingMDNodeRef(cast<llvm::MDNode>(Replaced));
  };

  for (auto &Ty : FwdDeclTypes) {
    auto *UID = llvm::MDString::get(IGM.getLLVMContext(), Ty.first);
    finalize(cast<llvm::MDNode>(Ty.second),
             llvm::cast_or_null<llvm::DIType>(DIRefMap.lookup(UID)), UID);
  }
  FwdDeclTypes.clear();

  // Finalize the DIBuilder.
  DBuilder.finalize();
}

#ifndef NDEBUG
bool IRGenDebugInfoImpl::lineEntryIsSane(FileAndLocation DL,
                                         const SILDebugScope *DS) {
  // All bets are off for optimized code.
  if (!VerifyLineTable || Opts.shouldOptimize())
    return true;
  // We entered a new lexical block.
  if (DS != LastScope)
    PreviousLineEntries.clear();
  if (DL.Line == 0 || DL == PreviousFileAndLocation)
    return true;
  // Save the last non-zero line entry.
  PreviousFileAndLocation = DL;
  auto ItNew = PreviousLineEntries.insert(FileAndLocationKey(DL));
  // Return true iff DL was not yet in PreviousLineEntries.
  return ItNew.second;
}
#endif

IRGenDebugInfoImpl::FileAndLocation
IRGenDebugInfoImpl::computeLLVMLocCodeView(const SILDebugScope *DS,
                                           SILLocation Loc) {
  // If the scope has not changed and the line number is either zero or
  // artificial, we want to keep the most recent debug location.
  if (DS == LastScope && (Loc.is<ArtificialUnreachableLocation>() ||
                          Loc.isLineZero(SM) || Loc.isHiddenFromDebugInfo()))
    return LastFileAndLocation;

  // Decode the location.
  return decodeFileAndLocation(Loc);
}

IRGenDebugInfoImpl::FileAndLocation
IRGenDebugInfoImpl::computeLLVMLoc(const SILDebugScope *DS, SILLocation Loc) {
  SILFunction *Fn = DS->getInlinedFunction();
  if (Fn && (Fn->isThunk() || Fn->isTransparent()))
    return {0, 0, CompilerGeneratedFile};

  if (Opts.DebugInfoFormat == IRGenDebugInfoFormat::CodeView)
    return computeLLVMLocCodeView(DS, Loc);

  FileAndLocation L =
      Loc.isInPrologue() ? FileAndLocation() : decodeFileAndLocation(Loc);

  // Otherwise use a line 0 artificial location, but the file from the location.
  if (Loc.isHiddenFromDebugInfo()) {
    L.Line = 0;
    L.Column = 0;
  }

  return L;
}

void IRGenDebugInfoImpl::setCurrentLoc(IRBuilder &Builder,
                                       const SILDebugScope *DS,
                                       SILLocation Loc) {
  assert(DS && "empty scope");
  auto *Scope = getOrCreateScope(DS);
  if (!Scope)
    return;

  FileAndLocation L = computeLLVMLoc(DS, Loc);

  if (L.getFilename() != Scope->getFilename()) {
    // We changed files in the middle of a scope. This happens, for
    // example, when constructors are inlined. Create a new scope to
    // reflect this.
    Scope = DBuilder.createLexicalBlockFile(Scope, L.File);
  }

  assert(lineEntryIsSane(L, DS) &&
         "non-contiguous debug location in same scope at -Onone");
  LastFileAndLocation = L;
  LastScope = DS;

  auto *InlinedAt = createInlinedAt(DS);
  assert(((!InlinedAt) || (InlinedAt && Scope)) && "inlined w/o scope");
  assert(parentScopesAreSane(DS) && "parent scope sanity check failed");
  auto DL = llvm::DILocation::get(IGM.getLLVMContext(), L.Line, L.Column, Scope,
                                  InlinedAt);
#ifndef NDEBUG
  {
    llvm::DILocalScope *Scope = DL->getInlinedAtScope();
    llvm::DISubprogram *SP = Scope->getSubprogram();
    llvm::Function *F = Builder.GetInsertBlock()->getParent();
    assert((!F || SP->describes(F)) && "location points to different function");
  }
#endif
  Builder.SetCurrentDebugLocation(DL);
}

void IRGenDebugInfoImpl::addFailureMessageToCurrentLoc(IRBuilder &Builder,
                                                       StringRef failureMsg) {
  auto TrapLoc = Builder.getCurrentDebugLocation();

  // Create a function in the debug info which has failureMsg as name.
  // TrapSc is the SIL debug scope which corresponds to TrapSP in the LLVM debug
  // info.
  RegularLocation ALoc = RegularLocation::getAutoGeneratedLocation();
  const SILDebugScope *TrapSc = new (IGM.getSILModule()) SILDebugScope(ALoc);

  llvm::DISubroutineType *DIFnTy = DBuilder.createSubroutineType(nullptr);

  llvm::DISubprogram *TrapSP;
  auto It = RuntimeErrorFnCache.find(failureMsg);
  if (It != RuntimeErrorFnCache.end())
    TrapSP = llvm::cast<llvm::DISubprogram>(It->second);
  else {
    std::string FuncName = "Swift runtime failure: ";
    FuncName += failureMsg;
    // CodeView consumers do not correctly handle an artificially generated
    // file, thus use the original location's file as the file for the debug
    // function, and prevent reuse of this debug function.
    bool useCompilerGeneratedFile = !Opts.isDebugInfoCodeView();
    llvm::DIFile *File =
        useCompilerGeneratedFile ? getOrCreateFile({}, {}) : TrapLoc->getFile();
    TrapSP = DBuilder.createFunction(
        File, FuncName, StringRef(), File, 0,
        DIFnTy, 0, llvm::DINode::FlagArtificial,
        llvm::DISubprogram::SPFlagDefinition, nullptr, nullptr, nullptr);
    if (useCompilerGeneratedFile)
      RuntimeErrorFnCache.insert({failureMsg, llvm::TrackingMDNodeRef(TrapSP)});
  }

  ScopeCache[TrapSc] = llvm::TrackingMDNodeRef(TrapSP);
  LastScope = TrapSc;

  assert(parentScopesAreSane(TrapSc) && "parent scope sanity check failed");

  // Wrap the existing TrapLoc into the failure function.
  // Line 0 is invalid in CodeView, so use the line and column from the original
  // trap location.
  auto DL = llvm::DILocation::get(
      IGM.getLLVMContext(), Opts.isDebugInfoCodeView() ? TrapLoc.getLine() : 0,
      Opts.isDebugInfoCodeView() ? TrapLoc.getCol() : 0, TrapSP, TrapLoc);
  Builder.SetCurrentDebugLocation(DL);
}

void IRGenDebugInfoImpl::clearLoc(IRBuilder &Builder) {
  LastFileAndLocation = {};
  LastScope = nullptr;
  Builder.SetCurrentDebugLocation(llvm::DebugLoc());
}

/// Push the current debug location onto a stack and initialize the
/// IRBuilder to an empty location.
void IRGenDebugInfoImpl::pushLoc() {
  LocationStack.push_back(std::make_pair(LastFileAndLocation, LastScope));
  LastFileAndLocation = {};
  LastScope = nullptr;
}

/// Restore the current debug location from the stack.
void IRGenDebugInfoImpl::popLoc() {
  std::tie(LastFileAndLocation, LastScope) = LocationStack.pop_back_val();
}

/// This is done for WinDbg to avoid having two non-contiguous sets of
/// instructions because the ``@llvm.trap`` instruction gets placed at the end
/// of the function.
void IRGenDebugInfoImpl::setInlinedTrapLocation(IRBuilder &Builder,
                                                const SILDebugScope *Scope) {
  if (Opts.DebugInfoFormat != IRGenDebugInfoFormat::CodeView)
    return;

  // The @llvm.trap could be inlined into a chunk of code that was also inlined.
  // If this is the case then simply using the LastScope's location would
  // generate debug info that claimed Function A owned Block X and Block X
  // thought it was owned by Function B. Therefore, we need to find the last
  // inlined scope to point to.
  const SILDebugScope *TheLastScope = LastScope;
  while (TheLastScope->InlinedCallSite &&
         TheLastScope->InlinedCallSite != TheLastScope) {
    TheLastScope = TheLastScope->InlinedCallSite;
  }
  auto LastLocation = llvm::DILocation::get(
      IGM.getLLVMContext(), LastFileAndLocation.Line,
      LastFileAndLocation.Column, getOrCreateScope(TheLastScope));
  // FIXME: This location should point to stdlib instead of being artificial.
  auto DL = llvm::DILocation::get(IGM.getLLVMContext(), 0, 0,
                                  getOrCreateScope(Scope), LastLocation);
  Builder.SetCurrentDebugLocation(DL);
}

void IRGenDebugInfoImpl::setEntryPointLoc(IRBuilder &Builder) {
  auto DL = llvm::DILocation::get(IGM.getLLVMContext(), 0, 0, getEntryPointFn(),
                                  nullptr);
  Builder.SetCurrentDebugLocation(DL);
}

llvm::DIScope *IRGenDebugInfoImpl::getEntryPointFn() {
  // Lazily create EntryPointFn.
  if (!EntryPointFn) {
    EntryPointFn = DBuilder.createReplaceableCompositeType(
        llvm::dwarf::DW_TAG_subroutine_type,
        IGM.getSILModule().getASTContext().getEntryPointFunctionName(),
        MainFile, MainFile, 0);
  }
  return EntryPointFn;
}

llvm::DIScope *IRGenDebugInfoImpl::getOrCreateScope(const SILDebugScope *DS) {
  if (DS == nullptr)
    return MainFile;

  // Try to find it in the cache first.
  auto CachedScope = ScopeCache.find(DS);
  if (CachedScope != ScopeCache.end())
    return cast<llvm::DIScope>(CachedScope->second);

  // If this is an (inlined) function scope, the function may
  // not have been created yet.
  if (auto *SILFn = DS->Parent.dyn_cast<SILFunction *>()) {
    auto *FnScope = SILFn->getDebugScope();
    // FIXME: This is a bug in the SIL deserialization.
    if (!FnScope)
      SILFn->setDebugScope(DS);

    auto CachedScope = ScopeCache.find(FnScope);
    if (CachedScope != ScopeCache.end())
      return cast<llvm::DIScope>(CachedScope->second);

    // Force the debug info for the function to be emitted, even if it
    // is external or has been inlined.
    llvm::Function *Fn = nullptr;
    // Avoid materializing generic functions in embedded Swift mode.
    bool genericInEmbedded =
        IGM.Context.LangOpts.hasFeature(Feature::Embedded) &&
        SILFn->isGeneric();
    if (!SILFn->getName().empty() && !SILFn->isZombie() && !genericInEmbedded)
      Fn = IGM.getAddrOfSILFunction(SILFn, NotForDefinition);
    auto *SP = emitFunction(*SILFn, Fn);

    // Cache it.
    ScopeCache[DS] = llvm::TrackingMDNodeRef(SP);
    return SP;
  }

  auto *ParentScope = cast<const SILDebugScope *>(DS->Parent);
  llvm::DIScope *Parent = getOrCreateScope(ParentScope);
  assert(isa<llvm::DILocalScope>(Parent) && "not a local scope");

  if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::LineTables)
    return Parent;

  assert(DS->Parent && "lexical block must have a parent subprogram");
  auto L = getStartLocation(DS->Loc);
  auto *DScope = DBuilder.createLexicalBlock(Parent, L.File, L.Line, L.Column);

  // Cache it.
  ScopeCache[DS] = llvm::TrackingMDNodeRef(DScope);
  return DScope;
}

void IRGenDebugInfoImpl::emitImport(ImportDecl *D) {
  if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::LineTables)
    return;

  assert(D->getModule() && "compiler-synthesized ImportDecl is incomplete");
  ImportedModule Imported = { D->getAccessPath(), D->getModule() };
  auto L = getFileAndLocation(D);
  createImportedModule(L.File, Imported, L.File, L.Line);
  ImportedModules.insert(Imported.importedModule);
}

/// This is effectively \p clang::CGDebugInfo::getCallSiteRelatedAttrs().
llvm::DINode::DIFlags IRGenDebugInfoImpl::getCallSiteRelatedAttrs() const {

  // Do not generate callsite attributes if unless the -gen-callsite-info flag
  // is passed.
  if (!Opts.DebugCallsiteInfo)
    return llvm::DINode::FlagZero;

  auto SwiftLangOpts = IGM.Context.LangOpts;
  auto Loader = IGM.getSILModule().getASTContext().getClangModuleLoader();
  auto *Importer = static_cast<ClangImporter *>(&*Loader);
  auto &CGO = Importer->getCodeGenOpts();

  // Do not generate callsite attributes if there is no debug info to be
  // emitted.
  if (CGO.getDebugInfo() == llvm::codegenoptions::NoDebugInfo ||
      CGO.getDebugInfo() == llvm::codegenoptions::LocTrackingOnly)
    return llvm::DINode::FlagZero;

  // Callsite attributes are available in DWARFv5. However, for swift, lldb can
  // accept these attributes as if they were part of DWARFv4.
  if (Opts.DWARFVersion < 4)
    return llvm::DINode::FlagZero;

  return llvm::DINode::FlagAllCallsDescribed;
}

llvm::DISubprogram *IRGenDebugInfoImpl::emitFunction(SILFunction &SILFn,
                                                     llvm::Function *Fn) {
  auto *DS = SILFn.getDebugScope();
  assert(DS && "SIL function has no debug scope");
  (void)DS;
  return emitFunction(SILFn.getDebugScope(), Fn, SILFn.getRepresentation(),
                      SILFn.getLoweredType(), SILFn.getDeclContext());
}

llvm::DISubprogram *
IRGenDebugInfoImpl::emitFunction(const SILDebugScope *DS, llvm::Function *Fn,
                                 SILFunctionTypeRepresentation Rep,
                                 SILType SILTy, DeclContext *DeclCtx,
                                 StringRef outlinedFromName) {
  auto Cached = ScopeCache.find(DS);
  if (Cached != ScopeCache.end()) {
    auto SP = cast<llvm::DISubprogram>(Cached->second);
    // If we created the DISubprogram for a forward declaration,
    // attach it to the function now.
    if (!Fn->getSubprogram() && !Fn->isDeclaration())
      Fn->setSubprogram(SP);
    return SP;
  }

  // Some IRGen-generated helper functions don't have a corresponding
  // SIL function, hence the dyn_cast.
  auto *SILFn = DS ? DS->Parent.dyn_cast<SILFunction *>() : nullptr;

  StringRef LinkageName;
  if (!outlinedFromName.empty())
    LinkageName = outlinedFromName;
  else if (Fn)
    LinkageName = Fn->getName();
  else if (DS)
    LinkageName = SILFn->getName();
  else
    llvm_unreachable("function has no mangled name");

  StringRef Name;
  if (DS) {
    if (DS->Loc.isSILFile())
      Name = SILFn->getName();
    else
      Name = getName(DS->Loc);
  }

  /// The source line used for the function prologue.
  unsigned ScopeLine = 0;
  FileAndLocation L;
  if (!DS || (SILFn && (SILFn->isBare() || SILFn->isThunk() ||
                        SILFn->isTransparent()))) {
    // Bare functions and thunks should not have any line numbers. This
    // is especially important for shared functions like reabstraction
    // thunk helpers, where DS->Loc is an arbitrary location of whichever use
    // was emitted first.
    L = {0, 0, CompilerGeneratedFile};
  } else {
    L = decodeFileAndLocation(DS->Loc);
    ScopeLine = L.Line;
  }

  auto Line = L.Line;
  auto File = L.File;
  llvm::DIScope *Scope = MainModule;
  if (SILFn && SILFn->getDeclContext())
    Scope = getOrCreateContext(SILFn->getDeclContext()->getParent());

  // We know that main always comes from MainFile.
  if (LinkageName ==
      IGM.getSILModule().getASTContext().getEntryPointFunctionName()) {
    File = MainFile;
    Line = 1;
    Name = LinkageName;
  }

  llvm::DISubprogram *ReplaceableType = DBuilder.createTempFunctionFwdDecl(
      Scope, Name, LinkageName, File, Line, /*Type=*/nullptr, ScopeLine);
  auto FwdDecl = llvm::TempDISubprogram(ReplaceableType);
  ScopeCache[DS] = llvm::TrackingMDNodeRef(FwdDecl.get());

  CanSILFunctionType FnTy = getFunctionType(SILTy);
  auto Params = Opts.DebugInfoLevel > IRGenDebugInfoLevel::LineTables
                    ? createParameterTypes(SILTy)
                    : nullptr;
  llvm::DISubroutineType *DIFnTy = DBuilder.createSubroutineType(Params);
  llvm::DITemplateParameterArray TemplateParameters = nullptr;
  llvm::DISubprogram *Decl = nullptr;

  // Various flags.
  llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
  // Mark everything that is not visible from the source code (i.e.,
  // does not have a Swift name) as artificial, so the debugger can
  // ignore it. Explicit closures are exempt from this rule. We also
  // make an exception for toplevel code, which, although it does not
  // have a Swift name, does appear prominently in the source code.
  // ObjC thunks should also not show up in the linetable, because we
  // never want to set a breakpoint there.
  if ((Name.empty() &&
       LinkageName !=
           IGM.getSILModule().getASTContext().getEntryPointFunctionName() &&
       !isExplicitClosure(SILFn)) ||
      (Rep == SILFunctionTypeRepresentation::ObjCMethod) ||
      isAllocatingConstructor(Rep, DeclCtx)) {
    Flags |= llvm::DINode::FlagArtificial;
    ScopeLine = 0;
  }

  if (FnTy &&
      FnTy->getRepresentation() == SILFunctionType::Representation::Block)
    Flags |= llvm::DINode::FlagAppleBlock;

  // Get the throws information.
  llvm::DITypeArray Error = nullptr;
  if (FnTy && (Opts.DebugInfoLevel > IRGenDebugInfoLevel::LineTables))
    if (auto ErrorInfo = FnTy->getOptionalErrorResult()) {
      GenericContextScope scope(IGM, FnTy->getInvocationGenericSignature());
      CanType errorResultTy = ErrorInfo->getReturnValueType(
          IGM.getSILModule(), FnTy,
          IGM.getMaximalTypeExpansionContext());
      SILType SILTy = IGM.silConv.getSILType(
          *ErrorInfo, FnTy, IGM.getMaximalTypeExpansionContext());

      errorResultTy = SILFn->mapTypeIntoEnvironment(errorResultTy)
          ->getCanonicalType();
      SILTy = SILFn->mapTypeIntoEnvironment(SILTy);

      auto DTI = DebugTypeInfo::getFromTypeInfo(
          errorResultTy,
          IGM.getTypeInfo(SILTy), IGM);
      Error = DBuilder.getOrCreateArray({getOrCreateType(DTI)}).get();
    }

  llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::toSPFlags(
      /*IsLocalToUnit=*/Fn ? Fn->hasInternalLinkage() : true,
      /*IsDefinition=*/true, /*IsOptimized=*/Opts.shouldOptimize());

  // When the function is a method, we want a DW_AT_declaration there.
  // Because there's no good way to cross the CU boundary to insert a nested
  // DISubprogram definition in one CU into a type defined in another CU when
  // doing LTO builds.
  if (llvm::isa<llvm::DICompositeType>(Scope) &&
      (Rep == SILFunctionTypeRepresentation::Method ||
       Rep == SILFunctionTypeRepresentation::ObjCMethod ||
       Rep == SILFunctionTypeRepresentation::WitnessMethod ||
       Rep == SILFunctionTypeRepresentation::CXXMethod ||
       Rep == SILFunctionTypeRepresentation::CFunctionPointer ||
       Rep == SILFunctionTypeRepresentation::Thin)) {
    llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::toSPFlags(
        /*IsLocalToUnit=*/Fn ? Fn->hasInternalLinkage() : true,
        /*IsDefinition=*/false, /*IsOptimized=*/Opts.shouldOptimize());
    Decl = DBuilder.createMethod(Scope, Name, LinkageName, File, Line, DIFnTy,
                                 0, 0, nullptr, Flags, SPFlags,
                                 TemplateParameters, Error);
  }

  // Construct the DISubprogram.
  llvm::DISubprogram *SP =
      DBuilder.createFunction(Scope, Name, LinkageName, File, Line, DIFnTy,
                              ScopeLine, Flags | getCallSiteRelatedAttrs(),
                              SPFlags, TemplateParameters, Decl, Error);

  if (Fn && !Fn->isDeclaration())
    Fn->setSubprogram(SP);

  // RAUW the entry point function forward declaration with the real thing.
  if (LinkageName ==
      IGM.getSILModule().getASTContext().getEntryPointFunctionName()) {
    if (EntryPointFn) {
      assert(EntryPointFn->isTemporary() &&
             "more than one entry point function");
      EntryPointFn->replaceAllUsesWith(SP);
      llvm::MDNode::deleteTemporary(EntryPointFn);
    }
    EntryPointFn = SP;
  }

  if (!DS)
    return nullptr;

  DBuilder.replaceTemporary(std::move(FwdDecl), SP);
  ScopeCache[DS] = llvm::TrackingMDNodeRef(SP);
  return SP;
}

void IRGenDebugInfoImpl::emitArtificialFunction(IRBuilder &Builder,
                                                llvm::Function *Fn,
                                                SILType SILTy) {
  RegularLocation ALoc = RegularLocation::getAutoGeneratedLocation();
  const SILDebugScope *Scope = new (IGM.getSILModule()) SILDebugScope(ALoc);
  emitFunction(Scope, Fn, SILFunctionTypeRepresentation::Thin, SILTy);
  /// Reusing the current file would be wrong: An objc thunk, for example, could
  /// be triggered from any random location. Use a placeholder name instead.
  setCurrentLoc(Builder, Scope, ALoc);
}

void IRGenDebugInfoImpl::emitOutlinedFunction(IRBuilder &Builder,
                                              llvm::Function *Fn,
                                              StringRef outlinedFromName) {
  RegularLocation ALoc = RegularLocation::getAutoGeneratedLocation();
  const SILDebugScope *Scope = new (IGM.getSILModule()) SILDebugScope(ALoc);
  emitFunction(Scope, Fn, SILFunctionTypeRepresentation::Thin, SILType(),
               nullptr, outlinedFromName);
  /// Reusing the current file would be wrong: An objc thunk, for example, could
  /// be triggered from any random location. Use a placeholder name instead.
  setCurrentLoc(Builder, Scope, ALoc);
}

bool IRGenDebugInfoImpl::handleFragmentDIExpr(
    const SILDIExprOperand &CurDIExprOp,
    llvm::DIExpression::FragmentInfo &Fragment) {
  if (CurDIExprOp.getOperator() == SILDIExprOperator::TupleFragment)
    return handleTupleFragmentDIExpr(CurDIExprOp, Fragment);
  assert(CurDIExprOp.getOperator() == SILDIExprOperator::Fragment);
  // Expecting a VarDecl that points to a field in an struct
  auto DIExprArgs = CurDIExprOp.args();
  auto *VD = dyn_cast_or_null<VarDecl>(DIExprArgs.size() ?
                                       DIExprArgs[0].getAsDecl() : nullptr);
  assert(VD && "Expecting a VarDecl as the operand for "
               "DIExprOperator::Fragment");
  // Translate the based type
  DeclContext *ParentDecl = VD->getDeclContext();
  assert(ParentDecl && "VarDecl has no parent context?");
  SILType ParentSILType =
      IGM.getLoweredType(ParentDecl->getDeclaredTypeInContext());
  // Retrieve the offset & size of the field
  llvm::Constant *Offset =
      emitPhysicalStructMemberFixedOffset(IGM, ParentSILType, VD);
  auto *FieldTypeInfo = getPhysicalStructFieldTypeInfo(IGM, ParentSILType, VD);
  // FIXME: This will only happen if IRGen hasn't processed ParentSILType
  // (into its own representation) but we probably should ask IRGen to process
  // it right now.
  if (!FieldTypeInfo)
    return false;
  llvm::Type *FieldTy = FieldTypeInfo->getStorageType();
  // Doesn't support non-fixed or empty types right now.
  if (!Offset || !FieldTy || !FieldTy->isSized())
    return false;

  uint64_t SizeOfByte = CI.getTargetInfo().getCharWidth();
  uint64_t SizeInBits = IGM.DataLayout.getTypeSizeInBits(FieldTy);
  uint64_t OffsetInBits =
      Offset->getUniqueInteger().getLimitedValue() * SizeOfByte;

  // Translate to DW_OP_LLVM_fragment operands
  Fragment = {SizeInBits, OffsetInBits};

  return true;
}

bool IRGenDebugInfoImpl::handleTupleFragmentDIExpr(
    const SILDIExprOperand &CurDIExprOp,
    llvm::DIExpression::FragmentInfo &Fragment) {
  assert(CurDIExprOp.getOperator() == SILDIExprOperator::TupleFragment);
  // Expecting a TupleType followed by an index
  auto DIExprArgs = CurDIExprOp.args();
  assert(DIExprArgs.size() >= 2 && "Expecting two arguments for "
         "DIExprOperator::TupleFragment");
  auto *TT = dyn_cast<TupleType>(DIExprArgs[0].getAsType().getPointer());
  assert(TT && "Expecting a TupleType as the first operand for "
               "DIExprOperator::TupleFragment");
  auto Idx = DIExprArgs[1].getAsConstInt();
  assert(Idx && "Expecting an index as the second operand for "
               "DIExprOperator::TupleFragment");
  // Translate the based type
  SILType ParentSILType = IGM.getLoweredType(TT);
  // Retrieve the offset & size of the field
  auto Offset = getFixedTupleElementOffset(IGM, ParentSILType, *Idx);
  auto ElementType = TT->getElement(*Idx).getType()->getCanonicalType();
  llvm::Type *FieldTy = IGM.getStorageTypeForLowered(ElementType);
  // Doesn't support non-fixed or empty types right now.
  if (!Offset || !FieldTy || !FieldTy->isSized())
    return false;

  uint64_t SizeInBits = IGM.DataLayout.getTypeSizeInBits(FieldTy);
  uint64_t OffsetInBits = Offset->getValueInBits();

  // Translate to DW_OP_LLVM_fragment operands
  Fragment = {SizeInBits, OffsetInBits};

  return true;
}

bool IRGenDebugInfoImpl::buildDebugInfoExpression(
    const SILDebugVariable &VarInfo, SmallVectorImpl<uint64_t> &Operands,
    llvm::DIExpression::FragmentInfo &Fragment) {
  assert(VarInfo.DIExpr && "SIL debug info expression not found");

  const auto &DIExpr = VarInfo.DIExpr;
  for (const SILDIExprOperand &ExprOperand : DIExpr.operands()) {
    llvm::DIExpression::FragmentInfo SubFragment = {0, 0};
    switch (ExprOperand.getOperator()) {
    case SILDIExprOperator::Fragment:
    case SILDIExprOperator::TupleFragment:
      if (!handleFragmentDIExpr(ExprOperand, SubFragment))
        return false;
      assert(!Fragment.SizeInBits
             || (SubFragment.OffsetInBits + SubFragment.SizeInBits
              <= Fragment.SizeInBits)
             && "Invalid nested fragments");
      Fragment.OffsetInBits += SubFragment.OffsetInBits;
      Fragment.SizeInBits = SubFragment.SizeInBits;
      break;
    case SILDIExprOperator::Dereference:
      Operands.push_back(llvm::dwarf::DW_OP_deref);
      break;
    case SILDIExprOperator::INVALID:
      return false;
    }
  }
  if (Operands.size() && Operands.back() != llvm::dwarf::DW_OP_deref) {
    Operands.push_back(llvm::dwarf::DW_OP_stack_value);
  }
  return true;
}

void IRGenDebugInfoImpl::emitVariableDeclaration(
    IRBuilder &Builder, ArrayRef<llvm::Value *> Storage, DebugTypeInfo DbgTy,
    const SILDebugScope *DS, std::optional<SILLocation> DbgInstLoc,
    SILDebugVariable VarInfo, bool InCoroContext,
    ArtificialKind Artificial, AddrDbgInstrKind AddrDInstrKind) {
  assert(DS && "variable has no scope");

  if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::LineTables)
    return;

  // We cannot yet represent local archetypes.
  if (DbgTy.getType()->hasLocalArchetype())
    return;

  auto *Scope = dyn_cast_or_null<llvm::DILocalScope>(getOrCreateScope(DS));
  assert(Scope && "variable has no local scope");
  auto DInstLoc = getStartLocation(DbgInstLoc);

  // FIXME: this should be the scope of the type's declaration.
  // If this is an argument, attach it to the current function scope.
  uint16_t ArgNo = VarInfo.ArgNo;
  if (ArgNo > 0) {
    while (isa<llvm::DILexicalBlock>(Scope))
      Scope = cast<llvm::DILexicalBlock>(Scope)->getScope();
  }
  assert(isa_and_nonnull<llvm::DIScope>(Scope) && "variable has no scope");
  llvm::DIFile *Unit = getFile(Scope);
  llvm::DIType *DITy = getOrCreateType(DbgTy);
  assert(DITy && "could not determine debug type of variable");
  if (VarInfo.Constant)
    DITy = DBuilder.createQualifiedType(llvm::dwarf::DW_TAG_const_type, DITy);

  unsigned DInstLine = DInstLoc.Line;

  // Self is always an artificial argument, so are variables without location.
  if (!DInstLine || (ArgNo > 0 && VarInfo.Name == IGM.Context.Id_self.str()))
    Artificial = ArtificialValue;

  llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
  if (Artificial || DITy->isArtificial() || DITy == InternalType)
    Flags |= llvm::DINode::FlagArtificial;

  // Create the descriptor for the variable.
  unsigned DVarLine = DInstLine;
  uint16_t DVarCol = DInstLoc.Column;
  auto VarInfoLoc = VarInfo.Loc ? VarInfo.Loc : DbgInstLoc;
  if (VarInfoLoc) {
    auto VarLoc = VarInfoLoc->strippedForDebugVariable();
    if (VarLoc != DbgInstLoc) {
      auto DVarLoc = getStartLocation(VarLoc);
      DVarLine = DVarLoc.Line;
      DVarCol = DVarLoc.Column;
    }
  }
  llvm::DIScope *VarScope = Scope;
  if (ArgNo == 0 && VarInfo.Scope) {
    if (auto *VS = dyn_cast_or_null<llvm::DILocalScope>(
            getOrCreateScope(VarInfo.Scope))) {
      VarScope = VS;
    }
  }

  // Get or create the DILocalVariable.
  llvm::DILocalVariable *Var;
  // VarInfo.Name points into tail-allocated storage in debug_value insns.
  llvm::StringRef UniqueName = VarNames.insert(VarInfo.Name).first->getKey();
  VarID Key(VarScope, UniqueName, DVarLine, DVarCol);
  auto CachedVar = LocalVarCache.find(Key);
  if (CachedVar != LocalVarCache.end()) {
    Var = cast<llvm::DILocalVariable>(CachedVar->second);
  } else {
    // The llvm.dbg.value(undef) emitted for zero-sized variables get filtered
    // out by DwarfDebug::collectEntityInfo(), so all variables need to be
    // preserved even at -Onone.
    bool Preserve = true;
    if (ArgNo > 0)
      Var = DBuilder.createParameterVariable(
          VarScope, VarInfo.Name, ArgNo, Unit, DVarLine, DITy, Preserve, Flags);
    else
      Var = DBuilder.createAutoVariable(VarScope, VarInfo.Name, Unit, DVarLine,
                                        DITy, Preserve, Flags);
    LocalVarCache.insert({Key, llvm::TrackingMDNodeRef(Var)});
  }

  // Running variables for the current/previous piece.
  bool IsPiece = Storage.size() > 1;
  uint64_t SizeOfByte = CI.getTargetInfo().getCharWidth();
  unsigned AlignInBits = SizeOfByte;
  unsigned OffsetInBits = 0;
  unsigned SizeInBits = 0;
  llvm::DIExpression::FragmentInfo Fragment = {0, 0};

  auto appendDIExpression =
      [&VarInfo, this](llvm::DIExpression *DIExpr,
                       llvm::DIExpression::FragmentInfo PieceFragment,
                       bool IsFirstAndOnlyPiece) -> llvm::DIExpression * {
    if (!VarInfo.DIExpr) {
      if (!PieceFragment.SizeInBits || IsFirstAndOnlyPiece)
        return DIExpr;

      return llvm::DIExpression::createFragmentExpression(
                 DIExpr, PieceFragment.OffsetInBits, PieceFragment.SizeInBits)
          .value_or(nullptr);
    }

    llvm::SmallVector<uint64_t, 2> Operands;
    llvm::DIExpression::FragmentInfo VarFragment = {0, 0};
    if (!buildDebugInfoExpression(VarInfo, Operands, VarFragment))
      return nullptr;

    if (!Operands.empty())
      DIExpr = llvm::DIExpression::append(DIExpr, Operands);

    // Add the fragment of the SIL variable.
    if (VarFragment.SizeInBits && !IsFirstAndOnlyPiece)
      DIExpr = llvm::DIExpression::createFragmentExpression(
                   DIExpr, VarFragment.OffsetInBits, VarFragment.SizeInBits)
                   .value_or(nullptr);

    if (!DIExpr)
      return nullptr;

    // When the fragment of the SIL variable is further split into other
    // fragments (PieceFragment), merge them into one DW_OP_LLVM_Fragment
    // expression.
    if (PieceFragment.SizeInBits)
      return llvm::DIExpression::createFragmentExpression(
                 DIExpr, PieceFragment.OffsetInBits, PieceFragment.SizeInBits)
          .value_or(nullptr);

    return DIExpr;
  };

  for (llvm::Value *Piece : Storage) {
    SmallVector<uint64_t, 3> Operands;

    if (DbgTy.getType()->isForeignReferenceType())
      Operands.push_back(llvm::dwarf::DW_OP_deref);

    if (IsPiece) {
      // Advance the offset for the next piece.
      OffsetInBits += SizeInBits;
      SizeInBits = IGM.DataLayout.getTypeSizeInBits(Piece->getType());
      AlignInBits = IGM.DataLayout.getABITypeAlign(Piece->getType()).value();
      if (!AlignInBits)
        AlignInBits = SizeOfByte;

      // Soundness checks.
#ifndef NDEBUG
      assert(SizeInBits && "zero-sized piece");
      if (getSizeInBits(Var)) {
        assert(SizeInBits < getSizeInBits(Var) && "piece covers entire var");
        assert(OffsetInBits + SizeInBits <= getSizeInBits(Var) &&
               "pars > totum");
      }
#endif

      // Add the piece DW_OP_LLVM_fragment operands
      Fragment.OffsetInBits = OffsetInBits;
      Fragment.SizeInBits = SizeInBits;
    }
    // LLVM complains if a single fragment covers the entire variable. This can
    // happen if, e.g., the optimizer takes the _value out of an Int
    // struct. Detect this case and don't emit a fragment.
    bool IsFirstAndOnlyPiece =
        !IsPiece && Fragment.OffsetInBits == 0 &&
        Fragment.SizeInBits == getSizeInBits(Var->getType());
    llvm::DIExpression *DIExpr = DBuilder.createExpression(Operands);
    DIExpr = appendDIExpression(DIExpr, Fragment, IsFirstAndOnlyPiece);
    if (DIExpr)
      emitDbgIntrinsic(
          Builder, Piece, Var, DIExpr, DInstLine, DInstLoc.Column, Scope, DS,
          InCoroContext, AddrDInstrKind);
  }

  // Emit locationless intrinsic for variables that were optimized away.
  if (Storage.empty()) {
    llvm::DIExpression::FragmentInfo NoFragment = {0, 0};
    if (auto *DIExpr =
            appendDIExpression(DBuilder.createExpression(), NoFragment, false))
      emitDbgIntrinsic(Builder, llvm::ConstantInt::get(IGM.Int64Ty, 0), Var,
                       DIExpr, DInstLine, DInstLoc.Column, Scope, DS,
                       InCoroContext, AddrDInstrKind);
  }
}

namespace {

/// Strip the leading DW_OP_deref from the expression.
/// dbg.declare implicitly provides one level of dereference, so the first
/// DW_OP_deref is redundant.
static llvm::DIExpression *stripLeadingDeref(llvm::DIExpression *Expr,
                                             llvm::LLVMContext &Ctx) {
  auto Elements = Expr->getElements();
  if (!Elements.empty() && Elements[0] == llvm::dwarf::DW_OP_deref)
    return llvm::DIExpression::get(Ctx, Elements.drop_front(1));
  return Expr;
}

/// A helper struct that is used by emitDbgIntrinsic to factor redundant code.
struct DbgIntrinsicEmitter {
  PointerUnion<llvm::BasicBlock *, llvm::Instruction *> InsertPt;
  irgen::IRBuilder &IRBuilder;
  llvm::DIBuilder &DIBuilder;
  AddrDbgInstrKind ForceDbgDeclareOrDeclareValue;

  /// Initialize the emitter and initialize the emitter to assume that it is
  /// going to insert an llvm.dbg.declare or an llvm.dbg.addr either at the
  /// current "generalized insertion point" of the IRBuilder. The "generalized
  /// insertion point" is
  DbgIntrinsicEmitter(irgen::IRBuilder &IRBuilder, llvm::DIBuilder &DIBuilder,
                      AddrDbgInstrKind AddrDInstrKind)
      : InsertPt(), IRBuilder(IRBuilder), DIBuilder(DIBuilder),
        ForceDbgDeclareOrDeclareValue(AddrDInstrKind) {
    auto *ParentBB = IRBuilder.GetInsertBlock();
    auto InsertBefore = IRBuilder.GetInsertPoint();

    if (InsertBefore != ParentBB->end())
      InsertPt = &*InsertBefore;
    else
      InsertPt = ParentBB;
  }

  ///

  llvm::DbgInstPtr insert(llvm::Value *Addr, llvm::DILocalVariable *VarInfo,
                          llvm::DIExpression *Expr,
                          const llvm::DILocation *DL) {
    if (auto *Inst = InsertPt.dyn_cast<llvm::Instruction *>()) {
      return insert(Addr, VarInfo, Expr, DL, Inst);
    } else {
      return insert(Addr, VarInfo, Expr, DL,
                    cast<llvm::BasicBlock *>(InsertPt));
    }
  }

  llvm::DbgInstPtr insert(llvm::Value *Addr, llvm::DILocalVariable *VarInfo,
                          llvm::DIExpression *Expr,
                          const llvm::DILocation *DL,
                          llvm::Instruction *InsertBefore) {
    if (ForceDbgDeclareOrDeclareValue == AddrDbgInstrKind::DbgDeclare) {
      Expr = stripLeadingDeref(Expr, InsertBefore->getContext());
      return DIBuilder.insertDeclare(Addr, VarInfo, Expr, DL,
                                     InsertBefore->getIterator());
    }

    if (ForceDbgDeclareOrDeclareValue == AddrDbgInstrKind::DbgDeclareValue) {
      Expr = stripLeadingDeref(Expr, InsertBefore->getContext());
      return DIBuilder.insertDeclareValue(Addr, VarInfo, Expr, DL,
                                          InsertBefore->getIterator());
    }

    // DbgValue: keep expression as-is (all derefs are explicit).
    return DIBuilder.insertDbgValueIntrinsic(Addr, VarInfo, Expr, DL,
                                             InsertBefore->getIterator());
  }

  llvm::DbgInstPtr insert(llvm::Value *Addr, llvm::DILocalVariable *VarInfo,
                          llvm::DIExpression *Expr,
                          const llvm::DILocation *DL,
                          llvm::BasicBlock *Block) {
    if (ForceDbgDeclareOrDeclareValue == AddrDbgInstrKind::DbgDeclare) {
      Expr = stripLeadingDeref(Expr, Block->getContext());
      return DIBuilder.insertDeclare(Addr, VarInfo, Expr, DL, Block);
    }

    if (ForceDbgDeclareOrDeclareValue == AddrDbgInstrKind::DbgDeclareValue) {
      Expr = stripLeadingDeref(Expr, Block->getContext());
      return DIBuilder.insertDeclareValue(Addr, VarInfo, Expr, DL, Block);
    }

    // DbgValue: keep expression as-is (all derefs are explicit).
    return DIBuilder.insertDbgValueIntrinsic(Addr, VarInfo, Expr, DL, Block);
  }
};

} // namespace

void IRGenDebugInfoImpl::emitDbgIntrinsic(
    IRBuilder &Builder, llvm::Value *Storage, llvm::DILocalVariable *Var,
    llvm::DIExpression *Expr, unsigned Line, unsigned Col,
    llvm::DILocalScope *Scope, const SILDebugScope *DS, bool InCoroContext,
    AddrDbgInstrKind AddrDInstKind) {
  Storage = Storage->stripPointerCasts();
  // Set the location/scope of the intrinsic.
  auto *InlinedAt = createInlinedAt(DS);
  auto DL =
      llvm::DILocation::get(IGM.getLLVMContext(), Line, Col, Scope, InlinedAt);

  // Fragment DIExpression cannot cover the whole variable
  // or going out-of-bound.
  if (auto Fragment = Expr->getFragmentInfo()) {
    if (auto VarSize = Var->getSizeInBits()) {
      unsigned FragSize = Fragment->SizeInBits;
      unsigned FragOffset = Fragment->OffsetInBits;
      if (FragOffset + FragSize > *VarSize || FragSize == *VarSize) {
        // Drop the fragment part
        assert(Expr->isValid());
        // Since this expression is valid, DW_OP_LLVM_fragment
        // and its arguments must be the last 3 elements.
        auto OrigElements = Expr->getElements();
        Expr = DBuilder.createExpression(OrigElements.drop_back(3));
      }
    }
  }

  auto *ParentBlock = Builder.GetInsertBlock();

  // First before we do anything, check if we have an Undef. In this case, we
  // /always/ emit an llvm.dbg.value of undef.
  // If we have undef, always emit a llvm.dbg.value in the current position.
  if (isa<llvm::UndefValue>(Storage)) {
    DBuilder.insertDbgValueIntrinsic(Storage, Var, Expr, DL, ParentBlock);
    return;
  }

  bool optimized = DS->getParentFunction()->shouldOptimize();
  if (optimized && (!InCoroContext || !Var->isParameter()))
    AddrDInstKind = AddrDbgInstrKind::DbgValue;

  if (InCoroContext && AddrDInstKind != AddrDbgInstrKind::DbgValue)
    AddrDInstKind = AddrDbgInstrKind::DbgDeclareValue;

  DbgIntrinsicEmitter inserter{Builder, DBuilder, AddrDInstKind};

  // If we have a single alloca...
  if (auto *Alloca = dyn_cast<llvm::AllocaInst>(Storage)) {
    auto InsertBefore = Builder.GetInsertPoint();

    if (AddrDInstKind == AddrDbgInstrKind::DbgDeclare ||
        AddrDInstKind == AddrDbgInstrKind::DbgDeclareValue) {
      ParentBlock = Alloca->getParent();
      InsertBefore = std::next(Alloca->getIterator());
    }

    if (InsertBefore != ParentBlock->end()) {
      inserter.insert(Alloca, Var, Expr, DL, &*InsertBefore);
    } else {
      inserter.insert(Alloca, Var, Expr, DL, ParentBlock);
    }
    return;
  }

  if ((isa<llvm::IntrinsicInst>(Storage) &&
       cast<llvm::IntrinsicInst>(Storage)->getIntrinsicID() ==
           llvm::Intrinsic::coro_alloca_get)) {
    inserter.insert(Storage, Var, Expr, DL, ParentBlock);
    return;
  }

  if (InCoroContext && (Var->isParameter() || !optimized)) {
    PointerUnion<llvm::BasicBlock *, llvm::Instruction *> InsertPt;

    // If we have a dbg.declare, we are relying on a contract with the coroutine
    // splitter that in split coroutines we always create debug info for values
    // in the coroutine context by creating a llvm.dbg.declare for the variable
    // in the entry block of each funclet.
    if (AddrDInstKind == AddrDbgInstrKind::DbgDeclare ||
        AddrDInstKind == AddrDbgInstrKind::DbgDeclareValue) {
      // Function arguments in async functions are emitted without a shadow copy
      // (that would interfere with coroutine splitting) but with a
      // llvm.dbg.declare to give CoroSplit.cpp license to emit a shadow copy
      // for them pointing inside the Swift Context argument that is valid
      // throughout the function.
      auto &EntryBlock = ParentBlock->getParent()->getEntryBlock();
      if (auto *InsertBefore = &*EntryBlock.getFirstInsertionPt()) {
        InsertPt = InsertBefore;
      } else {
        InsertPt = &EntryBlock;
      }
    } else {
      // For llvm.dbg.value, we just want to insert the intrinsic at the current
      // insertion point. This is because our contract with the coroutine
      // splitter is that the coroutine splitter just needs to emit the
      // llvm.dbg.value where we placed them. It shouldn't move them or do
      // anything special with it. Instead, we have previously inserted extra
      // debug_value clones previously after each instruction at the SIL level
      // that corresponds with a funclet edge. This operation effectively sets
      // up the rest of the pipeline to be stupid and just emit the
      // llvm.dbg.value in the correct places. This is done by the SILOptimizer
      // pass MovedAsyncVarDebugInfoPropagator.
      auto InsertBefore = Builder.GetInsertPoint();
      if (InsertBefore != ParentBlock->end()) {
        InsertPt = &*InsertBefore;
      } else {
        InsertPt = ParentBlock;
      }
    }

    // Ok, we now have our insert pt. Call the appropriate operations.
    assert(InsertPt);
    if (auto *InsertBefore = InsertPt.dyn_cast<llvm::Instruction *>()) {
      inserter.insert(Storage, Var, Expr, DL, InsertBefore);
    } else {
      inserter.insert(Storage, Var, Expr, DL,
                      cast<llvm::BasicBlock *>(InsertPt));
    }
    return;
  }

  // Insert a dbg.value at the current insertion point.
  if (isa<llvm::Argument>(Storage) && !Var->getArg()) {
    const auto InsertPt = ParentBlock->getFirstNonPHIOrDbg();
    if (InsertPt != ParentBlock->end()) {
      // SelectionDAGISel only generates debug info for a dbg.value
      // that is associated with a llvm::Argument if either its !DIVariable
      // is marked as argument or there is no non-debug intrinsic instruction
      // before it. So In the case of associating a llvm::Argument with a
      // non-argument debug variable -- usually via a !DIExpression -- we
      // need to make sure that dbg.value is before any non-phi / no-dbg
      // instruction.
      DBuilder.insertDbgValueIntrinsic(Storage, Var, Expr, DL, InsertPt);

      return;
    }
  }

  DBuilder.insertDbgValueIntrinsic(Storage, Var, Expr, DL, ParentBlock->end());
}

void IRGenDebugInfoImpl::emitGlobalVariableDeclaration(
    llvm::GlobalVariable *Var, StringRef Name, StringRef LinkageName,
    DebugTypeInfo DbgTy, bool IsLocalToUnit, std::optional<SILLocation> Loc) {
  if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::LineTables)
    return;

  llvm::DIType *DITy = getOrCreateType(DbgTy);
  VarDecl *VD = nullptr;
  if (Loc)
    VD = dyn_cast_or_null<VarDecl>(Loc->getAsASTNode<Decl>());
  if (!VD || VD->isLet())
    DITy = DBuilder.createQualifiedType(llvm::dwarf::DW_TAG_const_type, DITy);

  if (DITy->isArtificial() || DITy == InternalType || !Loc)
    // FIXME: Really these should be marked as artificial, but LLVM
    // currently has no support for flags to be put on global
    // variables. In the mean time, elide these variables, they
    // would confuse both the user and LLDB.
    return;

  if (DbgTy.isFixedBuffer())
    DITy = createFixedValueBufferStruct(DITy);

  auto L = getStartLocation(Loc);

  // Emit it as global variable of the current module.
  llvm::DIExpression *Expr = nullptr;
  if (!Var)
    Expr = DBuilder.createConstantValueExpression(0);
  auto *GV = DBuilder.createGlobalVariableExpression(
      MainModule, Name, LinkageName, L.File, L.Line, DITy, IsLocalToUnit, true,
      Expr);
  if (Var)
    Var->addDebugInfo(GV);
}

void IRGenDebugInfoImpl::emitTypeMetadata(IRGenFunction &IGF,
                                          llvm::Value *Metadata, unsigned Depth,
                                          unsigned Index, StringRef Name) {
  if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::LineTables)
    return;

  // Don't emit debug info in transparent functions.
  auto *DS = IGF.getDebugScope();
  if (!DS || DS->getInlinedFunction()->isTransparent())
    return;

  llvm::SmallString<8> Buf;
  static const char *Tau = SWIFT_UTF8("\u03C4");
  llvm::raw_svector_ostream OS(Buf);
  OS << '$' << Tau << '_' << Depth << '_' << Index;
  uint64_t PtrWidthInBits = CI.getTargetInfo().getPointerWidth(clang::LangAS::Default);
  assert(PtrWidthInBits % 8 == 0);
  auto DbgTy = DebugTypeInfo::getTypeMetadata(
      getMetadataType(Name)->getDeclaredInterfaceType().getPointer(),
      Size(PtrWidthInBits / 8),
      Alignment(CI.getTargetInfo().getPointerAlign(clang::LangAS::Default)));
  emitVariableDeclaration(IGF.Builder, Metadata, DbgTy, IGF.getDebugScope(),
                          {}, {OS.str().str(), 0, false},
                          /*InCoroContext=*/IGF.isAsync(),
                          ArtificialValue);
}

void IRGenDebugInfoImpl::emitPackCountParameter(IRGenFunction &IGF,
                                                llvm::Value *Metadata,
                                                SILDebugVariable VarInfo) {
  if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::LineTables)
    return;

  // Don't emit debug info in transparent functions.
  auto *DS = IGF.getDebugScope();
  if (!DS || DS->getInlinedFunction()->isTransparent())
    return;

  Type IntTy = BuiltinIntegerType::get(CI.getTargetInfo().getPointerWidth(clang::LangAS::Default),
                                       IGM.getSwiftModule()->getASTContext());
  auto &TI = IGM.getTypeInfoForUnlowered(IntTy);
  auto DbgTy = *CompletedDebugTypeInfo::getFromTypeInfo(IntTy, TI, IGM);
  emitVariableDeclaration(
      IGF.Builder, Metadata, DbgTy, IGF.getDebugScope(), {}, VarInfo,
      /*InCoroContext=*/IGF.isAsync(), ArtificialValue);
}

} // anonymous namespace

std::unique_ptr<IRGenDebugInfo> IRGenDebugInfo::createIRGenDebugInfo(
    const IRGenOptions &Opts, ClangImporter &CI, IRGenModule &IGM,
    llvm::Module &M, StringRef MainOutputFilenameForDebugInfo,
    StringRef PrivateDiscriminator, StringRef CacheKeyForJob) {
  return std::make_unique<IRGenDebugInfoImpl>(
      Opts, CI, IGM, M, MainOutputFilenameForDebugInfo, PrivateDiscriminator,
      CacheKeyForJob);
}

IRGenDebugInfo::~IRGenDebugInfo() {}

// Forwarding to the private implementation.
void IRGenDebugInfo::finalize() {
  static_cast<IRGenDebugInfoImpl *>(this)->finalize();
}

void IRGenDebugInfo::setCurrentLoc(IRBuilder &Builder, const SILDebugScope *DS,
                                   SILLocation Loc) {
  static_cast<IRGenDebugInfoImpl *>(this)->setCurrentLoc(Builder, DS, Loc);
}

void IRGenDebugInfo::addFailureMessageToCurrentLoc(IRBuilder &Builder,
                                                   StringRef failureMsg) {
  static_cast<IRGenDebugInfoImpl *>(this)->addFailureMessageToCurrentLoc(
      Builder, failureMsg);
}

void IRGenDebugInfo::clearLoc(IRBuilder &Builder) {
  static_cast<IRGenDebugInfoImpl *>(this)->clearLoc(Builder);
}

void IRGenDebugInfo::pushLoc() {
  static_cast<IRGenDebugInfoImpl *>(this)->pushLoc();
}

void IRGenDebugInfo::popLoc() {
  static_cast<IRGenDebugInfoImpl *>(this)->popLoc();
}

void IRGenDebugInfo::setInlinedTrapLocation(IRBuilder &Builder,
                                            const SILDebugScope *Scope) {
  static_cast<IRGenDebugInfoImpl *>(this)->setInlinedTrapLocation(Builder,
                                                                  Scope);
}

void IRGenDebugInfo::setEntryPointLoc(IRBuilder &Builder) {
  static_cast<IRGenDebugInfoImpl *>(this)->setEntryPointLoc(Builder);
}

llvm::DIScope *IRGenDebugInfo::getEntryPointFn() {
  return static_cast<IRGenDebugInfoImpl *>(this)->getEntryPointFn();
}

llvm::DIScope *IRGenDebugInfo::getOrCreateScope(const SILDebugScope *DS) {
  return static_cast<IRGenDebugInfoImpl *>(this)->getOrCreateScope(DS);
}

void IRGenDebugInfo::emitImport(ImportDecl *D) {
  static_cast<IRGenDebugInfoImpl *>(this)->emitImport(D);
}

llvm::DISubprogram *
IRGenDebugInfo::emitFunction(const SILDebugScope *DS, llvm::Function *Fn,
                             SILFunctionTypeRepresentation Rep, SILType Ty,
                             DeclContext *DeclCtx, GenericEnvironment *GE) {
  return static_cast<IRGenDebugInfoImpl *>(this)->emitFunction(DS, Fn, Rep, Ty,
                                                               DeclCtx);
}

llvm::DISubprogram *IRGenDebugInfo::emitFunction(SILFunction &SILFn,
                                                 llvm::Function *Fn) {
  return static_cast<IRGenDebugInfoImpl *>(this)->emitFunction(SILFn, Fn);
}

void IRGenDebugInfo::emitArtificialFunction(IRBuilder &Builder,
                                            llvm::Function *Fn, SILType SILTy) {
  static_cast<IRGenDebugInfoImpl *>(this)->emitArtificialFunction(Builder, Fn,
                                                                  SILTy);
}
void IRGenDebugInfo::emitOutlinedFunction(IRBuilder &Builder,
                                          llvm::Function *Fn, StringRef name) {
  static_cast<IRGenDebugInfoImpl *>(this)->emitOutlinedFunction(Builder, Fn,
                                                                name);
}
void IRGenDebugInfo::emitVariableDeclaration(
    IRBuilder &Builder, ArrayRef<llvm::Value *> Storage, DebugTypeInfo Ty,
    const SILDebugScope *DS, std::optional<SILLocation> VarLoc,
    SILDebugVariable VarInfo, bool InCoroContext,
    ArtificialKind Artificial, AddrDbgInstrKind AddrDInstKind) {
  static_cast<IRGenDebugInfoImpl *>(this)->emitVariableDeclaration(
      Builder, Storage, Ty, DS, VarLoc, VarInfo, InCoroContext, Artificial,
      AddrDInstKind);
}

void IRGenDebugInfo::emitDbgIntrinsic(IRBuilder &Builder, llvm::Value *Storage,
                                      llvm::DILocalVariable *Var,
                                      llvm::DIExpression *Expr, unsigned Line,
                                      unsigned Col, llvm::DILocalScope *Scope,
                                      const SILDebugScope *DS,
                                      bool InCoroContext,
                                      AddrDbgInstrKind AddrDInstKind) {
  static_cast<IRGenDebugInfoImpl *>(this)->emitDbgIntrinsic(
      Builder, Storage, Var, Expr, Line, Col, Scope, DS, InCoroContext,
      AddrDInstKind);
}

void IRGenDebugInfo::emitGlobalVariableDeclaration(
    llvm::GlobalVariable *Storage, StringRef Name, StringRef LinkageName,
    DebugTypeInfo DebugType, bool IsLocalToUnit,
    std::optional<SILLocation> Loc) {
  static_cast<IRGenDebugInfoImpl *>(this)->emitGlobalVariableDeclaration(
      Storage, Name, LinkageName, DebugType, IsLocalToUnit, Loc);
}

void IRGenDebugInfo::emitTypeMetadata(IRGenFunction &IGF, llvm::Value *Metadata,
                                      unsigned Depth, unsigned Index,
                                      StringRef Name) {
  static_cast<IRGenDebugInfoImpl *>(this)->emitTypeMetadata(IGF, Metadata,
                                                            Depth, Index, Name);
}

void IRGenDebugInfo::emitPackCountParameter(IRGenFunction &IGF,
                                            llvm::Value *Metadata,
                                            SILDebugVariable VarInfo) {
  static_cast<IRGenDebugInfoImpl *>(this)->emitPackCountParameter(IGF, Metadata,
                                                                  VarInfo);
}

void IRGenDebugInfo::emitExistentialPayloadType(swift::Type Ty) {
  static_cast<IRGenDebugInfoImpl *>(this)->emitExistentialPayloadType(Ty);
}

llvm::DIBuilder &IRGenDebugInfo::getBuilder() {
  return static_cast<IRGenDebugInfoImpl *>(this)->getBuilder();
}

AutoRestoreLocation::AutoRestoreLocation(IRGenDebugInfo *DI, IRBuilder &Builder)
    : DI(DI), Builder(Builder) {
  if (DI)
    SavedLocation = Builder.getCurrentDebugLocation();
}

/// Autorestore everything back to normal.
AutoRestoreLocation::~AutoRestoreLocation() {
  if (DI)
    Builder.SetCurrentDebugLocation(SavedLocation);
}

ArtificialLocation::ArtificialLocation(const SILDebugScope *DS,
                                       IRGenDebugInfo *DI, IRBuilder &Builder)
    : AutoRestoreLocation(DI, Builder) {
  if (DI) {
    unsigned Line = 0;
    auto *Scope = DI->getOrCreateScope(DS);
    auto DII = static_cast<IRGenDebugInfoImpl *>(DI);
    if (DII->getDebugInfoFormat() == IRGenDebugInfoFormat::CodeView) {
      // In CodeView, line zero is not an artificial line location and so we
      // try to use the location of the scope.
      if (auto *LB = dyn_cast<llvm::DILexicalBlock>(Scope))
        Line = LB->getLine();
      else if (auto *SP = dyn_cast<llvm::DISubprogram>(Scope))
        Line = SP->getLine();
    }
    auto DL = llvm::DILocation::get(Scope->getContext(), Line, 0, Scope,
                                    DII->createInlinedAt(DS));
    Builder.SetCurrentDebugLocation(DL);
  }
}

PrologueLocation::PrologueLocation(IRGenDebugInfo *DI, IRBuilder &Builder)
    : AutoRestoreLocation(DI, Builder) {
  if (DI)
    DI->clearLoc(Builder);
}
