//===--- CGDebugInfo.cpp - Emit Debug Information for a Module ------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This coordinates the debug information generation while generating code.
//
//===----------------------------------------------------------------------===//

#include "CGDebugInfo.h"
#include "CGBlocks.h"
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "ConstantEmitter.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/LambdaCapture.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/VTableBuilder.h"
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SHA1.h"
#include "llvm/Support/SHA256.h"
#include "llvm/Support/TimeProfiler.h"
#include <cstdint>
#include <optional>
using namespace clang;
using namespace clang::CodeGen;

static SourceLocation getMacroDebugLoc(const CodeGenModule &CGM,
                                       SourceLocation Loc) {
  if (CGM.getCodeGenOpts().DebugInfoMacroExpansionLoc)
    return Loc;
  return CGM.getContext().getSourceManager().getFileLoc(Loc);
}

static uint32_t getTypeAlignIfRequired(const Type *Ty, const ASTContext &Ctx) {
  auto TI = Ctx.getTypeInfo(Ty);
  if (TI.isAlignRequired())
    return TI.Align;

  // MaxFieldAlignmentAttr is the attribute added to types
  // declared after #pragma pack(n).
  if (auto *Decl = Ty->getAsRecordDecl())
    if (Decl->hasAttr<MaxFieldAlignmentAttr>())
      return TI.Align;

  return 0;
}

static uint32_t getTypeAlignIfRequired(QualType Ty, const ASTContext &Ctx) {
  return getTypeAlignIfRequired(Ty.getTypePtr(), Ctx);
}

static uint32_t getDeclAlignIfRequired(const Decl *D, const ASTContext &Ctx) {
  return D->hasAttr<AlignedAttr>() ? D->getMaxAlignment() : 0;
}

/// Returns true if \ref VD is a a holding variable (aka a
/// VarDecl retrieved using \ref BindingDecl::getHoldingVar).
static bool IsDecomposedVarDecl(VarDecl const *VD) {
  auto const *Init = VD->getInit();
  if (!Init)
    return false;

  auto const *RefExpr =
      llvm::dyn_cast_or_null<DeclRefExpr>(Init->IgnoreUnlessSpelledInSource());
  if (!RefExpr)
    return false;

  return llvm::dyn_cast_or_null<DecompositionDecl>(RefExpr->getDecl());
}

/// Returns true if \ref VD is a compiler-generated variable
/// and should be treated as artificial for the purposes
/// of debug-info generation.
static bool IsArtificial(VarDecl const *VD) {
  // Tuple-like bindings are marked as implicit despite
  // being spelled out in source. Don't treat them as artificial
  // variables.
  if (IsDecomposedVarDecl(VD))
    return false;

  return VD->isImplicit() || (isa<Decl>(VD->getDeclContext()) &&
                              cast<Decl>(VD->getDeclContext())->isImplicit());
}

/// Returns \c true if the specified variable \c VD is an explicit parameter of
/// a synthesized Objective-C property accessor. E.g., a synthesized property
/// setter method will have a single explicit parameter which is the property to
/// set.
static bool IsObjCSynthesizedPropertyExplicitParameter(VarDecl const *VD) {
  assert(VD);

  if (!llvm::isa<ParmVarDecl>(VD))
    return false;

  // Not a property method.
  const auto *Method =
      llvm::dyn_cast_or_null<ObjCMethodDecl>(VD->getDeclContext());
  if (!Method)
    return false;

  // Not a synthesized property accessor.
  if (!Method->isImplicit() || !Method->isPropertyAccessor())
    return false;

  // Not an explicit parameter.
  if (VD->isImplicit())
    return false;

  return true;
}

CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
    : CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()),
      DebugTypeExtRefs(CGM.getCodeGenOpts().DebugTypeExtRefs),
      DBuilder(CGM.getModule()) {
  CreateCompileUnit();
}

CGDebugInfo::~CGDebugInfo() {
  assert(LexicalBlockStack.empty() &&
         "Region stack mismatch, stack not empty!");
}

void CGDebugInfo::addInstSourceAtomMetadata(llvm::Instruction *I,
                                            uint64_t Group, uint8_t Rank) {
  if (!I->getDebugLoc() || Group == 0 || !I->getDebugLoc()->getLine())
    return;

  // Saturate the 3-bit rank.
  Rank = std::min<uint8_t>(Rank, 7);

  const llvm::DebugLoc &DL = I->getDebugLoc();

  // Each instruction can only be attributed to one source atom (a limitation of
  // the implementation). If this instruction is already part of a source atom,
  // pick the group in which it has highest precedence (lowest rank).
  if (DL->getAtomGroup() && DL->getAtomRank() && DL->getAtomRank() < Rank) {
    Group = DL->getAtomGroup();
    Rank = DL->getAtomRank();
  }

  // Update the function-local watermark so we don't reuse this number for
  // another atom.
  KeyInstructionsInfo.HighestEmittedAtom =
      std::max(Group, KeyInstructionsInfo.HighestEmittedAtom);

  // Apply the new DILocation to the instruction.
  llvm::DILocation *NewDL = llvm::DILocation::get(
      I->getContext(), DL.getLine(), DL.getCol(), DL.getScope(),
      DL.getInlinedAt(), DL.isImplicitCode(), Group, Rank);
  I->setDebugLoc(NewDL);
}

void CGDebugInfo::addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction,
                                             llvm::Value *Backup) {
  addInstToSpecificSourceAtom(KeyInstruction, Backup,
                              KeyInstructionsInfo.CurrentAtom);
}

void CGDebugInfo::addInstToSpecificSourceAtom(llvm::Instruction *KeyInstruction,
                                              llvm::Value *Backup,
                                              uint64_t Group) {
  if (!Group || !CGM.getCodeGenOpts().DebugKeyInstructions)
    return;

  llvm::DISubprogram *SP = KeyInstruction->getFunction()->getSubprogram();
  if (!SP || !SP->getKeyInstructionsEnabled())
    return;

  addInstSourceAtomMetadata(KeyInstruction, Group, /*Rank=*/1);

  llvm::Instruction *BackupI =
      llvm::dyn_cast_or_null<llvm::Instruction>(Backup);
  if (!BackupI)
    return;

  // Add the backup instruction to the group.
  addInstSourceAtomMetadata(BackupI, Group, /*Rank=*/2);

  // Look through chains of casts too, as they're probably going to evaporate.
  // FIXME: And other nops like zero length geps?
  // FIXME: Should use Cast->isNoopCast()?
  uint8_t Rank = 3;
  while (auto *Cast = dyn_cast<llvm::CastInst>(BackupI)) {
    BackupI = dyn_cast<llvm::Instruction>(Cast->getOperand(0));
    if (!BackupI)
      break;
    addInstSourceAtomMetadata(BackupI, Group, Rank++);
  }
}

void CGDebugInfo::completeFunction() {
  // Reset the atom group number tracker as the numbers are function-local.
  KeyInstructionsInfo.NextAtom = 1;
  KeyInstructionsInfo.HighestEmittedAtom = 0;
  KeyInstructionsInfo.CurrentAtom = 0;
}

ApplyAtomGroup::ApplyAtomGroup(CGDebugInfo *DI) : DI(DI) {
  if (!DI)
    return;
  OriginalAtom = DI->KeyInstructionsInfo.CurrentAtom;
  DI->KeyInstructionsInfo.CurrentAtom = DI->KeyInstructionsInfo.NextAtom++;
}

ApplyAtomGroup::~ApplyAtomGroup() {
  if (!DI)
    return;

  // We may not have used the group number at all.
  DI->KeyInstructionsInfo.NextAtom =
      std::min(DI->KeyInstructionsInfo.HighestEmittedAtom + 1,
               DI->KeyInstructionsInfo.NextAtom);

  DI->KeyInstructionsInfo.CurrentAtom = OriginalAtom;
}

ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF,
                                       SourceLocation TemporaryLocation)
    : CGF(&CGF) {
  init(TemporaryLocation);
}

ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF,
                                       bool DefaultToEmpty,
                                       SourceLocation TemporaryLocation)
    : CGF(&CGF) {
  init(TemporaryLocation, DefaultToEmpty);
}

void ApplyDebugLocation::init(SourceLocation TemporaryLocation,
                              bool DefaultToEmpty) {
  auto *DI = CGF->getDebugInfo();
  if (!DI) {
    CGF = nullptr;
    return;
  }

  OriginalLocation = CGF->Builder.getCurrentDebugLocation();

  if (OriginalLocation && !DI->CGM.getExpressionLocationsEnabled())
    return;

  if (TemporaryLocation.isValid()) {
    DI->EmitLocation(CGF->Builder, TemporaryLocation);
    return;
  }

  if (DefaultToEmpty) {
    CGF->Builder.SetCurrentDebugLocation(llvm::DebugLoc());
    return;
  }

  // Construct a location that has a valid scope, but no line info.
  assert(!DI->LexicalBlockStack.empty());
  CGF->Builder.SetCurrentDebugLocation(
      llvm::DILocation::get(DI->LexicalBlockStack.back()->getContext(), 0, 0,
                            DI->LexicalBlockStack.back(), DI->getInlinedAt()));
}

ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF, const Expr *E)
    : CGF(&CGF) {
  init(E->getExprLoc());
}

ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF, llvm::DebugLoc Loc)
    : CGF(&CGF) {
  if (!CGF.getDebugInfo()) {
    this->CGF = nullptr;
    return;
  }
  OriginalLocation = CGF.Builder.getCurrentDebugLocation();
  if (Loc) {
    // Key Instructions: drop the atom group and rank to avoid accidentally
    // propagating it around.
    if (Loc->getAtomGroup())
      Loc = llvm::DILocation::get(Loc->getContext(), Loc.getLine(),
                                  Loc->getColumn(), Loc->getScope(),
                                  Loc->getInlinedAt(), Loc.isImplicitCode());
    CGF.Builder.SetCurrentDebugLocation(std::move(Loc));
  }
}

ApplyDebugLocation::~ApplyDebugLocation() {
  // Query CGF so the location isn't overwritten when location updates are
  // temporarily disabled (for C++ default function arguments)
  if (CGF)
    CGF->Builder.SetCurrentDebugLocation(std::move(OriginalLocation));
}

ApplyInlineDebugLocation::ApplyInlineDebugLocation(CodeGenFunction &CGF,
                                                   GlobalDecl InlinedFn)
    : CGF(&CGF) {
  if (!CGF.getDebugInfo()) {
    this->CGF = nullptr;
    return;
  }
  auto &DI = *CGF.getDebugInfo();
  SavedLocation = DI.getLocation();
  assert((DI.getInlinedAt() ==
          CGF.Builder.getCurrentDebugLocation()->getInlinedAt()) &&
         "CGDebugInfo and IRBuilder are out of sync");

  DI.EmitInlineFunctionStart(CGF.Builder, InlinedFn);
}

ApplyInlineDebugLocation::~ApplyInlineDebugLocation() {
  if (!CGF)
    return;
  auto &DI = *CGF->getDebugInfo();
  DI.EmitInlineFunctionEnd(CGF->Builder);
  DI.EmitLocation(CGF->Builder, SavedLocation);
}

void CGDebugInfo::setLocation(SourceLocation Loc) {
  // If the new location isn't valid return.
  if (Loc.isInvalid())
    return;

  SourceManager &SM = CGM.getContext().getSourceManager();
  SourceLocation NewLoc = SM.getExpansionLoc(getMacroDebugLoc(CGM, Loc));
  if (CurLoc != NewLoc) {
    CurLoc = NewLoc;
    CurLocFile = nullptr;
    CurLocLine = 0;
    CurLocColumn = 0;

    PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc);
    if (PCLoc.isInvalid())
      return;

    CurLocLine = PCLoc.getLine();
    if (CGM.getCodeGenOpts().DebugColumnInfo)
      CurLocColumn = PCLoc.getColumn();
    CurLocFile = getOrCreateFile(CurLoc);
  }

  // If we've changed files in the middle of a lexical scope go ahead
  // and create a new lexical scope with file node if it's different
  // from the one in the scope.
  if (LexicalBlockStack.empty())
    return;

  auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back());
  if (!CurLocFile || Scope->getFile() == CurLocFile)
    return;

  if (auto *LBF = dyn_cast<llvm::DILexicalBlockFile>(Scope)) {
    LexicalBlockStack.pop_back();
    LexicalBlockStack.emplace_back(
        DBuilder.createLexicalBlockFile(LBF->getScope(), CurLocFile));
  } else if (isa<llvm::DILexicalBlock>(Scope) ||
             isa<llvm::DISubprogram>(Scope)) {
    LexicalBlockStack.pop_back();
    LexicalBlockStack.emplace_back(
        DBuilder.createLexicalBlockFile(Scope, CurLocFile));
  }
}

llvm::DIScope *CGDebugInfo::getDeclContextDescriptor(const Decl *D) {
  llvm::DIScope *Mod = getParentModuleOrNull(D);
  return getContextDescriptor(cast<Decl>(D->getDeclContext()),
                              Mod ? Mod : TheCU);
}

llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context,
                                                 llvm::DIScope *Default) {
  if (!Context)
    return Default;

  auto I = RegionMap.find(Context);
  if (I != RegionMap.end()) {
    llvm::Metadata *V = I->second;
    return dyn_cast_or_null<llvm::DIScope>(V);
  }

  // Check namespace.
  if (const auto *NSDecl = dyn_cast<NamespaceDecl>(Context))
    return getOrCreateNamespace(NSDecl);

  if (const auto *RDecl = dyn_cast<RecordDecl>(Context))
    if (!RDecl->isDependentType())
      return getOrCreateType(CGM.getContext().getCanonicalTagType(RDecl),
                             TheCU->getFile());
  return Default;
}

PrintingPolicy CGDebugInfo::getPrintingPolicy() const {
  PrintingPolicy PP = CGM.getContext().getPrintingPolicy();

  // If we're emitting codeview, it's important to try to match MSVC's naming so
  // that visualizers written for MSVC will trigger for our class names. In
  // particular, we can't have spaces between arguments of standard templates
  // like basic_string and vector, but we must have spaces between consecutive
  // angle brackets that close nested template argument lists.
  if (CGM.getCodeGenOpts().EmitCodeView) {
    PP.MSVCFormatting = true;
    PP.SplitTemplateClosers = true;
  } else {
    // For DWARF, printing rules are underspecified.
    // SplitTemplateClosers yields better interop with GCC and GDB (PR46052).
    PP.SplitTemplateClosers = true;
  }

  PP.SuppressInlineNamespace =
      llvm::to_underlying(PrintingPolicy::SuppressInlineNamespaceMode::None);
  PP.PrintAsCanonical = true;
  PP.UsePreferredNames = false;
  PP.AlwaysIncludeTypeForTemplateArgument = true;
  PP.UseEnumerators = false;
  PP.PrettyEnums = false;

  // Apply -fdebug-prefix-map.
  PP.Callbacks = &PrintCB;
  return PP;
}

StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD,
                                       bool *NameIsSimplified) {
  return internString(GetName(FD, false, NameIsSimplified));
}

StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {
  SmallString<256> MethodName;
  llvm::raw_svector_ostream OS(MethodName);
  OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
  const DeclContext *DC = OMD->getDeclContext();
  if (const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) {
    OS << OID->getName();
  } else if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) {
    OS << OID->getName();
  } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
    if (OC->IsClassExtension()) {
      OS << OC->getClassInterface()->getName();
    } else {
      OS << OC->getIdentifier()->getNameStart() << '('
         << OC->getIdentifier()->getNameStart() << ')';
    }
  } else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
    OS << OCD->getClassInterface()->getName() << '(' << OCD->getName() << ')';
  }
  OS << ' ' << OMD->getSelector().getAsString() << ']';

  return internString(OS.str());
}

StringRef CGDebugInfo::getSelectorName(Selector S) {
  return internString(S.getAsString());
}

StringRef CGDebugInfo::getClassName(const RecordDecl *RD,
                                    bool *NameIsSimplified) {
  if (isa<ClassTemplateSpecializationDecl>(RD)) {
    // Copy this name on the side and use its reference.
    return internString(GetName(RD, false, NameIsSimplified));
  }

  // quick optimization to avoid having to intern strings that are already
  // stored reliably elsewhere
  if (const IdentifierInfo *II = RD->getIdentifier())
    return II->getName();

  // The CodeView printer in LLVM wants to see the names of unnamed types
  // because they need to have a unique identifier.
  // These names are used to reconstruct the fully qualified type names.
  if (CGM.getCodeGenOpts().EmitCodeView) {
    if (const TypedefNameDecl *D = RD->getTypedefNameForAnonDecl()) {
      assert(RD->getDeclContext() == D->getDeclContext() &&
             "Typedef should not be in another decl context!");
      assert(D->getDeclName().getAsIdentifierInfo() &&
             "Typedef was not named!");
      return D->getDeclName().getAsIdentifierInfo()->getName();
    }

    if (CGM.getLangOpts().CPlusPlus) {
      StringRef Name;

      ASTContext &Context = CGM.getContext();
      if (const DeclaratorDecl *DD = Context.getDeclaratorForUnnamedTagDecl(RD))
        // Anonymous types without a name for linkage purposes have their
        // declarator mangled in if they have one.
        Name = DD->getName();
      else if (const TypedefNameDecl *TND =
                   Context.getTypedefNameForUnnamedTagDecl(RD))
        // Anonymous types without a name for linkage purposes have their
        // associate typedef mangled in if they have one.
        Name = TND->getName();

      // Give lambdas a display name based on their name mangling.
      if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
        if (CXXRD->isLambda())
          return internString(
              CGM.getCXXABI().getMangleContext().getLambdaString(CXXRD));

      if (!Name.empty()) {
        SmallString<256> UnnamedType("<unnamed-type-");
        UnnamedType += Name;
        UnnamedType += '>';
        return internString(UnnamedType);
      }
    }
  }

  return StringRef();
}

std::optional<llvm::DIFile::ChecksumKind>
CGDebugInfo::computeChecksum(FileID FID, SmallString<64> &Checksum) const {
  Checksum.clear();

  if (!CGM.getCodeGenOpts().EmitCodeView &&
      CGM.getCodeGenOpts().DwarfVersion < 5)
    return std::nullopt;

  SourceManager &SM = CGM.getContext().getSourceManager();
  std::optional<llvm::MemoryBufferRef> MemBuffer = SM.getBufferOrNone(FID);
  if (!MemBuffer)
    return std::nullopt;

  auto Data = llvm::arrayRefFromStringRef(MemBuffer->getBuffer());
  switch (CGM.getCodeGenOpts().getDebugSrcHash()) {
  case clang::CodeGenOptions::DSH_MD5:
    llvm::toHex(llvm::MD5::hash(Data), /*LowerCase=*/true, Checksum);
    return llvm::DIFile::CSK_MD5;
  case clang::CodeGenOptions::DSH_SHA1:
    llvm::toHex(llvm::SHA1::hash(Data), /*LowerCase=*/true, Checksum);
    return llvm::DIFile::CSK_SHA1;
  case clang::CodeGenOptions::DSH_SHA256:
    llvm::toHex(llvm::SHA256::hash(Data), /*LowerCase=*/true, Checksum);
    return llvm::DIFile::CSK_SHA256;
  case clang::CodeGenOptions::DSH_NONE:
    return std::nullopt;
  }
  llvm_unreachable("Unhandled DebugSrcHashKind enum");
}

std::optional<StringRef> CGDebugInfo::getSource(const SourceManager &SM,
                                                FileID FID) {
  if (!CGM.getCodeGenOpts().EmbedSource)
    return std::nullopt;

  bool SourceInvalid = false;
  StringRef Source = SM.getBufferData(FID, &SourceInvalid);

  if (SourceInvalid)
    return std::nullopt;

  return Source;
}

llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
  SourceManager &SM = CGM.getContext().getSourceManager();
  StringRef FileName;
  FileID FID;
  std::optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo;

  if (Loc.isInvalid()) {
    // The DIFile used by the CU is distinct from the main source file. Call
    // createFile() below for canonicalization if the source file was specified
    // with an absolute path.
    FileName = TheCU->getFile()->getFilename();
    CSInfo = TheCU->getFile()->getChecksum();
  } else {
    Loc = getMacroDebugLoc(CGM, Loc);
    if (Loc == CurLoc && CurLocFile)
      return CurLocFile;

    PresumedLoc PLoc = SM.getPresumedLoc(Loc);
    FileName = PLoc.getFilename();

    if (FileName.empty()) {
      FileName = TheCU->getFile()->getFilename();
    } else {
      FileName = PLoc.getFilename();
    }
    FID = PLoc.getFileID();
  }

  // Cache the results.
  auto It = DIFileCache.find(FileName.data());
  if (It != DIFileCache.end()) {
    // Verify that the information still exists.
    if (llvm::Metadata *V = It->second)
      return cast<llvm::DIFile>(V);
  }

  // Put Checksum at a scope where it will persist past the createFile call.
  SmallString<64> Checksum;
  if (!CSInfo) {
    std::optional<llvm::DIFile::ChecksumKind> CSKind =
      computeChecksum(FID, Checksum);
    if (CSKind)
      CSInfo.emplace(*CSKind, Checksum);
  }
  return createFile(FileName, CSInfo,
                    getSource(SM, SM.getFileID(getMacroDebugLoc(CGM, Loc))));
}

llvm::DIFile *CGDebugInfo::createFile(
    StringRef FileName,
    std::optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo,
    std::optional<StringRef> Source) {
  StringRef Dir;
  StringRef File;
  std::string RemappedFile = remapDIPath(FileName);
  std::string CurDir = remapDIPath(getCurrentDirname());
  SmallString<128> DirBuf;
  SmallString<128> FileBuf;
  if (llvm::sys::path::is_absolute(RemappedFile)) {
    // Strip the common prefix (if it is more than just "/" or "C:\") from
    // current directory and FileName for a more space-efficient encoding.
    auto FileIt = llvm::sys::path::begin(RemappedFile);
    auto FileE = llvm::sys::path::end(RemappedFile);
    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 (llvm::sys::path::root_path(DirBuf) == DirBuf) {
      // Don't strip the common prefix if it is only the root ("/" or "C:\")
      // since that would make LLVM diagnostic locations confusing.
      Dir = {};
      File = RemappedFile;
    } else {
      for (; FileIt != FileE; ++FileIt)
        llvm::sys::path::append(FileBuf, *FileIt);
      Dir = DirBuf;
      File = FileBuf;
    }
  } else {
    if (!llvm::sys::path::is_absolute(FileName))
      Dir = CurDir;
    File = RemappedFile;
  }
  llvm::DIFile *F = DBuilder.createFile(File, Dir, CSInfo, Source);
  DIFileCache[FileName.data()].reset(F);
  return F;
}

std::string CGDebugInfo::remapDIPath(StringRef Path) const {
  SmallString<256> P = Path;
  for (auto &[From, To] : llvm::reverse(CGM.getCodeGenOpts().DebugPrefixMap))
    if (llvm::sys::path::replace_path_prefix(P, From, To))
      break;
  return P.str().str();
}

unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) {
  if (Loc.isInvalid())
    return 0;
  SourceManager &SM = CGM.getContext().getSourceManager();
  SourceLocation DebugLoc = getMacroDebugLoc(CGM, Loc);
  if (DebugLoc == CurLoc)
    return CurLocLine;
  return SM.getPresumedLoc(DebugLoc).getLine();
}

unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc) {
  // We may not want column information at all.
  if (!CGM.getCodeGenOpts().DebugColumnInfo)
    return 0;

  // If the location is invalid then use the current column.
  if (Loc.isInvalid() && CurLoc.isInvalid())
    return 0;
  SourceManager &SM = CGM.getContext().getSourceManager();
  SourceLocation DebugLoc = Loc.isValid() ? getMacroDebugLoc(CGM, Loc) : CurLoc;
  if (DebugLoc == CurLoc)
    return CurLocColumn;
  PresumedLoc PLoc = SM.getPresumedLoc(DebugLoc);
  return PLoc.isValid() ? PLoc.getColumn() : 0;
}

StringRef CGDebugInfo::getCurrentDirname() {
  return CGM.getCodeGenOpts().DebugCompilationDir;
}

static llvm::dwarf::SourceLanguage GetSourceLanguage(const CodeGenModule &CGM) {
  const CodeGenOptions &CGO = CGM.getCodeGenOpts();
  const LangOptions &LO = CGM.getLangOpts();

  assert(CGO.DwarfVersion <= 5);

  llvm::dwarf::SourceLanguage LangTag;
  if (LO.CPlusPlus) {
    if (LO.HLSL)
      LangTag = llvm::dwarf::DW_LANG_HLSL;
    else if (LO.HIP)
      LangTag = llvm::dwarf::DW_LANG_HIP;
    else if (LO.ObjC)
      LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;
    else if (CGO.DebugStrictDwarf && CGO.DwarfVersion < 5)
      LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
    else if (LO.CPlusPlus14)
      LangTag = llvm::dwarf::DW_LANG_C_plus_plus_14;
    else if (LO.CPlusPlus11)
      LangTag = llvm::dwarf::DW_LANG_C_plus_plus_11;
    else
      LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
  } else if (LO.ObjC) {
    LangTag = llvm::dwarf::DW_LANG_ObjC;
  } else if (LO.OpenCL && (!CGO.DebugStrictDwarf || CGO.DwarfVersion >= 5)) {
    LangTag = llvm::dwarf::DW_LANG_OpenCL;
  } else if (LO.C11 && !(CGO.DebugStrictDwarf && CGO.DwarfVersion < 5)) {
    LangTag = llvm::dwarf::DW_LANG_C11;
  } else if (LO.C99) {
    LangTag = llvm::dwarf::DW_LANG_C99;
  } else {
    LangTag = llvm::dwarf::DW_LANG_C89;
  }

  return LangTag;
}

static llvm::DISourceLanguageName
GetDISourceLanguageName(const CodeGenModule &CGM) {
  // Emit pre-DWARFv6 language codes.
  if (CGM.getCodeGenOpts().DwarfVersion < 6)
    return llvm::DISourceLanguageName(GetSourceLanguage(CGM));

  const LangOptions &LO = CGM.getLangOpts();

  uint32_t LangVersion = 0;
  llvm::dwarf::SourceLanguageName LangTag;
  if (LO.CPlusPlus) {
    if (LO.HLSL) {
      LangTag = llvm::dwarf::DW_LNAME_HLSL;
    } else if (LO.HIP) {
      LangTag = llvm::dwarf::DW_LNAME_HIP;
    } else if (LO.ObjC) {
      LangTag = llvm::dwarf::DW_LNAME_ObjC_plus_plus;
    } else {
      LangTag = llvm::dwarf::DW_LNAME_C_plus_plus;
      LangVersion = LO.getCPlusPlusLangStd().value_or(0);
    }
  } else if (LO.ObjC) {
    LangTag = llvm::dwarf::DW_LNAME_ObjC;
  } else if (LO.OpenCL) {
    LangTag = llvm::dwarf::DW_LNAME_OpenCL_C;
  } else {
    LangTag = llvm::dwarf::DW_LNAME_C;
    LangVersion = LO.getCLangStd().value_or(0);
  }

  return llvm::DISourceLanguageName(LangTag, LangVersion);
}

void CGDebugInfo::CreateCompileUnit() {
  SmallString<64> Checksum;
  std::optional<llvm::DIFile::ChecksumKind> CSKind;
  std::optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo;

  // Should we be asking the SourceManager for the main file name, instead of
  // accepting it as an argument? This just causes the main file name to
  // mismatch with source locations and create extra lexical scopes or
  // mismatched debug info (a CU with a DW_AT_file of "-", because that's what
  // the driver passed, but functions/other things have DW_AT_file of "<stdin>"
  // because that's what the SourceManager says)

  // Get absolute path name.
  SourceManager &SM = CGM.getContext().getSourceManager();
  auto &CGO = CGM.getCodeGenOpts();
  const LangOptions &LO = CGM.getLangOpts();
  std::string MainFileName = CGO.MainFileName;
  if (MainFileName.empty())
    MainFileName = "<stdin>";

  // The main file name provided via the "-main-file-name" option contains just
  // the file name itself with no path information. This file name may have had
  // a relative path, so we look into the actual file entry for the main
  // file to determine the real absolute path for the file.
  std::string MainFileDir;
  if (OptionalFileEntryRef MainFile =
          SM.getFileEntryRefForID(SM.getMainFileID())) {
    MainFileDir = std::string(MainFile->getDir().getName());
    if (!llvm::sys::path::is_absolute(MainFileName)) {
      llvm::SmallString<1024> MainFileDirSS(MainFileDir);
      llvm::sys::path::Style Style =
          LO.UseTargetPathSeparator
              ? (CGM.getTarget().getTriple().isOSWindows()
                     ? llvm::sys::path::Style::windows_backslash
                     : llvm::sys::path::Style::posix)
              : llvm::sys::path::Style::native;
      llvm::sys::path::append(MainFileDirSS, Style, MainFileName);
      MainFileName = std::string(
          llvm::sys::path::remove_leading_dotslash(MainFileDirSS, Style));
    }
    // If the main file name provided is identical to the input file name, and
    // if the input file is a preprocessed source, use the module name for
    // debug info. The module name comes from the name specified in the first
    // linemarker if the input is a preprocessed source. In this case we don't
    // know the content to compute a checksum.
    if (MainFile->getName() == MainFileName &&
        FrontendOptions::getInputKindForExtension(
            MainFile->getName().rsplit('.').second)
            .isPreprocessed()) {
      MainFileName = CGM.getModule().getName().str();
    } else {
      CSKind = computeChecksum(SM.getMainFileID(), Checksum);
    }
  }

  std::string Producer = getClangFullVersion();

  // Figure out which version of the ObjC runtime we have.
  unsigned RuntimeVers = 0;
  if (LO.ObjC)
    RuntimeVers = LO.ObjCRuntime.isNonFragile() ? 2 : 1;

  llvm::DICompileUnit::DebugEmissionKind EmissionKind;
  switch (DebugKind) {
  case llvm::codegenoptions::NoDebugInfo:
  case llvm::codegenoptions::LocTrackingOnly:
    EmissionKind = llvm::DICompileUnit::NoDebug;
    break;
  case llvm::codegenoptions::DebugLineTablesOnly:
    EmissionKind = llvm::DICompileUnit::LineTablesOnly;
    break;
  case llvm::codegenoptions::DebugDirectivesOnly:
    EmissionKind = llvm::DICompileUnit::DebugDirectivesOnly;
    break;
  case llvm::codegenoptions::DebugInfoConstructor:
  case llvm::codegenoptions::LimitedDebugInfo:
  case llvm::codegenoptions::FullDebugInfo:
  case llvm::codegenoptions::UnusedTypeInfo:
    EmissionKind = llvm::DICompileUnit::FullDebug;
    break;
  }

  uint64_t DwoId = 0;
  auto &CGOpts = CGM.getCodeGenOpts();
  // The DIFile used by the CU is distinct from the main source
  // file. Its directory part specifies what becomes the
  // DW_AT_comp_dir (the compilation directory), even if the source
  // file was specified with an absolute path.
  if (CSKind)
    CSInfo.emplace(*CSKind, Checksum);
  llvm::DIFile *CUFile = DBuilder.createFile(
      remapDIPath(MainFileName), remapDIPath(getCurrentDirname()), CSInfo,
      getSource(SM, SM.getMainFileID()));

  StringRef Sysroot, SDK;
  if (CGM.getCodeGenOpts().getDebuggerTuning() == llvm::DebuggerKind::LLDB) {
    StringRef FullSysroot = CGM.getHeaderSearchOpts().Sysroot;
    if (CGM.getCodeGenOpts().DebugRecordSysroot)
      Sysroot = FullSysroot;
    auto B = llvm::sys::path::rbegin(FullSysroot);
    auto E = llvm::sys::path::rend(FullSysroot);
    auto It =
        std::find_if(B, E, [](auto SDK) { return SDK.ends_with(".sdk"); });
    if (It != E)
      SDK = *It;
  }

  llvm::DICompileUnit::DebugNameTableKind NameTableKind =
      static_cast<llvm::DICompileUnit::DebugNameTableKind>(
          CGOpts.DebugNameTable);
  if (CGM.getTarget().getTriple().isNVPTX())
    NameTableKind = llvm::DICompileUnit::DebugNameTableKind::None;
  else if (CGM.getTarget().getTriple().getVendor() == llvm::Triple::Apple)
    NameTableKind = llvm::DICompileUnit::DebugNameTableKind::Apple;

  // Create new compile unit.
  TheCU = DBuilder.createCompileUnit(
      GetDISourceLanguageName(CGM), CUFile,
      CGOpts.EmitVersionIdentMetadata ? Producer : "",
      CGOpts.OptimizationLevel != 0 || CGOpts.PrepareForLTO ||
          CGOpts.PrepareForThinLTO,
      CGOpts.DwarfDebugFlags, RuntimeVers, CGOpts.SplitDwarfFile, EmissionKind,
      DwoId, CGOpts.SplitDwarfInlining, CGOpts.DebugInfoForProfiling,
      NameTableKind, CGOpts.DebugRangesBaseAddress, remapDIPath(Sysroot), SDK);
}

llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
  llvm::dwarf::TypeKind Encoding;
  StringRef BTName;
  switch (BT->getKind()) {
#define BUILTIN_TYPE(Id, SingletonId)
#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
#include "clang/AST/BuiltinTypes.def"
  case BuiltinType::Dependent:
    llvm_unreachable("Unexpected builtin type");
  case BuiltinType::NullPtr:
    return DBuilder.createNullPtrType();
  case BuiltinType::Void:
    return nullptr;
  case BuiltinType::ObjCClass:
    if (!ClassTy)
      ClassTy =
          DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
                                     "objc_class", TheCU, TheCU->getFile(), 0);
    return ClassTy;
  case BuiltinType::ObjCId: {
    // typedef struct objc_class *Class;
    // typedef struct objc_object {
    //  Class isa;
    // } *id;

    if (ObjTy)
      return ObjTy;

    if (!ClassTy)
      ClassTy =
          DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
                                     "objc_class", TheCU, TheCU->getFile(), 0);

    unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);

    auto *ISATy = DBuilder.createPointerType(ClassTy, Size);

    ObjTy = DBuilder.createStructType(TheCU, "objc_object", TheCU->getFile(), 0,
                                      (uint64_t)0, 0, llvm::DINode::FlagZero,
                                      nullptr, llvm::DINodeArray());

    DBuilder.replaceArrays(
        ObjTy, DBuilder.getOrCreateArray(&*DBuilder.createMemberType(
                   ObjTy, "isa", TheCU->getFile(), 0, Size, 0, 0,
                   llvm::DINode::FlagZero, ISATy)));
    return ObjTy;
  }
  case BuiltinType::ObjCSel: {
    if (!SelTy)
      SelTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
                                         "objc_selector", TheCU,
                                         TheCU->getFile(), 0);
    return SelTy;
  }

#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix)                   \
  case BuiltinType::Id:                                                        \
    return getOrCreateStructPtrType("opencl_" #ImgType "_" #Suffix "_t",       \
                                    SingletonId);
#include "clang/Basic/OpenCLImageTypes.def"
  case BuiltinType::OCLSampler:
    return getOrCreateStructPtrType("opencl_sampler_t", OCLSamplerDITy);
  case BuiltinType::OCLEvent:
    return getOrCreateStructPtrType("opencl_event_t", OCLEventDITy);
  case BuiltinType::OCLClkEvent:
    return getOrCreateStructPtrType("opencl_clk_event_t", OCLClkEventDITy);
  case BuiltinType::OCLQueue:
    return getOrCreateStructPtrType("opencl_queue_t", OCLQueueDITy);
  case BuiltinType::OCLReserveID:
    return getOrCreateStructPtrType("opencl_reserve_id_t", OCLReserveIDDITy);
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
  case BuiltinType::Id: \
    return getOrCreateStructPtrType("opencl_" #ExtType, Id##Ty);
#include "clang/Basic/OpenCLExtensionTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId)                            \
  case BuiltinType::Id:                                                        \
    return getOrCreateStructPtrType(#Name, SingletonId);
#include "clang/Basic/HLSLIntangibleTypes.def"

#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/AArch64ACLETypes.def"
    {
      if (BT->getKind() == BuiltinType::MFloat8) {
        Encoding = llvm::dwarf::DW_ATE_unsigned_char;
        BTName = BT->getName(CGM.getLangOpts());
        // Bit size and offset of the type.
        uint64_t Size = CGM.getContext().getTypeSize(BT);
        return DBuilder.createBasicType(BTName, Size, Encoding);
      }
      ASTContext::BuiltinVectorTypeInfo Info =
          // For svcount_t, only the lower 2 bytes are relevant.
          BT->getKind() == BuiltinType::SveCount
              ? ASTContext::BuiltinVectorTypeInfo(
                    CGM.getContext().BoolTy, llvm::ElementCount::getFixed(16),
                    1)
              : CGM.getContext().getBuiltinVectorTypeInfo(BT);

      // A single vector of bytes may not suffice as the representation of
      // svcount_t tuples because of the gap between the active 16bits of
      // successive tuple members. Currently no such tuples are defined for
      // svcount_t, so assert that NumVectors is 1.
      assert((BT->getKind() != BuiltinType::SveCount || Info.NumVectors == 1) &&
             "Unsupported number of vectors for svcount_t");

      unsigned NumElems = Info.EC.getKnownMinValue() * Info.NumVectors;
      llvm::Metadata *BitStride = nullptr;
      if (BT->getKind() == BuiltinType::SveBool) {
        Info.ElementType = CGM.getContext().UnsignedCharTy;
        BitStride = llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
            llvm::Type::getInt64Ty(CGM.getLLVMContext()), 1));
      } else if (BT->getKind() == BuiltinType::SveCount) {
        NumElems /= 8;
        Info.ElementType = CGM.getContext().UnsignedCharTy;
      }

      llvm::Metadata *LowerBound, *UpperBound;
      LowerBound = llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
          llvm::Type::getInt64Ty(CGM.getLLVMContext()), 0));
      if (Info.EC.isScalable()) {
        unsigned NumElemsPerVG = NumElems / 2;
        SmallVector<uint64_t, 9> Expr(
            {llvm::dwarf::DW_OP_constu, NumElemsPerVG, llvm::dwarf::DW_OP_bregx,
             /* AArch64::VG */ 46, 0, llvm::dwarf::DW_OP_mul,
             llvm::dwarf::DW_OP_constu, 1, llvm::dwarf::DW_OP_minus});
        UpperBound = DBuilder.createExpression(Expr);
      } else
        UpperBound = llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
            llvm::Type::getInt64Ty(CGM.getLLVMContext()), NumElems - 1));

      llvm::Metadata *Subscript = DBuilder.getOrCreateSubrange(
          /*count*/ nullptr, LowerBound, UpperBound, /*stride*/ nullptr);
      llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscript);
      llvm::DIType *ElemTy =
          getOrCreateType(Info.ElementType, TheCU->getFile());
      auto Align = getTypeAlignIfRequired(BT, CGM.getContext());
      return DBuilder.createVectorType(/*Size*/ 0, Align, ElemTy,
                                       SubscriptArray, BitStride);
    }
  // It doesn't make sense to generate debug info for PowerPC MMA vector types.
  // So we return a safe type here to avoid generating an error.
#define PPC_VECTOR_TYPE(Name, Id, size) \
  case BuiltinType::Id:
#include "clang/Basic/PPCTypes.def"
    return CreateType(cast<const BuiltinType>(CGM.getContext().IntTy));

#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/RISCVVTypes.def"
    {
      ASTContext::BuiltinVectorTypeInfo Info =
          CGM.getContext().getBuiltinVectorTypeInfo(BT);

      unsigned ElementCount = Info.EC.getKnownMinValue();
      unsigned SEW = CGM.getContext().getTypeSize(Info.ElementType);

      bool Fractional = false;
      unsigned LMUL;
      unsigned NFIELDS = Info.NumVectors;
      unsigned FixedSize = ElementCount * SEW;
      if (Info.ElementType == CGM.getContext().BoolTy) {
        // Mask type only occupies one vector register.
        LMUL = 1;
      } else if (FixedSize < 64) {
        // In RVV scalable vector types, we encode 64 bits in the fixed part.
        Fractional = true;
        LMUL = 64 / FixedSize;
      } else {
        LMUL = FixedSize / 64;
      }

      // Element count = (VLENB / SEW) x LMUL x NFIELDS
      SmallVector<uint64_t, 12> Expr(
          // The DW_OP_bregx operation has two operands: a register which is
          // specified by an unsigned LEB128 number, followed by a signed LEB128
          // offset.
          {llvm::dwarf::DW_OP_bregx, // Read the contents of a register.
           4096 + 0xC22,             // RISC-V VLENB CSR register.
           0, // Offset for DW_OP_bregx. It is dummy here.
           llvm::dwarf::DW_OP_constu,
           SEW / 8, // SEW is in bits.
           llvm::dwarf::DW_OP_div, llvm::dwarf::DW_OP_constu, LMUL});
      if (Fractional)
        Expr.push_back(llvm::dwarf::DW_OP_div);
      else
        Expr.push_back(llvm::dwarf::DW_OP_mul);
      // NFIELDS multiplier
      if (NFIELDS > 1)
        Expr.append({llvm::dwarf::DW_OP_constu, NFIELDS, llvm::dwarf::DW_OP_mul});
      // Element max index = count - 1
      Expr.append({llvm::dwarf::DW_OP_constu, 1, llvm::dwarf::DW_OP_minus});

      auto *LowerBound =
          llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
              llvm::Type::getInt64Ty(CGM.getLLVMContext()), 0));
      auto *UpperBound = DBuilder.createExpression(Expr);
      llvm::Metadata *Subscript = DBuilder.getOrCreateSubrange(
          /*count*/ nullptr, LowerBound, UpperBound, /*stride*/ nullptr);
      llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscript);
      llvm::DIType *ElemTy =
          getOrCreateType(Info.ElementType, TheCU->getFile());

      auto Align = getTypeAlignIfRequired(BT, CGM.getContext());
      return DBuilder.createVectorType(/*Size=*/0, Align, ElemTy,
                                       SubscriptArray);
    }

#define WASM_REF_TYPE(Name, MangledName, Id, SingletonId, AS)                  \
  case BuiltinType::Id: {                                                      \
    if (!SingletonId)                                                          \
      SingletonId =                                                            \
          DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,       \
                                     MangledName, TheCU, TheCU->getFile(), 0); \
    return SingletonId;                                                        \
  }
#include "clang/Basic/WebAssemblyReferenceTypes.def"
#define AMDGPU_OPAQUE_PTR_TYPE(Name, Id, SingletonId, Width, Align, AS)        \
  case BuiltinType::Id: {                                                      \
    if (!SingletonId)                                                          \
      SingletonId =                                                            \
          DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, Name, \
                                     TheCU, TheCU->getFile(), 0);              \
    return SingletonId;                                                        \
  }
#define AMDGPU_NAMED_BARRIER_TYPE(Name, Id, SingletonId, Width, Align, Scope)  \
  case BuiltinType::Id: {                                                      \
    if (!SingletonId)                                                          \
      SingletonId =                                                            \
          DBuilder.createBasicType(Name, Width, llvm::dwarf::DW_ATE_unsigned); \
    return SingletonId;                                                        \
  }
#define AMDGPU_FEATURE_PREDICATE_TYPE(Name, Id, SingletonId, Width, Align)     \
  case BuiltinType::Id: {                                                      \
    if (!SingletonId)                                                          \
      SingletonId =                                                            \
          DBuilder.createBasicType(Name, Width, llvm::dwarf::DW_ATE_boolean);  \
    return SingletonId;                                                        \
  }
#include "clang/Basic/AMDGPUTypes.def"
  case BuiltinType::UChar:
  case BuiltinType::Char_U:
    Encoding = llvm::dwarf::DW_ATE_unsigned_char;
    break;
  case BuiltinType::Char_S:
  case BuiltinType::SChar:
    Encoding = llvm::dwarf::DW_ATE_signed_char;
    break;
  case BuiltinType::Char8:
  case BuiltinType::Char16:
  case BuiltinType::Char32:
    Encoding = llvm::dwarf::DW_ATE_UTF;
    break;
  case BuiltinType::UShort:
  case BuiltinType::UInt:
  case BuiltinType::UInt128:
  case BuiltinType::ULong:
  case BuiltinType::WChar_U:
  case BuiltinType::ULongLong:
    Encoding = llvm::dwarf::DW_ATE_unsigned;
    break;
  case BuiltinType::Short:
  case BuiltinType::Int:
  case BuiltinType::Int128:
  case BuiltinType::Long:
  case BuiltinType::WChar_S:
  case BuiltinType::LongLong:
    Encoding = llvm::dwarf::DW_ATE_signed;
    break;
  case BuiltinType::Bool:
    Encoding = llvm::dwarf::DW_ATE_boolean;
    break;
  case BuiltinType::Half:
  case BuiltinType::Float:
  case BuiltinType::LongDouble:
  case BuiltinType::Float16:
  case BuiltinType::BFloat16:
  case BuiltinType::Float128:
  case BuiltinType::Double:
  case BuiltinType::Ibm128:
    // FIXME: For targets where long double, __ibm128 and __float128 have the
    // same size, they are currently indistinguishable in the debugger without
    // some special treatment. However, there is currently no consensus on
    // encoding and this should be updated once a DWARF encoding exists for
    // distinct floating point types of the same size.
    Encoding = llvm::dwarf::DW_ATE_float;
    break;
  case BuiltinType::ShortAccum:
  case BuiltinType::Accum:
  case BuiltinType::LongAccum:
  case BuiltinType::ShortFract:
  case BuiltinType::Fract:
  case BuiltinType::LongFract:
  case BuiltinType::SatShortFract:
  case BuiltinType::SatFract:
  case BuiltinType::SatLongFract:
  case BuiltinType::SatShortAccum:
  case BuiltinType::SatAccum:
  case BuiltinType::SatLongAccum:
    Encoding = llvm::dwarf::DW_ATE_signed_fixed;
    break;
  case BuiltinType::UShortAccum:
  case BuiltinType::UAccum:
  case BuiltinType::ULongAccum:
  case BuiltinType::UShortFract:
  case BuiltinType::UFract:
  case BuiltinType::ULongFract:
  case BuiltinType::SatUShortAccum:
  case BuiltinType::SatUAccum:
  case BuiltinType::SatULongAccum:
  case BuiltinType::SatUShortFract:
  case BuiltinType::SatUFract:
  case BuiltinType::SatULongFract:
    Encoding = llvm::dwarf::DW_ATE_unsigned_fixed;
    break;
  }

  BTName = BT->getName(CGM.getLangOpts());
  // Bit size and offset of the type.
  uint64_t Size = CGM.getContext().getTypeSize(BT);
  return DBuilder.createBasicType(BTName, Size, Encoding);
}

llvm::DIType *CGDebugInfo::CreateType(const BitIntType *Ty) {
  SmallString<32> Name;
  llvm::raw_svector_ostream OS(Name);
  OS << (Ty->isUnsigned() ? "unsigned _BitInt(" : "_BitInt(")
     << Ty->getNumBits() << ")";
  llvm::dwarf::TypeKind Encoding = Ty->isUnsigned()
                                       ? llvm::dwarf::DW_ATE_unsigned
                                       : llvm::dwarf::DW_ATE_signed;
  return DBuilder.createBasicType(Name, CGM.getContext().getTypeSize(Ty),
                                  Encoding, llvm::DINode::FlagZero, 0,
                                  Ty->getNumBits());
}

llvm::DIType *CGDebugInfo::CreateType(const OverflowBehaviorType *Ty,
                                      llvm::DIFile *U) {
  return getOrCreateType(Ty->getUnderlyingType(), U);
}

llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) {
  // Bit size and offset of the type.
  llvm::dwarf::TypeKind Encoding = llvm::dwarf::DW_ATE_complex_float;
  if (Ty->isComplexIntegerType())
    Encoding = llvm::dwarf::DW_ATE_lo_user;

  uint64_t Size = CGM.getContext().getTypeSize(Ty);
  return DBuilder.createBasicType("complex", Size, Encoding);
}

static void stripUnusedQualifiers(Qualifiers &Q) {
  // Ignore these qualifiers for now.
  Q.removeObjCGCAttr();
  Q.removeAddressSpace();
  Q.removeObjCLifetime();
  Q.removeUnaligned();
}

static llvm::dwarf::Tag getNextQualifier(Qualifiers &Q) {
  if (Q.hasConst()) {
    Q.removeConst();
    return llvm::dwarf::DW_TAG_const_type;
  }
  if (Q.hasVolatile()) {
    Q.removeVolatile();
    return llvm::dwarf::DW_TAG_volatile_type;
  }
  if (Q.hasRestrict()) {
    Q.removeRestrict();
    return llvm::dwarf::DW_TAG_restrict_type;
  }
  return (llvm::dwarf::Tag)0;
}

llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty,
                                               llvm::DIFile *Unit) {
  QualifierCollector Qc;
  const Type *T = Qc.strip(Ty);

  stripUnusedQualifiers(Qc);

  // We will create one Derived type for one qualifier and recurse to handle any
  // additional ones.
  llvm::dwarf::Tag Tag = getNextQualifier(Qc);
  if (!Tag) {
    if (Qc.getPointerAuth()) {
      unsigned Key = Qc.getPointerAuth().getKey();
      bool IsDiscr = Qc.getPointerAuth().isAddressDiscriminated();
      unsigned ExtraDiscr = Qc.getPointerAuth().getExtraDiscriminator();
      bool IsaPointer = Qc.getPointerAuth().isIsaPointer();
      bool AuthenticatesNullValues =
          Qc.getPointerAuth().authenticatesNullValues();
      Qc.removePointerAuth();
      assert(Qc.empty() && "Unknown type qualifier for debug info");
      llvm::DIType *FromTy = getOrCreateType(QualType(T, 0), Unit);
      return DBuilder.createPtrAuthQualifiedType(FromTy, Key, IsDiscr,
                                                 ExtraDiscr, IsaPointer,
                                                 AuthenticatesNullValues);
    } else {
      assert(Qc.empty() && "Unknown type qualifier for debug info");
      return getOrCreateType(QualType(T, 0), Unit);
    }
  }

  auto *FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit);

  // No need to fill in the Name, Line, Size, Alignment, Offset in case of
  // CVR derived types.
  return DBuilder.createQualifiedType(Tag, FromTy);
}

llvm::DIType *CGDebugInfo::CreateQualifiedType(const FunctionProtoType *F,
                                               llvm::DIFile *Unit) {
  FunctionProtoType::ExtProtoInfo EPI = F->getExtProtoInfo();
  Qualifiers &Q = EPI.TypeQuals;
  stripUnusedQualifiers(Q);

  // We will create one Derived type for one qualifier and recurse to handle any
  // additional ones.
  llvm::dwarf::Tag Tag = getNextQualifier(Q);
  if (!Tag) {
    assert(Q.empty() && "Unknown type qualifier for debug info");
    return nullptr;
  }

  auto *FromTy =
      getOrCreateType(CGM.getContext().getFunctionType(F->getReturnType(),
                                                       F->getParamTypes(), EPI),
                      Unit);

  // No need to fill in the Name, Line, Size, Alignment, Offset in case of
  // CVR derived types.
  return DBuilder.createQualifiedType(Tag, FromTy);
}

llvm::DIType *CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
                                      llvm::DIFile *Unit) {

  // The frontend treats 'id' as a typedef to an ObjCObjectType,
  // whereas 'id<protocol>' is treated as an ObjCPointerType. For the
  // debug info, we want to emit 'id' in both cases.
  if (Ty->isObjCQualifiedIdType())
    return getOrCreateType(CGM.getContext().getObjCIdType(), Unit);

  return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
                               Ty->getPointeeType(), Unit);
}

llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty,
                                      llvm::DIFile *Unit) {
  return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
                               Ty->getPointeeType(), Unit);
}

static bool hasCXXMangling(llvm::dwarf::SourceLanguage Lang, bool IsTagDecl) {
  switch (Lang) {
  case llvm::dwarf::DW_LANG_C_plus_plus:
  case llvm::dwarf::DW_LANG_C_plus_plus_11:
  case llvm::dwarf::DW_LANG_C_plus_plus_14:
  case llvm::dwarf::DW_LANG_HIP:
    return true;
  case llvm::dwarf::DW_LANG_ObjC_plus_plus:
    return IsTagDecl;
  default:
    return false;
  }
}

static bool hasCXXMangling(llvm::dwarf::SourceLanguageName Lang,
                           bool IsTagDecl) {
  switch (Lang) {
  case llvm::dwarf::DW_LNAME_C_plus_plus:
  case llvm::dwarf::DW_LNAME_HIP:
    return true;
  case llvm::dwarf::DW_LNAME_ObjC_plus_plus:
    return IsTagDecl;
  default:
    return false;
  }
}

/// \return whether a C++ mangling exists for the type defined by TD.
static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) {
  const bool IsTagDecl = isa<CXXRecordDecl>(TD) || isa<EnumDecl>(TD);

  if (llvm::DISourceLanguageName SourceLang = TheCU->getSourceLanguage();
      SourceLang.hasVersionedName())
    return hasCXXMangling(
        static_cast<llvm::dwarf::SourceLanguageName>(SourceLang.getName()),
        IsTagDecl);
  else
    return hasCXXMangling(
        static_cast<llvm::dwarf::SourceLanguage>(SourceLang.getName()),
        IsTagDecl);
}

// Determines if the debug info for this tag declaration needs a type
// identifier. The purpose of the unique identifier is to deduplicate type
// information for identical types across TUs. Because of the C++ one definition
// rule (ODR), it is valid to assume that the type is defined the same way in
// every TU and its debug info is equivalent.
//
// C does not have the ODR, and it is common for codebases to contain multiple
// different definitions of a struct with the same name in different TUs.
// Therefore, if the type doesn't have a C++ mangling, don't give it an
// identifer. Type information in C is smaller and simpler than C++ type
// information, so the increase in debug info size is negligible.
//
// If the type is not externally visible, it should be unique to the current TU,
// and should not need an identifier to participate in type deduplication.
// However, when emitting CodeView, the format internally uses these
// unique type name identifers for references between debug info. For example,
// the method of a class in an anonymous namespace uses the identifer to refer
// to its parent class. The Microsoft C++ ABI attempts to provide unique names
// for such types, so when emitting CodeView, always use identifiers for C++
// types. This may create problems when attempting to emit CodeView when the MS
// C++ ABI is not in use.
static bool needsTypeIdentifier(const TagDecl *TD, CodeGenModule &CGM,
                                llvm::DICompileUnit *TheCU) {
  // We only add a type identifier for types with C++ name mangling.
  if (!hasCXXMangling(TD, TheCU))
    return false;

  // Externally visible types with C++ mangling need a type identifier.
  if (TD->isExternallyVisible())
    return true;

  // CodeView types with C++ mangling need a type identifier.
  if (CGM.getCodeGenOpts().EmitCodeView)
    return true;

  return false;
}

// Returns a unique type identifier string if one exists, or an empty string.
static SmallString<256> getTypeIdentifier(const TagType *Ty, CodeGenModule &CGM,
                                          llvm::DICompileUnit *TheCU) {
  SmallString<256> Identifier;
  const TagDecl *TD = Ty->getDecl()->getDefinitionOrSelf();

  if (!needsTypeIdentifier(TD, CGM, TheCU))
    return Identifier;
  if (const auto *RD = dyn_cast<CXXRecordDecl>(TD))
    if (RD->getDefinition())
      if (RD->isDynamicClass() &&
          CGM.getVTableLinkage(RD) == llvm::GlobalValue::ExternalLinkage)
        return Identifier;

  // TODO: This is using the RTTI name. Is there a better way to get
  // a unique string for a type?
  llvm::raw_svector_ostream Out(Identifier);
  CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(QualType(Ty, 0), Out);
  return Identifier;
}

/// \return the appropriate DWARF tag for a composite type.
static llvm::dwarf::Tag getTagForRecord(const RecordDecl *RD) {
  llvm::dwarf::Tag Tag;
  if (RD->isStruct() || RD->isInterface())
    Tag = llvm::dwarf::DW_TAG_structure_type;
  else if (RD->isUnion())
    Tag = llvm::dwarf::DW_TAG_union_type;
  else {
    // FIXME: This could be a struct type giving a default visibility different
    // than C++ class type, but needs llvm metadata changes first.
    assert(RD->isClass());
    Tag = llvm::dwarf::DW_TAG_class_type;
  }
  return Tag;
}

llvm::DICompositeType *
CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
                                      llvm::DIScope *Ctx) {
  const RecordDecl *RD = Ty->getDecl()->getDefinitionOrSelf();
  if (llvm::DIType *T = getTypeOrNull(QualType(Ty, 0)))
    return cast<llvm::DICompositeType>(T);
  llvm::DIFile *DefUnit = getOrCreateFile(RD->getLocation());
  const unsigned Line =
      getLineNumber(RD->getLocation().isValid() ? RD->getLocation() : CurLoc);
  StringRef RDName = getClassName(RD);

  uint64_t Size = 0;
  uint32_t Align = 0;

  const RecordDecl *D = RD->getDefinition();
  if (D && D->isCompleteDefinition())
    Size = CGM.getContext().getTypeSize(Ty);

  llvm::DINode::DIFlags Flags = llvm::DINode::FlagFwdDecl;

  // Add flag to nontrivial forward declarations. To be consistent with MSVC,
  // add the flag if a record has no definition because we don't know whether
  // it will be trivial or not.
  if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
    if (!CXXRD->hasDefinition() ||
        (CXXRD->hasDefinition() && !CXXRD->isTrivial()))
      Flags |= llvm::DINode::FlagNonTrivial;

  // Create the type.
  SmallString<256> Identifier;
  // Don't include a linkage name in line tables only.
  if (CGM.getCodeGenOpts().hasReducedDebugInfo())
    Identifier = getTypeIdentifier(Ty, CGM, TheCU);
  llvm::DICompositeType *RetTy = DBuilder.createReplaceableCompositeType(
      getTagForRecord(RD), RDName, Ctx, DefUnit, Line, 0, Size, Align, Flags,
      Identifier);
  if (CGM.getCodeGenOpts().DebugFwdTemplateParams)
    if (auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD))
      DBuilder.replaceArrays(RetTy, llvm::DINodeArray(),
                             CollectCXXTemplateParams(TSpecial, DefUnit));
  ReplaceMap.emplace_back(
      std::piecewise_construct, std::make_tuple(Ty),
      std::make_tuple(static_cast<llvm::Metadata *>(RetTy)));
  return RetTy;
}

llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag,
                                                 const Type *Ty,
                                                 QualType PointeeTy,
                                                 llvm::DIFile *Unit) {
  // Bit size, align and offset of the type.
  // Size is always the size of a pointer.
  uint64_t Size = CGM.getContext().getTypeSize(Ty);
  auto Align = getTypeAlignIfRequired(Ty, CGM.getContext());
  std::optional<unsigned> DWARFAddressSpace =
      CGM.getTarget().getDWARFAddressSpace(
          CGM.getTypes().getTargetAddressSpace(PointeeTy));

  if (Tag == llvm::dwarf::DW_TAG_reference_type ||
      Tag == llvm::dwarf::DW_TAG_rvalue_reference_type) {
    return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit),
                                        Size, Align, DWARFAddressSpace);
  } else {
    SmallVector<llvm::Metadata *, 4> Annots;
    CollectBTFTypeTagAnnotations(PointeeTy, Annots);

    llvm::DINodeArray Annotations = nullptr;
    if (Annots.size() > 0)
      Annotations = DBuilder.getOrCreateArray(Annots);
    return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size,
                                      Align, DWARFAddressSpace, StringRef(),
                                      Annotations);
  }
}

llvm::DIType *CGDebugInfo::getOrCreateStructPtrType(StringRef Name,
                                                    llvm::DIType *&Cache) {
  if (Cache)
    return Cache;
  Cache = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, Name,
                                     TheCU, TheCU->getFile(), 0);
  unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
  Cache = DBuilder.createPointerType(Cache, Size);
  return Cache;
}

uint64_t CGDebugInfo::collectDefaultElementTypesForBlockPointer(
    const BlockPointerType *Ty, llvm::DIFile *Unit, llvm::DIDerivedType *DescTy,
    unsigned LineNo, SmallVectorImpl<llvm::Metadata *> &EltTys) {
  QualType FType;

  // Advanced by calls to CreateMemberType in increments of FType, then
  // returned as the overall size of the default elements.
  uint64_t FieldOffset = 0;

  // Blocks in OpenCL have unique constraints which make the standard fields
  // redundant while requiring size and align fields for enqueue_kernel. See
  // initializeForBlockHeader in CGBlocks.cpp
  if (CGM.getLangOpts().OpenCL) {
    FType = CGM.getContext().IntTy;
    EltTys.push_back(CreateMemberType(Unit, FType, "__size", &FieldOffset));
    EltTys.push_back(CreateMemberType(Unit, FType, "__align", &FieldOffset));
  } else {
    FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
    EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset));
    FType = CGM.getContext().IntTy;
    EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));
    EltTys.push_back(CreateMemberType(Unit, FType, "__reserved", &FieldOffset));
    FType = CGM.getContext().getPointerType(Ty->getPointeeType());
    EltTys.push_back(CreateMemberType(Unit, FType, "__FuncPtr", &FieldOffset));
    FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
    uint64_t FieldSize = CGM.getContext().getTypeSize(Ty);
    uint32_t FieldAlign = CGM.getContext().getTypeAlign(Ty);
    EltTys.push_back(DBuilder.createMemberType(
        Unit, "__descriptor", nullptr, LineNo, FieldSize, FieldAlign,
        FieldOffset, llvm::DINode::FlagZero, DescTy));
    FieldOffset += FieldSize;
  }

  return FieldOffset;
}

llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
                                      llvm::DIFile *Unit) {
  SmallVector<llvm::Metadata *, 8> EltTys;
  QualType FType;
  uint64_t FieldOffset;
  llvm::DINodeArray Elements;

  FieldOffset = 0;
  FType = CGM.getContext().UnsignedLongTy;
  EltTys.push_back(CreateMemberType(Unit, FType, "reserved", &FieldOffset));
  EltTys.push_back(CreateMemberType(Unit, FType, "Size", &FieldOffset));

  Elements = DBuilder.getOrCreateArray(EltTys);
  EltTys.clear();

  llvm::DINode::DIFlags Flags = llvm::DINode::FlagAppleBlock;

  auto *EltTy =
      DBuilder.createStructType(Unit, "__block_descriptor", nullptr, 0,
                                FieldOffset, 0, Flags, nullptr, Elements);

  // Bit size, align and offset of the type.
  uint64_t Size = CGM.getContext().getTypeSize(Ty);

  auto *DescTy = DBuilder.createPointerType(EltTy, Size);

  FieldOffset = collectDefaultElementTypesForBlockPointer(Ty, Unit, DescTy,
                                                          0, EltTys);

  Elements = DBuilder.getOrCreateArray(EltTys);

  // The __block_literal_generic structs are marked with a special
  // DW_AT_APPLE_BLOCK attribute and are an implementation detail only
  // the debugger needs to know about. To allow type uniquing, emit
  // them without a name or a location.
  EltTy = DBuilder.createStructType(Unit, "", nullptr, 0, FieldOffset, 0,
                                    Flags, nullptr, Elements);

  return DBuilder.createPointerType(EltTy, Size);
}

static llvm::SmallVector<TemplateArgument>
GetTemplateArgs(const TemplateDecl *TD, const TemplateSpecializationType *Ty) {
  assert(Ty->isTypeAlias());
  // TemplateSpecializationType doesn't know if its template args are
  // being substituted into a parameter pack. We can find out if that's
  // the case now by inspecting the TypeAliasTemplateDecl template
  // parameters. Insert Ty's template args into SpecArgs, bundling args
  // passed to a parameter pack into a TemplateArgument::Pack. It also
  // doesn't know the value of any defaulted args, so collect those now
  // too.
  SmallVector<TemplateArgument> SpecArgs;
  ArrayRef SubstArgs = Ty->template_arguments();
  for (const NamedDecl *Param : TD->getTemplateParameters()->asArray()) {
    // If Param is a parameter pack, pack the remaining arguments.
    if (Param->isParameterPack()) {
      SpecArgs.push_back(TemplateArgument(SubstArgs));
      break;
    }

    // Skip defaulted args.
    // FIXME: Ideally, we wouldn't do this. We can read the default values
    // for each parameter. However, defaulted arguments which are dependent
    // values or dependent types can't (easily?) be resolved here.
    if (SubstArgs.empty()) {
      // If SubstArgs is now empty (we're taking from it each iteration) and
      // this template parameter isn't a pack, then that should mean we're
      // using default values for the remaining template parameters (after
      // which there may be an empty pack too which we will ignore).
      break;
    }

    // Take the next argument.
    SpecArgs.push_back(SubstArgs.front());
    SubstArgs = SubstArgs.drop_front();
  }
  return SpecArgs;
}

llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
                                      llvm::DIFile *Unit) {
  assert(Ty->isTypeAlias());
  llvm::DIType *Src = getOrCreateType(Ty->getAliasedType(), Unit);

  const TemplateDecl *TD = Ty->getTemplateName().getAsTemplateDecl();
  if (isa<BuiltinTemplateDecl>(TD))
    return Src;

  const auto *AliasDecl = cast<TypeAliasTemplateDecl>(TD)->getTemplatedDecl();
  if (AliasDecl->hasAttr<NoDebugAttr>())
    return Src;

  SmallString<128> NS;
  llvm::raw_svector_ostream OS(NS);

  auto PP = getPrintingPolicy();
  Ty->getTemplateName().print(OS, PP, TemplateName::Qualified::None);

  SourceLocation Loc = AliasDecl->getLocation();

  if (CGM.getCodeGenOpts().DebugTemplateAlias) {
    auto ArgVector = ::GetTemplateArgs(TD, Ty);
    TemplateArgs Args = {TD->getTemplateParameters(), ArgVector};

    // FIXME: Respect DebugTemplateNameKind::Mangled, e.g. by using GetName.
    // Note we can't use GetName without additional work: TypeAliasTemplateDecl
    // doesn't have instantiation information, so
    // TypeAliasTemplateDecl::getNameForDiagnostic wouldn't have access to the
    // template args.
    std::string Name;
    llvm::raw_string_ostream OS(Name);
    TD->getNameForDiagnostic(OS, PP, /*Qualified=*/false);
    if (CGM.getCodeGenOpts().getDebugSimpleTemplateNames() !=
            llvm::codegenoptions::DebugTemplateNamesKind::Simple ||
        !HasReconstitutableArgs(Args.Args))
      printTemplateArgumentList(OS, Args.Args, PP);

    llvm::DIDerivedType *AliasTy = DBuilder.createTemplateAlias(
        Src, Name, getOrCreateFile(Loc), getLineNumber(Loc),
        getDeclContextDescriptor(AliasDecl), CollectTemplateParams(Args, Unit));
    return AliasTy;
  }

  printTemplateArgumentList(OS, Ty->template_arguments(), PP,
                            TD->getTemplateParameters());
  return DBuilder.createTypedef(Src, OS.str(), getOrCreateFile(Loc),
                                getLineNumber(Loc),
                                getDeclContextDescriptor(AliasDecl));
}

/// Convert an AccessSpecifier into the corresponding DINode flag.
/// As an optimization, return 0 if the access specifier equals the
/// default for the containing type.
static llvm::DINode::DIFlags getAccessFlag(AccessSpecifier Access,
                                           const RecordDecl *RD) {
  AccessSpecifier Default = clang::AS_none;
  if (RD && RD->isClass())
    Default = clang::AS_private;
  else if (RD && (RD->isStruct() || RD->isUnion()))
    Default = clang::AS_public;

  if (Access == Default)
    return llvm::DINode::FlagZero;

  switch (Access) {
  case clang::AS_private:
    return llvm::DINode::FlagPrivate;
  case clang::AS_protected:
    return llvm::DINode::FlagProtected;
  case clang::AS_public:
    return llvm::DINode::FlagPublic;
  case clang::AS_none:
    return llvm::DINode::FlagZero;
  }
  llvm_unreachable("unexpected access enumerator");
}

llvm::DIType *CGDebugInfo::CreateType(const TypedefType *Ty,
                                      llvm::DIFile *Unit) {
  llvm::DIType *Underlying =
      getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit);

  if (Ty->getDecl()->hasAttr<NoDebugAttr>())
    return Underlying;

  // We don't set size information, but do specify where the typedef was
  // declared.
  SourceLocation Loc = Ty->getDecl()->getLocation();

  uint32_t Align = getDeclAlignIfRequired(Ty->getDecl(), CGM.getContext());

  // Typedefs are derived from some other type. Collect both btf_decl_tag
  // annotations on the typedef declaration and btf_type_tag annotations on
  // the (possibly non-pointer) underlying type, e.g.
  //   typedef struct foo __attribute__((btf_type_tag("tag"))) foo_t;
  SmallVector<llvm::Metadata *, 4> Annots;
  llvm::DINodeArray Annotations;
  CollectBTFTypeTagAnnotations(Ty->getDecl()->getUnderlyingType(), Annots);
  CollectBTFDeclTagAnnotations(Ty->getDecl(), Annots);
  if (!Annots.empty())
    Annotations = DBuilder.getOrCreateArray(Annots);

  llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
  const DeclContext *DC = Ty->getDecl()->getDeclContext();
  if (isa<RecordDecl>(DC))
    Flags = getAccessFlag(Ty->getDecl()->getAccess(), cast<RecordDecl>(DC));

  return DBuilder.createTypedef(Underlying, Ty->getDecl()->getName(),
                                getOrCreateFile(Loc), getLineNumber(Loc),
                                getDeclContextDescriptor(Ty->getDecl()), Align,
                                Flags, Annotations);
}

static unsigned getDwarfCC(CallingConv CC) {
  switch (CC) {
  case CC_C:
    // Avoid emitting DW_AT_calling_convention if the C convention was used.
    return 0;

  case CC_X86StdCall:
    return llvm::dwarf::DW_CC_BORLAND_stdcall;
  case CC_X86FastCall:
    return llvm::dwarf::DW_CC_BORLAND_msfastcall;
  case CC_X86ThisCall:
    return llvm::dwarf::DW_CC_BORLAND_thiscall;
  case CC_X86VectorCall:
    return llvm::dwarf::DW_CC_LLVM_vectorcall;
  case CC_X86Pascal:
    return llvm::dwarf::DW_CC_BORLAND_pascal;
  case CC_Win64:
    return llvm::dwarf::DW_CC_LLVM_Win64;
  case CC_X86_64SysV:
    return llvm::dwarf::DW_CC_LLVM_X86_64SysV;
  case CC_AAPCS:
  case CC_AArch64VectorCall:
  case CC_AArch64SVEPCS:
    return llvm::dwarf::DW_CC_LLVM_AAPCS;
  case CC_AAPCS_VFP:
    return llvm::dwarf::DW_CC_LLVM_AAPCS_VFP;
  case CC_IntelOclBicc:
    return llvm::dwarf::DW_CC_LLVM_IntelOclBicc;
  case CC_SpirFunction:
    return llvm::dwarf::DW_CC_LLVM_SpirFunction;
  case CC_DeviceKernel:
    return llvm::dwarf::DW_CC_LLVM_DeviceKernel;
  case CC_Swift:
    return llvm::dwarf::DW_CC_LLVM_Swift;
  case CC_SwiftAsync:
    return llvm::dwarf::DW_CC_LLVM_SwiftTail;
  case CC_PreserveMost:
    return llvm::dwarf::DW_CC_LLVM_PreserveMost;
  case CC_PreserveAll:
    return llvm::dwarf::DW_CC_LLVM_PreserveAll;
  case CC_X86RegCall:
    return llvm::dwarf::DW_CC_LLVM_X86RegCall;
  case CC_M68kRTD:
    return llvm::dwarf::DW_CC_LLVM_M68kRTD;
  case CC_PreserveNone:
    return llvm::dwarf::DW_CC_LLVM_PreserveNone;
  case CC_RISCVVectorCall:
    return llvm::dwarf::DW_CC_LLVM_RISCVVectorCall;
#define CC_VLS_CASE(ABI_VLEN) case CC_RISCVVLSCall_##ABI_VLEN:
    CC_VLS_CASE(32)
    CC_VLS_CASE(64)
    CC_VLS_CASE(128)
    CC_VLS_CASE(256)
    CC_VLS_CASE(512)
    CC_VLS_CASE(1024)
    CC_VLS_CASE(2048)
    CC_VLS_CASE(4096)
    CC_VLS_CASE(8192)
    CC_VLS_CASE(16384)
    CC_VLS_CASE(32768)
    CC_VLS_CASE(65536)
#undef CC_VLS_CASE
    return llvm::dwarf::DW_CC_LLVM_RISCVVLSCall;
  }
  return 0;
}

static llvm::DINode::DIFlags getRefFlags(const FunctionProtoType *Func) {
  llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
  if (Func->getExtProtoInfo().RefQualifier == RQ_LValue)
    Flags |= llvm::DINode::FlagLValueReference;
  if (Func->getExtProtoInfo().RefQualifier == RQ_RValue)
    Flags |= llvm::DINode::FlagRValueReference;
  return Flags;
}

llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty,
                                      llvm::DIFile *Unit) {
  const auto *FPT = dyn_cast<FunctionProtoType>(Ty);
  if (FPT) {
    if (llvm::DIType *QTy = CreateQualifiedType(FPT, Unit))
      return QTy;
  }

  // Create the type without any qualifiers

  SmallVector<llvm::Metadata *, 16> EltTys;

  // Add the result type at least.
  EltTys.push_back(getOrCreateType(Ty->getReturnType(), Unit));

  llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
  // Set up remainder of arguments if there is a prototype.
  // otherwise emit it as a variadic function.
  if (!FPT) {
    EltTys.push_back(DBuilder.createUnspecifiedParameter());
  } else {
    Flags = getRefFlags(FPT);
    for (const QualType &ParamType : FPT->param_types())
      EltTys.push_back(getOrCreateType(ParamType, Unit));
    if (FPT->isVariadic())
      EltTys.push_back(DBuilder.createUnspecifiedParameter());
  }

  llvm::DITypeArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys);
  llvm::DIType *F = DBuilder.createSubroutineType(
      EltTypeArray, Flags, getDwarfCC(Ty->getCallConv()));
  return F;
}

llvm::DIDerivedType *
CGDebugInfo::createBitFieldType(const FieldDecl *BitFieldDecl,
                                llvm::DIScope *RecordTy, const RecordDecl *RD) {
  StringRef Name = BitFieldDecl->getName();
  QualType Ty = BitFieldDecl->getType();
  if (BitFieldDecl->hasAttr<PreferredTypeAttr>())
    Ty = BitFieldDecl->getAttr<PreferredTypeAttr>()->getType();
  SourceLocation Loc = BitFieldDecl->getLocation();
  llvm::DIFile *VUnit = getOrCreateFile(Loc);
  llvm::DIType *DebugType = getOrCreateType(Ty, VUnit);

  // Get the location for the field.
  llvm::DIFile *File = getOrCreateFile(Loc);
  unsigned Line = getLineNumber(Loc);

  const CGBitFieldInfo &BitFieldInfo =
      CGM.getTypes().getCGRecordLayout(RD).getBitFieldInfo(BitFieldDecl);
  uint64_t SizeInBits = BitFieldInfo.Size;
  assert(SizeInBits > 0 && "found named 0-width bitfield");
  uint64_t StorageOffsetInBits =
      CGM.getContext().toBits(BitFieldInfo.StorageOffset);
  uint64_t Offset = BitFieldInfo.Offset;
  // The bit offsets for big endian machines are reversed for big
  // endian target, compensate for that as the DIDerivedType requires
  // un-reversed offsets.
  if (CGM.getDataLayout().isBigEndian())
    Offset = BitFieldInfo.StorageSize - BitFieldInfo.Size - Offset;
  uint64_t OffsetInBits = StorageOffsetInBits + Offset;
  llvm::DINode::DIFlags Flags = getAccessFlag(BitFieldDecl->getAccess(), RD);
  llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(BitFieldDecl);
  return DBuilder.createBitFieldMemberType(
      RecordTy, Name, File, Line, SizeInBits, OffsetInBits, StorageOffsetInBits,
      Flags, DebugType, Annotations);
}

llvm::DIDerivedType *CGDebugInfo::createBitFieldSeparatorIfNeeded(
    const FieldDecl *BitFieldDecl, const llvm::DIDerivedType *BitFieldDI,
    llvm::ArrayRef<llvm::Metadata *> PreviousFieldsDI, const RecordDecl *RD) {

  if (!CGM.getTargetCodeGenInfo().shouldEmitDWARFBitFieldSeparators())
    return nullptr;

  /*
  Add a *single* zero-bitfield separator between two non-zero bitfields
  separated by one or more zero-bitfields. This is used to distinguish between
  structures such the ones below, where the memory layout is the same, but how
  the ABI assigns fields to registers differs.

  struct foo {
    int space[4];
    char a : 8; // on amdgpu, passed on v4
    char b : 8;
    char x : 8;
    char y : 8;
  };
  struct bar {
    int space[4];
    char a : 8; // on amdgpu, passed on v4
    char b : 8;
    char : 0;
    char x : 8; // passed on v5
    char y : 8;
  };
  */
  if (PreviousFieldsDI.empty())
    return nullptr;

  // If we already emitted metadata for a 0-length bitfield, nothing to do here.
  auto *PreviousMDEntry =
      PreviousFieldsDI.empty() ? nullptr : PreviousFieldsDI.back();
  auto *PreviousMDField =
      dyn_cast_or_null<llvm::DIDerivedType>(PreviousMDEntry);
  if (!PreviousMDField || !PreviousMDField->isBitField() ||
      PreviousMDField->getSizeInBits() == 0)
    return nullptr;

  auto PreviousBitfield = RD->field_begin();
  std::advance(PreviousBitfield, BitFieldDecl->getFieldIndex() - 1);

  assert(PreviousBitfield->isBitField());

  if (!PreviousBitfield->isZeroLengthBitField())
    return nullptr;

  QualType Ty = PreviousBitfield->getType();
  SourceLocation Loc = PreviousBitfield->getLocation();
  llvm::DIFile *VUnit = getOrCreateFile(Loc);
  llvm::DIType *DebugType = getOrCreateType(Ty, VUnit);
  llvm::DIScope *RecordTy = BitFieldDI->getScope();

  llvm::DIFile *File = getOrCreateFile(Loc);
  unsigned Line = getLineNumber(Loc);

  uint64_t StorageOffsetInBits =
      cast<llvm::ConstantInt>(BitFieldDI->getStorageOffsetInBits())
          ->getZExtValue();

  llvm::DINode::DIFlags Flags =
      getAccessFlag(PreviousBitfield->getAccess(), RD);
  llvm::DINodeArray Annotations =
      CollectBTFDeclTagAnnotations(*PreviousBitfield);
  return DBuilder.createBitFieldMemberType(
      RecordTy, "", File, Line, 0, StorageOffsetInBits, StorageOffsetInBits,
      Flags, DebugType, Annotations);
}

llvm::DIType *CGDebugInfo::createFieldType(
    StringRef name, QualType type, SourceLocation loc, AccessSpecifier AS,
    uint64_t offsetInBits, uint32_t AlignInBits, llvm::DIFile *tunit,
    llvm::DIScope *scope, const RecordDecl *RD, llvm::DINodeArray Annotations) {
  llvm::DIType *debugType = getOrCreateType(type, tunit);

  // Get the location for the field.
  llvm::DIFile *file = getOrCreateFile(loc);
  const unsigned line = getLineNumber(loc.isValid() ? loc : CurLoc);

  uint64_t SizeInBits = 0;
  auto Align = AlignInBits;
  if (!type->isIncompleteArrayType()) {
    TypeInfo TI = CGM.getContext().getTypeInfo(type);
    SizeInBits = TI.Width;
    if (!Align)
      Align = getTypeAlignIfRequired(type, CGM.getContext());
  }

  llvm::DINode::DIFlags flags = getAccessFlag(AS, RD);
  return DBuilder.createMemberType(scope, name, file, line, SizeInBits, Align,
                                   offsetInBits, flags, debugType, Annotations);
}

llvm::DISubprogram *
CGDebugInfo::createInlinedSubprogram(StringRef FuncName,
                                     llvm::DIFile *FileScope) {
  // We are caching the subprogram because we don't want to duplicate
  // subprograms with the same message. Note that `SPFlagDefinition` prevents
  // subprograms from being uniqued.
  llvm::DISubprogram *&SP = InlinedSubprogramMap[FuncName];

  if (!SP) {
    llvm::DISubroutineType *DIFnTy = DBuilder.createSubroutineType(nullptr);
    SP = DBuilder.createFunction(
        /*Scope=*/FileScope, /*Name=*/FuncName, /*LinkageName=*/StringRef(),
        /*File=*/FileScope, /*LineNo=*/0, /*Ty=*/DIFnTy,
        /*ScopeLine=*/0,
        /*Flags=*/llvm::DINode::FlagArtificial,
        /*SPFlags=*/llvm::DISubprogram::SPFlagDefinition,
        /*TParams=*/nullptr, /*Decl=*/nullptr, /*ThrownTypes=*/nullptr,
        /*Annotations=*/nullptr, /*TargetFuncName=*/StringRef(),
        /*UseKeyInstructions=*/CGM.getCodeGenOpts().DebugKeyInstructions);
  }

  return SP;
}

llvm::StringRef
CGDebugInfo::GetLambdaCaptureName(const LambdaCapture &Capture) {
  if (Capture.capturesThis())
    return CGM.getCodeGenOpts().EmitCodeView ? "__this" : "this";

  assert(Capture.capturesVariable());

  const ValueDecl *CaptureDecl = Capture.getCapturedVar();
  assert(CaptureDecl && "Expected valid decl for captured variable.");

  return CaptureDecl->getName();
}

void CGDebugInfo::CollectRecordLambdaFields(
    const CXXRecordDecl *CXXDecl, SmallVectorImpl<llvm::Metadata *> &elements,
    llvm::DIType *RecordTy) {
  // For C++11 Lambdas a Field will be the same as a Capture, but the Capture
  // has the name and the location of the variable so we should iterate over
  // both concurrently.
  RecordDecl::field_iterator Field = CXXDecl->field_begin();
  unsigned fieldno = 0;
  for (CXXRecordDecl::capture_const_iterator I = CXXDecl->captures_begin(),
                                             E = CXXDecl->captures_end();
       I != E; ++I, ++Field, ++fieldno) {
    const LambdaCapture &Capture = *I;
    const uint64_t FieldOffset =
        CGM.getContext().getASTRecordLayout(CXXDecl).getFieldOffset(fieldno);

    assert(!Field->isBitField() && "lambdas don't have bitfield members!");

    SourceLocation Loc;
    uint32_t Align = 0;

    if (Capture.capturesThis()) {
      // TODO: Need to handle 'this' in some way by probably renaming the
      // this of the lambda class and having a field member of 'this' or
      // by using AT_object_pointer for the function and having that be
      // used as 'this' for semantic references.
      Loc = Field->getLocation();
    } else if (Capture.capturesVariable()) {
      Loc = Capture.getLocation();

      const ValueDecl *CaptureDecl = Capture.getCapturedVar();
      assert(CaptureDecl && "Expected valid decl for captured variable.");

      Align = getDeclAlignIfRequired(CaptureDecl, CGM.getContext());
    } else {
      continue;
    }

    llvm::DIFile *VUnit = getOrCreateFile(Loc);

    elements.push_back(createFieldType(
        GetLambdaCaptureName(Capture), Field->getType(), Loc,
        Field->getAccess(), FieldOffset, Align, VUnit, RecordTy, CXXDecl));
  }
}

/// Build an llvm::ConstantDataArray from the initialized elements of an
/// APValue array, using the narrowest integer type that fits the element width.
template <typename T>
static llvm::Constant *
buildConstantDataArrayFromElements(llvm::LLVMContext &Ctx, const APValue &Arr) {
  const unsigned NumElts = Arr.getArraySize();
  SmallVector<T, 64> Vals(
      NumElts,
      Arr.hasArrayFiller()
          ? static_cast<T>(Arr.getArrayFiller().getInt().getZExtValue())
          : 0);
  for (unsigned I : llvm::seq(Arr.getArrayInitializedElts()))
    Vals[I] =
        static_cast<T>(Arr.getArrayInitializedElt(I).getInt().getZExtValue());
  return llvm::ConstantDataArray::get(Ctx, Vals);
}

/// Try to create an llvm::Constant for a constexpr array of integer elements.
/// Handles arrays of char, short, int, long with element width up to 64 bits.
/// Returns nullptr if the array cannot be represented.
static llvm::Constant *tryEmitConstexprArrayAsConstant(CodeGenModule &CGM,
                                                       const VarDecl *Var,
                                                       const APValue *Value) {
  const auto *ArrayTy = CGM.getContext().getAsConstantArrayType(Var->getType());
  if (!ArrayTy)
    return nullptr;

  const QualType ElemQTy = ArrayTy->getElementType();
  if (ElemQTy.isNull() || !ElemQTy->isIntegerType())
    return nullptr;

  const uint64_t ElemBitWidth = CGM.getContext().getTypeSize(ElemQTy);

  llvm::LLVMContext &Ctx = CGM.getLLVMContext();
  switch (ElemBitWidth) {
  case 8:
    return buildConstantDataArrayFromElements<uint8_t>(Ctx, *Value);
  case 16:
    return buildConstantDataArrayFromElements<uint16_t>(Ctx, *Value);
  case 32:
    return buildConstantDataArrayFromElements<uint32_t>(Ctx, *Value);
  case 64:
    return buildConstantDataArrayFromElements<uint64_t>(Ctx, *Value);
  default:
    // ConstantDataArray only supports 8/16/32/64-bit elements.
    // Wider types (e.g. __int128) are not representable.
    return nullptr;
  }
}

llvm::DIDerivedType *
CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy,
                                     const RecordDecl *RD) {
  // Create the descriptor for the static variable, with or without
  // constant initializers.
  Var = Var->getCanonicalDecl();
  llvm::DIFile *VUnit = getOrCreateFile(Var->getLocation());
  llvm::DIType *VTy = getOrCreateType(Var->getType(), VUnit);

  unsigned LineNumber = getLineNumber(Var->getLocation());
  StringRef VName = Var->getName();

  // FIXME: to avoid complications with type merging we should
  // emit the constant on the definition instead of the declaration.
  llvm::Constant *C = nullptr;
  if (Var->getInit()) {
    const APValue *Value = Var->evaluateValue();
    if (Value) {
      if (Value->isInt())
        C = llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt());
      if (Value->isFloat())
        C = llvm::ConstantFP::get(CGM.getLLVMContext(), Value->getFloat());
      if (Value->isArray())
        C = tryEmitConstexprArrayAsConstant(CGM, Var, Value);
    }
  }

  llvm::DINode::DIFlags Flags = getAccessFlag(Var->getAccess(), RD);
  auto Tag = CGM.getCodeGenOpts().DwarfVersion >= 5
                 ? llvm::dwarf::DW_TAG_variable
                 : llvm::dwarf::DW_TAG_member;
  auto Align = getDeclAlignIfRequired(Var, CGM.getContext());
  llvm::DIDerivedType *GV = DBuilder.createStaticMemberType(
      RecordTy, VName, VUnit, LineNumber, VTy, Flags, C, Tag, Align);
  StaticDataMemberCache[Var->getCanonicalDecl()].reset(GV);
  return GV;
}

void CGDebugInfo::CollectRecordNormalField(
    const FieldDecl *field, uint64_t OffsetInBits, llvm::DIFile *tunit,
    SmallVectorImpl<llvm::Metadata *> &elements, llvm::DIType *RecordTy,
    const RecordDecl *RD) {
  StringRef name = field->getName();
  QualType type = field->getType();

  // Ignore unnamed fields unless they're anonymous structs/unions.
  if (name.empty() && !type->isRecordType())
    return;

  llvm::DIType *FieldType;
  if (field->isBitField()) {
    llvm::DIDerivedType *BitFieldType;
    FieldType = BitFieldType = createBitFieldType(field, RecordTy, RD);
    if (llvm::DIType *Separator =
            createBitFieldSeparatorIfNeeded(field, BitFieldType, elements, RD))
      elements.push_back(Separator);
  } else {
    auto Align = getDeclAlignIfRequired(field, CGM.getContext());
    llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(field);
    FieldType =
        createFieldType(name, type, field->getLocation(), field->getAccess(),
                        OffsetInBits, Align, tunit, RecordTy, RD, Annotations);
  }

  elements.push_back(FieldType);
}

void CGDebugInfo::CollectRecordNestedType(
    const TypeDecl *TD, SmallVectorImpl<llvm::Metadata *> &elements) {
  QualType Ty = CGM.getContext().getTypeDeclType(TD);
  // Injected class names are not considered nested records.
  // FIXME: Is this supposed to be testing for injected class name declarations
  // instead?
  if (isa<InjectedClassNameType>(Ty))
    return;
  SourceLocation Loc = TD->getLocation();
  if (llvm::DIType *nestedType = getOrCreateType(Ty, getOrCreateFile(Loc)))
    elements.push_back(nestedType);
}

void CGDebugInfo::CollectRecordFields(
    const RecordDecl *record, llvm::DIFile *tunit,
    SmallVectorImpl<llvm::Metadata *> &elements,
    llvm::DICompositeType *RecordTy) {
  const auto *CXXDecl = dyn_cast<CXXRecordDecl>(record);

  if (CXXDecl && CXXDecl->isLambda())
    CollectRecordLambdaFields(CXXDecl, elements, RecordTy);
  else {
    const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record);

    // Field number for non-static fields.
    unsigned fieldNo = 0;

    // Static and non-static members should appear in the same order as
    // the corresponding declarations in the source program.
    for (const auto *I : record->decls())
      if (const auto *V = dyn_cast<VarDecl>(I)) {
        if (V->hasAttr<NoDebugAttr>())
          continue;

        // Skip variable template specializations when emitting CodeView. MSVC
        // doesn't emit them.
        if (CGM.getCodeGenOpts().EmitCodeView &&
            isa<VarTemplateSpecializationDecl>(V))
          continue;

        if (isa<VarTemplatePartialSpecializationDecl>(V))
          continue;

        // Reuse the existing static member declaration if one exists
        auto MI = StaticDataMemberCache.find(V->getCanonicalDecl());
        if (MI != StaticDataMemberCache.end()) {
          assert(MI->second &&
                 "Static data member declaration should still exist");
          elements.push_back(MI->second);
        } else {
          auto Field = CreateRecordStaticField(V, RecordTy, record);
          elements.push_back(Field);
        }
      } else if (const auto *field = dyn_cast<FieldDecl>(I)) {
        CollectRecordNormalField(field, layout.getFieldOffset(fieldNo), tunit,
                                 elements, RecordTy, record);

        // Bump field number for next field.
        ++fieldNo;
      } else if (CGM.getCodeGenOpts().EmitCodeView) {
        // Debug info for nested types is included in the member list only for
        // CodeView.
        if (const auto *nestedType = dyn_cast<TypeDecl>(I)) {
          // MSVC doesn't generate nested type for anonymous struct/union.
          if (isa<RecordDecl>(I) &&
              cast<RecordDecl>(I)->isAnonymousStructOrUnion())
            continue;
          if (!nestedType->isImplicit() &&
              nestedType->getDeclContext() == record)
            CollectRecordNestedType(nestedType, elements);
        }
      }
  }
}

llvm::DISubroutineType *
CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
                                   llvm::DIFile *Unit) {
  const FunctionProtoType *Func = Method->getType()->getAs<FunctionProtoType>();
  if (Method->isStatic())
    return cast_or_null<llvm::DISubroutineType>(
        getOrCreateType(QualType(Func, 0), Unit));

  QualType ThisType;
  if (!Method->hasCXXExplicitFunctionObjectParameter())
    ThisType = Method->getThisType();

  return getOrCreateInstanceMethodType(ThisType, Func, Unit);
}

llvm::DISubroutineType *CGDebugInfo::getOrCreateMethodTypeForDestructor(
    const CXXMethodDecl *Method, llvm::DIFile *Unit, QualType FNType) {
  const FunctionProtoType *Func = FNType->getAs<FunctionProtoType>();
  // skip the first param since it is also this
  return getOrCreateInstanceMethodType(Method->getThisType(), Func, Unit, true);
}

llvm::DISubroutineType *
CGDebugInfo::getOrCreateInstanceMethodType(QualType ThisPtr,
                                           const FunctionProtoType *Func,
                                           llvm::DIFile *Unit, bool SkipFirst) {
  FunctionProtoType::ExtProtoInfo EPI = Func->getExtProtoInfo();
  Qualifiers &Qc = EPI.TypeQuals;
  Qc.removeConst();
  Qc.removeVolatile();
  Qc.removeRestrict();
  Qc.removeUnaligned();
  // Keep the removed qualifiers in sync with
  // CreateQualifiedType(const FunctionPrototype*, DIFile *Unit)
  // On a 'real' member function type, these qualifiers are carried on the type
  // of the first parameter, not as separate DW_TAG_const_type (etc) decorator
  // tags around them. (But, in the raw function types with qualifiers, they have
  // to use wrapper types.)

  // Add "this" pointer.
  const auto *OriginalFunc = cast<llvm::DISubroutineType>(
      getOrCreateType(CGM.getContext().getFunctionType(
                          Func->getReturnType(), Func->getParamTypes(), EPI),
                      Unit));
  llvm::DITypeArray Args = OriginalFunc->getTypeArray();
  assert(Args.size() && "Invalid number of arguments!");

  SmallVector<llvm::Metadata *, 16> Elts;

  // First element is always return type. For 'void' functions it is NULL.
  Elts.push_back(Args[0]);

  const bool HasExplicitObjectParameter = ThisPtr.isNull();

  // "this" pointer is always first argument. For explicit "this"
  // parameters, it will already be in Args[1].
  if (!HasExplicitObjectParameter) {
    llvm::DIType *ThisPtrType = getOrCreateType(ThisPtr, Unit);
    TypeCache[ThisPtr.getAsOpaquePtr()].reset(ThisPtrType);
    ThisPtrType =
        DBuilder.createObjectPointerType(ThisPtrType, /*Implicit=*/true);
    Elts.push_back(ThisPtrType);
  }

  // Copy rest of the arguments.
  for (unsigned i = (SkipFirst ? 2 : 1), e = Args.size(); i < e; ++i)
    Elts.push_back(Args[i]);

  // Attach FlagObjectPointer to the explicit "this" parameter.
  if (HasExplicitObjectParameter) {
    assert(Elts.size() >= 2 && Args.size() >= 2 &&
           "Expected at least return type and object parameter.");
    Elts[1] = DBuilder.createObjectPointerType(Args[1], /*Implicit=*/false);
  }

  llvm::DITypeArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts);

  return DBuilder.createSubroutineType(EltTypeArray, OriginalFunc->getFlags(),
                                       getDwarfCC(Func->getCallConv()));
}

/// isFunctionLocalClass - Return true if CXXRecordDecl is defined
/// inside a function.
static bool isFunctionLocalClass(const CXXRecordDecl *RD) {
  if (const auto *NRD = dyn_cast<CXXRecordDecl>(RD->getDeclContext()))
    return isFunctionLocalClass(NRD);
  if (isa<FunctionDecl>(RD->getDeclContext()))
    return true;
  return false;
}

llvm::StringRef
CGDebugInfo::GetMethodLinkageName(const CXXMethodDecl *Method) const {
  assert(Method);

  const bool IsCtorOrDtor =
      isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method);

  if (IsCtorOrDtor && !CGM.getCodeGenOpts().DebugStructorDeclLinkageNames)
    return {};

  // In some ABIs (particularly Itanium) a single ctor/dtor
  // corresponds to multiple functions. Attach a "unified"
  // linkage name for those (which is the convention GCC uses).
  // Otherwise, attach no linkage name.
  if (IsCtorOrDtor && !CGM.getTarget().getCXXABI().hasConstructorVariants())
    return {};

  if (const auto *Ctor = llvm::dyn_cast<CXXConstructorDecl>(Method))
    return CGM.getMangledName(GlobalDecl(Ctor, CXXCtorType::Ctor_Unified));

  if (const auto *Dtor = llvm::dyn_cast<CXXDestructorDecl>(Method))
    return CGM.getMangledName(GlobalDecl(Dtor, CXXDtorType::Dtor_Unified));

  return CGM.getMangledName(Method);
}

bool CGDebugInfo::shouldGenerateVirtualCallSite() const {
  // Check general conditions for call site generation.
  return ((getCallSiteRelatedAttrs() != llvm::DINode::FlagZero) &&
          (CGM.getCodeGenOpts().DwarfVersion >= 5));
}

llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
    const CXXMethodDecl *Method, llvm::DIFile *Unit, llvm::DIType *RecordTy) {
  assert(Method);

  StringRef MethodName = getFunctionName(Method);
  llvm::DISubroutineType *MethodTy = getOrCreateMethodType(Method, Unit);

  StringRef MethodLinkageName;
  // FIXME: 'isFunctionLocalClass' seems like an arbitrary/unintentional
  // property to use here. It may've been intended to model "is non-external
  // type" but misses cases of non-function-local but non-external classes such
  // as those in anonymous namespaces as well as the reverse - external types
  // that are function local, such as those in (non-local) inline functions.
  if (!isFunctionLocalClass(Method->getParent()))
    MethodLinkageName = GetMethodLinkageName(Method);

  // Get the location for the method.
  llvm::DIFile *MethodDefUnit = nullptr;
  unsigned MethodLine = 0;
  if (!Method->isImplicit()) {
    MethodDefUnit = getOrCreateFile(Method->getLocation());
    MethodLine = getLineNumber(Method->getLocation());
  }

  // Collect virtual method info.
  llvm::DIType *ContainingType = nullptr;
  unsigned VIndex = 0;
  llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
  llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::SPFlagZero;
  int ThisAdjustment = 0;

  if (VTableContextBase::hasVtableSlot(Method)) {
    if (Method->isPureVirtual())
      SPFlags |= llvm::DISubprogram::SPFlagPureVirtual;
    else
      SPFlags |= llvm::DISubprogram::SPFlagVirtual;

    if (CGM.getTarget().getCXXABI().isItaniumFamily()) {
      // It doesn't make sense to give a virtual destructor a vtable index,
      // since a single destructor has two entries in the vtable.
      if (!isa<CXXDestructorDecl>(Method))
        VIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(Method);
    } else {
      // Emit MS ABI vftable information.  There is only one entry for the
      // deleting dtor.
      const auto *DD = dyn_cast<CXXDestructorDecl>(Method);
      GlobalDecl GD =
          DD ? GlobalDecl(
                   DD, CGM.getContext().getTargetInfo().emitVectorDeletingDtors(
                           CGM.getContext().getLangOpts())
                           ? Dtor_VectorDeleting
                           : Dtor_Deleting)
             : GlobalDecl(Method);
      MethodVFTableLocation ML =
          CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD);
      VIndex = ML.Index;

      // CodeView only records the vftable offset in the class that introduces
      // the virtual method. This is possible because, unlike Itanium, the MS
      // C++ ABI does not include all virtual methods from non-primary bases in
      // the vtable for the most derived class. For example, if C inherits from
      // A and B, C's primary vftable will not include B's virtual methods.
      if (Method->size_overridden_methods() == 0)
        Flags |= llvm::DINode::FlagIntroducedVirtual;

      // The 'this' adjustment accounts for both the virtual and non-virtual
      // portions of the adjustment. Presumably the debugger only uses it when
      // it knows the dynamic type of an object.
      ThisAdjustment = CGM.getCXXABI()
                           .getVirtualFunctionPrologueThisAdjustment(GD)
                           .getQuantity();
    }
    ContainingType = RecordTy;
  }

  if (Method->getCanonicalDecl()->isDeleted())
    SPFlags |= llvm::DISubprogram::SPFlagDeleted;

  if (Method->isNoReturn())
    Flags |= llvm::DINode::FlagNoReturn;

  if (Method->isStatic())
    Flags |= llvm::DINode::FlagStaticMember;
  if (Method->isImplicit())
    Flags |= llvm::DINode::FlagArtificial;
  Flags |= getAccessFlag(Method->getAccess(), Method->getParent());
  if (const auto *CXXC = dyn_cast<CXXConstructorDecl>(Method)) {
    if (CXXC->isExplicit())
      Flags |= llvm::DINode::FlagExplicit;
  } else if (const auto *CXXC = dyn_cast<CXXConversionDecl>(Method)) {
    if (CXXC->isExplicit())
      Flags |= llvm::DINode::FlagExplicit;
  }
  if (Method->hasPrototype())
    Flags |= llvm::DINode::FlagPrototyped;
  if (Method->getRefQualifier() == RQ_LValue)
    Flags |= llvm::DINode::FlagLValueReference;
  if (Method->getRefQualifier() == RQ_RValue)
    Flags |= llvm::DINode::FlagRValueReference;
  if (!Method->isExternallyVisible())
    SPFlags |= llvm::DISubprogram::SPFlagLocalToUnit;
  if (CGM.getCodeGenOpts().OptimizationLevel != 0)
    SPFlags |= llvm::DISubprogram::SPFlagOptimized;

  // In this debug mode, emit type info for a class when its constructor type
  // info is emitted.
  if (DebugKind == llvm::codegenoptions::DebugInfoConstructor)
    if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(Method))
      completeUnusedClass(*CD->getParent());

  llvm::DINodeArray TParamsArray = CollectFunctionTemplateParams(Method, Unit);
  llvm::DISubprogram *SP = DBuilder.createMethod(
      RecordTy, MethodName, MethodLinkageName, MethodDefUnit, MethodLine,
      MethodTy, VIndex, ThisAdjustment, ContainingType, Flags, SPFlags,
      TParamsArray.get(), /*ThrownTypes*/ nullptr,
      CGM.getCodeGenOpts().DebugKeyInstructions);

  SPCache[Method->getCanonicalDecl()].reset(SP);

  return SP;
}

void CGDebugInfo::CollectCXXMemberFunctions(
    const CXXRecordDecl *RD, llvm::DIFile *Unit,
    SmallVectorImpl<llvm::Metadata *> &EltTys, llvm::DIType *RecordTy) {

  // Since we want more than just the individual member decls if we
  // have templated functions iterate over every declaration to gather
  // the functions.
  for (const auto *I : RD->decls()) {
    const auto *Method = dyn_cast<CXXMethodDecl>(I);
    // If the member is implicit, don't add it to the member list. This avoids
    // the member being added to type units by LLVM, while still allowing it
    // to be emitted into the type declaration/reference inside the compile
    // unit.
    // Ditto 'nodebug' methods, for consistency with CodeGenFunction.cpp.
    // FIXME: Handle Using(Shadow?)Decls here to create
    // DW_TAG_imported_declarations inside the class for base decls brought into
    // derived classes. GDB doesn't seem to notice/leverage these when I tried
    // it, so I'm not rushing to fix this. (GCC seems to produce them, if
    // referenced)
    if (!Method || Method->isImplicit() || Method->hasAttr<NoDebugAttr>())
      continue;

    if (Method->getType()->castAs<FunctionProtoType>()->getContainedAutoType())
      continue;

    // Reuse the existing member function declaration if it exists.
    // It may be associated with the declaration of the type & should be
    // reused as we're building the definition.
    //
    // This situation can arise in the vtable-based debug info reduction where
    // implicit members are emitted in a non-vtable TU.
    auto MI = SPCache.find(Method->getCanonicalDecl());
    EltTys.push_back(MI == SPCache.end()
                         ? CreateCXXMemberFunction(Method, Unit, RecordTy)
                         : static_cast<llvm::Metadata *>(MI->second));
  }
}

void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit,
                                  SmallVectorImpl<llvm::Metadata *> &EltTys,
                                  llvm::DIType *RecordTy) {
  llvm::DenseSet<CanonicalDeclPtr<const CXXRecordDecl>> SeenTypes;
  CollectCXXBasesAux(RD, Unit, EltTys, RecordTy, RD->bases(), SeenTypes,
                     llvm::DINode::FlagZero);

  // If we are generating CodeView debug info, we also need to emit records for
  // indirect virtual base classes.
  if (CGM.getCodeGenOpts().EmitCodeView) {
    CollectCXXBasesAux(RD, Unit, EltTys, RecordTy, RD->vbases(), SeenTypes,
                       llvm::DINode::FlagIndirectVirtualBase);
  }
}

void CGDebugInfo::CollectCXXBasesAux(
    const CXXRecordDecl *RD, llvm::DIFile *Unit,
    SmallVectorImpl<llvm::Metadata *> &EltTys, llvm::DIType *RecordTy,
    const CXXRecordDecl::base_class_const_range &Bases,
    llvm::DenseSet<CanonicalDeclPtr<const CXXRecordDecl>> &SeenTypes,
    llvm::DINode::DIFlags StartingFlags) {
  const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
  for (const auto &BI : Bases) {
    const auto *Base =
        cast<CXXRecordDecl>(
            BI.getType()->castAsCanonical<RecordType>()->getDecl())
            ->getDefinition();
    if (!SeenTypes.insert(Base).second)
      continue;
    auto *BaseTy = getOrCreateType(BI.getType(), Unit);
    llvm::DINode::DIFlags BFlags = StartingFlags;
    uint64_t BaseOffset;
    uint32_t VBPtrOffset = 0;

    if (BI.isVirtual()) {
      if (CGM.getTarget().getCXXABI().isItaniumFamily()) {
        // virtual base offset offset is -ve. The code generator emits dwarf
        // expression where it expects +ve number.
        BaseOffset = 0 - CGM.getItaniumVTableContext()
                             .getVirtualBaseOffsetOffset(RD, Base)
                             .getQuantity();
      } else {
        // In the MS ABI, store the vbtable offset, which is analogous to the
        // vbase offset offset in Itanium.
        BaseOffset =
            4 * CGM.getMicrosoftVTableContext().getVBTableIndex(RD, Base);
        VBPtrOffset = CGM.getContext()
                          .getASTRecordLayout(RD)
                          .getVBPtrOffset()
                          .getQuantity();
      }
      BFlags |= llvm::DINode::FlagVirtual;
    } else
      BaseOffset = CGM.getContext().toBits(RL.getBaseClassOffset(Base));
    // FIXME: Inconsistent units for BaseOffset. It is in bytes when
    // BI->isVirtual() and bits when not.

    BFlags |= getAccessFlag(BI.getAccessSpecifier(), RD);
    llvm::DIType *DTy = DBuilder.createInheritance(RecordTy, BaseTy, BaseOffset,
                                                   VBPtrOffset, BFlags);
    EltTys.push_back(DTy);
  }
}

llvm::DINodeArray
CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs,
                                   llvm::DIFile *Unit) {
  if (!OArgs)
    return llvm::DINodeArray();
  TemplateArgs &Args = *OArgs;
  SmallVector<llvm::Metadata *, 16> TemplateParams;
  for (unsigned i = 0, e = Args.Args.size(); i != e; ++i) {
    const TemplateArgument &TA = Args.Args[i];
    StringRef Name;
    const bool defaultParameter = TA.getIsDefaulted();
    if (Args.TList)
      Name = Args.TList->getParam(i)->getName();

    switch (TA.getKind()) {
    case TemplateArgument::Type: {
      llvm::DIType *TTy = getOrCreateType(TA.getAsType(), Unit);
      TemplateParams.push_back(DBuilder.createTemplateTypeParameter(
          TheCU, Name, TTy, defaultParameter));

    } break;
    case TemplateArgument::Integral: {
      llvm::DIType *TTy = getOrCreateType(TA.getIntegralType(), Unit);
      TemplateParams.push_back(DBuilder.createTemplateValueParameter(
          TheCU, Name, TTy, defaultParameter,
          llvm::ConstantInt::get(CGM.getLLVMContext(), TA.getAsIntegral())));
    } break;
    case TemplateArgument::Declaration: {
      const ValueDecl *D = TA.getAsDecl();
      QualType T = TA.getParamTypeForDecl().getDesugaredType(CGM.getContext());
      llvm::DIType *TTy = getOrCreateType(T, Unit);
      llvm::Constant *V = nullptr;
      // Skip retrieve the value if that template parameter has cuda device
      // attribute, i.e. that value is not available at the host side.
      if (!CGM.getLangOpts().CUDA || CGM.getLangOpts().CUDAIsDevice ||
          !D->hasAttr<CUDADeviceAttr>()) {
        // Variable pointer template parameters have a value that is the address
        // of the variable.
        if (const auto *VD = dyn_cast<VarDecl>(D))
          V = CGM.GetAddrOfGlobalVar(VD);
        // Member function pointers have special support for building them,
        // though this is currently unsupported in LLVM CodeGen.
        else if (const auto *MD = dyn_cast<CXXMethodDecl>(D);
                 MD && MD->isImplicitObjectMemberFunction())
          V = CGM.getCXXABI().EmitMemberFunctionPointer(MD);
        else if (const auto *FD = dyn_cast<FunctionDecl>(D))
          V = CGM.GetAddrOfFunction(FD);
        // Member data pointers have special handling too to compute the fixed
        // offset within the object.
        else if (const auto *MPT =
                     dyn_cast<MemberPointerType>(T.getTypePtr())) {
          // These five lines (& possibly the above member function pointer
          // handling) might be able to be refactored to use similar code in
          // CodeGenModule::getMemberPointerConstant
          uint64_t fieldOffset = CGM.getContext().getFieldOffset(D);
          CharUnits chars =
              CGM.getContext().toCharUnitsFromBits((int64_t)fieldOffset);
          V = CGM.getCXXABI().EmitMemberDataPointer(MPT, chars);
        } else if (const auto *GD = dyn_cast<MSGuidDecl>(D)) {
          V = CGM.GetAddrOfMSGuidDecl(GD).getPointer();
        } else if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(D)) {
          if (T->isRecordType())
            V = ConstantEmitter(CGM).emitAbstract(
                SourceLocation(), TPO->getValue(), TPO->getType());
          else
            V = CGM.GetAddrOfTemplateParamObject(TPO).getPointer();
        }
        assert(V && "Failed to find template parameter pointer");
        V = V->stripPointerCasts();
      }
      TemplateParams.push_back(DBuilder.createTemplateValueParameter(
          TheCU, Name, TTy, defaultParameter, cast_or_null<llvm::Constant>(V)));
    } break;
    case TemplateArgument::NullPtr: {
      QualType T = TA.getNullPtrType();
      llvm::DIType *TTy = getOrCreateType(T, Unit);
      llvm::Constant *V = nullptr;
      // Special case member data pointer null values since they're actually -1
      // instead of zero.
      if (const auto *MPT = dyn_cast<MemberPointerType>(T.getTypePtr()))
        // But treat member function pointers as simple zero integers because
        // it's easier than having a special case in LLVM's CodeGen. If LLVM
        // CodeGen grows handling for values of non-null member function
        // pointers then perhaps we could remove this special case and rely on
        // EmitNullMemberPointer for member function pointers.
        if (MPT->isMemberDataPointer())
          V = CGM.getCXXABI().EmitNullMemberPointer(MPT);
      if (!V)
        V = llvm::ConstantInt::get(CGM.Int8Ty, 0);
      TemplateParams.push_back(DBuilder.createTemplateValueParameter(
          TheCU, Name, TTy, defaultParameter, V));
    } break;
    case TemplateArgument::StructuralValue: {
      QualType T = TA.getStructuralValueType();
      llvm::DIType *TTy = getOrCreateType(T, Unit);
      llvm::Constant *V = ConstantEmitter(CGM).emitAbstract(
          SourceLocation(), TA.getAsStructuralValue(), T);
      TemplateParams.push_back(DBuilder.createTemplateValueParameter(
          TheCU, Name, TTy, defaultParameter, V));
    } break;
    case TemplateArgument::Template: {
      std::string QualName;
      llvm::raw_string_ostream OS(QualName);
      TA.getAsTemplate().getAsTemplateDecl()->printQualifiedName(
          OS, getPrintingPolicy());
      TemplateParams.push_back(DBuilder.createTemplateTemplateParameter(
          TheCU, Name, nullptr, QualName, defaultParameter));
      break;
    }
    case TemplateArgument::Pack:
      TemplateParams.push_back(DBuilder.createTemplateParameterPack(
          TheCU, Name, nullptr,
          CollectTemplateParams({{nullptr, TA.getPackAsArray()}}, Unit)));
      break;
    case TemplateArgument::Expression: {
      const Expr *E = TA.getAsExpr();
      QualType T = E->getType();
      if (E->isGLValue())
        T = CGM.getContext().getLValueReferenceType(T);
      llvm::Constant *V = ConstantEmitter(CGM).emitAbstract(E, T);
      assert(V && "Expression in template argument isn't constant");
      llvm::DIType *TTy = getOrCreateType(T, Unit);
      TemplateParams.push_back(DBuilder.createTemplateValueParameter(
          TheCU, Name, TTy, defaultParameter, V->stripPointerCasts()));
    } break;
    // And the following should never occur:
    case TemplateArgument::TemplateExpansion:
    case TemplateArgument::Null:
      llvm_unreachable(
          "These argument types shouldn't exist in concrete types");
    }
  }
  return DBuilder.getOrCreateArray(TemplateParams);
}

std::optional<CGDebugInfo::TemplateArgs>
CGDebugInfo::GetTemplateArgs(const FunctionDecl *FD) const {
  if (FD->getTemplatedKind() ==
      FunctionDecl::TK_FunctionTemplateSpecialization) {
    const TemplateParameterList *TList = FD->getTemplateSpecializationInfo()
                                             ->getTemplate()
                                             ->getTemplateParameters();
    return {{TList, FD->getTemplateSpecializationArgs()->asArray()}};
  }
  return std::nullopt;
}
std::optional<CGDebugInfo::TemplateArgs>
CGDebugInfo::GetTemplateArgs(const VarDecl *VD) const {
  // Always get the full list of parameters, not just the ones from the
  // specialization. A partial specialization may have fewer parameters than
  // there are arguments.
  auto *TS = dyn_cast<VarTemplateSpecializationDecl>(VD);
  if (!TS)
    return std::nullopt;
  VarTemplateDecl *T = TS->getSpecializedTemplate();
  const TemplateParameterList *TList = T->getTemplateParameters();
  auto TA = TS->getTemplateArgs().asArray();
  return {{TList, TA}};
}
std::optional<CGDebugInfo::TemplateArgs>
CGDebugInfo::GetTemplateArgs(const RecordDecl *RD) const {
  if (auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
    // Always get the full list of parameters, not just the ones from the
    // specialization. A partial specialization may have fewer parameters than
    // there are arguments.
    TemplateParameterList *TPList =
        TSpecial->getSpecializedTemplate()->getTemplateParameters();
    const TemplateArgumentList &TAList = TSpecial->getTemplateArgs();
    return {{TPList, TAList.asArray()}};
  }
  return std::nullopt;
}

llvm::DINodeArray
CGDebugInfo::CollectFunctionTemplateParams(const FunctionDecl *FD,
                                           llvm::DIFile *Unit) {
  return CollectTemplateParams(GetTemplateArgs(FD), Unit);
}

llvm::DINodeArray CGDebugInfo::CollectVarTemplateParams(const VarDecl *VL,
                                                        llvm::DIFile *Unit) {
  return CollectTemplateParams(GetTemplateArgs(VL), Unit);
}

llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams(const RecordDecl *RD,
                                                        llvm::DIFile *Unit) {
  return CollectTemplateParams(GetTemplateArgs(RD), Unit);
}

void CGDebugInfo::CollectBTFDeclTagAnnotations(
    const Decl *D, SmallVectorImpl<llvm::Metadata *> &Annotations) {
  for (const auto *I : D->specific_attrs<BTFDeclTagAttr>()) {
    llvm::Metadata *Ops[2] = {
        llvm::MDString::get(CGM.getLLVMContext(), StringRef("btf_decl_tag")),
        llvm::MDString::get(CGM.getLLVMContext(), I->getBTFDeclTag())};
    Annotations.push_back(llvm::MDNode::get(CGM.getLLVMContext(), Ops));
  }
}

llvm::DINodeArray CGDebugInfo::CollectBTFDeclTagAnnotations(const Decl *D) {
  if (!D->hasAttr<BTFDeclTagAttr>())
    return nullptr;

  SmallVector<llvm::Metadata *, 4> Annotations;
  CollectBTFDeclTagAnnotations(D, Annotations);
  return DBuilder.getOrCreateArray(Annotations);
}

void CGDebugInfo::CollectBTFTypeTagAnnotations(
    QualType Ty, SmallVectorImpl<llvm::Metadata *> &Annotations) {
  const BTFTagAttributedType *BTFAttrTy;
  if (auto *Atomic = Ty->getAs<AtomicType>())
    BTFAttrTy = dyn_cast<BTFTagAttributedType>(Atomic->getValueType());
  else
    BTFAttrTy = dyn_cast<BTFTagAttributedType>(Ty);

  while (BTFAttrTy) {
    StringRef Tag = BTFAttrTy->getAttr()->getBTFTypeTag();
    if (!Tag.empty()) {
      llvm::Metadata *Ops[2] = {
          llvm::MDString::get(CGM.getLLVMContext(), StringRef("btf_type_tag")),
          llvm::MDString::get(CGM.getLLVMContext(), Tag)};
      Annotations.insert(Annotations.begin(),
                         llvm::MDNode::get(CGM.getLLVMContext(), Ops));
    }
    BTFAttrTy = dyn_cast<BTFTagAttributedType>(BTFAttrTy->getWrappedType());
  }
}

llvm::DIType *CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile *Unit) {
  if (VTablePtrType)
    return VTablePtrType;

  ASTContext &Context = CGM.getContext();

  /* Function type */
  llvm::Metadata *STy = getOrCreateType(Context.IntTy, Unit);
  llvm::DITypeArray SElements = DBuilder.getOrCreateTypeArray(STy);
  llvm::DIType *SubTy = DBuilder.createSubroutineType(SElements);
  unsigned Size = Context.getTypeSize(Context.VoidPtrTy);
  unsigned VtblPtrAddressSpace = CGM.getTarget().getVtblPtrAddressSpace();
  std::optional<unsigned> DWARFAddressSpace =
      CGM.getTarget().getDWARFAddressSpace(VtblPtrAddressSpace);

  llvm::DIType *vtbl_ptr_type = DBuilder.createPointerType(
      SubTy, Size, 0, DWARFAddressSpace, "__vtbl_ptr_type");
  VTablePtrType = DBuilder.createPointerType(vtbl_ptr_type, Size);
  return VTablePtrType;
}

StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
  // Copy the gdb compatible name on the side and use its reference.
  return internString("_vptr$", RD->getNameAsString());
}

// Emit symbol for the debugger that points to the vtable address for
// the given class. The symbol is named as '__clang_vtable'.
// The debugger does not need to know any details about the contents of the
// vtable as it can work this out using its knowledge of the ABI and the
// existing information in the DWARF. The type is assumed to be 'void *'.
void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable,
                                   const CXXRecordDecl *RD) {
  if (!CGM.getTarget().getCXXABI().isItaniumFamily())
    return;
  if (DebugKind <= llvm::codegenoptions::DebugLineTablesOnly)
    return;

  // On COFF platform, we shouldn't emit a reference to an external entity (i.e.
  // VTable) into debug info, which is constructed within a discardable section.
  // If that entity ends up implicitly dllimported from another DLL, the linker
  // may produce a runtime pseudo-relocation for it (BFD-ld only. LLD prohibits
  // to emit such relocation). If the debug section is stripped, the runtime
  // pseudo-relocation points to memory space outside of the module, causing an
  // access violation.
  if (CGM.getTarget().getTriple().isOSBinFormatCOFF() &&
      VTable->isDeclarationForLinker())
    return;

  ASTContext &Context = CGM.getContext();
  StringRef SymbolName = "__clang_vtable";
  SourceLocation Loc;
  QualType VoidPtr = Context.getPointerType(Context.VoidTy);

  // We deal with two different contexts:
  // - The type for the variable, which is part of the class that has the
  //   vtable, is placed in the context of the DICompositeType metadata.
  // - The DIGlobalVariable for the vtable is put in the DICompileUnitScope.

  // The created non-member should be mark as 'artificial'. It will be
  // placed inside the scope of the C++ class/structure.
  llvm::DIScope *DContext = getContextDescriptor(RD, TheCU);
  auto *Ctxt = cast<llvm::DICompositeType>(DContext);
  llvm::DIFile *Unit = getOrCreateFile(Loc);
  llvm::DIType *VTy = getOrCreateType(VoidPtr, Unit);
  llvm::DINode::DIFlags Flags = getAccessFlag(AccessSpecifier::AS_private, RD) |
                                llvm::DINode::FlagArtificial;
  auto Tag = CGM.getCodeGenOpts().DwarfVersion >= 5
                 ? llvm::dwarf::DW_TAG_variable
                 : llvm::dwarf::DW_TAG_member;
  llvm::DIDerivedType *DT = DBuilder.createStaticMemberType(
      Ctxt, SymbolName, Unit, /*LineNumber=*/0, VTy, Flags,
      /*Val=*/nullptr, Tag);

  // Use the same vtable pointer to global alignment for the symbol.
  unsigned PAlign = CGM.getVtableGlobalVarAlignment();

  // The global variable is in the CU scope, and links back to the type it's
  // "within" via the declaration field.
  llvm::DIGlobalVariableExpression *GVE =
      DBuilder.createGlobalVariableExpression(
          TheCU, SymbolName, VTable->getName(), Unit, /*LineNo=*/0,
          getOrCreateType(VoidPtr, Unit), VTable->hasLocalLinkage(),
          /*isDefined=*/true, nullptr, DT, /*TemplateParameters=*/nullptr,
          PAlign);
  VTable->addDebugInfo(GVE);
}

StringRef CGDebugInfo::getDynamicInitializerName(const VarDecl *VD,
                                                 DynamicInitKind StubKind,
                                                 llvm::Function *InitFn) {
  // If we're not emitting codeview, use the mangled name. For Itanium, this is
  // arbitrary.
  if (!CGM.getCodeGenOpts().EmitCodeView ||
      StubKind == DynamicInitKind::GlobalArrayDestructor)
    return InitFn->getName();

  // Print the normal qualified name for the variable, then break off the last
  // NNS, and add the appropriate other text. Clang always prints the global
  // variable name without template arguments, so we can use rsplit("::") and
  // then recombine the pieces.
  SmallString<128> QualifiedGV;
  StringRef Quals;
  StringRef GVName;
  {
    llvm::raw_svector_ostream OS(QualifiedGV);
    VD->printQualifiedName(OS, getPrintingPolicy());
    std::tie(Quals, GVName) = OS.str().rsplit("::");
    if (GVName.empty())
      std::swap(Quals, GVName);
  }

  SmallString<128> InitName;
  llvm::raw_svector_ostream OS(InitName);
  if (!Quals.empty())
    OS << Quals << "::";

  switch (StubKind) {
  case DynamicInitKind::NoStub:
  case DynamicInitKind::GlobalArrayDestructor:
    llvm_unreachable("not an initializer");
  case DynamicInitKind::Initializer:
    OS << "`dynamic initializer for '";
    break;
  case DynamicInitKind::AtExit:
    OS << "`dynamic atexit destructor for '";
    break;
  }

  OS << GVName;

  // Add any template specialization args.
  if (const auto *VTpl = dyn_cast<VarTemplateSpecializationDecl>(VD)) {
    printTemplateArgumentList(OS, VTpl->getTemplateArgs().asArray(),
                              getPrintingPolicy());
  }

  OS << '\'';

  return internString(OS.str());
}

void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit,
                                    SmallVectorImpl<llvm::Metadata *> &EltTys) {
  // If this class is not dynamic then there is not any vtable info to collect.
  if (!RD->isDynamicClass())
    return;

  // Don't emit any vtable shape or vptr info if this class doesn't have an
  // extendable vfptr. This can happen if the class doesn't have virtual
  // methods, or in the MS ABI if those virtual methods only come from virtually
  // inherited bases.
  const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
  if (!RL.hasExtendableVFPtr())
    return;

  // CodeView needs to know how large the vtable of every dynamic class is, so
  // emit a special named pointer type into the element list. The vptr type
  // points to this type as well.
  llvm::DIType *VPtrTy = nullptr;
  bool NeedVTableShape = CGM.getCodeGenOpts().EmitCodeView &&
                         CGM.getTarget().getCXXABI().isMicrosoft();
  if (NeedVTableShape) {
    uint64_t PtrWidth =
        CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
    const VTableLayout &VFTLayout =
        CGM.getMicrosoftVTableContext().getVFTableLayout(RD, CharUnits::Zero());
    unsigned VSlotCount =
        VFTLayout.vtable_components().size() - CGM.getLangOpts().RTTIData;
    unsigned VTableWidth = PtrWidth * VSlotCount;
    unsigned VtblPtrAddressSpace = CGM.getTarget().getVtblPtrAddressSpace();
    std::optional<unsigned> DWARFAddressSpace =
        CGM.getTarget().getDWARFAddressSpace(VtblPtrAddressSpace);

    // Create a very wide void* type and insert it directly in the element list.
    llvm::DIType *VTableType = DBuilder.createPointerType(
        nullptr, VTableWidth, 0, DWARFAddressSpace, "__vtbl_ptr_type");
    EltTys.push_back(VTableType);

    // The vptr is a pointer to this special vtable type.
    VPtrTy = DBuilder.createPointerType(VTableType, PtrWidth);
  }

  // If there is a primary base then the artificial vptr member lives there.
  if (RL.getPrimaryBase())
    return;

  if (!VPtrTy)
    VPtrTy = getOrCreateVTablePtrType(Unit);

  unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
  llvm::DIType *VPtrMember =
      DBuilder.createMemberType(Unit, getVTableName(RD), Unit, 0, Size, 0, 0,
                                llvm::DINode::FlagArtificial, VPtrTy);
  EltTys.push_back(VPtrMember);
}

llvm::DIType *CGDebugInfo::getOrCreateRecordType(QualType RTy,
                                                 SourceLocation Loc) {
  assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
  llvm::DIType *T = getOrCreateType(RTy, getOrCreateFile(Loc));
  return T;
}

llvm::DIType *CGDebugInfo::getOrCreateInterfaceType(QualType D,
                                                    SourceLocation Loc) {
  return getOrCreateStandaloneType(D, Loc);
}

llvm::DIType *CGDebugInfo::getOrCreateStandaloneType(QualType D,
                                                     SourceLocation Loc) {
  assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
  assert(!D.isNull() && "null type");
  llvm::DIType *T = getOrCreateType(D, getOrCreateFile(Loc));
  assert(T && "could not create debug info for type");

  RetainedTypes.push_back(D.getAsOpaquePtr());
  return T;
}

void CGDebugInfo::addHeapAllocSiteMetadata(llvm::CallBase *CI,
                                           QualType AllocatedTy,
                                           SourceLocation Loc) {
  if (CGM.getCodeGenOpts().getDebugInfo() <=
      llvm::codegenoptions::DebugLineTablesOnly)
    return;
  llvm::MDNode *node;
  if (AllocatedTy->isVoidType())
    node = llvm::MDNode::get(CGM.getLLVMContext(), {});
  else
    node = getOrCreateType(AllocatedTy, getOrCreateFile(Loc));

  CI->setMetadata("heapallocsite", node);
}

void CGDebugInfo::completeType(const EnumDecl *ED) {
  if (DebugKind <= llvm::codegenoptions::DebugLineTablesOnly)
    return;
  CanQualType Ty = CGM.getContext().getCanonicalTagType(ED);
  void *TyPtr = Ty.getAsOpaquePtr();
  auto I = TypeCache.find(TyPtr);
  if (I == TypeCache.end() || !cast<llvm::DIType>(I->second)->isForwardDecl())
    return;
  llvm::DIType *Res = CreateTypeDefinition(dyn_cast<EnumType>(Ty));
  assert(!Res->isForwardDecl());
  TypeCache[TyPtr].reset(Res);
}

void CGDebugInfo::completeType(const RecordDecl *RD) {
  if (DebugKind > llvm::codegenoptions::LimitedDebugInfo ||
      !CGM.getLangOpts().CPlusPlus)
    completeRequiredType(RD);
}

/// Return true if the class or any of its methods are marked dllimport.
static bool isClassOrMethodDLLImport(const CXXRecordDecl *RD) {
  if (RD->hasAttr<DLLImportAttr>())
    return true;
  for (const CXXMethodDecl *MD : RD->methods())
    if (MD->hasAttr<DLLImportAttr>())
      return true;
  return false;
}

/// Does a type definition exist in an imported clang module?
static bool isDefinedInClangModule(const RecordDecl *RD) {
  // Only definitions that where imported from an AST file come from a module.
  if (!RD || !RD->isFromASTFile())
    return false;
  // Anonymous entities cannot be addressed. Treat them as not from module.
  if (!RD->isExternallyVisible() && RD->getName().empty())
    return false;
  if (auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD)) {
    if (!CXXDecl->isCompleteDefinition())
      return false;
    // Check wether RD is a template.
    auto TemplateKind = CXXDecl->getTemplateSpecializationKind();
    if (TemplateKind != TSK_Undeclared) {
      // Unfortunately getOwningModule() isn't accurate enough to find the
      // owning module of a ClassTemplateSpecializationDecl that is inside a
      // namespace spanning multiple modules.
      bool Explicit = false;
      if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(CXXDecl))
        Explicit = TD->isExplicitInstantiationOrSpecialization();
      if (!Explicit && CXXDecl->getEnclosingNamespaceContext())
        return false;
      // This is a template, check the origin of the first member.
      if (CXXDecl->fields().empty())
        return TemplateKind == TSK_ExplicitInstantiationDeclaration;
      if (!CXXDecl->field_begin()->isFromASTFile())
        return false;
    }
  }
  return true;
}

void CGDebugInfo::completeClassData(const RecordDecl *RD) {
  if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
    if (CXXRD->isDynamicClass() &&
        CGM.getVTableLinkage(CXXRD) ==
            llvm::GlobalValue::AvailableExternallyLinkage &&
        !isClassOrMethodDLLImport(CXXRD))
      return;

  if (DebugTypeExtRefs && isDefinedInClangModule(RD->getDefinition()))
    return;

  completeClass(RD);
}

void CGDebugInfo::completeClass(const RecordDecl *RD) {
  if (DebugKind <= llvm::codegenoptions::DebugLineTablesOnly)
    return;
  CanQualType Ty = CGM.getContext().getCanonicalTagType(RD);
  void *TyPtr = Ty.getAsOpaquePtr();
  auto I = TypeCache.find(TyPtr);
  if (I != TypeCache.end() && !cast<llvm::DIType>(I->second)->isForwardDecl())
    return;

  // We want the canonical definition of the structure to not
  // be the typedef. Since that would lead to circular typedef
  // metadata.
  auto [Res, PrefRes] = CreateTypeDefinition(dyn_cast<RecordType>(Ty));
  assert(!Res->isForwardDecl());
  TypeCache[TyPtr].reset(Res);
}

static bool hasExplicitMemberDefinition(CXXRecordDecl::method_iterator I,
                                        CXXRecordDecl::method_iterator End) {
  for (CXXMethodDecl *MD : llvm::make_range(I, End))
    if (FunctionDecl *Tmpl = MD->getInstantiatedFromMemberFunction())
      if (!Tmpl->isImplicit() && Tmpl->isThisDeclarationADefinition() &&
          !MD->getMemberSpecializationInfo()->isExplicitSpecialization())
        return true;
  return false;
}

static bool canUseCtorHoming(const CXXRecordDecl *RD) {
  // Constructor homing can be used for classes that cannnot be constructed
  // without emitting code for one of their constructors. This is classes that
  // don't have trivial or constexpr constructors, or can be created from
  // aggregate initialization. Also skip lambda objects because they don't call
  // constructors.

  // Skip this optimization if the class or any of its methods are marked
  // dllimport.
  if (isClassOrMethodDLLImport(RD))
    return false;

  if (RD->isLambda() || RD->isAggregate() ||
      RD->hasTrivialDefaultConstructor() ||
      RD->hasConstexprNonCopyMoveConstructor())
    return false;

  for (const CXXConstructorDecl *Ctor : RD->ctors()) {
    if (Ctor->isCopyOrMoveConstructor())
      continue;
    if (!Ctor->isDeleted())
      return true;
  }
  return false;
}

static bool shouldOmitDefinition(llvm::codegenoptions::DebugInfoKind DebugKind,
                                 bool DebugTypeExtRefs, const RecordDecl *RD,
                                 const LangOptions &LangOpts) {
  if (DebugTypeExtRefs && isDefinedInClangModule(RD->getDefinition()))
    return true;

  if (auto *ES = RD->getASTContext().getExternalSource())
    if (ES->hasExternalDefinitions(RD) == ExternalASTSource::EK_Always)
      return true;

  // Only emit forward declarations in line tables only to keep debug info size
  // small. This only applies to CodeView, since we don't emit types in DWARF
  // line tables only.
  if (DebugKind == llvm::codegenoptions::DebugLineTablesOnly)
    return true;

  if (DebugKind > llvm::codegenoptions::LimitedDebugInfo ||
      RD->hasAttr<StandaloneDebugAttr>())
    return false;

  if (!LangOpts.CPlusPlus)
    return false;

  if (!RD->isCompleteDefinitionRequired())
    return true;

  const auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD);

  if (!CXXDecl)
    return false;

  // Only emit complete debug info for a dynamic class when its vtable is
  // emitted.  However, Microsoft debuggers don't resolve type information
  // across DLL boundaries, so skip this optimization if the class or any of its
  // methods are marked dllimport. This isn't a complete solution, since objects
  // without any dllimport methods can be used in one DLL and constructed in
  // another, but it is the current behavior of LimitedDebugInfo.
  if (CXXDecl->hasDefinition() && CXXDecl->isDynamicClass() &&
      !isClassOrMethodDLLImport(CXXDecl) && !CXXDecl->hasAttr<MSNoVTableAttr>())
    return true;

  TemplateSpecializationKind Spec = TSK_Undeclared;
  if (const auto *SD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
    Spec = SD->getSpecializationKind();

  if (Spec == TSK_ExplicitInstantiationDeclaration &&
      hasExplicitMemberDefinition(CXXDecl->method_begin(),
                                  CXXDecl->method_end()))
    return true;

  // In constructor homing mode, only emit complete debug info for a class
  // when its constructor is emitted.
  if ((DebugKind == llvm::codegenoptions::DebugInfoConstructor) &&
      canUseCtorHoming(CXXDecl))
    return true;

  return false;
}

void CGDebugInfo::completeRequiredType(const RecordDecl *RD) {
  if (shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD, CGM.getLangOpts()))
    return;

  CanQualType Ty = CGM.getContext().getCanonicalTagType(RD);
  llvm::DIType *T = getTypeOrNull(Ty);
  if (T && T->isForwardDecl())
    completeClassData(RD);
}

llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) {
  RecordDecl *RD = Ty->getDecl()->getDefinitionOrSelf();
  llvm::DIType *T = cast_or_null<llvm::DIType>(getTypeOrNull(QualType(Ty, 0)));
  if (T || shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD,
                                CGM.getLangOpts())) {
    if (!T)
      T = getOrCreateRecordFwdDecl(Ty, getDeclContextDescriptor(RD));
    return T;
  }

  auto [Def, Pref] = CreateTypeDefinition(Ty);

  return Pref ? Pref : Def;
}

llvm::DIType *CGDebugInfo::GetPreferredNameType(const CXXRecordDecl *RD,
                                                llvm::DIFile *Unit) {
  if (!RD)
    return nullptr;

  auto const *PNA = RD->getAttr<PreferredNameAttr>();
  if (!PNA)
    return nullptr;

  return getOrCreateType(PNA->getTypedefType(), Unit);
}

std::pair<llvm::DIType *, llvm::DIType *>
CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
  RecordDecl *RD = Ty->getDecl()->getDefinitionOrSelf();

  // Get overall information about the record type for the debug info.
  llvm::DIFile *DefUnit = getOrCreateFile(RD->getLocation());

  // Records and classes and unions can all be recursive.  To handle them, we
  // first generate a debug descriptor for the struct as a forward declaration.
  // Then (if it is a definition) we go through and get debug info for all of
  // its members.  Finally, we create a descriptor for the complete type (which
  // may refer to the forward decl if the struct is recursive) and replace all
  // uses of the forward declaration with the final definition.
  llvm::DICompositeType *FwdDecl = getOrCreateLimitedType(Ty);

  const RecordDecl *D = RD->getDefinition();
  if (!D || !D->isCompleteDefinition())
    return {FwdDecl, nullptr};

  if (const auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD))
    CollectContainingType(CXXDecl, FwdDecl);

  // Push the struct on region stack.
  LexicalBlockStack.emplace_back(&*FwdDecl);
  RegionMap[RD].reset(FwdDecl);

  // Convert all the elements.
  SmallVector<llvm::Metadata *, 16> EltTys;
  // what about nested types?

  // Note: The split of CXXDecl information here is intentional, the
  // gdb tests will depend on a certain ordering at printout. The debug
  // information offsets are still correct if we merge them all together
  // though.
  const auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
  if (CXXDecl) {
    CollectCXXBases(CXXDecl, DefUnit, EltTys, FwdDecl);
    CollectVTableInfo(CXXDecl, DefUnit, EltTys);
  }

  // Collect data fields (including static variables and any initializers).
  CollectRecordFields(RD, DefUnit, EltTys, FwdDecl);
  if (CXXDecl && !CGM.getCodeGenOpts().DebugOmitUnreferencedMethods)
    CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl);

  LexicalBlockStack.pop_back();
  RegionMap.erase(RD);

  llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
  DBuilder.replaceArrays(FwdDecl, Elements);

  if (FwdDecl->isTemporary())
    FwdDecl =
        llvm::MDNode::replaceWithPermanent(llvm::TempDICompositeType(FwdDecl));

  RegionMap[RD].reset(FwdDecl);

  if (CGM.getCodeGenOpts().getDebuggerTuning() == llvm::DebuggerKind::LLDB)
    if (auto *PrefDI = GetPreferredNameType(CXXDecl, DefUnit))
      return {FwdDecl, PrefDI};

  return {FwdDecl, nullptr};
}

llvm::DIType *CGDebugInfo::CreateType(const ObjCObjectType *Ty,
                                      llvm::DIFile *Unit) {
  // Ignore protocols.
  return getOrCreateType(Ty->getBaseType(), Unit);
}

llvm::DIType *CGDebugInfo::CreateType(const ObjCTypeParamType *Ty,
                                      llvm::DIFile *Unit) {
  // Ignore protocols.
  SourceLocation Loc = Ty->getDecl()->getLocation();

  // Use Typedefs to represent ObjCTypeParamType.
  return DBuilder.createTypedef(
      getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit),
      Ty->getDecl()->getName(), getOrCreateFile(Loc), getLineNumber(Loc),
      getDeclContextDescriptor(Ty->getDecl()));
}

/// \return true if Getter has the default name for the property PD.
static bool hasDefaultGetterName(const ObjCPropertyDecl *PD,
                                 const ObjCMethodDecl *Getter) {
  assert(PD);
  if (!Getter)
    return true;

  assert(Getter->getDeclName().isObjCZeroArgSelector());
  return PD->getName() ==
         Getter->getDeclName().getObjCSelector().getNameForSlot(0);
}

/// \return true if Setter has the default name for the property PD.
static bool hasDefaultSetterName(const ObjCPropertyDecl *PD,
                                 const ObjCMethodDecl *Setter) {
  assert(PD);
  if (!Setter)
    return true;

  assert(Setter->getDeclName().isObjCOneArgSelector());
  return SelectorTable::constructSetterName(PD->getName()) ==
         Setter->getDeclName().getObjCSelector().getNameForSlot(0);
}

llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
                                      llvm::DIFile *Unit) {
  ObjCInterfaceDecl *ID = Ty->getDecl();
  if (!ID)
    return nullptr;

  auto RuntimeLang = static_cast<llvm::dwarf::SourceLanguage>(
      TheCU->getSourceLanguage().getUnversionedName());

  // Return a forward declaration if this type was imported from a clang module,
  // and this is not the compile unit with the implementation of the type (which
  // may contain hidden ivars).
  if (DebugTypeExtRefs && ID->isFromASTFile() && ID->getDefinition() &&
      !ID->getImplementation())
    return DBuilder.createForwardDecl(
        llvm::dwarf::DW_TAG_structure_type, ID->getName(),
        getDeclContextDescriptor(ID), Unit, 0, RuntimeLang);

  // Get overall information about the record type for the debug info.
  llvm::DIFile *DefUnit = getOrCreateFile(ID->getLocation());
  unsigned Line = getLineNumber(ID->getLocation());

  // If this is just a forward declaration return a special forward-declaration
  // debug type since we won't be able to lay out the entire type.
  ObjCInterfaceDecl *Def = ID->getDefinition();
  if (!Def || !Def->getImplementation()) {
    llvm::DIScope *Mod = getParentModuleOrNull(ID);
    llvm::DIType *FwdDecl = DBuilder.createReplaceableCompositeType(
        llvm::dwarf::DW_TAG_structure_type, ID->getName(), Mod ? Mod : TheCU,
        DefUnit, Line, RuntimeLang);
    ObjCInterfaceCache.push_back(ObjCInterfaceCacheEntry(Ty, FwdDecl, Unit));
    return FwdDecl;
  }

  return CreateTypeDefinition(Ty, Unit);
}

llvm::DIModule *CGDebugInfo::getOrCreateModuleRef(ASTSourceDescriptor Mod,
                                                  bool CreateSkeletonCU) {
  // Use the Module pointer as the key into the cache. This is a
  // nullptr if the "Module" is a PCH, which is safe because we don't
  // support chained PCH debug info, so there can only be a single PCH.
  const Module *M = Mod.getModuleOrNull();
  auto ModRef = ModuleCache.find(M);
  if (ModRef != ModuleCache.end())
    return cast<llvm::DIModule>(ModRef->second);

  // Macro definitions that were defined with "-D" on the command line.
  SmallString<128> ConfigMacros;
  {
    llvm::raw_svector_ostream OS(ConfigMacros);
    const auto &PPOpts = CGM.getPreprocessorOpts();
    unsigned I = 0;
    // Translate the macro definitions back into a command line.
    for (auto &M : PPOpts.Macros) {
      if (++I > 1)
        OS << " ";
      const std::string &Macro = M.first;
      bool Undef = M.second;
      OS << "\"-" << (Undef ? 'U' : 'D');
      for (char c : Macro)
        switch (c) {
        case '\\':
          OS << "\\\\";
          break;
        case '"':
          OS << "\\\"";
          break;
        default:
          OS << c;
        }
      OS << '\"';
    }
  }

  bool IsRootModule = M ? !M->Parent : true;
  // When a module name is specified as -fmodule-name, that module gets a
  // clang::Module object, but it won't actually be built or imported; it will
  // be textual.
  if (CreateSkeletonCU && IsRootModule && Mod.getASTFile().empty() && M)
    assert(StringRef(M->Name).starts_with(CGM.getLangOpts().ModuleName) &&
           "clang module without ASTFile must be specified by -fmodule-name");

  // Return a StringRef to the remapped Path.
  auto RemapPath = [this](StringRef Path) -> std::string {
    std::string Remapped = remapDIPath(Path);
    StringRef Relative(Remapped);
    StringRef CompDir = TheCU->getDirectory();
    if (CompDir.empty())
      return Remapped;

    if (Relative.consume_front(CompDir))
      Relative.consume_front(llvm::sys::path::get_separator());

    return Relative.str();
  };

  if (CreateSkeletonCU && IsRootModule && !Mod.getASTFile().empty()) {
    // 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 = 0;
    if (const auto &ModSig = Mod.getSignature())
      Signature = ModSig.truncatedValue();
    else
      Signature = ~1ULL;

    llvm::DIBuilder DIB(CGM.getModule());
    SmallString<0> PCM;
    if (!llvm::sys::path::is_absolute(Mod.getASTFile())) {
      if (CGM.getHeaderSearchOpts().ModuleFileHomeIsCwd)
        PCM = getCurrentDirname();
      else
        PCM = Mod.getPath();
    }
    llvm::sys::path::append(PCM, Mod.getASTFile());
    DIB.createCompileUnit(
        TheCU->getSourceLanguage(),
        // TODO: Support "Source" from external AST providers?
        DIB.createFile(Mod.getModuleName(), TheCU->getDirectory()),
        TheCU->getProducer(), false, StringRef(), 0, RemapPath(PCM),
        llvm::DICompileUnit::FullDebug, Signature);
    DIB.finalize();
  }

  llvm::DIModule *Parent =
      IsRootModule ? nullptr
                   : getOrCreateModuleRef(ASTSourceDescriptor(*M->Parent),
                                          CreateSkeletonCU);
  StringRef IncludePath = Mod.getPath();
  if (!CGM.getCodeGenOpts().DebugRecordSysroot) {
    StringRef Sysroot = CGM.getHeaderSearchOpts().Sysroot;
    if (!Sysroot.empty() && IncludePath.starts_with(Sysroot))
      IncludePath = "";
  }
  llvm::DIModule *DIMod =
      DBuilder.createModule(Parent, Mod.getModuleName(), ConfigMacros,
                            RemapPath(IncludePath));
  ModuleCache[M].reset(DIMod);
  return DIMod;
}

llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
                                                llvm::DIFile *Unit) {
  ObjCInterfaceDecl *ID = Ty->getDecl();
  llvm::DIFile *DefUnit = getOrCreateFile(ID->getLocation());
  unsigned Line = getLineNumber(ID->getLocation());

  unsigned RuntimeLang = TheCU->getSourceLanguage().getUnversionedName();

  // Bit size, align and offset of the type.
  uint64_t Size = CGM.getContext().getTypeSize(Ty);
  auto Align = getTypeAlignIfRequired(Ty, CGM.getContext());

  llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
  if (ID->getImplementation())
    Flags |= llvm::DINode::FlagObjcClassComplete;

  llvm::DIScope *Mod = getParentModuleOrNull(ID);
  llvm::DICompositeType *RealDecl = DBuilder.createStructType(
      Mod ? Mod : Unit, ID->getName(), DefUnit, Line, Size, Align, Flags,
      nullptr, llvm::DINodeArray(), RuntimeLang);

  QualType QTy(Ty, 0);
  TypeCache[QTy.getAsOpaquePtr()].reset(RealDecl);

  // Push the struct on region stack.
  LexicalBlockStack.emplace_back(RealDecl);
  RegionMap[Ty->getDecl()].reset(RealDecl);

  // Convert all the elements.
  SmallVector<llvm::Metadata *, 16> EltTys;

  ObjCInterfaceDecl *SClass = ID->getSuperClass();
  if (SClass) {
    llvm::DIType *SClassTy =
        getOrCreateType(CGM.getContext().getObjCInterfaceType(SClass), Unit);
    if (!SClassTy)
      return nullptr;

    llvm::DIType *InhTag = DBuilder.createInheritance(RealDecl, SClassTy, 0, 0,
                                                      llvm::DINode::FlagZero);
    EltTys.push_back(InhTag);
  }

  // Create entries for all of the properties.
  auto AddProperty = [&](const ObjCPropertyDecl *PD) {
    SourceLocation Loc = PD->getLocation();
    llvm::DIFile *PUnit = getOrCreateFile(Loc);
    unsigned PLine = getLineNumber(Loc);
    ObjCMethodDecl *Getter = PD->getGetterMethodDecl();
    ObjCMethodDecl *Setter = PD->getSetterMethodDecl();
    llvm::MDNode *PropertyNode = DBuilder.createObjCProperty(
        PD->getName(), PUnit, PLine,
        hasDefaultGetterName(PD, Getter) ? ""
                                         : getSelectorName(PD->getGetterName()),
        hasDefaultSetterName(PD, Setter) ? ""
                                         : getSelectorName(PD->getSetterName()),
        PD->getPropertyAttributes(), getOrCreateType(PD->getType(), PUnit));
    EltTys.push_back(PropertyNode);
  };
  {
    // Use 'char' for the isClassProperty bit as DenseSet requires space for
    // the empty key in the data type (and bool is too small for that).
    typedef std::pair<char, const IdentifierInfo *> IsClassAndIdent;
    /// List of already emitted properties. Two distinct class and instance
    /// properties can share the same identifier (but not two instance
    /// properties or two class properties).
    llvm::DenseSet<IsClassAndIdent> PropertySet;
    /// Returns the IsClassAndIdent key for the given property.
    auto GetIsClassAndIdent = [](const ObjCPropertyDecl *PD) {
      return std::make_pair(PD->isClassProperty(), PD->getIdentifier());
    };
    for (const ObjCCategoryDecl *ClassExt : ID->known_extensions())
      for (auto *PD : ClassExt->properties()) {
        PropertySet.insert(GetIsClassAndIdent(PD));
        AddProperty(PD);
      }
    for (const auto *PD : ID->properties()) {
      // Don't emit duplicate metadata for properties that were already in a
      // class extension.
      if (!PropertySet.insert(GetIsClassAndIdent(PD)).second)
        continue;
      AddProperty(PD);
    }
  }

  const ASTRecordLayout &RL = CGM.getContext().getASTObjCInterfaceLayout(ID);
  unsigned FieldNo = 0;
  for (ObjCIvarDecl *Field = ID->all_declared_ivar_begin(); Field;
       Field = Field->getNextIvar(), ++FieldNo) {
    llvm::DIType *FieldTy = getOrCreateType(Field->getType(), Unit);
    if (!FieldTy)
      return nullptr;

    StringRef FieldName = Field->getName();

    // Ignore unnamed fields.
    if (FieldName.empty())
      continue;

    // Get the location for the field.
    llvm::DIFile *FieldDefUnit = getOrCreateFile(Field->getLocation());
    unsigned FieldLine = getLineNumber(Field->getLocation());
    QualType FType = Field->getType();
    uint64_t FieldSize = 0;
    uint32_t FieldAlign = 0;

    if (!FType->isIncompleteArrayType()) {

      // Bit size, align and offset of the type.
      FieldSize = Field->isBitField() ? Field->getBitWidthValue()
                                      : CGM.getContext().getTypeSize(FType);
      FieldAlign = getTypeAlignIfRequired(FType, CGM.getContext());
    }

    uint64_t FieldOffset;
    if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {
      // We don't know the runtime offset of an ivar if we're using the
      // non-fragile ABI.  For bitfields, use the bit offset into the first
      // byte of storage of the bitfield.  For other fields, use zero.
      if (Field->isBitField()) {
        FieldOffset =
            CGM.getObjCRuntime().ComputeBitfieldBitOffset(CGM, ID, Field);
        FieldOffset %= CGM.getContext().getCharWidth();
      } else {
        FieldOffset = 0;
      }
    } else {
      FieldOffset = RL.getFieldOffset(FieldNo);
    }

    llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
    if (Field->getAccessControl() == ObjCIvarDecl::Protected)
      Flags = llvm::DINode::FlagProtected;
    else if (Field->getAccessControl() == ObjCIvarDecl::Private)
      Flags = llvm::DINode::FlagPrivate;
    else if (Field->getAccessControl() == ObjCIvarDecl::Public)
      Flags = llvm::DINode::FlagPublic;

    if (Field->isBitField())
      Flags |= llvm::DINode::FlagBitField;

    llvm::MDNode *PropertyNode = nullptr;
    if (ObjCImplementationDecl *ImpD = ID->getImplementation()) {
      if (ObjCPropertyImplDecl *PImpD =
              ImpD->FindPropertyImplIvarDecl(Field->getIdentifier())) {
        if (ObjCPropertyDecl *PD = PImpD->getPropertyDecl()) {
          SourceLocation Loc = PD->getLocation();
          llvm::DIFile *PUnit = getOrCreateFile(Loc);
          unsigned PLine = getLineNumber(Loc);
          ObjCMethodDecl *Getter = PImpD->getGetterMethodDecl();
          ObjCMethodDecl *Setter = PImpD->getSetterMethodDecl();
          PropertyNode = DBuilder.createObjCProperty(
              PD->getName(), PUnit, PLine,
              hasDefaultGetterName(PD, Getter)
                  ? ""
                  : getSelectorName(PD->getGetterName()),
              hasDefaultSetterName(PD, Setter)
                  ? ""
                  : getSelectorName(PD->getSetterName()),
              PD->getPropertyAttributes(),
              getOrCreateType(PD->getType(), PUnit));
        }
      }
    }
    FieldTy = DBuilder.createObjCIVar(FieldName, FieldDefUnit, FieldLine,
                                      FieldSize, FieldAlign, FieldOffset, Flags,
                                      FieldTy, PropertyNode);
    EltTys.push_back(FieldTy);
  }

  llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
  DBuilder.replaceArrays(RealDecl, Elements);

  LexicalBlockStack.pop_back();
  return RealDecl;
}

llvm::DIType *CGDebugInfo::CreateType(const VectorType *Ty,
                                      llvm::DIFile *Unit) {
  if (Ty->isPackedVectorBoolType(CGM.getContext())) {
    // Boolean ext_vector_type(N) are special because their real element type
    // (bits of bit size) is not their Clang element type (_Bool of size byte).
    // For now, we pretend the boolean vector were actually a vector of bytes
    // (where each byte represents 8 bits of the actual vector).
    // FIXME Debug info should actually represent this proper as a vector mask
    // type.
    auto &Ctx = CGM.getContext();
    uint64_t Size = CGM.getContext().getTypeSize(Ty);
    uint64_t NumVectorBytes = Size / Ctx.getCharWidth();

    // Construct the vector of 'char' type.
    QualType CharVecTy =
        Ctx.getVectorType(Ctx.CharTy, NumVectorBytes, VectorKind::Generic);
    return CreateType(CharVecTy->getAs<VectorType>(), Unit);
  }

  llvm::DIType *ElementTy = getOrCreateType(Ty->getElementType(), Unit);
  int64_t Count = Ty->getNumElements();

  llvm::Metadata *Subscript;
  QualType QTy(Ty, 0);
  auto SizeExpr = SizeExprCache.find(QTy);
  if (SizeExpr != SizeExprCache.end())
    Subscript = DBuilder.getOrCreateSubrange(
        SizeExpr->getSecond() /*count*/, nullptr /*lowerBound*/,
        nullptr /*upperBound*/, nullptr /*stride*/);
  else {
    auto *CountNode =
        llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
            llvm::Type::getInt64Ty(CGM.getLLVMContext()), Count ? Count : -1));
    Subscript = DBuilder.getOrCreateSubrange(
        CountNode /*count*/, nullptr /*lowerBound*/, nullptr /*upperBound*/,
        nullptr /*stride*/);
  }
  llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscript);

  uint64_t Size = CGM.getContext().getTypeSize(Ty);
  auto Align = getTypeAlignIfRequired(Ty, CGM.getContext());

  return DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray);
}

llvm::DIType *CGDebugInfo::CreateType(const ConstantMatrixType *Ty,
                                      llvm::DIFile *Unit) {
  // FIXME: Create another debug type for matrices
  // For the time being, it treats it like a nested ArrayType.

  llvm::DIType *ElementTy = getOrCreateType(Ty->getElementType(), Unit);
  uint64_t Size = CGM.getContext().getTypeSize(Ty);
  uint32_t Align = getTypeAlignIfRequired(Ty, CGM.getContext());

  // Create ranges for both dimensions.
  llvm::SmallVector<llvm::Metadata *, 2> Subscripts;
  auto *ColumnCountNode =
      llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
          llvm::Type::getInt64Ty(CGM.getLLVMContext()), Ty->getNumColumns()));
  auto *RowCountNode =
      llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
          llvm::Type::getInt64Ty(CGM.getLLVMContext()), Ty->getNumRows()));
  Subscripts.push_back(DBuilder.getOrCreateSubrange(
      ColumnCountNode /*count*/, nullptr /*lowerBound*/, nullptr /*upperBound*/,
      nullptr /*stride*/));
  Subscripts.push_back(DBuilder.getOrCreateSubrange(
      RowCountNode /*count*/, nullptr /*lowerBound*/, nullptr /*upperBound*/,
      nullptr /*stride*/));
  llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscripts);
  return DBuilder.createArrayType(Size, Align, ElementTy, SubscriptArray);
}

llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) {
  uint64_t Size;
  uint32_t Align;

  // FIXME: make getTypeAlign() aware of VLAs and incomplete array types
  if (const auto *VAT = dyn_cast<VariableArrayType>(Ty)) {
    Size = 0;
    Align = getTypeAlignIfRequired(CGM.getContext().getBaseElementType(VAT),
                                   CGM.getContext());
  } else if (Ty->isIncompleteArrayType()) {
    Size = 0;
    if (Ty->getElementType()->isIncompleteType())
      Align = 0;
    else
      Align = getTypeAlignIfRequired(Ty->getElementType(), CGM.getContext());
  } else if (Ty->isIncompleteType()) {
    Size = 0;
    Align = 0;
  } else {
    // Size and align of the whole array, not the element type.
    Size = CGM.getContext().getTypeSize(Ty);
    Align = getTypeAlignIfRequired(Ty, CGM.getContext());
  }

  // Add the dimensions of the array.  FIXME: This loses CV qualifiers from
  // interior arrays, do we care?  Why aren't nested arrays represented the
  // obvious/recursive way?
  SmallVector<llvm::Metadata *, 8> Subscripts;
  QualType EltTy(Ty, 0);
  while ((Ty = dyn_cast<ArrayType>(EltTy))) {
    // If the number of elements is known, then count is that number. Otherwise,
    // it's -1. This allows us to represent a subrange with an array of 0
    // elements, like this:
    //
    //   struct foo {
    //     int x[0];
    //   };
    int64_t Count = -1; // Count == -1 is an unbounded array.
    if (const auto *CAT = dyn_cast<ConstantArrayType>(Ty))
      Count = CAT->getZExtSize();
    else if (const auto *VAT = dyn_cast<VariableArrayType>(Ty)) {
      if (Expr *Size = VAT->getSizeExpr()) {
        Expr::EvalResult Result;
        if (Size->EvaluateAsInt(Result, CGM.getContext()))
          Count = Result.Val.getInt().getExtValue();
      }
    }

    auto SizeNode = SizeExprCache.find(EltTy);
    if (SizeNode != SizeExprCache.end())
      Subscripts.push_back(DBuilder.getOrCreateSubrange(
          SizeNode->getSecond() /*count*/, nullptr /*lowerBound*/,
          nullptr /*upperBound*/, nullptr /*stride*/));
    else {
      auto *CountNode =
          llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
              llvm::Type::getInt64Ty(CGM.getLLVMContext()), Count));
      Subscripts.push_back(DBuilder.getOrCreateSubrange(
          CountNode /*count*/, nullptr /*lowerBound*/, nullptr /*upperBound*/,
          nullptr /*stride*/));
    }
    EltTy = Ty->getElementType();
  }

  llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscripts);

  return DBuilder.createArrayType(Size, Align, getOrCreateType(EltTy, Unit),
                                  SubscriptArray);
}

llvm::DIType *CGDebugInfo::CreateType(const LValueReferenceType *Ty,
                                      llvm::DIFile *Unit) {
  return CreatePointerLikeType(llvm::dwarf::DW_TAG_reference_type, Ty,
                               Ty->getPointeeType(), Unit);
}

llvm::DIType *CGDebugInfo::CreateType(const RValueReferenceType *Ty,
                                      llvm::DIFile *Unit) {
  llvm::dwarf::Tag Tag = llvm::dwarf::DW_TAG_rvalue_reference_type;
  // DW_TAG_rvalue_reference_type was introduced in DWARF 4.
  if (CGM.getCodeGenOpts().DebugStrictDwarf &&
      CGM.getCodeGenOpts().DwarfVersion < 4)
    Tag = llvm::dwarf::DW_TAG_reference_type;

  return CreatePointerLikeType(Tag, Ty, Ty->getPointeeType(), Unit);
}

llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty,
                                      llvm::DIFile *U) {
  llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
  uint64_t Size = 0;

  if (!Ty->isIncompleteType()) {
    Size = CGM.getContext().getTypeSize(Ty);

    // Set the MS inheritance model. There is no flag for the unspecified model.
    if (CGM.getTarget().getCXXABI().isMicrosoft()) {
      switch (Ty->getMostRecentCXXRecordDecl()->getMSInheritanceModel()) {
      case MSInheritanceModel::Single:
        Flags |= llvm::DINode::FlagSingleInheritance;
        break;
      case MSInheritanceModel::Multiple:
        Flags |= llvm::DINode::FlagMultipleInheritance;
        break;
      case MSInheritanceModel::Virtual:
        Flags |= llvm::DINode::FlagVirtualInheritance;
        break;
      case MSInheritanceModel::Unspecified:
        break;
      }
    }
  }

  CanQualType T =
      CGM.getContext().getCanonicalTagType(Ty->getMostRecentCXXRecordDecl());
  llvm::DIType *ClassType = getOrCreateType(T, U);
  if (Ty->isMemberDataPointerType())
    return DBuilder.createMemberPointerType(
        getOrCreateType(Ty->getPointeeType(), U), ClassType, Size, /*Align=*/0,
        Flags);

  const FunctionProtoType *FPT =
      Ty->getPointeeType()->castAs<FunctionProtoType>();
  return DBuilder.createMemberPointerType(
      getOrCreateInstanceMethodType(
          CXXMethodDecl::getThisType(FPT, Ty->getMostRecentCXXRecordDecl()),
          FPT, U),
      ClassType, Size, /*Align=*/0, Flags);
}

llvm::DIType *CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile *U) {
  auto *FromTy = getOrCreateType(Ty->getValueType(), U);
  return DBuilder.createQualifiedType(llvm::dwarf::DW_TAG_atomic_type, FromTy);
}

llvm::DIType *CGDebugInfo::CreateType(const PipeType *Ty, llvm::DIFile *U) {
  return getOrCreateType(Ty->getElementType(), U);
}

llvm::DIType *CGDebugInfo::CreateType(const HLSLAttributedResourceType *Ty,
                                      llvm::DIFile *U) {
  return getOrCreateType(Ty->getWrappedType(), U);
}

llvm::DIType *CGDebugInfo::CreateType(const HLSLInlineSpirvType *Ty,
                                      llvm::DIFile *U) {
  // Debug information unneeded.
  return nullptr;
}

static auto getEnumInfo(CodeGenModule &CGM, llvm::DICompileUnit *TheCU,
                        const EnumType *Ty) {
  const EnumDecl *ED = Ty->getDecl()->getDefinitionOrSelf();

  uint64_t Size = 0;
  uint32_t Align = 0;
  if (ED->isComplete()) {
    Size = CGM.getContext().getTypeSize(QualType(Ty, 0));
    Align = getDeclAlignIfRequired(ED, CGM.getContext());
  }
  return std::make_tuple(ED, Size, Align, getTypeIdentifier(Ty, CGM, TheCU));
}

llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
  auto [ED, Size, Align, Identifier] = getEnumInfo(CGM, TheCU, Ty);

  bool isImportedFromModule =
      DebugTypeExtRefs && ED->isFromASTFile() && ED->getDefinition();

  // If this is just a forward declaration, construct an appropriately
  // marked node and just return it.
  if (isImportedFromModule || !ED->getDefinition()) {
    // Note that it is possible for enums to be created as part of
    // their own declcontext. In this case a FwdDecl will be created
    // twice. This doesn't cause a problem because both FwdDecls are
    // entered into the ReplaceMap: finalize() will replace the first
    // FwdDecl with the second and then replace the second with
    // complete type.
    llvm::DIScope *EDContext = getDeclContextDescriptor(ED);
    llvm::DIFile *DefUnit = getOrCreateFile(ED->getLocation());
    llvm::TempDIScope TmpContext(DBuilder.createReplaceableCompositeType(
        llvm::dwarf::DW_TAG_enumeration_type, "", TheCU, DefUnit, 0));

    unsigned Line = getLineNumber(ED->getLocation());
    StringRef EDName = ED->getName();
    llvm::DIType *RetTy = DBuilder.createReplaceableCompositeType(
        llvm::dwarf::DW_TAG_enumeration_type, EDName, EDContext, DefUnit, Line,
        0, Size, Align, llvm::DINode::FlagFwdDecl, Identifier);

    ReplaceMap.emplace_back(
        std::piecewise_construct, std::make_tuple(Ty),
        std::make_tuple(static_cast<llvm::Metadata *>(RetTy)));
    return RetTy;
  }

  return CreateTypeDefinition(Ty);
}

llvm::DIType *CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) {
  auto [ED, Size, Align, Identifier] = getEnumInfo(CGM, TheCU, Ty);

  SmallVector<llvm::Metadata *, 16> Enumerators;
  ED = ED->getDefinition();
  assert(ED && "An enumeration definition is required");
  for (const auto *Enum : ED->enumerators()) {
    Enumerators.push_back(
        DBuilder.createEnumerator(Enum->getName(), Enum->getInitVal()));
  }

  std::optional<EnumExtensibilityAttr::Kind> EnumKind;
  if (auto *Attr = ED->getAttr<EnumExtensibilityAttr>())
    EnumKind = Attr->getExtensibility();

  // Return a CompositeType for the enum itself.
  llvm::DINodeArray EltArray = DBuilder.getOrCreateArray(Enumerators);

  llvm::DIFile *DefUnit = getOrCreateFile(ED->getLocation());
  unsigned Line = getLineNumber(ED->getLocation());
  llvm::DIScope *EnumContext = getDeclContextDescriptor(ED);
  llvm::DIType *ClassTy = getOrCreateType(ED->getIntegerType(), DefUnit);
  return DBuilder.createEnumerationType(
      EnumContext, ED->getName(), DefUnit, Line, Size, Align, EltArray, ClassTy,
      /*RunTimeLang=*/0, Identifier, ED->isScoped(), EnumKind);
}

llvm::DIMacro *CGDebugInfo::CreateMacro(llvm::DIMacroFile *Parent,
                                        unsigned MType, SourceLocation LineLoc,
                                        StringRef Name, StringRef Value) {
  unsigned Line = LineLoc.isInvalid() ? 0 : getLineNumber(LineLoc);
  return DBuilder.createMacro(Parent, Line, MType, Name, Value);
}

llvm::DIMacroFile *CGDebugInfo::CreateTempMacroFile(llvm::DIMacroFile *Parent,
                                                    SourceLocation LineLoc,
                                                    SourceLocation FileLoc) {
  llvm::DIFile *FName = getOrCreateFile(FileLoc);
  unsigned Line = LineLoc.isInvalid() ? 0 : getLineNumber(LineLoc);
  return DBuilder.createTempMacroFile(Parent, Line, FName);
}

llvm::DILocation *
CGDebugInfo::CreateSyntheticInlineAt(llvm::DebugLoc ParentLocation,
                                     llvm::DISubprogram *SynthSubprogram) {
  return llvm::DILocation::get(CGM.getLLVMContext(), /*Line=*/0, /*Column=*/0,
                               SynthSubprogram, ParentLocation);
}

llvm::DILocation *
CGDebugInfo::CreateSyntheticInlineAt(llvm::DebugLoc ParentLocation,
                                     StringRef SynthFuncName,
                                     llvm::DIFile *SynthFile) {
  llvm::DISubprogram *SP = createInlinedSubprogram(SynthFuncName, SynthFile);
  return CreateSyntheticInlineAt(ParentLocation, SP);
}

llvm::DILocation *CGDebugInfo::CreateTrapFailureMessageFor(
    llvm::DebugLoc TrapLocation, StringRef Category, StringRef FailureMsg) {
  // Create a debug location from `TrapLocation` that adds an artificial inline
  // frame.
  SmallString<64> FuncName(ClangTrapPrefix);

  FuncName += "$";
  FuncName += Category;
  FuncName += "$";
  FuncName += FailureMsg;

  return CreateSyntheticInlineAt(TrapLocation, FuncName,
                                 TrapLocation->getFile());
}

static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
  Qualifiers Quals;
  do {
    Qualifiers InnerQuals = T.getLocalQualifiers();
    // Qualifiers::operator+() doesn't like it if you add a Qualifier
    // that is already there.
    Quals += Qualifiers::removeCommonQualifiers(Quals, InnerQuals);
    Quals += InnerQuals;
    QualType LastT = T;
    switch (T->getTypeClass()) {
    default:
      return C.getQualifiedType(T.getTypePtr(), Quals);
    case Type::Enum:
    case Type::Record:
    case Type::InjectedClassName:
      return C.getQualifiedType(T->getCanonicalTypeUnqualified().getTypePtr(),
                                Quals);
    case Type::TemplateSpecialization: {
      const auto *Spec = cast<TemplateSpecializationType>(T);
      if (Spec->isTypeAlias())
        return C.getQualifiedType(T.getTypePtr(), Quals);
      T = Spec->desugar();
      break;
    }
    case Type::TypeOfExpr:
      T = cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType();
      break;
    case Type::TypeOf:
      T = cast<TypeOfType>(T)->getUnmodifiedType();
      break;
    case Type::Decltype:
      T = cast<DecltypeType>(T)->getUnderlyingType();
      break;
    case Type::UnaryTransform:
      T = cast<UnaryTransformType>(T)->getUnderlyingType();
      break;
    case Type::Attributed:
      T = cast<AttributedType>(T)->getEquivalentType();
      break;
    case Type::BTFTagAttributed:
      T = cast<BTFTagAttributedType>(T)->getWrappedType();
      break;
    case Type::CountAttributed:
      T = cast<CountAttributedType>(T)->desugar();
      break;
    case Type::Using:
      T = cast<UsingType>(T)->desugar();
      break;
    case Type::Paren:
      T = cast<ParenType>(T)->getInnerType();
      break;
    case Type::MacroQualified:
      T = cast<MacroQualifiedType>(T)->getUnderlyingType();
      break;
    case Type::SubstTemplateTypeParm:
      T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
      break;
    case Type::Auto:
    case Type::DeducedTemplateSpecialization: {
      QualType DT = cast<DeducedType>(T)->getDeducedType();
      assert(!DT.isNull() && "Undeduced types shouldn't reach here.");
      T = DT;
      break;
    }
    case Type::PackIndexing: {
      T = cast<PackIndexingType>(T)->getSelectedType();
      break;
    }
    case Type::Adjusted:
    case Type::Decayed:
      // Decayed and adjusted types use the adjusted type in LLVM and DWARF.
      T = cast<AdjustedType>(T)->getAdjustedType();
      break;
    }

    assert(T != LastT && "Type unwrapping failed to unwrap!");
    (void)LastT;
  } while (true);
}

llvm::DIType *CGDebugInfo::getTypeOrNull(QualType Ty) {
  assert(Ty == UnwrapTypeForDebugInfo(Ty, CGM.getContext()));
  auto It = TypeCache.find(Ty.getAsOpaquePtr());
  if (It != TypeCache.end()) {
    // Verify that the debug info still exists.
    if (llvm::Metadata *V = It->second)
      return cast<llvm::DIType>(V);
  }

  return nullptr;
}

void CGDebugInfo::completeTemplateDefinition(
    const ClassTemplateSpecializationDecl &SD) {
  completeUnusedClass(SD);
}

void CGDebugInfo::completeUnusedClass(const CXXRecordDecl &D) {
  if (DebugKind <= llvm::codegenoptions::DebugLineTablesOnly ||
      D.isDynamicClass())
    return;

  completeClassData(&D);
  // In case this type has no member function definitions being emitted, ensure
  // it is retained
  RetainedTypes.push_back(
      CGM.getContext().getCanonicalTagType(&D).getAsOpaquePtr());
}

llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
  if (Ty.isNull())
    return nullptr;

  llvm::TimeTraceScope TimeScope("DebugType", [&]() {
    std::string Name;
    llvm::raw_string_ostream OS(Name);
    Ty.print(OS, getPrintingPolicy());
    return Name;
  });

  // Unwrap the type as needed for debug information.
  Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());

  if (auto *T = getTypeOrNull(Ty))
    return T;

  llvm::DIType *Res = CreateTypeNode(Ty, Unit);
  void *TyPtr = Ty.getAsOpaquePtr();

  // And update the type cache.
  TypeCache[TyPtr].reset(Res);

  return Res;
}

llvm::DIModule *CGDebugInfo::getParentModuleOrNull(const Decl *D) {
  // A forward declaration inside a module header does not belong to the module.
  if (isa<RecordDecl>(D) && !cast<RecordDecl>(D)->getDefinition())
    return nullptr;
  if (DebugTypeExtRefs && D->isFromASTFile()) {
    // Record a reference to an imported clang module or precompiled header.
    auto *Reader = CGM.getContext().getExternalSource();
    auto Idx = D->getOwningModuleID();
    auto Info = Reader->getSourceDescriptor(Idx);
    if (Info)
      return getOrCreateModuleRef(*Info, /*SkeletonCU=*/true);
  } else if (ClangModuleMap) {
    // We are building a clang module or a precompiled header.
    //
    // TODO: When D is a CXXRecordDecl or a C++ Enum, the ODR applies
    // and it wouldn't be necessary to specify the parent scope
    // because the type is already unique by definition (it would look
    // like the output of -fno-standalone-debug). On the other hand,
    // the parent scope helps a consumer to quickly locate the object
    // file where the type's definition is located, so it might be
    // best to make this behavior a command line or debugger tuning
    // option.
    if (Module *M = D->getOwningModule()) {
      // This is a (sub-)module.
      auto Info = ASTSourceDescriptor(*M);
      return getOrCreateModuleRef(Info, /*SkeletonCU=*/false);
    } else {
      // This the precompiled header being built.
      return getOrCreateModuleRef(PCHDescriptor, /*SkeletonCU=*/false);
    }
  }

  return nullptr;
}

llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
  // Handle qualifiers, which recursively handles what they refer to.
  if (Ty.hasLocalQualifiers())
    return CreateQualifiedType(Ty, Unit);

  // Work out details of type.
  switch (Ty->getTypeClass()) {
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
#define NON_CANONICAL_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
#include "clang/AST/TypeNodes.inc"
    llvm_unreachable("Dependent types cannot show up in debug information");

  case Type::ExtVector:
  case Type::Vector:
    return CreateType(cast<VectorType>(Ty), Unit);
  case Type::ConstantMatrix:
    return CreateType(cast<ConstantMatrixType>(Ty), Unit);
  case Type::ObjCObjectPointer:
    return CreateType(cast<ObjCObjectPointerType>(Ty), Unit);
  case Type::ObjCObject:
    return CreateType(cast<ObjCObjectType>(Ty), Unit);
  case Type::ObjCTypeParam:
    return CreateType(cast<ObjCTypeParamType>(Ty), Unit);
  case Type::ObjCInterface:
    return CreateType(cast<ObjCInterfaceType>(Ty), Unit);
  case Type::Builtin:
    return CreateType(cast<BuiltinType>(Ty));
  case Type::Complex:
    return CreateType(cast<ComplexType>(Ty));
  case Type::Pointer:
    return CreateType(cast<PointerType>(Ty), Unit);
  case Type::BlockPointer:
    return CreateType(cast<BlockPointerType>(Ty), Unit);
  case Type::Typedef:
    return CreateType(cast<TypedefType>(Ty), Unit);
  case Type::Record:
    return CreateType(cast<RecordType>(Ty));
  case Type::Enum:
    return CreateEnumType(cast<EnumType>(Ty));
  case Type::FunctionProto:
  case Type::FunctionNoProto:
    return CreateType(cast<FunctionType>(Ty), Unit);
  case Type::ConstantArray:
  case Type::VariableArray:
  case Type::IncompleteArray:
  case Type::ArrayParameter:
    return CreateType(cast<ArrayType>(Ty), Unit);

  case Type::LValueReference:
    return CreateType(cast<LValueReferenceType>(Ty), Unit);
  case Type::RValueReference:
    return CreateType(cast<RValueReferenceType>(Ty), Unit);

  case Type::MemberPointer:
    return CreateType(cast<MemberPointerType>(Ty), Unit);

  case Type::Atomic:
    return CreateType(cast<AtomicType>(Ty), Unit);

  case Type::BitInt:
    return CreateType(cast<BitIntType>(Ty));
  case Type::OverflowBehavior:
    return CreateType(cast<OverflowBehaviorType>(Ty), Unit);
  case Type::Pipe:
    return CreateType(cast<PipeType>(Ty), Unit);

  case Type::TemplateSpecialization:
    return CreateType(cast<TemplateSpecializationType>(Ty), Unit);
  case Type::HLSLAttributedResource:
    return CreateType(cast<HLSLAttributedResourceType>(Ty), Unit);
  case Type::HLSLInlineSpirv:
    return CreateType(cast<HLSLInlineSpirvType>(Ty), Unit);
  case Type::PredefinedSugar:
    return getOrCreateType(cast<PredefinedSugarType>(Ty)->desugar(), Unit);
  case Type::CountAttributed:
  case Type::LateParsedAttr:
  case Type::Auto:
  case Type::Attributed:
  case Type::BTFTagAttributed:
  case Type::Adjusted:
  case Type::Decayed:
  case Type::DeducedTemplateSpecialization:
  case Type::Using:
  case Type::Paren:
  case Type::MacroQualified:
  case Type::SubstTemplateTypeParm:
  case Type::TypeOfExpr:
  case Type::TypeOf:
  case Type::Decltype:
  case Type::PackIndexing:
  case Type::UnaryTransform:
    break;
  }

  llvm_unreachable("type should have been unwrapped!");
}

llvm::DICompositeType *
CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty) {
  QualType QTy(Ty, 0);

  auto *T = cast_or_null<llvm::DICompositeType>(getTypeOrNull(QTy));

  // We may have cached a forward decl when we could have created
  // a non-forward decl. Go ahead and create a non-forward decl
  // now.
  if (T && !T->isForwardDecl())
    return T;

  // Otherwise create the type.
  llvm::DICompositeType *Res = CreateLimitedType(Ty);

  // Propagate members from the declaration to the definition
  // CreateType(const RecordType*) will overwrite this with the members in the
  // correct order if the full type is needed.
  DBuilder.replaceArrays(Res, T ? T->getElements() : llvm::DINodeArray());

  // And update the type cache.
  TypeCache[QTy.getAsOpaquePtr()].reset(Res);
  return Res;
}

// TODO: Currently used for context chains when limiting debug info.
llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
  RecordDecl *RD = Ty->getDecl()->getDefinitionOrSelf();
  bool NameIsSimplified = false;

  // Get overall information about the record type for the debug info.
  StringRef RDName = getClassName(RD, &NameIsSimplified);
  const SourceLocation Loc = RD->getLocation();
  llvm::DIFile *DefUnit = nullptr;
  unsigned Line = 0;
  if (Loc.isValid()) {
    DefUnit = getOrCreateFile(Loc);
    Line = getLineNumber(Loc);
  }

  llvm::DIScope *RDContext = getDeclContextDescriptor(RD);

  // If we ended up creating the type during the context chain construction,
  // just return that.
  auto *T = cast_or_null<llvm::DICompositeType>(
      getTypeOrNull(CGM.getContext().getCanonicalTagType(RD)));
  if (T && (!T->isForwardDecl() || !RD->getDefinition()))
    return T;

  // If this is just a forward or incomplete declaration, construct an
  // appropriately marked node and just return it.
  const RecordDecl *D = RD->getDefinition();
  if (!D || !D->isCompleteDefinition())
    return getOrCreateRecordFwdDecl(Ty, RDContext);

  uint64_t Size = CGM.getContext().getTypeSize(Ty);
  // __attribute__((aligned)) can increase or decrease alignment *except* on a
  // struct or struct member, where it only increases  alignment unless 'packed'
  // is also specified. To handle this case, the `getTypeAlignIfRequired` needs
  // to be used.
  auto Align = getTypeAlignIfRequired(Ty, CGM.getContext());

  SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU);

  // Explicitly record the calling convention and export symbols for C++
  // records.
  auto Flags = llvm::DINode::FlagZero;
  if (NameIsSimplified)
    Flags |= llvm::DINode::FlagNameIsSimplified;
  if (auto CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
    if (CGM.getCXXABI().getRecordArgABI(CXXRD) == CGCXXABI::RAA_Indirect)
      Flags |= llvm::DINode::FlagTypePassByReference;
    else
      Flags |= llvm::DINode::FlagTypePassByValue;

    // Record if a C++ record is non-trivial type.
    if (!CXXRD->isTrivial())
      Flags |= llvm::DINode::FlagNonTrivial;

    // Record exports it symbols to the containing structure.
    if (CXXRD->isAnonymousStructOrUnion())
        Flags |= llvm::DINode::FlagExportSymbols;

    Flags |= getAccessFlag(CXXRD->getAccess(),
                           dyn_cast<CXXRecordDecl>(CXXRD->getDeclContext()));
  }

  llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(D);
  llvm::DICompositeType *RealDecl = DBuilder.createReplaceableCompositeType(
      getTagForRecord(RD), RDName, RDContext, DefUnit, Line, 0, Size, Align,
      Flags, Identifier, Annotations);

  // Elements of composite types usually have back to the type, creating
  // uniquing cycles.  Distinct nodes are more efficient.
  switch (RealDecl->getTag()) {
  default:
    llvm_unreachable("invalid composite type tag");

  case llvm::dwarf::DW_TAG_array_type:
  case llvm::dwarf::DW_TAG_enumeration_type:
    // Array elements and most enumeration elements don't have back references,
    // so they don't tend to be involved in uniquing cycles and there is some
    // chance of merging them when linking together two modules.  Only make
    // them distinct if they are ODR-uniqued.
    if (Identifier.empty())
      break;
    [[fallthrough]];

  case llvm::dwarf::DW_TAG_structure_type:
  case llvm::dwarf::DW_TAG_union_type:
  case llvm::dwarf::DW_TAG_class_type:
    // Immediately resolve to a distinct node.
    RealDecl =
        llvm::MDNode::replaceWithDistinct(llvm::TempDICompositeType(RealDecl));
    break;
  }

  if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Ty->getDecl())) {
    CXXRecordDecl *TemplateDecl =
        CTSD->getSpecializedTemplate()->getTemplatedDecl();
    RegionMap[TemplateDecl].reset(RealDecl);
  } else {
    RegionMap[RD].reset(RealDecl);
  }
  TypeCache[QualType(Ty, 0).getAsOpaquePtr()].reset(RealDecl);

  if (const auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD))
    DBuilder.replaceArrays(RealDecl, llvm::DINodeArray(),
                           CollectCXXTemplateParams(TSpecial, DefUnit));
  return RealDecl;
}

void CGDebugInfo::CollectContainingType(const CXXRecordDecl *RD,
                                        llvm::DICompositeType *RealDecl) {
  // A class's primary base or the class itself contains the vtable.
  llvm::DIType *ContainingType = nullptr;
  const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
  if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) {
    // Seek non-virtual primary base root.
    while (true) {
      const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase);
      const CXXRecordDecl *PBT = BRL.getPrimaryBase();
      if (PBT && !BRL.isPrimaryBaseVirtual())
        PBase = PBT;
      else
        break;
    }
    CanQualType T = CGM.getContext().getCanonicalTagType(PBase);
    ContainingType = getOrCreateType(T, getOrCreateFile(RD->getLocation()));
  } else if (RD->isDynamicClass())
    ContainingType = RealDecl;

  DBuilder.replaceVTableHolder(RealDecl, ContainingType);
}

llvm::DIType *CGDebugInfo::CreateMemberType(llvm::DIFile *Unit, QualType FType,
                                            StringRef Name, uint64_t *Offset) {
  llvm::DIType *FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
  uint64_t FieldSize = CGM.getContext().getTypeSize(FType);
  auto FieldAlign = getTypeAlignIfRequired(FType, CGM.getContext());
  llvm::DIType *Ty =
      DBuilder.createMemberType(Unit, Name, Unit, 0, FieldSize, FieldAlign,
                                *Offset, llvm::DINode::FlagZero, FieldTy);
  *Offset += FieldSize;
  return Ty;
}

void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit,
                                           StringRef &Name,
                                           StringRef &LinkageName,
                                           llvm::DIScope *&FDContext,
                                           llvm::DINodeArray &TParamsArray,
                                           llvm::DINode::DIFlags &Flags) {
  const auto *FD = cast<FunctionDecl>(GD.getCanonicalDecl().getDecl());
  bool NameIsSimplified = false;
  Name = getFunctionName(FD, &NameIsSimplified);
  if (NameIsSimplified)
    Flags |= llvm::DINode::FlagNameIsSimplified;
  Name = getFunctionName(FD);
  // Use mangled name as linkage name for C/C++ functions.
  if (FD->getType()->getAs<FunctionProtoType>())
    LinkageName = CGM.getMangledName(GD);
  if (FD->hasPrototype())
    Flags |= llvm::DINode::FlagPrototyped;
  // No need to replicate the linkage name if it isn't different from the
  // subprogram name, no need to have it at all unless coverage is enabled or
  // debug is set to more than just line tables or extra debug info is needed.
  if (LinkageName == Name ||
      (CGM.getCodeGenOpts().CoverageNotesFile.empty() &&
       CGM.getCodeGenOpts().CoverageDataFile.empty() &&
       !CGM.getCodeGenOpts().DebugInfoForProfiling &&
       !CGM.getCodeGenOpts().PseudoProbeForProfiling &&
       DebugKind <= llvm::codegenoptions::DebugLineTablesOnly))
    LinkageName = StringRef();

  // Emit the function scope in line tables only mode (if CodeView) to
  // differentiate between function names.
  if (CGM.getCodeGenOpts().hasReducedDebugInfo() ||
      (DebugKind == llvm::codegenoptions::DebugLineTablesOnly &&
       CGM.getCodeGenOpts().EmitCodeView)) {
    if (const NamespaceDecl *NSDecl =
            dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))
      FDContext = getOrCreateNamespace(NSDecl);
    else if (const RecordDecl *RDecl =
                 dyn_cast_or_null<RecordDecl>(FD->getDeclContext())) {
      llvm::DIScope *Mod = getParentModuleOrNull(RDecl);
      FDContext = getContextDescriptor(RDecl, Mod ? Mod : TheCU);
    }
  }
  if (CGM.getCodeGenOpts().hasReducedDebugInfo()) {
    // Check if it is a noreturn-marked function
    if (FD->isNoReturn())
      Flags |= llvm::DINode::FlagNoReturn;
    // Collect template parameters.
    TParamsArray = CollectFunctionTemplateParams(FD, Unit);
  }
}

void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile *&Unit,
                                      unsigned &LineNo, QualType &T,
                                      StringRef &Name, StringRef &LinkageName,
                                      llvm::MDTuple *&TemplateParameters,
                                      llvm::DIScope *&VDContext) {
  Unit = getOrCreateFile(VD->getLocation());
  LineNo = getLineNumber(VD->getLocation());

  setLocation(VD->getLocation());

  T = VD->getType();
  if (T->isIncompleteArrayType()) {
    // CodeGen turns int[] into int[1] so we'll do the same here.
    llvm::APInt ConstVal(32, 1);
    QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();

    T = CGM.getContext().getConstantArrayType(ET, ConstVal, nullptr,
                                              ArraySizeModifier::Normal, 0);
  }

  Name = VD->getName();
  if (VD->getDeclContext() && !isa<FunctionDecl>(VD->getDeclContext()) &&
      !isa<ObjCMethodDecl>(VD->getDeclContext()))
    LinkageName = CGM.getMangledName(VD);
  if (LinkageName == Name)
    LinkageName = StringRef();

  if (isa<VarTemplateSpecializationDecl>(VD)) {
    llvm::DINodeArray parameterNodes = CollectVarTemplateParams(VD, &*Unit);
    TemplateParameters = parameterNodes.get();
  } else {
    TemplateParameters = nullptr;
  }

  // Since we emit declarations (DW_AT_members) for static members, place the
  // definition of those static members in the namespace they were declared in
  // in the source code (the lexical decl context).
  // FIXME: Generalize this for even non-member global variables where the
  // declaration and definition may have different lexical decl contexts, once
  // we have support for emitting declarations of (non-member) global variables.
  const DeclContext *DC = VD->isStaticDataMember() ? VD->getLexicalDeclContext()
                                                   : VD->getDeclContext();
  // When a record type contains an in-line initialization of a static data
  // member, and the record type is marked as __declspec(dllexport), an implicit
  // definition of the member will be created in the record context.  DWARF
  // doesn't seem to have a nice way to describe this in a form that consumers
  // are likely to understand, so fake the "normal" situation of a definition
  // outside the class by putting it in the global scope.
  if (DC->isRecord())
    DC = CGM.getContext().getTranslationUnitDecl();

  llvm::DIScope *Mod = getParentModuleOrNull(VD);
  VDContext = getContextDescriptor(cast<Decl>(DC), Mod ? Mod : TheCU);
}

llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD,
                                                          bool Stub) {
  llvm::DINodeArray TParamsArray;
  StringRef Name, LinkageName;
  llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
  llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::SPFlagZero;
  SourceLocation Loc = GD.getDecl()->getLocation();
  llvm::DIFile *Unit = getOrCreateFile(Loc);
  llvm::DIScope *DContext = Unit;
  unsigned Line = getLineNumber(Loc);
  collectFunctionDeclProps(GD, Unit, Name, LinkageName, DContext, TParamsArray,
                           Flags);
  auto *FD = cast<FunctionDecl>(GD.getDecl());

  // Build function type.
  SmallVector<QualType, 16> ArgTypes;
  for (const ParmVarDecl *Parm : FD->parameters())
    ArgTypes.push_back(Parm->getType());

  CallingConv CC = FD->getType()->castAs<FunctionType>()->getCallConv();
  QualType FnType = CGM.getContext().getFunctionType(
      FD->getReturnType(), ArgTypes, FunctionProtoType::ExtProtoInfo(CC));
  if (!FD->isExternallyVisible())
    SPFlags |= llvm::DISubprogram::SPFlagLocalToUnit;
  if (CGM.getCodeGenOpts().OptimizationLevel != 0)
    SPFlags |= llvm::DISubprogram::SPFlagOptimized;

  if (Stub) {
    Flags |= getCallSiteRelatedAttrs();
    SPFlags |= llvm::DISubprogram::SPFlagDefinition;
    return DBuilder.createFunction(
        DContext, Name, LinkageName, Unit, Line,
        getOrCreateFunctionType(GD.getDecl(), FnType, Unit), 0, Flags, SPFlags,
        TParamsArray.get(), getFunctionDeclaration(FD), /*ThrownTypes*/ nullptr,
        /*Annotations*/ nullptr, /*TargetFuncName*/ "",
        CGM.getCodeGenOpts().DebugKeyInstructions);
  }

  llvm::DISubprogram *SP = DBuilder.createTempFunctionFwdDecl(
      DContext, Name, LinkageName, Unit, Line,
      getOrCreateFunctionType(GD.getDecl(), FnType, Unit), 0, Flags, SPFlags,
      TParamsArray.get(), getFunctionDeclaration(FD));
  const FunctionDecl *CanonDecl = FD->getCanonicalDecl();
  FwdDeclReplaceMap.emplace_back(std::piecewise_construct,
                                 std::make_tuple(CanonDecl),
                                 std::make_tuple(SP));
  return SP;
}

llvm::DISubprogram *CGDebugInfo::getFunctionForwardDeclaration(GlobalDecl GD) {
  return getFunctionFwdDeclOrStub(GD, /* Stub = */ false);
}

llvm::DISubprogram *CGDebugInfo::getFunctionStub(GlobalDecl GD) {
  return getFunctionFwdDeclOrStub(GD, /* Stub = */ true);
}

llvm::DIGlobalVariable *
CGDebugInfo::getGlobalVariableForwardDeclaration(const VarDecl *VD) {
  QualType T;
  StringRef Name, LinkageName;
  SourceLocation Loc = VD->getLocation();
  llvm::DIFile *Unit = getOrCreateFile(Loc);
  llvm::DIScope *DContext = Unit;
  unsigned Line = getLineNumber(Loc);
  llvm::MDTuple *TemplateParameters = nullptr;

  collectVarDeclProps(VD, Unit, Line, T, Name, LinkageName, TemplateParameters,
                      DContext);
  auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
  auto *GV = DBuilder.createTempGlobalVariableFwdDecl(
      DContext, Name, LinkageName, Unit, Line, getOrCreateType(T, Unit),
      !VD->isExternallyVisible(), nullptr, TemplateParameters, Align);
  FwdDeclReplaceMap.emplace_back(
      std::piecewise_construct,
      std::make_tuple(cast<VarDecl>(VD->getCanonicalDecl())),
      std::make_tuple(static_cast<llvm::Metadata *>(GV)));
  return GV;
}

llvm::DINode *CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
  // We only need a declaration (not a definition) of the type - so use whatever
  // we would otherwise do to get a type for a pointee. (forward declarations in
  // limited debug info, full definitions (if the type definition is available)
  // in unlimited debug info)
  if (const auto *TD = dyn_cast<TypeDecl>(D)) {
    QualType Ty = CGM.getContext().getTypeDeclType(TD);
    return getOrCreateType(Ty, getOrCreateFile(TD->getLocation()));
  }
  auto I = DeclCache.find(D->getCanonicalDecl());

  if (I != DeclCache.end()) {
    auto N = I->second;
    if (auto *GVE = dyn_cast_or_null<llvm::DIGlobalVariableExpression>(N))
      return GVE->getVariable();
    return cast<llvm::DINode>(N);
  }

  // Search imported declaration cache if it is already defined
  // as imported declaration.
  auto IE = ImportedDeclCache.find(D->getCanonicalDecl());

  if (IE != ImportedDeclCache.end()) {
    auto N = IE->second;
    if (auto *GVE = dyn_cast_or_null<llvm::DIImportedEntity>(N))
      return cast<llvm::DINode>(GVE);
    return dyn_cast_or_null<llvm::DINode>(N);
  }

  // No definition for now. Emit a forward definition that might be
  // merged with a potential upcoming definition.
  if (const auto *FD = dyn_cast<FunctionDecl>(D))
    return getFunctionForwardDeclaration(FD);
  else if (const auto *VD = dyn_cast<VarDecl>(D))
    return getGlobalVariableForwardDeclaration(VD);

  return nullptr;
}

llvm::DISubprogram *CGDebugInfo::getFunctionDeclaration(const Decl *D) {
  if (!D || DebugKind <= llvm::codegenoptions::DebugLineTablesOnly)
    return nullptr;

  const auto *FD = dyn_cast<FunctionDecl>(D);
  if (!FD)
    return nullptr;

  // Setup context.
  auto *S = getDeclContextDescriptor(D);

  auto MI = SPCache.find(FD->getCanonicalDecl());
  if (MI == SPCache.end()) {
    if (const auto *MD = dyn_cast<CXXMethodDecl>(FD->getCanonicalDecl())) {
      return CreateCXXMemberFunction(MD, getOrCreateFile(MD->getLocation()),
                                     cast<llvm::DICompositeType>(S));
    }
  }
  if (MI != SPCache.end()) {
    auto *SP = dyn_cast_or_null<llvm::DISubprogram>(MI->second);
    if (SP && !SP->isDefinition())
      return SP;
  }

  for (auto *NextFD : FD->redecls()) {
    auto MI = SPCache.find(NextFD->getCanonicalDecl());
    if (MI != SPCache.end()) {
      auto *SP = dyn_cast_or_null<llvm::DISubprogram>(MI->second);
      if (SP && !SP->isDefinition())
        return SP;
    }
  }
  return nullptr;
}

llvm::DISubprogram *CGDebugInfo::getObjCMethodDeclaration(
    const Decl *D, llvm::DISubroutineType *FnType, unsigned LineNo,
    llvm::DINode::DIFlags Flags, llvm::DISubprogram::DISPFlags SPFlags) {
  if (!D || DebugKind <= llvm::codegenoptions::DebugLineTablesOnly)
    return nullptr;

  const auto *OMD = dyn_cast<ObjCMethodDecl>(D);
  if (!OMD)
    return nullptr;

  if (CGM.getCodeGenOpts().DwarfVersion < 5 && !OMD->isDirectMethod())
    return nullptr;

  if (OMD->isDirectMethod())
    SPFlags |= llvm::DISubprogram::SPFlagObjCDirect;

  // Starting with DWARF V5 method declarations are emitted as children of
  // the interface type.
  auto *ID = dyn_cast_or_null<ObjCInterfaceDecl>(D->getDeclContext());
  if (!ID)
    ID = OMD->getClassInterface();
  if (!ID)
    return nullptr;
  QualType QTy(ID->getTypeForDecl(), 0);
  auto It = TypeCache.find(QTy.getAsOpaquePtr());
  if (It == TypeCache.end())
    return nullptr;
  auto *InterfaceType = cast<llvm::DICompositeType>(It->second);
  llvm::DISubprogram *FD = DBuilder.createFunction(
      InterfaceType, getObjCMethodName(OMD), StringRef(),
      InterfaceType->getFile(), LineNo, FnType, LineNo, Flags, SPFlags);
  DBuilder.finalizeSubprogram(FD);
  ObjCMethodCache[ID].push_back({FD, OMD->isDirectMethod()});
  return FD;
}

// getOrCreateFunctionType - Construct type. If it is a c++ method, include
// implicit parameter "this".
llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
                                                             QualType FnType,
                                                             llvm::DIFile *F) {
  // In CodeView, we emit the function types in line tables only because the
  // only way to distinguish between functions is by display name and type.
  if (!D || (DebugKind <= llvm::codegenoptions::DebugLineTablesOnly &&
             !CGM.getCodeGenOpts().EmitCodeView))
    // Create fake but valid subroutine type. Otherwise -verify would fail, and
    // subprogram DIE will miss DW_AT_decl_file and DW_AT_decl_line fields.
    return DBuilder.createSubroutineType(DBuilder.getOrCreateTypeArray({}));

  if (const auto *Method = dyn_cast<CXXDestructorDecl>(D)) {
    // Read method type from 'FnType' because 'D.getType()' does not cover
    // implicit arguments for destructors.
    return getOrCreateMethodTypeForDestructor(Method, F, FnType);
  }

  if (const auto *Method = dyn_cast<CXXMethodDecl>(D))
    return getOrCreateMethodType(Method, F);

  const auto *FTy = FnType->getAs<FunctionType>();
  CallingConv CC = FTy ? FTy->getCallConv() : CallingConv::CC_C;

  if (const auto *OMethod = dyn_cast<ObjCMethodDecl>(D)) {
    // Add "self" and "_cmd"
    SmallVector<llvm::Metadata *, 16> Elts;

    // First element is always return type. For 'void' functions it is NULL.
    QualType ResultTy = OMethod->getReturnType();

    // Replace the instancetype keyword with the actual type.
    if (ResultTy == CGM.getContext().getObjCInstanceType())
      ResultTy = CGM.getContext().getPointerType(
          QualType(OMethod->getClassInterface()->getTypeForDecl(), 0));

    Elts.push_back(getOrCreateType(ResultTy, F));
    // "self" pointer is always first argument.
    QualType SelfDeclTy;
    if (auto *SelfDecl = OMethod->getSelfDecl())
      SelfDeclTy = SelfDecl->getType();
    else if (auto *FPT = dyn_cast<FunctionProtoType>(FnType))
      if (FPT->getNumParams() > 1)
        SelfDeclTy = FPT->getParamType(0);
    if (!SelfDeclTy.isNull())
      Elts.push_back(
          CreateSelfType(SelfDeclTy, getOrCreateType(SelfDeclTy, F)));
    // "_cmd" pointer is always second argument.
    Elts.push_back(DBuilder.createArtificialType(
        getOrCreateType(CGM.getContext().getObjCSelType(), F)));
    // Get rest of the arguments.
    for (const auto *PI : OMethod->parameters())
      Elts.push_back(getOrCreateType(PI->getType(), F));
    // Variadic methods need a special marker at the end of the type list.
    if (OMethod->isVariadic())
      Elts.push_back(DBuilder.createUnspecifiedParameter());

    llvm::DITypeArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts);
    return DBuilder.createSubroutineType(EltTypeArray, llvm::DINode::FlagZero,
                                         getDwarfCC(CC));
  }

  // Handle variadic function types; they need an additional
  // unspecified parameter.
  if (const auto *FD = dyn_cast<FunctionDecl>(D))
    if (FD->isVariadic()) {
      SmallVector<llvm::Metadata *, 16> EltTys;
      EltTys.push_back(getOrCreateType(FD->getReturnType(), F));
      if (const auto *FPT = dyn_cast<FunctionProtoType>(FnType))
        for (QualType ParamType : FPT->param_types())
          EltTys.push_back(getOrCreateType(ParamType, F));
      EltTys.push_back(DBuilder.createUnspecifiedParameter());
      llvm::DITypeArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys);
      return DBuilder.createSubroutineType(EltTypeArray, llvm::DINode::FlagZero,
                                           getDwarfCC(CC));
    }

  return cast<llvm::DISubroutineType>(getOrCreateType(FnType, F));
}

QualType
CGDebugInfo::getFunctionType(const FunctionDecl *FD, QualType RetTy,
                             const SmallVectorImpl<const VarDecl *> &Args) {
  CallingConv CC = CallingConv::CC_C;
  if (FD)
    if (const auto *SrcFnTy = FD->getType()->getAs<FunctionType>())
      CC = SrcFnTy->getCallConv();
  SmallVector<QualType, 16> ArgTypes;
  for (const VarDecl *VD : Args)
    ArgTypes.push_back(VD->getType());
  return CGM.getContext().getFunctionType(RetTy, ArgTypes,
                                          FunctionProtoType::ExtProtoInfo(CC));
}

void CGDebugInfo::emitFunctionStart(GlobalDecl GD, SourceLocation Loc,
                                    SourceLocation ScopeLoc, QualType FnType,
                                    llvm::Function *Fn, bool CurFuncIsThunk) {
  StringRef Name;
  StringRef LinkageName;

  FnBeginRegionCount.push_back(LexicalBlockStack.size());

  const Decl *D = GD.getDecl();
  bool HasDecl = (D != nullptr);

  llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
  llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::SPFlagZero;
  llvm::DIFile *Unit = getOrCreateFile(Loc);
  llvm::DIScope *FDContext = Unit;
  llvm::DINodeArray TParamsArray;
  bool KeyInstructions = CGM.getCodeGenOpts().DebugKeyInstructions;
  if (!HasDecl) {
    // Use llvm function name.
    LinkageName = Fn->getName();
  } else if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
    // If there is a subprogram for this function available then use it.
    auto FI = SPCache.find(FD->getCanonicalDecl());
    if (FI != SPCache.end()) {
      auto *SP = dyn_cast_or_null<llvm::DISubprogram>(FI->second);
      if (SP && SP->isDefinition()) {
        LexicalBlockStack.emplace_back(SP);
        RegionMap[D].reset(SP);
        return;
      }
    }
    collectFunctionDeclProps(GD, Unit, Name, LinkageName, FDContext,
                             TParamsArray, Flags);
    // Disable KIs if this is a coroutine.
    KeyInstructions =
        KeyInstructions && !isa_and_present<CoroutineBodyStmt>(FD->getBody());
  } else if (const auto *OMD = dyn_cast<ObjCMethodDecl>(D)) {
    Name = getObjCMethodName(OMD);
    Flags |= llvm::DINode::FlagPrototyped;
  } else if (isa<VarDecl>(D) &&
             GD.getDynamicInitKind() != DynamicInitKind::NoStub) {
    // This is a global initializer or atexit destructor for a global variable.
    Name = getDynamicInitializerName(cast<VarDecl>(D), GD.getDynamicInitKind(),
                                     Fn);
    if (Name != Fn->getName())
      LinkageName = Fn->getName();
  } else {
    Name = Fn->getName();

    if (isa<BlockDecl>(D))
      LinkageName = Name;

    Flags |= llvm::DINode::FlagPrototyped;
  }
  Name.consume_front("\01");

  assert((!D || !isa<VarDecl>(D) ||
          GD.getDynamicInitKind() != DynamicInitKind::NoStub) &&
         "Unexpected DynamicInitKind !");

  if (!HasDecl || D->isImplicit() || D->hasAttr<ArtificialAttr>() ||
      isa<VarDecl>(D) || isa<CapturedDecl>(D)) {
    Flags |= llvm::DINode::FlagArtificial;
    // Artificial functions should not silently reuse CurLoc.
    clearCurLoc();
  }

  if (CurFuncIsThunk)
    Flags |= llvm::DINode::FlagThunk;

  if (Fn->hasLocalLinkage())
    SPFlags |= llvm::DISubprogram::SPFlagLocalToUnit;
  if (CGM.getCodeGenOpts().OptimizationLevel != 0)
    SPFlags |= llvm::DISubprogram::SPFlagOptimized;

  llvm::DINode::DIFlags FlagsForDef = Flags | getCallSiteRelatedAttrs();
  llvm::DISubprogram::DISPFlags SPFlagsForDef =
      SPFlags | llvm::DISubprogram::SPFlagDefinition;

  const unsigned LineNo = getLineNumber(Loc.isValid() ? Loc : CurLoc);
  unsigned ScopeLine = getLineNumber(ScopeLoc);
  llvm::DISubroutineType *DIFnType = getOrCreateFunctionType(D, FnType, Unit);
  llvm::DISubprogram *Decl = nullptr;
  llvm::DINodeArray Annotations = nullptr;
  if (D) {
    Decl = isa<ObjCMethodDecl>(D)
               ? getObjCMethodDeclaration(D, DIFnType, LineNo, Flags, SPFlags)
               : getFunctionDeclaration(D);
    Annotations = CollectBTFDeclTagAnnotations(D);
  }

  // FIXME: The function declaration we're constructing here is mostly reusing
  // declarations from CXXMethodDecl and not constructing new ones for arbitrary
  // FunctionDecls. When/if we fix this we can have FDContext be TheCU/null for
  // all subprograms instead of the actual context since subprogram definitions
  // are emitted as CU level entities by the backend.
  llvm::DISubprogram *SP = DBuilder.createFunction(
      FDContext, Name, LinkageName, Unit, LineNo, DIFnType, ScopeLine,
      FlagsForDef, SPFlagsForDef, TParamsArray.get(), Decl, nullptr,
      Annotations, "", KeyInstructions);
  Fn->setSubprogram(SP);

  // We might get here with a VarDecl in the case we're generating
  // code for the initialization of globals. Do not record these decls
  // as they will overwrite the actual VarDecl Decl in the cache.
  if (HasDecl && isa<FunctionDecl>(D))
    DeclCache[D->getCanonicalDecl()].reset(SP);

  // Push the function onto the lexical block stack.
  LexicalBlockStack.emplace_back(SP);

  if (HasDecl)
    RegionMap[D].reset(SP);
}

void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc,
                                   QualType FnType, llvm::Function *Fn) {
  StringRef Name;
  StringRef LinkageName;

  const Decl *D = GD.getDecl();
  if (!D)
    return;

  llvm::TimeTraceScope TimeScope("DebugFunction", [&]() {
    return GetName(D, true);
  });

  llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
  llvm::DIFile *Unit = getOrCreateFile(Loc);
  bool IsDeclForCallSite = Fn ? true : false;
  llvm::DIScope *FDContext =
      IsDeclForCallSite ? Unit : getDeclContextDescriptor(D);
  llvm::DINodeArray TParamsArray;
  if (isa<FunctionDecl>(D)) {
    // If there is a DISubprogram for this function available then use it.
    collectFunctionDeclProps(GD, Unit, Name, LinkageName, FDContext,
                             TParamsArray, Flags);
  } else if (const auto *OMD = dyn_cast<ObjCMethodDecl>(D)) {
    Name = getObjCMethodName(OMD);
    Flags |= llvm::DINode::FlagPrototyped;
  } else {
    llvm_unreachable("not a function or ObjC method");
  }
  Name.consume_front("\01");

  if (D->isImplicit()) {
    Flags |= llvm::DINode::FlagArtificial;
    // Artificial functions without a location should not silently reuse CurLoc.
    if (Loc.isInvalid())
      clearCurLoc();
  }
  unsigned LineNo = getLineNumber(Loc);
  unsigned ScopeLine = 0;
  llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::SPFlagZero;
  if (CGM.getCodeGenOpts().OptimizationLevel != 0)
    SPFlags |= llvm::DISubprogram::SPFlagOptimized;

  llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(D);
  llvm::DISubroutineType *STy = getOrCreateFunctionType(D, FnType, Unit);
  // Key Instructions: Don't set flag on declarations.
  assert(~SPFlags & llvm::DISubprogram::SPFlagDefinition);
  llvm::DISubprogram *SP = DBuilder.createFunction(
      FDContext, Name, LinkageName, Unit, LineNo, STy, ScopeLine, Flags,
      SPFlags, TParamsArray.get(), nullptr, nullptr, Annotations,
      /*TargetFunctionName*/ "", /*UseKeyInstructions*/ false);

  // Preserve btf_decl_tag attributes for parameters of extern functions
  // for BPF target. The parameters created in this loop are attached as
  // DISubprogram's retainedNodes in the DIBuilder::finalize() call.
  if (IsDeclForCallSite && CGM.getTarget().getTriple().isBPF()) {
    if (auto *FD = dyn_cast<FunctionDecl>(D)) {
      llvm::DITypeArray ParamTypes = STy->getTypeArray();
      unsigned ArgNo = 1;
      for (ParmVarDecl *PD : FD->parameters()) {
        llvm::DINodeArray ParamAnnotations = CollectBTFDeclTagAnnotations(PD);
        DBuilder.createParameterVariable(
            SP, PD->getName(), ArgNo, Unit, LineNo, ParamTypes[ArgNo], true,
            llvm::DINode::FlagZero, ParamAnnotations);
        ++ArgNo;
      }
    }
  }

  if (IsDeclForCallSite)
    Fn->setSubprogram(SP);
}

void CGDebugInfo::addCallTargetIfVirtual(const FunctionDecl *FD,
                                         llvm::CallBase *CI) {
  if (!shouldGenerateVirtualCallSite())
    return;

  if (!FD)
    return;

  assert(CI && "Invalid Call Instruction.");
  if (!CI->isIndirectCall())
    return;

  // Always get the method declaration.
  if (llvm::DISubprogram *MD = getFunctionDeclaration(FD))
    CI->setMetadata(llvm::LLVMContext::MD_call_target, MD);
}

void CGDebugInfo::EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
                                          QualType CalleeType,
                                          GlobalDecl CalleeGlobalDecl) {
  if (!CallOrInvoke)
    return;
  auto *Func = dyn_cast<llvm::Function>(CallOrInvoke->getCalledOperand());
  if (!Func)
    return;
  if (Func->getSubprogram())
    return;

  const FunctionDecl *CalleeDecl =
      cast<FunctionDecl>(CalleeGlobalDecl.getDecl());

  // Do not emit a declaration subprogram for a function with nodebug
  // attribute, or if call site info isn't required.
  if (CalleeDecl->hasAttr<NoDebugAttr>() ||
      getCallSiteRelatedAttrs() == llvm::DINode::FlagZero)
    return;

  // If there is no DISubprogram attached to the function being called,
  // create the one describing the function in order to have complete
  // call site debug info.
  if (!CalleeDecl->isStatic() && !CalleeDecl->isInlined())
    EmitFunctionDecl(CalleeGlobalDecl, CalleeDecl->getLocation(), CalleeType,
                     Func);
}

void CGDebugInfo::EmitInlineFunctionStart(CGBuilderTy &Builder, GlobalDecl GD) {
  const auto *FD = cast<FunctionDecl>(GD.getDecl());
  // If there is a subprogram for this function available then use it.
  auto FI = SPCache.find(FD->getCanonicalDecl());
  llvm::DISubprogram *SP = nullptr;
  if (FI != SPCache.end())
    SP = dyn_cast_or_null<llvm::DISubprogram>(FI->second);
  if (!SP || !SP->isDefinition())
    SP = getFunctionStub(GD);
  FnBeginRegionCount.push_back(LexicalBlockStack.size());
  LexicalBlockStack.emplace_back(SP);
  setInlinedAt(Builder.getCurrentDebugLocation());
  EmitLocation(Builder, FD->getLocation());
}

void CGDebugInfo::EmitInlineFunctionEnd(CGBuilderTy &Builder) {
  assert(CurInlinedAt && "unbalanced inline scope stack");
  EmitFunctionEnd(Builder, nullptr);
  setInlinedAt(llvm::DebugLoc(CurInlinedAt).getInlinedAt());
}

void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) {
  // Update our current location
  setLocation(Loc);

  if (CurLoc.isInvalid() ||
      (CGM.getCodeGenOpts().DebugInfoMacroExpansionLoc && CurLoc.isMacroID()) ||
      LexicalBlockStack.empty())
    return;

  llvm::MDNode *Scope = LexicalBlockStack.back();
  Builder.SetCurrentDebugLocation(llvm::DILocation::get(
      CGM.getLLVMContext(), CurLocLine, CurLocColumn, Scope, CurInlinedAt));
}

void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) {
  llvm::MDNode *Back = nullptr;
  if (!LexicalBlockStack.empty())
    Back = LexicalBlockStack.back().get();
  LexicalBlockStack.emplace_back(DBuilder.createLexicalBlock(
      cast<llvm::DIScope>(Back), getOrCreateFile(CurLoc), getLineNumber(CurLoc),
      getColumnNumber(CurLoc)));
}

void CGDebugInfo::AppendAddressSpaceXDeref(
    unsigned AddressSpace, SmallVectorImpl<uint64_t> &Expr) const {
  std::optional<unsigned> DWARFAddressSpace =
      CGM.getTarget().getDWARFAddressSpace(AddressSpace);
  if (!DWARFAddressSpace)
    return;

  Expr.push_back(llvm::dwarf::DW_OP_constu);
  Expr.push_back(*DWARFAddressSpace);
  Expr.push_back(llvm::dwarf::DW_OP_swap);
  Expr.push_back(llvm::dwarf::DW_OP_xderef);
}

void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder,
                                        SourceLocation Loc) {
  // Set our current location.
  setLocation(Loc);

  // Emit a line table change for the current location inside the new scope.
  Builder.SetCurrentDebugLocation(llvm::DILocation::get(
      CGM.getLLVMContext(), getLineNumber(Loc), getColumnNumber(Loc),
      LexicalBlockStack.back(), CurInlinedAt));

  if (DebugKind <= llvm::codegenoptions::DebugLineTablesOnly)
    return;

  // Create a new lexical block and push it on the stack.
  CreateLexicalBlock(Loc);
}

void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder,
                                      SourceLocation Loc) {
  assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");

  // Provide an entry in the line table for the end of the block.
  EmitLocation(Builder, Loc);

  if (DebugKind <= llvm::codegenoptions::DebugLineTablesOnly)
    return;

  LexicalBlockStack.pop_back();
}

void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder, llvm::Function *Fn) {
  assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
  unsigned RCount = FnBeginRegionCount.back();
  assert(RCount <= LexicalBlockStack.size() && "Region stack mismatch");

  // Pop all regions for this function.
  while (LexicalBlockStack.size() != RCount) {
    // Provide an entry in the line table for the end of the block.
    EmitLocation(Builder, CurLoc);
    LexicalBlockStack.pop_back();
  }
  FnBeginRegionCount.pop_back();

  if (Fn && Fn->getSubprogram())
    DBuilder.finalizeSubprogram(Fn->getSubprogram());
}

CGDebugInfo::BlockByRefType
CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
                                          uint64_t *XOffset) {
  SmallVector<llvm::Metadata *, 5> EltTys;
  QualType FType;
  uint64_t FieldSize, FieldOffset;
  uint32_t FieldAlign;

  llvm::DIFile *Unit = getOrCreateFile(VD->getLocation());
  QualType Type = VD->getType();

  FieldOffset = 0;
  FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
  EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset));
  EltTys.push_back(CreateMemberType(Unit, FType, "__forwarding", &FieldOffset));
  FType = CGM.getContext().IntTy;
  EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));
  EltTys.push_back(CreateMemberType(Unit, FType, "__size", &FieldOffset));

  bool HasCopyAndDispose = CGM.getContext().BlockRequiresCopying(Type, VD);
  if (HasCopyAndDispose) {
    FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
    EltTys.push_back(
        CreateMemberType(Unit, FType, "__copy_helper", &FieldOffset));
    EltTys.push_back(
        CreateMemberType(Unit, FType, "__destroy_helper", &FieldOffset));
  }
  bool HasByrefExtendedLayout;
  Qualifiers::ObjCLifetime Lifetime;
  if (CGM.getContext().getByrefLifetime(Type, Lifetime,
                                        HasByrefExtendedLayout) &&
      HasByrefExtendedLayout) {
    FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
    EltTys.push_back(
        CreateMemberType(Unit, FType, "__byref_variable_layout", &FieldOffset));
  }

  CharUnits Align = CGM.getContext().getDeclAlign(VD);
  if (Align > CGM.getContext().toCharUnitsFromBits(
                  CGM.getTarget().getPointerAlign(LangAS::Default))) {
    CharUnits FieldOffsetInBytes =
        CGM.getContext().toCharUnitsFromBits(FieldOffset);
    CharUnits AlignedOffsetInBytes = FieldOffsetInBytes.alignTo(Align);
    CharUnits NumPaddingBytes = AlignedOffsetInBytes - FieldOffsetInBytes;

    if (NumPaddingBytes.isPositive()) {
      llvm::APInt pad(32, NumPaddingBytes.getQuantity());
      FType = CGM.getContext().getConstantArrayType(
          CGM.getContext().CharTy, pad, nullptr, ArraySizeModifier::Normal, 0);
      EltTys.push_back(CreateMemberType(Unit, FType, "", &FieldOffset));
    }
  }

  FType = Type;
  llvm::DIType *WrappedTy = getOrCreateType(FType, Unit);
  FieldSize = CGM.getContext().getTypeSize(FType);
  FieldAlign = CGM.getContext().toBits(Align);

  *XOffset = FieldOffset;
  llvm::DIType *FieldTy = DBuilder.createMemberType(
      Unit, VD->getName(), Unit, 0, FieldSize, FieldAlign, FieldOffset,
      llvm::DINode::FlagZero, WrappedTy);
  EltTys.push_back(FieldTy);
  FieldOffset += FieldSize;

  llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
  return {DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0,
                                    llvm::DINode::FlagZero, nullptr, Elements),
          WrappedTy};
}

llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
                                                llvm::Value *Storage,
                                                std::optional<unsigned> ArgNo,
                                                CGBuilderTy &Builder,
                                                const bool UsePointerValue) {
  assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
  assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
  if (VD->hasAttr<NoDebugAttr>())
    return nullptr;

  const bool VarIsArtificial = IsArtificial(VD);

  llvm::DIFile *Unit = nullptr;
  if (!VarIsArtificial)
    Unit = getOrCreateFile(VD->getLocation());
  llvm::DIType *Ty;
  uint64_t XOffset = 0;
  if (VD->hasAttr<BlocksAttr>())
    Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset).WrappedType;
  else
    Ty = getOrCreateType(VD->getType(), Unit);

  // If there is no debug info for this type then do not emit debug info
  // for this variable.
  if (!Ty)
    return nullptr;

  // Get location information.
  unsigned Line = 0;
  unsigned Column = 0;
  if (!VarIsArtificial) {
    Line = getLineNumber(VD->getLocation());
    Column = getColumnNumber(VD->getLocation());
  }
  SmallVector<uint64_t, 13> Expr;
  llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;

  // While synthesized Objective-C property setters are "artificial" (i.e., they
  // are not spelled out in source), we want to pretend they are just like a
  // regular non-compiler generated method. Hence, don't mark explicitly passed
  // parameters of such methods as artificial.
  if (VarIsArtificial && !IsObjCSynthesizedPropertyExplicitParameter(VD))
    Flags |= llvm::DINode::FlagArtificial;

  auto Align = getDeclAlignIfRequired(VD, CGM.getContext());

  unsigned AddressSpace = CGM.getTypes().getTargetAddressSpace(VD->getType());
  AppendAddressSpaceXDeref(AddressSpace, Expr);

  // If this is implicit parameter of CXXThis or ObjCSelf kind, then give it an
  // object pointer flag.
  if (const auto *IPD = dyn_cast<ImplicitParamDecl>(VD)) {
    if (IPD->getParameterKind() == ImplicitParamKind::CXXThis ||
        IPD->getParameterKind() == ImplicitParamKind::ObjCSelf)
      Flags |= llvm::DINode::FlagObjectPointer;
  } else if (const auto *PVD = dyn_cast<ParmVarDecl>(VD)) {
    if (PVD->isExplicitObjectParameter())
      Flags |= llvm::DINode::FlagObjectPointer;
  }

  // Note: Older versions of clang used to emit byval references with an extra
  // DW_OP_deref, because they referenced the IR arg directly instead of
  // referencing an alloca. Newer versions of LLVM don't treat allocas
  // differently from other function arguments when used in a dbg.declare.
  auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back());
  StringRef Name = VD->getName();
  if (!Name.empty()) {
    // __block vars are stored on the heap if they are captured by a block that
    // can escape the local scope.
    if (VD->isEscapingByref()) {
      // Here, we need an offset *into* the alloca.
      CharUnits offset = CharUnits::fromQuantity(32);
      Expr.push_back(llvm::dwarf::DW_OP_plus_uconst);
      // offset of __forwarding field
      offset = CGM.getContext().toCharUnitsFromBits(
          CGM.getTarget().getPointerWidth(LangAS::Default));
      Expr.push_back(offset.getQuantity());
      Expr.push_back(llvm::dwarf::DW_OP_deref);
      Expr.push_back(llvm::dwarf::DW_OP_plus_uconst);
      // offset of x field
      offset = CGM.getContext().toCharUnitsFromBits(XOffset);
      Expr.push_back(offset.getQuantity());
    }
  } else if (const auto *RT = dyn_cast<RecordType>(VD->getType())) {
    // If VD is an anonymous union then Storage represents value for
    // all union fields.
    const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();
    if (RD->isUnion() && RD->isAnonymousStructOrUnion()) {
      // GDB has trouble finding local variables in anonymous unions, so we emit
      // artificial local variables for each of the members.
      //
      // FIXME: Remove this code as soon as GDB supports this.
      // The debug info verifier in LLVM operates based on the assumption that a
      // variable has the same size as its storage and we had to disable the
      // check for artificial variables.
      for (const auto *Field : RD->fields()) {
        llvm::DIType *FieldTy = getOrCreateType(Field->getType(), Unit);
        StringRef FieldName = Field->getName();

        // Ignore unnamed fields. Do not ignore unnamed records.
        if (FieldName.empty() && !isa<RecordType>(Field->getType()))
          continue;

        // Use VarDecl's Tag, Scope and Line number.
        auto FieldAlign = getDeclAlignIfRequired(Field, CGM.getContext());
        auto *D = DBuilder.createAutoVariable(
            Scope, FieldName, Unit, Line, FieldTy,
            CGM.getCodeGenOpts().OptimizationLevel != 0,
            Flags | llvm::DINode::FlagArtificial, FieldAlign);

        // Insert an llvm.dbg.declare into the current block.
        DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
                               llvm::DILocation::get(CGM.getLLVMContext(), Line,
                                                     Column, Scope,
                                                     CurInlinedAt),
                               Builder.GetInsertBlock());
      }
    }
  }

  // Clang stores the sret pointer provided by the caller in a static alloca.
  // Use DW_OP_deref to tell the debugger to load the pointer and treat it as
  // the address of the variable.
  if (UsePointerValue) {
    assert(!llvm::is_contained(Expr, llvm::dwarf::DW_OP_deref) &&
           "Debug info already contains DW_OP_deref.");
    Expr.push_back(llvm::dwarf::DW_OP_deref);
  }

  // Create the descriptor for the variable.
  llvm::DILocalVariable *D = nullptr;
  if (ArgNo) {
    llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(VD);
    D = DBuilder.createParameterVariable(
        Scope, Name, *ArgNo, Unit, Line, Ty,
        CGM.getCodeGenOpts().OptimizationLevel != 0, Flags, Annotations);
  } else {
    // For normal local variable, we will try to find out whether 'VD' is the
    // copy parameter of coroutine.
    // If yes, we are going to use DIVariable of the origin parameter instead
    // of creating the new one.
    // If no, it might be a normal alloc, we just create a new one for it.

    // Check whether the VD is move parameters.
    auto RemapCoroArgToLocalVar = [&]() -> llvm::DILocalVariable * {
      // The scope of parameter and move-parameter should be distinct
      // DISubprogram.
      if (!isa<llvm::DISubprogram>(Scope) || !Scope->isDistinct())
        return nullptr;

      auto Iter = llvm::find_if(CoroutineParameterMappings, [&](auto &Pair) {
        Stmt *StmtPtr = const_cast<Stmt *>(Pair.second);
        if (DeclStmt *DeclStmtPtr = dyn_cast<DeclStmt>(StmtPtr)) {
          DeclGroupRef DeclGroup = DeclStmtPtr->getDeclGroup();
          Decl *Decl = DeclGroup.getSingleDecl();
          if (VD == dyn_cast_or_null<VarDecl>(Decl))
            return true;
        }
        return false;
      });

      if (Iter != CoroutineParameterMappings.end()) {
        ParmVarDecl *PD = const_cast<ParmVarDecl *>(Iter->first);
        auto Iter2 = llvm::find_if(ParamDbgMappings, [&](auto &DbgPair) {
          return DbgPair.first == PD && DbgPair.second->getScope() == Scope;
        });
        if (Iter2 != ParamDbgMappings.end())
          return const_cast<llvm::DILocalVariable *>(Iter2->second);
      }
      return nullptr;
    };

    // If we couldn't find a move param DIVariable, create a new one.
    D = RemapCoroArgToLocalVar();
    // Or we will create a new DIVariable for this Decl if D dose not exists.
    if (!D)
      D = DBuilder.createAutoVariable(
          Scope, Name, Unit, Line, Ty,
          CGM.getCodeGenOpts().OptimizationLevel != 0, Flags, Align);
  }
  // Insert an llvm.dbg.declare into the current block.
  DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
                         llvm::DILocation::get(CGM.getLLVMContext(), Line,
                                               Column, Scope, CurInlinedAt),
                         Builder.GetInsertBlock());

  return D;
}

llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD,
                                                llvm::Value *Storage,
                                                std::optional<unsigned> ArgNo,
                                                CGBuilderTy &Builder,
                                                const bool UsePointerValue) {
  assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
  assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
  if (BD->hasAttr<NoDebugAttr>())
    return nullptr;

  // Skip the tuple like case, we don't handle that here
  if (isa<DeclRefExpr>(BD->getBinding()))
    return nullptr;

  llvm::DIFile *Unit = getOrCreateFile(BD->getLocation());
  llvm::DIType *Ty = getOrCreateType(BD->getType(), Unit);

  // If there is no debug info for this type then do not emit debug info
  // for this variable.
  if (!Ty)
    return nullptr;

  auto Align = getDeclAlignIfRequired(BD, CGM.getContext());
  unsigned AddressSpace = CGM.getTypes().getTargetAddressSpace(BD->getType());

  SmallVector<uint64_t, 3> Expr;
  AppendAddressSpaceXDeref(AddressSpace, Expr);

  // Clang stores the sret pointer provided by the caller in a static alloca.
  // Use DW_OP_deref to tell the debugger to load the pointer and treat it as
  // the address of the variable.
  if (UsePointerValue) {
    assert(!llvm::is_contained(Expr, llvm::dwarf::DW_OP_deref) &&
           "Debug info already contains DW_OP_deref.");
    Expr.push_back(llvm::dwarf::DW_OP_deref);
  }

  unsigned Line = getLineNumber(BD->getLocation());
  unsigned Column = getColumnNumber(BD->getLocation());
  StringRef Name = BD->getName();
  auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back());
  // Create the descriptor for the variable.
  llvm::DILocalVariable *D = DBuilder.createAutoVariable(
      Scope, Name, Unit, Line, Ty, CGM.getCodeGenOpts().OptimizationLevel != 0,
      llvm::DINode::FlagZero, Align);

  if (const MemberExpr *ME = dyn_cast<MemberExpr>(BD->getBinding())) {
    if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
      const unsigned fieldIndex = FD->getFieldIndex();
      const clang::CXXRecordDecl *parent =
          (const CXXRecordDecl *)FD->getParent();
      const ASTRecordLayout &layout =
          CGM.getContext().getASTRecordLayout(parent);
      const uint64_t fieldOffset = layout.getFieldOffset(fieldIndex);
      if (FD->isBitField()) {
        const CGRecordLayout &RL =
            CGM.getTypes().getCGRecordLayout(FD->getParent());
        const CGBitFieldInfo &Info = RL.getBitFieldInfo(FD);
        // Use DW_OP_plus_uconst to adjust to the start of the bitfield
        // storage.
        if (!Info.StorageOffset.isZero()) {
          Expr.push_back(llvm::dwarf::DW_OP_plus_uconst);
          Expr.push_back(Info.StorageOffset.getQuantity());
        }
        // Use LLVM_extract_bits to extract the appropriate bits from this
        // bitfield.
        Expr.push_back(Info.IsSigned
                           ? llvm::dwarf::DW_OP_LLVM_extract_bits_sext
                           : llvm::dwarf::DW_OP_LLVM_extract_bits_zext);
        Expr.push_back(Info.Offset);
        // If we have an oversized bitfield then the value won't be more than
        // the size of the type.
        const uint64_t TypeSize = CGM.getContext().getTypeSize(BD->getType());
        Expr.push_back(std::min((uint64_t)Info.Size, TypeSize));
      } else if (fieldOffset != 0) {
        assert(fieldOffset % CGM.getContext().getCharWidth() == 0 &&
               "Unexpected non-bitfield with non-byte-aligned offset");
        Expr.push_back(llvm::dwarf::DW_OP_plus_uconst);
        Expr.push_back(
            CGM.getContext().toCharUnitsFromBits(fieldOffset).getQuantity());
      }
    }
  } else if (const ArraySubscriptExpr *ASE =
                 dyn_cast<ArraySubscriptExpr>(BD->getBinding())) {
    if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(ASE->getIdx())) {
      const uint64_t value = IL->getValue().getZExtValue();
      const uint64_t typeSize = CGM.getContext().getTypeSize(BD->getType());

      if (value != 0) {
        Expr.push_back(llvm::dwarf::DW_OP_plus_uconst);
        Expr.push_back(CGM.getContext()
                           .toCharUnitsFromBits(value * typeSize)
                           .getQuantity());
      }
    }
  }

  // Insert an llvm.dbg.declare into the current block.
  DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
                         llvm::DILocation::get(CGM.getLLVMContext(), Line,
                                               Column, Scope, CurInlinedAt),
                         Builder.GetInsertBlock());

  return D;
}

llvm::DILocalVariable *
CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, llvm::Value *Storage,
                                       CGBuilderTy &Builder,
                                       const bool UsePointerValue) {
  assert(CGM.getCodeGenOpts().hasReducedDebugInfo());

  if (auto *DD = dyn_cast<DecompositionDecl>(VD)) {
    for (BindingDecl *B : DD->flat_bindings())
      EmitDeclare(B, Storage, std::nullopt, Builder,
                  VD->getType()->isReferenceType());
    // Don't emit an llvm.dbg.declare for the composite storage as it doesn't
    // correspond to a user variable.
    return nullptr;
  }

  return EmitDeclare(VD, Storage, std::nullopt, Builder, UsePointerValue);
}

void CGDebugInfo::EmitLabel(const LabelDecl *D, CGBuilderTy &Builder) {
  assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
  assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");

  if (D->hasAttr<NoDebugAttr>())
    return;

  auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back());
  llvm::DIFile *Unit = getOrCreateFile(D->getLocation());

  // Get location information.
  unsigned Line = getLineNumber(D->getLocation());
  unsigned Column = getColumnNumber(D->getLocation());

  StringRef Name = D->getName();

  // Create the descriptor for the label.
  auto *L = DBuilder.createLabel(Scope, Name, Unit, Line, Column,
                                 /*IsArtificial=*/false,
                                 /*CoroSuspendIdx=*/std::nullopt,
                                 CGM.getCodeGenOpts().OptimizationLevel != 0);

  // Insert an llvm.dbg.label into the current block.
  DBuilder.insertLabel(L,
                       llvm::DILocation::get(CGM.getLLVMContext(), Line, Column,
                                             Scope, CurInlinedAt),
                       Builder.GetInsertBlock()->end());
}

llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy,
                                          llvm::DIType *Ty) {
  llvm::DIType *CachedTy = getTypeOrNull(QualTy);
  if (CachedTy)
    Ty = CachedTy;
  return DBuilder.createObjectPointerType(Ty, /*Implicit=*/true);
}

void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
    const VarDecl *VD, llvm::Value *Storage, CGBuilderTy &Builder,
    const CGBlockInfo &blockInfo, llvm::Instruction *InsertPoint) {
  assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
  assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");

  if (Builder.GetInsertBlock() == nullptr)
    return;
  if (VD->hasAttr<NoDebugAttr>())
    return;

  bool isByRef = VD->hasAttr<BlocksAttr>();

  uint64_t XOffset = 0;
  llvm::DIFile *Unit = getOrCreateFile(VD->getLocation());
  llvm::DIType *Ty;
  if (isByRef)
    Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset).WrappedType;
  else
    Ty = getOrCreateType(VD->getType(), Unit);

  // Self is passed along as an implicit non-arg variable in a
  // block. Mark it as the object pointer.
  if (const auto *IPD = dyn_cast<ImplicitParamDecl>(VD))
    if (IPD->getParameterKind() == ImplicitParamKind::ObjCSelf)
      Ty = CreateSelfType(VD->getType(), Ty);

  // Get location information.
  const unsigned Line =
      getLineNumber(VD->getLocation().isValid() ? VD->getLocation() : CurLoc);
  unsigned Column = getColumnNumber(VD->getLocation());

  const llvm::DataLayout &target = CGM.getDataLayout();

  CharUnits offset = CharUnits::fromQuantity(
      target.getStructLayout(blockInfo.StructureType)
          ->getElementOffset(blockInfo.getCapture(VD).getIndex()));

  SmallVector<uint64_t, 9> addr;
  addr.push_back(llvm::dwarf::DW_OP_deref);
  addr.push_back(llvm::dwarf::DW_OP_plus_uconst);
  addr.push_back(offset.getQuantity());
  if (isByRef) {
    addr.push_back(llvm::dwarf::DW_OP_deref);
    addr.push_back(llvm::dwarf::DW_OP_plus_uconst);
    // offset of __forwarding field
    offset =
        CGM.getContext().toCharUnitsFromBits(target.getPointerSizeInBits(0));
    addr.push_back(offset.getQuantity());
    addr.push_back(llvm::dwarf::DW_OP_deref);
    addr.push_back(llvm::dwarf::DW_OP_plus_uconst);
    // offset of x field
    offset = CGM.getContext().toCharUnitsFromBits(XOffset);
    addr.push_back(offset.getQuantity());
  }

  // Create the descriptor for the variable.
  auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
  auto *D = DBuilder.createAutoVariable(
      cast<llvm::DILocalScope>(LexicalBlockStack.back()), VD->getName(), Unit,
      Line, Ty, false, llvm::DINode::FlagZero, Align);

  // Insert an llvm.dbg.declare into the current block.
  auto DL = llvm::DILocation::get(CGM.getLLVMContext(), Line, Column,
                                  LexicalBlockStack.back(), CurInlinedAt);
  auto *Expr = DBuilder.createExpression(addr);
  if (InsertPoint)
    DBuilder.insertDeclare(Storage, D, Expr, DL, InsertPoint->getIterator());
  else
    DBuilder.insertDeclare(Storage, D, Expr, DL, Builder.GetInsertBlock());
}

llvm::DILocalVariable *
CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
                                      unsigned ArgNo, CGBuilderTy &Builder,
                                      bool UsePointerValue) {
  assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
  return EmitDeclare(VD, AI, ArgNo, Builder, UsePointerValue);
}

namespace {
struct BlockLayoutChunk {
  uint64_t OffsetInBits;
  const BlockDecl::Capture *Capture;
};
bool operator<(const BlockLayoutChunk &l, const BlockLayoutChunk &r) {
  return l.OffsetInBits < r.OffsetInBits;
}
} // namespace

void CGDebugInfo::collectDefaultFieldsForBlockLiteralDeclare(
    const CGBlockInfo &Block, const ASTContext &Context, SourceLocation Loc,
    const llvm::StructLayout &BlockLayout, llvm::DIFile *Unit,
    SmallVectorImpl<llvm::Metadata *> &Fields) {
  // Blocks in OpenCL have unique constraints which make the standard fields
  // redundant while requiring size and align fields for enqueue_kernel. See
  // initializeForBlockHeader in CGBlocks.cpp
  if (CGM.getLangOpts().OpenCL) {
    Fields.push_back(createFieldType("__size", Context.IntTy, Loc, AS_public,
                                     BlockLayout.getElementOffsetInBits(0),
                                     Unit, Unit));
    Fields.push_back(createFieldType("__align", Context.IntTy, Loc, AS_public,
                                     BlockLayout.getElementOffsetInBits(1),
                                     Unit, Unit));
  } else {
    Fields.push_back(createFieldType("__isa", Context.VoidPtrTy, Loc, AS_public,
                                     BlockLayout.getElementOffsetInBits(0),
                                     Unit, Unit));
    Fields.push_back(createFieldType("__flags", Context.IntTy, Loc, AS_public,
                                     BlockLayout.getElementOffsetInBits(1),
                                     Unit, Unit));
    Fields.push_back(
        createFieldType("__reserved", Context.IntTy, Loc, AS_public,
                        BlockLayout.getElementOffsetInBits(2), Unit, Unit));
    auto *FnTy = Block.getBlockExpr()->getFunctionType();
    auto FnPtrType = CGM.getContext().getPointerType(FnTy->desugar());
    Fields.push_back(createFieldType("__FuncPtr", FnPtrType, Loc, AS_public,
                                     BlockLayout.getElementOffsetInBits(3),
                                     Unit, Unit));
    Fields.push_back(createFieldType(
        "__descriptor",
        Context.getPointerType(Block.NeedsCopyDispose
                                   ? Context.getBlockDescriptorExtendedType()
                                   : Context.getBlockDescriptorType()),
        Loc, AS_public, BlockLayout.getElementOffsetInBits(4), Unit, Unit));
  }
}

void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
                                                       StringRef Name,
                                                       unsigned ArgNo,
                                                       llvm::AllocaInst *Alloca,
                                                       CGBuilderTy &Builder) {
  assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
  ASTContext &C = CGM.getContext();
  const BlockDecl *blockDecl = block.getBlockDecl();

  // Collect some general information about the block's location.
  SourceLocation loc = blockDecl->getCaretLocation();
  llvm::DIFile *tunit = getOrCreateFile(loc);
  unsigned line = getLineNumber(loc);
  unsigned column = getColumnNumber(loc);

  // Build the debug-info type for the block literal.
  getDeclContextDescriptor(blockDecl);

  const llvm::StructLayout *blockLayout =
      CGM.getDataLayout().getStructLayout(block.StructureType);

  SmallVector<llvm::Metadata *, 16> fields;
  collectDefaultFieldsForBlockLiteralDeclare(block, C, loc, *blockLayout, tunit,
                                             fields);

  // We want to sort the captures by offset, not because DWARF
  // requires this, but because we're paranoid about debuggers.
  SmallVector<BlockLayoutChunk, 8> chunks;

  // 'this' capture.
  if (blockDecl->capturesCXXThis()) {
    BlockLayoutChunk chunk;
    chunk.OffsetInBits =
        blockLayout->getElementOffsetInBits(block.CXXThisIndex);
    chunk.Capture = nullptr;
    chunks.push_back(chunk);
  }

  // Variable captures.
  for (const auto &capture : blockDecl->captures()) {
    const VarDecl *variable = capture.getVariable();
    const CGBlockInfo::Capture &captureInfo = block.getCapture(variable);

    // Ignore constant captures.
    if (captureInfo.isConstant())
      continue;

    BlockLayoutChunk chunk;
    chunk.OffsetInBits =
        blockLayout->getElementOffsetInBits(captureInfo.getIndex());
    chunk.Capture = &capture;
    chunks.push_back(chunk);
  }

  // Sort by offset.
  llvm::array_pod_sort(chunks.begin(), chunks.end());

  for (const BlockLayoutChunk &Chunk : chunks) {
    uint64_t offsetInBits = Chunk.OffsetInBits;
    const BlockDecl::Capture *capture = Chunk.Capture;

    // If we have a null capture, this must be the C++ 'this' capture.
    if (!capture) {
      QualType type;
      if (auto *Method =
              cast_or_null<CXXMethodDecl>(blockDecl->getNonClosureContext()))
        type = Method->getThisType();
      else if (auto *RDecl = dyn_cast<CXXRecordDecl>(blockDecl->getParent()))
        type = CGM.getContext().getCanonicalTagType(RDecl);
      else
        llvm_unreachable("unexpected block declcontext");

      fields.push_back(createFieldType("this", type, loc, AS_public,
                                       offsetInBits, tunit, tunit));
      continue;
    }

    const VarDecl *variable = capture->getVariable();
    StringRef name = variable->getName();

    llvm::DIType *fieldType;
    if (capture->isByRef()) {
      TypeInfo PtrInfo = C.getTypeInfo(C.VoidPtrTy);
      auto Align = PtrInfo.isAlignRequired() ? PtrInfo.Align : 0;
      // FIXME: This recomputes the layout of the BlockByRefWrapper.
      uint64_t xoffset;
      fieldType =
          EmitTypeForVarWithBlocksAttr(variable, &xoffset).BlockByRefWrapper;
      fieldType = DBuilder.createPointerType(fieldType, PtrInfo.Width);
      fieldType = DBuilder.createMemberType(tunit, name, tunit, line,
                                            PtrInfo.Width, Align, offsetInBits,
                                            llvm::DINode::FlagZero, fieldType);
    } else {
      auto Align = getDeclAlignIfRequired(variable, CGM.getContext());
      fieldType = createFieldType(name, variable->getType(), loc, AS_public,
                                  offsetInBits, Align, tunit, tunit);
    }
    fields.push_back(fieldType);
  }

  SmallString<36> typeName;
  llvm::raw_svector_ostream(typeName)
      << "__block_literal_" << CGM.getUniqueBlockCount();

  llvm::DINodeArray fieldsArray = DBuilder.getOrCreateArray(fields);

  llvm::DIType *type =
      DBuilder.createStructType(tunit, typeName.str(), tunit, line,
                                CGM.getContext().toBits(block.BlockSize), 0,
                                llvm::DINode::FlagZero, nullptr, fieldsArray);
  type = DBuilder.createPointerType(type, CGM.PointerWidthInBits);

  // Get overall information about the block.
  llvm::DINode::DIFlags flags = llvm::DINode::FlagArtificial;
  auto *scope = cast<llvm::DILocalScope>(LexicalBlockStack.back());

  // Create the descriptor for the parameter.
  auto *debugVar = DBuilder.createParameterVariable(
      scope, Name, ArgNo, tunit, line, type,
      CGM.getCodeGenOpts().OptimizationLevel != 0, flags);

  // Insert an llvm.dbg.declare into the current block.
  DBuilder.insertDeclare(Alloca, debugVar, DBuilder.createExpression(),
                         llvm::DILocation::get(CGM.getLLVMContext(), line,
                                               column, scope, CurInlinedAt),
                         Builder.GetInsertBlock());
}

llvm::DIDerivedType *
CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) {
  if (!D || !D->isStaticDataMember())
    return nullptr;

  auto MI = StaticDataMemberCache.find(D->getCanonicalDecl());
  if (MI != StaticDataMemberCache.end()) {
    assert(MI->second && "Static data member declaration should still exist");
    return MI->second;
  }

  // If the member wasn't found in the cache, lazily construct and add it to the
  // type (used when a limited form of the type is emitted).
  auto DC = D->getDeclContext();
  auto *Ctxt = cast<llvm::DICompositeType>(getDeclContextDescriptor(D));
  return CreateRecordStaticField(D, Ctxt, cast<RecordDecl>(DC));
}

llvm::DIGlobalVariableExpression *CGDebugInfo::CollectAnonRecordDecls(
    const RecordDecl *RD, llvm::DIFile *Unit, unsigned LineNo,
    StringRef LinkageName, llvm::GlobalVariable *Var, llvm::DIScope *DContext) {
  llvm::DIGlobalVariableExpression *GVE = nullptr;

  for (const auto *Field : RD->fields()) {
    llvm::DIType *FieldTy = getOrCreateType(Field->getType(), Unit);
    StringRef FieldName = Field->getName();

    // Ignore unnamed fields, but recurse into anonymous records.
    if (FieldName.empty()) {
      if (const auto *RT = dyn_cast<RecordType>(Field->getType()))
        GVE = CollectAnonRecordDecls(RT->getDecl()->getDefinitionOrSelf(), Unit,
                                     LineNo, LinkageName, Var, DContext);
      continue;
    }
    // Use VarDecl's Tag, Scope and Line number.
    GVE = DBuilder.createGlobalVariableExpression(
        DContext, FieldName, LinkageName, Unit, LineNo, FieldTy,
        Var->hasLocalLinkage());
    Var->addDebugInfo(GVE);
  }
  return GVE;
}

static bool ReferencesAnonymousEntity(ArrayRef<TemplateArgument> Args);
static bool ReferencesAnonymousEntity(RecordType *RT) {
  // Unnamed classes/lambdas can't be reconstituted due to a lack of column
  // info we produce in the DWARF, so we can't get Clang's full name back.
  // But so long as it's not one of those, it doesn't matter if some sub-type
  // of the record (a template parameter) can't be reconstituted - because the
  // un-reconstitutable type itself will carry its own name.
  const auto *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
  if (!RD)
    return false;
  if (!RD->getIdentifier())
    return true;
  auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD);
  if (!TSpecial)
    return false;
  return ReferencesAnonymousEntity(TSpecial->getTemplateArgs().asArray());
}
static bool ReferencesAnonymousEntity(ArrayRef<TemplateArgument> Args) {
  return llvm::any_of(Args, [&](const TemplateArgument &TA) {
    switch (TA.getKind()) {
    case TemplateArgument::Pack:
      return ReferencesAnonymousEntity(TA.getPackAsArray());
    case TemplateArgument::Type: {
      struct ReferencesAnonymous
          : public RecursiveASTVisitor<ReferencesAnonymous> {
        bool RefAnon = false;
        bool VisitRecordType(RecordType *RT) {
          if (ReferencesAnonymousEntity(RT)) {
            RefAnon = true;
            return false;
          }
          return true;
        }
      };
      ReferencesAnonymous RT;
      RT.TraverseType(TA.getAsType());
      if (RT.RefAnon)
        return true;
      break;
    }
    default:
      break;
    }
    return false;
  });
}
namespace {
struct ReconstitutableType : public RecursiveASTVisitor<ReconstitutableType> {
  bool Reconstitutable = true;
  bool VisitVectorType(VectorType *FT) {
    Reconstitutable = false;
    return false;
  }
  bool VisitAtomicType(AtomicType *FT) {
    Reconstitutable = false;
    return false;
  }
  bool TraverseEnumType(EnumType *ET, bool = false) {
    // Unnamed enums can't be reconstituted due to a lack of column info we
    // produce in the DWARF, so we can't get Clang's full name back.
    const EnumDecl *ED = ET->getDecl();
    if (!ED->getIdentifier()) {
      Reconstitutable = false;
      return false;
    }
    if (!ED->getDefinitionOrSelf()->isExternallyVisible()) {
      Reconstitutable = false;
      return false;
    }
    return true;
  }
  bool VisitFunctionProtoType(FunctionProtoType *FT) {
    // noexcept is not encoded in DWARF, so the reversi
    Reconstitutable &= !isNoexceptExceptionSpec(FT->getExceptionSpecType());
    Reconstitutable &= !FT->getNoReturnAttr();
    return Reconstitutable;
  }
  bool VisitRecordType(RecordType *RT, bool = false) {
    if (ReferencesAnonymousEntity(RT)) {
      Reconstitutable = false;
      return false;
    }
    return true;
  }
};
} // anonymous namespace

// Test whether a type name could be rebuilt from emitted debug info.
static bool IsReconstitutableType(QualType QT) {
  ReconstitutableType T;
  T.TraverseType(QT);
  return T.Reconstitutable;
}

bool CGDebugInfo::HasReconstitutableArgs(
    ArrayRef<TemplateArgument> Args) const {
  return llvm::all_of(Args, [&](const TemplateArgument &TA) {
    switch (TA.getKind()) {
    case TemplateArgument::Template:
      // Easy to reconstitute - the value of the parameter in the debug
      // info is the string name of the template. The template name
      // itself won't benefit from any name rebuilding, but that's a
      // representational limitation - maybe DWARF could be
      // changed/improved to use some more structural representation.
      return true;
    case TemplateArgument::Declaration:
      // Reference and pointer non-type template parameters point to
      // variables, functions, etc and their value is, at best (for
      // variables) represented as an address - not a reference to the
      // DWARF describing the variable/function/etc. This makes it hard,
      // possibly impossible to rebuild the original name - looking up
      // the address in the executable file's symbol table would be
      // needed.
      return false;
    case TemplateArgument::NullPtr:
      // These could be rebuilt, but figured they're close enough to the
      // declaration case, and not worth rebuilding.
      return false;
    case TemplateArgument::Pack:
      // A pack is invalid if any of the elements of the pack are
      // invalid.
      return HasReconstitutableArgs(TA.getPackAsArray());
    case TemplateArgument::Integral:
      // Larger integers get encoded as DWARF blocks which are a bit
      // harder to parse back into a large integer, etc - so punting on
      // this for now. Re-parsing the integers back into APInt is
      // probably feasible some day.
      return TA.getAsIntegral().getBitWidth() <= 64 &&
             IsReconstitutableType(TA.getIntegralType());
    case TemplateArgument::StructuralValue:
      return false;
    case TemplateArgument::Type:
      return IsReconstitutableType(TA.getAsType());
    case TemplateArgument::Expression:
      return IsReconstitutableType(TA.getAsExpr()->getType());
    default:
      llvm_unreachable("Other, unresolved, template arguments should "
                       "not be seen here");
    }
  });
}

std::string CGDebugInfo::GetName(const Decl *D, bool Qualified,
                                 bool *NameIsSimplified) const {
  std::string Name;
  llvm::raw_string_ostream OS(Name);
  const NamedDecl *ND = dyn_cast<NamedDecl>(D);
  if (!ND)
    return Name;
  llvm::codegenoptions::DebugTemplateNamesKind TemplateNamesKind =
      CGM.getCodeGenOpts().getDebugSimpleTemplateNames();

  if (!CGM.getCodeGenOpts().hasReducedDebugInfo())
    TemplateNamesKind = llvm::codegenoptions::DebugTemplateNamesKind::Full;

  std::optional<TemplateArgs> Args;

  bool IsOperatorOverload = false; // isa<CXXConversionDecl>(ND);
  if (auto *RD = dyn_cast<CXXRecordDecl>(ND)) {
    Args = GetTemplateArgs(RD);
  } else if (auto *FD = dyn_cast<FunctionDecl>(ND)) {
    Args = GetTemplateArgs(FD);
    auto NameKind = ND->getDeclName().getNameKind();
    IsOperatorOverload |=
        NameKind == DeclarationName::CXXOperatorName ||
        NameKind == DeclarationName::CXXConversionFunctionName;
  } else if (auto *VD = dyn_cast<VarDecl>(ND)) {
    Args = GetTemplateArgs(VD);
  }

  // A conversion operator presents complications/ambiguity if there's a
  // conversion to class template that is itself a template, eg:
  // template<typename T>
  // operator ns::t1<T, int>();
  // This should be named, eg: "operator ns::t1<float, int><float>"
  // (ignoring clang bug that means this is currently "operator t1<float>")
  // but if the arguments were stripped, the consumer couldn't differentiate
  // whether the template argument list for the conversion type was the
  // function's argument list (& no reconstitution was needed) or not.
  // This could be handled if reconstitutable names had a separate attribute
  // annotating them as such - this would remove the ambiguity.
  //
  // Alternatively the template argument list could be parsed enough to check
  // whether there's one list or two, then compare that with the DWARF
  // description of the return type and the template argument lists to determine
  // how many lists there should be and if one is missing it could be assumed(?)
  // to be the function's template argument list  & then be rebuilt.
  //
  // Other operator overloads that aren't conversion operators could be
  // reconstituted but would require a bit more nuance about detecting the
  // difference between these different operators during that rebuilding.
  bool Reconstitutable =
      Args && HasReconstitutableArgs(Args->Args) && !IsOperatorOverload;

  PrintingPolicy PP = getPrintingPolicy();

  if (TemplateNamesKind == llvm::codegenoptions::DebugTemplateNamesKind::Full ||
      !Reconstitutable) {
    ND->getNameForDiagnostic(OS, PP, Qualified);
  } else {
    // Treat both "simple" and "mangled" as simplified.
    if (NameIsSimplified)
      *NameIsSimplified = true;
    bool Mangled = TemplateNamesKind ==
                   llvm::codegenoptions::DebugTemplateNamesKind::Mangled;
    // check if it's a template
    if (Mangled)
      OS << "_STN|";

    OS << ND->getDeclName();
    std::string EncodedOriginalName;
    llvm::raw_string_ostream EncodedOriginalNameOS(EncodedOriginalName);
    EncodedOriginalNameOS << ND->getDeclName();

    if (Mangled) {
      OS << "|";
      printTemplateArgumentList(OS, Args->Args, PP);
      printTemplateArgumentList(EncodedOriginalNameOS, Args->Args, PP);
#ifndef NDEBUG
      std::string CanonicalOriginalName;
      llvm::raw_string_ostream OriginalOS(CanonicalOriginalName);
      ND->getNameForDiagnostic(OriginalOS, PP, Qualified);
      assert(EncodedOriginalName == CanonicalOriginalName);
#endif
    }
  }
  return Name;
}

void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
                                     const VarDecl *D) {
  assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
  if (D->hasAttr<NoDebugAttr>())
    return;

  llvm::TimeTraceScope TimeScope("DebugGlobalVariable", [&]() {
    return GetName(D, true);
  });

  // If we already created a DIGlobalVariable for this declaration, just attach
  // it to the llvm::GlobalVariable.
  auto Cached = DeclCache.find(D->getCanonicalDecl());
  if (Cached != DeclCache.end())
    return Var->addDebugInfo(
        cast<llvm::DIGlobalVariableExpression>(Cached->second));

  // Create global variable debug descriptor.
  llvm::DIFile *Unit = nullptr;
  llvm::DIScope *DContext = nullptr;
  unsigned LineNo;
  StringRef DeclName, LinkageName;
  QualType T;
  llvm::MDTuple *TemplateParameters = nullptr;
  collectVarDeclProps(D, Unit, LineNo, T, DeclName, LinkageName,
                      TemplateParameters, DContext);

  // Attempt to store one global variable for the declaration - even if we
  // emit a lot of fields.
  llvm::DIGlobalVariableExpression *GVE = nullptr;

  // If this is an anonymous union then we'll want to emit a global
  // variable for each member of the anonymous union so that it's possible
  // to find the name of any field in the union.
  if (T->isUnionType() && DeclName.empty()) {
    const auto *RD = T->castAsRecordDecl();
    assert(RD->isAnonymousStructOrUnion() &&
           "unnamed non-anonymous struct or union?");
    GVE = CollectAnonRecordDecls(RD, Unit, LineNo, LinkageName, Var, DContext);
  } else {
    auto Align = getDeclAlignIfRequired(D, CGM.getContext());

    SmallVector<uint64_t, 4> Expr;
    unsigned AddressSpace = CGM.getTypes().getTargetAddressSpace(D->getType());
    if (CGM.getLangOpts().CUDA && CGM.getLangOpts().CUDAIsDevice) {
      if (D->hasAttr<CUDASharedAttr>())
        AddressSpace =
            CGM.getContext().getTargetAddressSpace(LangAS::cuda_shared);
      else if (D->hasAttr<CUDAConstantAttr>())
        AddressSpace =
            CGM.getContext().getTargetAddressSpace(LangAS::cuda_constant);
    }
    AppendAddressSpaceXDeref(AddressSpace, Expr);

    llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(D);
    GVE = DBuilder.createGlobalVariableExpression(
        DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
        Var->hasLocalLinkage(), true,
        Expr.empty() ? nullptr : DBuilder.createExpression(Expr),
        getOrCreateStaticDataMemberDeclarationOrNull(D), TemplateParameters,
        Align, Annotations);
    Var->addDebugInfo(GVE);
  }
  DeclCache[D->getCanonicalDecl()].reset(GVE);
}

void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) {
  assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
  if (VD->hasAttr<NoDebugAttr>())
    return;
  llvm::TimeTraceScope TimeScope("DebugConstGlobalVariable", [&]() {
    return GetName(VD, true);
  });

  auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
  // Create the descriptor for the variable.
  llvm::DIFile *Unit = getOrCreateFile(VD->getLocation());
  StringRef Name = VD->getName();
  llvm::DIType *Ty = getOrCreateType(VD->getType(), Unit);

  if (const auto *ECD = dyn_cast<EnumConstantDecl>(VD)) {
    const auto *ED = cast<EnumDecl>(ECD->getDeclContext());
    if (CGM.getCodeGenOpts().EmitCodeView) {
      // If CodeView, emit enums as global variables, unless they are defined
      // inside a class. We do this because MSVC doesn't emit S_CONSTANTs for
      // enums in classes, and because it is difficult to attach this scope
      // information to the global variable.
      if (isa<RecordDecl>(ED->getDeclContext()))
        return;
    } else {
      // If not CodeView, emit DW_TAG_enumeration_type if necessary. For
      // example: for "enum { ZERO };", a DW_TAG_enumeration_type is created the
      // first time `ZERO` is referenced in a function.
      CanQualType T = CGM.getContext().getCanonicalTagType(ED);
      [[maybe_unused]] llvm::DIType *EDTy = getOrCreateType(T, Unit);
      assert(EDTy->getTag() == llvm::dwarf::DW_TAG_enumeration_type);
      return;
    }
  }

  // Do not emit separate definitions for function local consts.
  if (isa<FunctionDecl>(VD->getDeclContext()))
    return;

  VD = cast<ValueDecl>(VD->getCanonicalDecl());
  auto *VarD = dyn_cast<VarDecl>(VD);
  if (VarD && VarD->isStaticDataMember()) {
    auto *RD = cast<RecordDecl>(VarD->getDeclContext());
    getDeclContextDescriptor(VarD);
    // Ensure that the type is retained even though it's otherwise unreferenced.
    //
    // FIXME: This is probably unnecessary, since Ty should reference RD
    // through its scope.
    RetainedTypes.push_back(
        CGM.getContext().getCanonicalTagType(RD).getAsOpaquePtr());

    return;
  }
  llvm::DIScope *DContext = getDeclContextDescriptor(VD);

  auto &GV = DeclCache[VD];
  if (GV)
    return;

  llvm::DIExpression *InitExpr = createConstantValueExpression(VD, Init);
  llvm::MDTuple *TemplateParameters = nullptr;

  if (isa<VarTemplateSpecializationDecl>(VD))
    if (VarD) {
      llvm::DINodeArray parameterNodes = CollectVarTemplateParams(VarD, &*Unit);
      TemplateParameters = parameterNodes.get();
    }

  GV.reset(DBuilder.createGlobalVariableExpression(
      DContext, Name, StringRef(), Unit, getLineNumber(VD->getLocation()), Ty,
      true, true, InitExpr, getOrCreateStaticDataMemberDeclarationOrNull(VarD),
      TemplateParameters, Align));
}

void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var,
                                       const VarDecl *D) {
  assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
  if (D->hasAttr<NoDebugAttr>())
    return;

  auto Align = getDeclAlignIfRequired(D, CGM.getContext());
  llvm::DIFile *Unit = getOrCreateFile(D->getLocation());
  StringRef Name = D->getName();
  llvm::DIType *Ty = getOrCreateType(D->getType(), Unit);

  llvm::DIScope *DContext = getDeclContextDescriptor(D);
  llvm::DIGlobalVariableExpression *GVE =
      DBuilder.createGlobalVariableExpression(
          DContext, Name, StringRef(), Unit, getLineNumber(D->getLocation()),
          Ty, false, false, nullptr, nullptr, nullptr, Align);
  Var->addDebugInfo(GVE);
}

void CGDebugInfo::EmitPseudoVariable(CGBuilderTy &Builder,
                                     llvm::Instruction *Value, QualType Ty) {
  // Only when -g2 or above is specified, debug info for variables will be
  // generated.
  if (CGM.getCodeGenOpts().getDebugInfo() <=
      llvm::codegenoptions::DebugLineTablesOnly)
    return;

  llvm::DILocation *DIL = Value->getDebugLoc().get();
  if (!DIL)
    return;

  llvm::DIFile *Unit = DIL->getFile();
  llvm::DIType *Type = getOrCreateType(Ty, Unit);

  // Check if Value is already a declared variable and has debug info, in this
  // case we have nothing to do. Clang emits a declared variable as alloca, and
  // it is loaded upon use, so we identify such pattern here.
  if (llvm::LoadInst *Load = dyn_cast<llvm::LoadInst>(Value)) {
    llvm::Value *Var = Load->getPointerOperand();
    // There can be implicit type cast applied on a variable if it is an opaque
    // ptr, in this case its debug info may not match the actual type of object
    // being used as in the next instruction, so we will need to emit a pseudo
    // variable for type-casted value.
    auto DeclareTypeMatches = [&](llvm::DbgVariableRecord *DbgDeclare) {
      return DbgDeclare->getVariable()->getType() == Type;
    };
    if (any_of(llvm::findDVRDeclares(Var), DeclareTypeMatches))
      return;
  }

  llvm::DILocalVariable *D =
      DBuilder.createAutoVariable(LexicalBlockStack.back(), "", nullptr, 0,
                                  Type, false, llvm::DINode::FlagArtificial);

  if (auto InsertPoint = Value->getInsertionPointAfterDef()) {
    DBuilder.insertDbgValue(Value, D, DBuilder.createExpression(), DIL,
                            *InsertPoint);
  }
}

void CGDebugInfo::EmitGlobalAlias(const llvm::GlobalValue *GV,
                                  const GlobalDecl GD) {

  assert(GV);

  if (!CGM.getCodeGenOpts().hasReducedDebugInfo())
    return;

  const auto *D = cast<ValueDecl>(GD.getDecl());
  if (D->hasAttr<NoDebugAttr>())
    return;

  auto AliaseeDecl = CGM.getMangledNameDecl(GV->getName());
  llvm::DINode *DI;

  if (!AliaseeDecl)
    // FIXME: Aliasee not declared yet - possibly declared later
    // For example,
    //
    //   1 extern int newname __attribute__((alias("oldname")));
    //   2 int oldname = 1;
    //
    // No debug info would be generated for 'newname' in this case.
    //
    // Fix compiler to generate "newname" as imported_declaration
    // pointing to the DIE of "oldname".
    return;
  if (!(DI = getDeclarationOrDefinition(
            AliaseeDecl.getCanonicalDecl().getDecl())))
    return;

  llvm::DIScope *DContext = getDeclContextDescriptor(D);
  auto Loc = D->getLocation();

  llvm::DIImportedEntity *ImportDI = DBuilder.createImportedDeclaration(
      DContext, DI, getOrCreateFile(Loc), getLineNumber(Loc), D->getName());

  // Record this DIE in the cache for nested declaration reference.
  ImportedDeclCache[GD.getCanonicalDecl().getDecl()].reset(ImportDI);
}

void CGDebugInfo::AddStringLiteralDebugInfo(llvm::GlobalVariable *GV,
                                            const StringLiteral *S) {
  SourceLocation Loc = S->getStrTokenLoc(0);
  SourceManager &SM = CGM.getContext().getSourceManager();
  PresumedLoc PLoc = SM.getPresumedLoc(getMacroDebugLoc(CGM, Loc));
  if (!PLoc.isValid())
    return;

  llvm::DIFile *File = getOrCreateFile(Loc);
  llvm::DIGlobalVariableExpression *Debug =
      DBuilder.createGlobalVariableExpression(
          nullptr, StringRef(), StringRef(), getOrCreateFile(Loc),
          getLineNumber(Loc), getOrCreateType(S->getType(), File), true);
  GV->addDebugInfo(Debug);
}

llvm::DIScope *CGDebugInfo::getCurrentContextDescriptor(const Decl *D) {
  if (!LexicalBlockStack.empty())
    return LexicalBlockStack.back();
  llvm::DIScope *Mod = getParentModuleOrNull(D);
  return getContextDescriptor(D, Mod ? Mod : TheCU);
}

void CGDebugInfo::EmitUsingDirective(const UsingDirectiveDecl &UD) {
  if (!CGM.getCodeGenOpts().hasReducedDebugInfo())
    return;
  const NamespaceDecl *NSDecl = UD.getNominatedNamespace();
  if (!NSDecl->isAnonymousNamespace() ||
      CGM.getCodeGenOpts().DebugExplicitImport) {
    auto Loc = UD.getLocation();
    if (!Loc.isValid())
      Loc = CurLoc;
    DBuilder.createImportedModule(
        getCurrentContextDescriptor(cast<Decl>(UD.getDeclContext())),
        getOrCreateNamespace(NSDecl), getOrCreateFile(Loc), getLineNumber(Loc));
  }
}

void CGDebugInfo::EmitUsingShadowDecl(const UsingShadowDecl &USD) {
  if (llvm::DINode *Target =
          getDeclarationOrDefinition(USD.getUnderlyingDecl())) {
    auto Loc = USD.getLocation();
    DBuilder.createImportedDeclaration(
        getCurrentContextDescriptor(cast<Decl>(USD.getDeclContext())), Target,
        getOrCreateFile(Loc), getLineNumber(Loc));
  }
}

void CGDebugInfo::EmitUsingDecl(const UsingDecl &UD) {
  if (!CGM.getCodeGenOpts().hasReducedDebugInfo())
    return;
  assert(UD.shadow_size() &&
         "We shouldn't be codegening an invalid UsingDecl containing no decls");

  for (const auto *USD : UD.shadows()) {
    // FIXME: Skip functions with undeduced auto return type for now since we
    // don't currently have the plumbing for separate declarations & definitions
    // of free functions and mismatched types (auto in the declaration, concrete
    // return type in the definition)
    if (const auto *FD = dyn_cast<FunctionDecl>(USD->getUnderlyingDecl()))
      if (const auto *AT = FD->getType()
                               ->castAs<FunctionProtoType>()
                               ->getContainedAutoType())
        if (AT->getDeducedType().isNull())
          continue;

    EmitUsingShadowDecl(*USD);
    // Emitting one decl is sufficient - debuggers can detect that this is an
    // overloaded name & provide lookup for all the overloads.
    break;
  }
}

void CGDebugInfo::EmitUsingEnumDecl(const UsingEnumDecl &UD) {
  if (!CGM.getCodeGenOpts().hasReducedDebugInfo())
    return;
  assert(UD.shadow_size() &&
         "We shouldn't be codegening an invalid UsingEnumDecl"
         " containing no decls");

  for (const auto *USD : UD.shadows())
    EmitUsingShadowDecl(*USD);
}

void CGDebugInfo::EmitImportDecl(const ImportDecl &ID) {
  if (CGM.getCodeGenOpts().getDebuggerTuning() != llvm::DebuggerKind::LLDB)
    return;
  if (Module *M = ID.getImportedModule()) {
    auto Info = ASTSourceDescriptor(*M);
    auto Loc = ID.getLocation();
    DBuilder.createImportedDeclaration(
        getCurrentContextDescriptor(cast<Decl>(ID.getDeclContext())),
        getOrCreateModuleRef(Info, DebugTypeExtRefs), getOrCreateFile(Loc),
        getLineNumber(Loc));
  }
}

llvm::DIImportedEntity *
CGDebugInfo::EmitNamespaceAlias(const NamespaceAliasDecl &NA) {
  if (!CGM.getCodeGenOpts().hasReducedDebugInfo())
    return nullptr;
  auto &VH = NamespaceAliasCache[&NA];
  if (VH)
    return cast<llvm::DIImportedEntity>(VH);
  llvm::DIImportedEntity *R;
  auto Loc = NA.getLocation();
  if (const auto *Underlying =
          dyn_cast<NamespaceAliasDecl>(NA.getAliasedNamespace()))
    // This could cache & dedup here rather than relying on metadata deduping.
    R = DBuilder.createImportedDeclaration(
        getCurrentContextDescriptor(cast<Decl>(NA.getDeclContext())),
        EmitNamespaceAlias(*Underlying), getOrCreateFile(Loc),
        getLineNumber(Loc), NA.getName());
  else
    R = DBuilder.createImportedDeclaration(
        getCurrentContextDescriptor(cast<Decl>(NA.getDeclContext())),
        getOrCreateNamespace(cast<NamespaceDecl>(NA.getAliasedNamespace())),
        getOrCreateFile(Loc), getLineNumber(Loc), NA.getName());
  VH.reset(R);
  return R;
}

llvm::DINamespace *
CGDebugInfo::getOrCreateNamespace(const NamespaceDecl *NSDecl) {
  // Don't canonicalize the NamespaceDecl here: The DINamespace will be uniqued
  // if necessary, and this way multiple declarations of the same namespace in
  // different parent modules stay distinct.
  auto I = NamespaceCache.find(NSDecl);
  if (I != NamespaceCache.end())
    return cast<llvm::DINamespace>(I->second);

  llvm::DIScope *Context = getDeclContextDescriptor(NSDecl);
  // Don't trust the context if it is a DIModule (see comment above).
  llvm::DINamespace *NS =
      DBuilder.createNameSpace(Context, NSDecl->getName(), NSDecl->isInline());
  NamespaceCache[NSDecl].reset(NS);
  return NS;
}

void CGDebugInfo::setDwoId(uint64_t Signature) {
  assert(TheCU && "no main compile unit");
  TheCU->setDWOId(Signature);
}

void CGDebugInfo::finalize() {
  // Creating types might create further types - invalidating the current
  // element and the size(), so don't cache/reference them.
  for (size_t i = 0; i != ObjCInterfaceCache.size(); ++i) {
    ObjCInterfaceCacheEntry E = ObjCInterfaceCache[i];
    llvm::DIType *Ty = E.Type->getDecl()->getDefinition()
                           ? CreateTypeDefinition(E.Type, E.Unit)
                           : E.Decl;
    DBuilder.replaceTemporary(llvm::TempDIType(E.Decl), Ty);
  }

  // Add methods to interface.
  for (const auto &P : ObjCMethodCache) {
    if (P.second.empty())
      continue;

    QualType QTy(P.first->getTypeForDecl(), 0);
    auto It = TypeCache.find(QTy.getAsOpaquePtr());
    assert(It != TypeCache.end());

    llvm::DICompositeType *InterfaceDecl =
        cast<llvm::DICompositeType>(It->second);

    auto CurElts = InterfaceDecl->getElements();
    SmallVector<llvm::Metadata *, 16> EltTys(CurElts.begin(), CurElts.end());

    // For DWARF v4 or earlier, only add objc_direct methods.
    for (auto &SubprogramDirect : P.second)
      if (CGM.getCodeGenOpts().DwarfVersion >= 5 || SubprogramDirect.getInt())
        EltTys.push_back(SubprogramDirect.getPointer());

    llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
    DBuilder.replaceArrays(InterfaceDecl, Elements);
  }

  for (const auto &P : ReplaceMap) {
    assert(P.second);
    auto *Ty = cast<llvm::DIType>(P.second);
    assert(Ty->isForwardDecl());

    auto It = TypeCache.find(P.first);
    assert(It != TypeCache.end());
    assert(It->second);

    DBuilder.replaceTemporary(llvm::TempDIType(Ty),
                              cast<llvm::DIType>(It->second));
  }

  for (const auto &P : FwdDeclReplaceMap) {
    assert(P.second);
    llvm::TempMDNode FwdDecl(cast<llvm::MDNode>(P.second));
    llvm::Metadata *Repl;

    auto It = DeclCache.find(P.first);
    // If there has been no definition for the declaration, call RAUW
    // with ourselves, that will destroy the temporary MDNode and
    // replace it with a standard one, avoiding leaking memory.
    if (It == DeclCache.end())
      Repl = P.second;
    else
      Repl = It->second;

    if (auto *GVE = dyn_cast_or_null<llvm::DIGlobalVariableExpression>(Repl))
      Repl = GVE->getVariable();
    DBuilder.replaceTemporary(std::move(FwdDecl), cast<llvm::MDNode>(Repl));
  }

  // We keep our own list of retained types, because we need to look
  // up the final type in the type cache.
  for (auto &RT : RetainedTypes)
    if (auto MD = TypeCache[RT])
      DBuilder.retainType(cast<llvm::DIType>(MD));

  DBuilder.finalize();
}

// Don't ignore in case of explicit cast where it is referenced indirectly.
void CGDebugInfo::EmitExplicitCastType(QualType Ty) {
  if (CGM.getCodeGenOpts().hasReducedDebugInfo())
    if (auto *DieTy = getOrCreateType(Ty, TheCU->getFile()))
      DBuilder.retainType(DieTy);
}

void CGDebugInfo::EmitAndRetainType(QualType Ty) {
  if (CGM.getCodeGenOpts().hasMaybeUnusedDebugInfo())
    if (auto *DieTy = getOrCreateType(Ty, TheCU->getFile()))
      DBuilder.retainType(DieTy);
}

llvm::DebugLoc CGDebugInfo::SourceLocToDebugLoc(SourceLocation Loc) {
  if (LexicalBlockStack.empty())
    return llvm::DebugLoc();

  llvm::MDNode *Scope = LexicalBlockStack.back();
  return llvm::DILocation::get(CGM.getLLVMContext(), getLineNumber(Loc),
                               getColumnNumber(Loc), Scope);
}

llvm::DINode::DIFlags CGDebugInfo::getCallSiteRelatedAttrs() const {
  // Call site-related attributes are only useful in optimized programs, and
  // when there's a possibility of debugging backtraces.
  if (CGM.getCodeGenOpts().OptimizationLevel == 0 ||
      DebugKind == llvm::codegenoptions::NoDebugInfo ||
      DebugKind == llvm::codegenoptions::LocTrackingOnly ||
      !CGM.getCodeGenOpts().DebugCallSiteInfo)
    return llvm::DINode::FlagZero;

  // Call site-related attributes are available in DWARF v5. Some debuggers,
  // while not fully DWARF v5-compliant, may accept these attributes as if they
  // were part of DWARF v4.
  bool SupportsDWARFv4Ext =
      CGM.getCodeGenOpts().DwarfVersion == 4 &&
      (CGM.getCodeGenOpts().getDebuggerTuning() == llvm::DebuggerKind::LLDB ||
       CGM.getCodeGenOpts().getDebuggerTuning() == llvm::DebuggerKind::GDB);

  if (!SupportsDWARFv4Ext && CGM.getCodeGenOpts().DwarfVersion < 5)
    return llvm::DINode::FlagZero;

  return llvm::DINode::FlagAllCallsDescribed;
}

llvm::DIExpression *
CGDebugInfo::createConstantValueExpression(const clang::ValueDecl *VD,
                                           const APValue &Val) {
  // FIXME: Add a representation for integer constants wider than 64 bits.
  if (CGM.getContext().getTypeSize(VD->getType()) > 64)
    return nullptr;

  if (Val.isFloat())
    return DBuilder.createConstantValueExpression(
        Val.getFloat().bitcastToAPInt().getZExtValue());

  if (!Val.isInt())
    return nullptr;

  llvm::APSInt const &ValInt = Val.getInt();
  std::optional<uint64_t> ValIntOpt;
  if (ValInt.isUnsigned())
    ValIntOpt = ValInt.tryZExtValue();
  else if (auto tmp = ValInt.trySExtValue())
    // Transform a signed optional to unsigned optional. When cpp 23 comes,
    // use std::optional::transform
    ValIntOpt = static_cast<uint64_t>(*tmp);

  if (ValIntOpt)
    return DBuilder.createConstantValueExpression(ValIntOpt.value());

  return nullptr;
}

CodeGenFunction::LexicalScope::LexicalScope(CodeGenFunction &CGF,
                                            SourceRange Range)
    : RunCleanupsScope(CGF), Range(Range), ParentScope(CGF.CurLexicalScope) {
  CGF.CurLexicalScope = this;
  if (CGDebugInfo *DI = CGF.getDebugInfo())
    DI->EmitLexicalBlockStart(CGF.Builder, Range.getBegin());
}

CodeGenFunction::LexicalScope::~LexicalScope() {
  if (CGDebugInfo *DI = CGF.getDebugInfo())
    DI->EmitLexicalBlockEnd(CGF.Builder, Range.getEnd());

  // If we should perform a cleanup, force them now.  Note that
  // this ends the cleanup scope before rescoping any labels.
  if (PerformCleanup) {
    ApplyDebugLocation DL(CGF, Range.getEnd());
    ForceCleanup();
  }
}

static std::string SanitizerHandlerToCheckLabel(SanitizerHandler Handler) {
  std::string Label;
  switch (Handler) {
#define SANITIZER_CHECK(Enum, Name, Version, Msg)                              \
  case Enum:                                                                   \
    Label = "__ubsan_check_" #Name;                                            \
    break;

    LIST_SANITIZER_CHECKS
#undef SANITIZER_CHECK
  };

  // Label doesn't require sanitization
  return Label;
}

static std::string
SanitizerOrdinalToCheckLabel(SanitizerKind::SanitizerOrdinal Ordinal) {
  std::string Label;
  switch (Ordinal) {
#define SANITIZER(NAME, ID)                                                    \
  case SanitizerKind::SO_##ID:                                                 \
    Label = "__ubsan_check_" NAME;                                             \
    break;
#include "clang/Basic/Sanitizers.def"
  default:
    llvm_unreachable("unexpected sanitizer kind");
  }

  // Sanitize label (convert hyphens to underscores; also futureproof against
  // non-alpha)
  for (unsigned int i = 0; i < Label.length(); i++)
    if (!std::isalpha(Label[i]))
      Label[i] = '_';

  return Label;
}

llvm::DILocation *CodeGenFunction::SanitizerAnnotateDebugInfo(
    ArrayRef<SanitizerKind::SanitizerOrdinal> Ordinals,
    SanitizerHandler Handler) {
  llvm::DILocation *CheckDebugLoc = Builder.getCurrentDebugLocation();
  auto *DI = getDebugInfo();
  if (!DI || !CheckDebugLoc)
    return CheckDebugLoc;
  const auto &AnnotateDebugInfo =
      CGM.getCodeGenOpts().SanitizeAnnotateDebugInfo;
  if (AnnotateDebugInfo.empty())
    return CheckDebugLoc;

  std::string Label;
  if (Ordinals.size() == 1)
    Label = SanitizerOrdinalToCheckLabel(Ordinals[0]);
  else
    Label = SanitizerHandlerToCheckLabel(Handler);

  if (any_of(Ordinals, [&](auto Ord) { return AnnotateDebugInfo.has(Ord); })) {
    // Use ubsan header file to have the same filename for all checks. There is
    // nothing special in that file, we just want to make tools to count all
    // syntetic functions of a check as the same.
    llvm::DIFile *File = llvm::DIFile::get(CGM.getLLVMContext(),
                                           /*Filename=*/"ubsan_interface.h",
                                           /*Directory=*/"sanitizer");
    return DI->CreateSyntheticInlineAt(CheckDebugLoc, Label, File);
  }

  return CheckDebugLoc;
}

SanitizerDebugLocation::SanitizerDebugLocation(
    CodeGenFunction *CGF, ArrayRef<SanitizerKind::SanitizerOrdinal> Ordinals,
    SanitizerHandler Handler)
    : CGF(CGF),
      Apply(*CGF, CGF->SanitizerAnnotateDebugInfo(Ordinals, Handler)) {
  assert(!CGF->IsSanitizerScope);
  CGF->IsSanitizerScope = true;
}

SanitizerDebugLocation::~SanitizerDebugLocation() {
  assert(CGF->IsSanitizerScope);
  CGF->IsSanitizerScope = false;
}
