//===--- IRGenDebugInfo.cpp - Debug Info Support --------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements IR debug info generation for Swift.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "debug-info"
#include "IRGenDebugInfo.h"
#include "GenOpaque.h"
#include "GenType.h"
#include "Linking.h"
#include "swift/AST/Expr.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/ASTMangler.h"
#include "swift/AST/Module.h"
#include "swift/AST/ModuleLoader.h"
#include "swift/AST/Pattern.h"
#include "swift/Basic/Dwarf.h"
#include "swift/Basic/Punycode.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Basic/Version.h"
#include "swift/Basic/ManglingMacros.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILBasicBlock.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILModule.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/Config/config.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/Local.h"

using namespace swift;
using namespace irgen;

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

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

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

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

#ifndef NDEBUG

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

#endif

IRGenDebugInfo::IRGenDebugInfo(const IRGenOptions &Opts,
                               ClangImporter &CI,
                               IRGenModule &IGM,
                               llvm::Module &M,
                               SourceFile *SF)
  : Opts(Opts),
    CI(CI),
    SM(IGM.Context.SourceMgr),
    M(M),
    DBuilder(M),
    IGM(IGM),
    MetadataTypeDecl(nullptr),
    InternalType(nullptr),
    LastDebugLoc({}),
    LastScope(nullptr)
{
  assert(Opts.DebugInfoKind > IRGenDebugInfoKind::None
         && "no debug info should be generated");
  StringRef SourceFileName = SF ? SF->getFilename() :
                                  StringRef(Opts.MainInputFilename);
  StringRef Dir;
  llvm::SmallString<256> AbsMainFile;
  if (SourceFileName.empty())
    AbsMainFile = "<unknown>";
  else {
    AbsMainFile = SourceFileName;
    llvm::sys::fs::make_absolute(AbsMainFile);
  }

  unsigned Lang = llvm::dwarf::DW_LANG_Swift;
  std::string Producer = version::getSwiftFullVersion(
    IGM.Context.LangOpts.EffectiveLanguageVersion);
  bool IsOptimized = Opts.Optimize;
  StringRef Flags = Opts.DWARFDebugFlags;
  unsigned Major, Minor;
  std::tie(Major, Minor) = version::getSwiftNumericVersion();
  unsigned MajorRuntimeVersion = Major;

  // No split DWARF on Darwin.
  StringRef SplitName = StringRef();
  // Note that File + Dir need not result in a valid path.
  // Clang is doing the same thing here.
  TheCU = DBuilder.createCompileUnit(
      Lang, DBuilder.createFile(AbsMainFile, Opts.DebugCompilationDir),
      Producer, IsOptimized, Flags, MajorRuntimeVersion, SplitName,
      Opts.DebugInfoKind > IRGenDebugInfoKind::LineTables
          ? llvm::DICompileUnit::FullDebug
          : llvm::DICompileUnit::LineTablesOnly);
  MainFile = getOrCreateFile(BumpAllocatedString(AbsMainFile));

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

  // Create a module for the current compile unit.
  llvm::sys::path::remove_filename(AbsMainFile);
  MainModule =
      getOrCreateModule(Opts.ModuleName, TheCU, Opts.ModuleName, AbsMainFile);
  DBuilder.createImportedModule(MainFile, MainModule, 1);
}

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

SILLocation::DebugLoc getDeserializedLoc(Pattern *) { return {}; }
SILLocation::DebugLoc getDeserializedLoc(Expr *) { return {}; }
SILLocation::DebugLoc getDeserializedLoc(Stmt *) { return {}; }
SILLocation::DebugLoc getDeserializedLoc(Decl *D) {
  SILLocation::DebugLoc L;
  const DeclContext *DC = D->getDeclContext()->getModuleScopeContext();
  StringRef Filename = getFilenameFromDC(DC);
  if (!Filename.empty())
    L.Filename = Filename;
  return L;
}

/// Use the SM to figure out the actual line/column of a SourceLoc.
template <typename WithLoc>
SILLocation::DebugLoc getDebugLoc(SourceManager &SM, WithLoc *S,
                                  bool End = false) {
  SILLocation::DebugLoc L;
  if (S == nullptr)
    return L;

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

  return SILLocation::decode(Loc, SM);
}

/// Return the start of the location's source range.
static SILLocation::DebugLoc getStartLocation(Optional<SILLocation> OptLoc,
                                              SourceManager &SM) {
  if (!OptLoc) return {};
  return SILLocation::decode(OptLoc->getStartSourceLoc(), SM);
}

/// Return the debug location from a SILLocation.
static SILLocation::DebugLoc getDebugLocation(Optional<SILLocation> OptLoc,
                                              SourceManager &SM) {
  if (!OptLoc || OptLoc->isInPrologue())
    return {};
  return OptLoc->decodeDebugLoc(SM);
}


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

/// Determine whether this location is some kind of closure.
static bool isAbstractClosure(const SILLocation &Loc) {
  if (Expr *E = Loc.getAsASTNode<Expr>())
    if (isa<AbstractClosureExpr>(E))
      return true;
  return false;
}

llvm::MDNode *IRGenDebugInfo::createInlinedAt(const SILDebugScope *DS) {
  llvm::MDNode *InlinedAt = nullptr;
  if (DS) {
    // The inlined-at chain, starting with the innermost (noninlined) scope.
    auto Scopes = DS->flattenedInlineTree();

    // See if we share a common prefix with the last chain of inline scopes.
    unsigned N = 0;
    while (N < LastInlineChain.size() && N < Scopes.size() &&
           LastInlineChain[N].first == Scopes[N])
      InlinedAt = LastInlineChain[N++].second;
    LastInlineChain.resize(N);

    // Construct the new suffix.
    for (; N < Scopes.size(); ++N) {
      auto *CS = Scopes[N];
      // In SIL the inlined-at information is part of the scopes, in
      // LLVM IR it is part of the location. Transforming the inlined-at
      // SIL scope to a location means skipping the inlined-at scope.
      auto *Parent = CS->Parent.get<const SILDebugScope *>();
      auto *ParentScope = getOrCreateScope(Parent);
      auto L = CS->Loc.decodeDebugLoc(SM);
      InlinedAt = llvm::DebugLoc::get(L.Line, L.Column, ParentScope, InlinedAt);

      // Cache the suffix.
      LastInlineChain.push_back({CS, llvm::TrackingMDNodeRef(InlinedAt)});
    }
  }
  return InlinedAt;
}

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

bool IRGenDebugInfo::lineNumberIsSane(IRBuilder &Builder, unsigned Line) {
  if (IGM.IRGen.Opts.Optimize)
    return true;

  // Assert monotonically increasing line numbers within the same basic block;
  llvm::BasicBlock *CurBasicBlock = Builder.GetInsertBlock();
  if (CurBasicBlock == LastBasicBlock) {
    return Line >= LastDebugLoc.Line;
  }
  LastBasicBlock = CurBasicBlock;
  return true;
}
#endif

void IRGenDebugInfo::setCurrentLoc(IRBuilder &Builder, const SILDebugScope *DS,
                                   Optional<SILLocation> Loc) {
  assert(DS && "empty scope");
  // Inline info is emitted as part of the location below; extract the
  // original scope here.
  auto *Scope = getOrCreateScope(DS->getInlinedScope());
  if (!Scope)
    return;

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

  // Both the code that is used to set up a closure object and the
  // (beginning of) the closure itself has the AbstractClosureExpr as
  // location. We are only interested in the latter case and want to
  // ignore the setup code.
  //
  // callWithClosure(
  //  { // <-- a breakpoint here should only stop inside of the closure.
  //    foo();
  //  })
  //
  // The actual closure has a closure expression as scope.
  if (Loc && isAbstractClosure(*Loc) && DS && !isAbstractClosure(DS->Loc) &&
      !Loc->is<ImplicitReturnLocation>())
    L.Line = L.Column = 0;

  if (auto *Fn = DS->getInlinedFunction())
    if (Fn->isThunk())
      L.Line = L.Column = 0;

  // Reuse the last source location if we are still in the same
  // scope to get a more contiguous line table.
  if (L.Line == 0 && DS == LastScope)
    L = LastDebugLoc;

  // FIXME: Enable this assertion.
  //assert(lineNumberIsSane(Builder, L.Line) &&
  //       "-Onone, but line numbers are not monotonically increasing within bb");
  LastDebugLoc = L;
  LastScope = DS;

  auto *InlinedAt = createInlinedAt(DS);
  assert(((!InlinedAt) || (InlinedAt && Scope)) && "inlined w/o scope");
  assert(parentScopesAreSane(DS) && "parent scope sanity check failed");
  auto DL = llvm::DebugLoc::get(L.Line, L.Column, Scope, InlinedAt);
  // TODO: Write a strongly-worded letter to the person that came up
  // with a pair of functions spelled "get" and "Set".
  Builder.SetCurrentDebugLocation(DL);
}

void IRGenDebugInfo::setEntryPointLoc(IRBuilder &Builder) {
  auto DL = llvm::DebugLoc::get(0, 0, getEntryPointFn(), nullptr);
  Builder.SetCurrentDebugLocation(DL);
}

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

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

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

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

    // Force the debug info for the function to be emitted, even if it
    // is external or has been inlined.
    llvm::Function *Fn = nullptr;
    if (!SILFn->getName().empty() && !SILFn->isZombie())
      Fn = IGM.getAddrOfSILFunction(SILFn, NotForDefinition);
    auto *SP = emitFunction(*SILFn, Fn);

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

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

  if (Opts.DebugInfoKind <= IRGenDebugInfoKind::LineTables)
    return Parent;

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

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

  return DScope;
}

llvm::DIFile *IRGenDebugInfo::getOrCreateFile(StringRef Filename) {
  if (Filename.empty())
    return MainFile;

  if (MainFile) {
    SmallString<256> AbsMainFile, ThisFile;
    AbsMainFile = Filename;
    llvm::sys::fs::make_absolute(AbsMainFile);
    llvm::sys::path::append(ThisFile, MainFile->getDirectory(),
                            MainFile->getFilename());
    if (ThisFile == AbsMainFile) {
      DIFileCache[Filename] = llvm::TrackingMDNodeRef(MainFile);
      return MainFile;
    }
  }

  // Look in the cache first.
  auto CachedFile = DIFileCache.find(Filename);

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

  // Create a new one.
  StringRef File = llvm::sys::path::filename(Filename);
  llvm::SmallString<512> Path(Filename);
  llvm::sys::path::remove_filename(Path);
  llvm::DIFile *F = DBuilder.createFile(File, Path);

  // Cache it.
  DIFileCache[Filename] = llvm::TrackingMDNodeRef(F);
  return F;
}

StringRef IRGenDebugInfo::getName(const FuncDecl &FD) {
  // Getters and Setters are anonymous functions, so we forge a name
  // using its parent declaration.
  if (FD.isAccessor())
    if (ValueDecl *VD = FD.getAccessorStorageDecl()) {
      const char *Kind;
      switch (FD.getAccessorKind()) {
      case AccessorKind::NotAccessor: llvm_unreachable("this is an accessor");
      case AccessorKind::IsGetter: Kind = ".get"; break;
      case AccessorKind::IsSetter: Kind = ".set"; break;
      case AccessorKind::IsWillSet: Kind = ".willset"; break;
      case AccessorKind::IsDidSet: Kind = ".didset"; break;
      case AccessorKind::IsMaterializeForSet: Kind = ".materialize"; break;
      case AccessorKind::IsAddressor: Kind = ".addressor"; break;
      case AccessorKind::IsMutableAddressor: Kind = ".mutableAddressor"; break;
      }

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

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

  return StringRef();
}

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

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

  if (L.isASTNode<ConstructorDecl>())
    return "init";

  if (L.isASTNode<DestructorDecl>())
    return "deinit";

  return StringRef();
}

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

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

  return FnTy;
}

llvm::DIScope *IRGenDebugInfo::getEntryPointFn() {
  // Lazily create EntryPointFn.
  if (!EntryPointFn) {
    EntryPointFn = DBuilder.createReplaceableCompositeType(
      llvm::dwarf::DW_TAG_subroutine_type, SWIFT_ENTRY_POINT_FUNCTION,
        MainFile, MainFile, 0);
  }
  return EntryPointFn;
}


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

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

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

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

  case DeclContextKind::Module:
    return getOrCreateModule({ModuleDecl::AccessPathTy(), cast<ModuleDecl>(DC)});
  case DeclContextKind::FileUnit:
    // A module may contain multiple files.
    return getOrCreateContext(DC->getParent());
  case DeclContextKind::GenericTypeDecl: {
    auto *NTD = cast<NominalTypeDecl>(DC);
    auto *Ty = NTD->getDeclaredType().getPointer();
    if (auto *DITy = getTypeOrNull(Ty))
      return DITy;

    // Create a Forward-declared type.
    auto Loc = getDebugLoc(SM, NTD);
    auto File = getOrCreateFile(Loc.Filename);
    auto Line = Loc.Line;
    auto FwdDecl = DBuilder.createReplaceableCompositeType(
        llvm::dwarf::DW_TAG_structure_type, NTD->getName().str(),
        getOrCreateContext(DC->getParent()), File, Line,
        llvm::dwarf::DW_LANG_Swift, 0, 0);
    ReplaceMap.emplace_back(
        std::piecewise_construct, std::make_tuple(Ty),
        std::make_tuple(static_cast<llvm::Metadata *>(FwdDecl)));
    return FwdDecl;
  }
  }
  return TheCU;
}

void IRGenDebugInfo::createParameterType(
    llvm::SmallVectorImpl<llvm::Metadata *> &Parameters, SILType type,
    DeclContext *DeclCtx) {
  auto RealType = type.getSwiftRValueType();
  if (type.isAddress())
    RealType = CanInOutType::get(RealType);
  auto DbgTy = DebugTypeInfo::getFromTypeInfo(DeclCtx, RealType,
                                              IGM.getTypeInfo(type));
  Parameters.push_back(getOrCreateType(DbgTy));
}

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

llvm::DITypeRefArray
IRGenDebugInfo::createParameterTypes(SILType SILTy, DeclContext *DeclCtx) {
  if (!SILTy)
    return nullptr;
  return createParameterTypes(SILTy.castTo<SILFunctionType>(), DeclCtx);
}

llvm::DITypeRefArray
IRGenDebugInfo::createParameterTypes(CanSILFunctionType FnTy,
                                     DeclContext *DeclCtx) {
  SmallVector<llvm::Metadata *, 16> Parameters;

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

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

  // Actually, the input type is either a single type or a tuple
  // type. We currently represent a function with one n-tuple argument
  // as an n-ary function.
  for (auto Param : FnTy->getParameters())
    createParameterType(Parameters, IGM.silConv.getSILType(Param), DeclCtx);

  return DBuilder.getOrCreateTypeArray(Parameters);
}

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

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

  // Some IRGen-generated helper functions don't have a corresponding
  // SIL function, hence the dyn_cast.
  SILFunction *SILFn = DS ? DS->Parent.dyn_cast<SILFunction *>() : nullptr;
  StringRef LinkageName;
  if (Fn)
    LinkageName = Fn->getName();
  else if (DS)
    LinkageName = SILFn->getName();
  else
    llvm_unreachable("function has no mangled name");

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

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

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

  // We know that main always comes from MainFile.
  if (LinkageName == SWIFT_ENTRY_POINT_FUNCTION) {
    if (L.Filename.empty())
      File = MainFile;
    Line = 1;
    Name = LinkageName;
  }

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

  // Various flags
  bool IsLocalToUnit = Fn ? Fn->hasInternalLinkage() : true;
  bool IsDefinition = true;
  bool IsOptimized = Opts.Optimize;
  llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;

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

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

  llvm::DISubprogram *SP = DBuilder.createFunction(
      Scope, Name, LinkageName, File, Line, DIFnTy, IsLocalToUnit, IsDefinition,
      ScopeLine, Flags, IsOptimized, TemplateParameters, Decl);

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

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

  if (!DS)
    return nullptr;

  ScopeCache[DS] = llvm::TrackingMDNodeRef(SP);
  return SP;
}

void IRGenDebugInfo::emitImport(ImportDecl *D) {
  if (Opts.DebugInfoKind <= IRGenDebugInfoKind::LineTables)
    return;

  swift::ModuleDecl *M = IGM.Context.getModule(D->getModulePath());
  if (!M &&
      D->getModulePath()[0].first == IGM.Context.TheBuiltinModule->getName())
    M = IGM.Context.TheBuiltinModule;
  if (!M) {
    assert(M && "Could not find module for import decl.");
    return;
  }
  auto DIMod = getOrCreateModule({D->getModulePath(), M});
  auto L = getDebugLoc(SM, D);
  DBuilder.createImportedModule(getOrCreateFile(L.Filename), DIMod, L.Line);
}

llvm::DIModule *
IRGenDebugInfo::getOrCreateModule(ModuleDecl::ImportedModule M) {
  StringRef Path = getFilenameFromDC(M.second);
  if (M.first.empty()) {
    StringRef Name = M.second->getName().str();
    return getOrCreateModule(Name, TheCU, Name, Path);
  }

  unsigned I = 0;
  SmallString<128> AccessPath;
  llvm::DIScope *Scope = TheCU;
  llvm::raw_svector_ostream OS(AccessPath);
  for (auto elt : M.first) {
    auto Component = elt.first.str();
    if (++I > 1)
      OS << '.';
    OS << Component;
    Scope = getOrCreateModule(AccessPath, Scope, Component, Path);
  }
  return cast<llvm::DIModule>(Scope);
}

llvm::DIModule *IRGenDebugInfo::getOrCreateModule(StringRef Key,
                                                  llvm::DIScope *Parent,
                                                  StringRef Name,
                                                  StringRef IncludePath) {
  // Look in the cache first.
  auto Val = DIModuleCache.find(Key);
  if (Val != DIModuleCache.end())
    return cast<llvm::DIModule>(Val->second);

  StringRef ConfigMacros;
  StringRef Sysroot = IGM.Context.SearchPathOpts.SDKPath;
  auto M =
      DBuilder.createModule(Parent, Name, ConfigMacros, IncludePath, Sysroot);
  DIModuleCache.insert({Key, llvm::TrackingMDNodeRef(M)});
  return M;
}

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

void IRGenDebugInfo::emitArtificialFunction(IRBuilder &Builder,
                                            llvm::Function *Fn, SILType SILTy) {
  RegularLocation ALoc = RegularLocation::getAutoGeneratedLocation();
  const SILDebugScope *Scope = new (IGM.getSILModule()) SILDebugScope(ALoc);
  emitFunction(Scope, Fn, SILFunctionTypeRepresentation::Thin, SILTy);
  setCurrentLoc(Builder, Scope);
}

TypeAliasDecl *IRGenDebugInfo::getMetadataType() {
  if (!MetadataTypeDecl) {
    MetadataTypeDecl = new (IGM.Context) TypeAliasDecl(
        SourceLoc(), SourceLoc(),
        IGM.Context.getIdentifier("$swift.type"), SourceLoc(),
        /*genericparams*/nullptr, IGM.Context.TheBuiltinModule);
    MetadataTypeDecl->setUnderlyingType(IGM.Context.TheRawPointerType);
  }
  return MetadataTypeDecl;
}

void IRGenDebugInfo::emitTypeMetadata(IRGenFunction &IGF,
                                      llvm::Value *Metadata,
                                      StringRef Name) {
  if (Opts.DebugInfoKind <= IRGenDebugInfoKind::LineTables)
    return;

  auto TName = BumpAllocatedString(("$swift.type." + Name).str());
  auto DbgTy = DebugTypeInfo::getMetadata(
      getMetadataType()->getDeclaredInterfaceType().getPointer(),
      Metadata->getType(), Size(CI.getTargetInfo().getPointerWidth(0)),
      Alignment(CI.getTargetInfo().getPointerAlign(0)));
  emitVariableDeclaration(IGF.Builder, Metadata, DbgTy, IGF.getDebugScope(),
                          nullptr, TName, 0,
                          // swift.type is already a pointer type,
                          // having a shadow copy doesn't add another
                          // layer of indirection.
                          DirectValue, ArtificialValue);
}

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

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

void IRGenDebugInfo::emitVariableDeclaration(
    IRBuilder &Builder, ArrayRef<llvm::Value *> Storage, DebugTypeInfo DbgTy,
    const SILDebugScope *DS, ValueDecl *VarDecl, StringRef Name, unsigned ArgNo,
    IndirectionKind Indirection, ArtificialKind Artificial) {
  // Self is always an artificial argument.
  if (ArgNo > 0 && Name == IGM.Context.Id_self.str())
    Artificial = ArtificialValue;

  // FIXME: Make this an assertion.
  // assert(DS && "variable has no scope");
  if (!DS)
    return;

  if (Opts.DebugInfoKind <= IRGenDebugInfoKind::LineTables)
    return;

  if (!DbgTy.size)
    DbgTy.size = getStorageSize(IGM.DataLayout, Storage);

  auto *Scope = dyn_cast<llvm::DILocalScope>(getOrCreateScope(DS));
  assert(Scope && "variable has no local scope");
  auto Loc = getDebugLoc(SM, VarDecl);

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

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

  // This could be Opts.Optimize if we would also unique DIVariables here.
  bool Optimized = false;
  // Create the descriptor for the variable.
  llvm::DILocalVariable *Var =
      (ArgNo > 0)
          ? DBuilder.createParameterVariable(Scope, Name, ArgNo, Unit, Line,
                                             DITy, Optimized, Flags)
          : DBuilder.createAutoVariable(Scope, Name, Unit, Line, DITy,
                                        Optimized, Flags);

  // Running variables for the current/previous piece.
  bool IsPiece = Storage.size() > 1;
  uint64_t SizeOfByte = CI.getTargetInfo().getCharWidth();
  unsigned AlignInBits = SizeOfByte;
  unsigned OffsetInBits = 0;
  unsigned SizeInBits = 0;

  for (llvm::Value *Piece : Storage) {
    SmallVector<uint64_t, 3> Operands;
    if (Indirection)
      Operands.push_back(llvm::dwarf::DW_OP_deref);

    // There are variables without storage, such as "struct { func foo() {} }".
    // Emit them as constant 0.
    if (isa<llvm::UndefValue>(Piece))
      Piece = llvm::ConstantInt::get(IGM.Int64Ty, 0);

    if (IsPiece) {
      // Advance the offset and align it for the next piece.
      OffsetInBits += llvm::alignTo(SizeInBits, AlignInBits);
      SizeInBits = IGM.DataLayout.getTypeSizeInBits(Piece->getType());
      AlignInBits = IGM.DataLayout.getABITypeAlignment(Piece->getType());
      if (!AlignInBits)
        AlignInBits = SizeOfByte;

      // Sanity checks.
      assert(SizeInBits && "zero-sized piece");
      assert(SizeInBits < getSizeInBits(Var) && "piece covers entire var");
      assert(OffsetInBits+SizeInBits <= getSizeInBits(Var) && "pars > totum");

      // Add the piece DWARF expression.
      Operands.push_back(llvm::dwarf::DW_OP_LLVM_fragment);
      Operands.push_back(OffsetInBits);
      Operands.push_back(SizeInBits);
    }
    emitDbgIntrinsic(Builder, Piece, Var, DBuilder.createExpression(Operands),
                     Line, Loc.Column, Scope, DS);
  }

  // Emit locationless intrinsic for variables that were optimized away.
  if (Storage.size() == 0)
    emitDbgIntrinsic(Builder, llvm::ConstantInt::get(IGM.Int64Ty, 0), Var,
                     DBuilder.createExpression(), Line, Loc.Column, Scope, DS);
}

void IRGenDebugInfo::emitDbgIntrinsic(IRBuilder &Builder, llvm::Value *Storage,
                                      llvm::DILocalVariable *Var,
                                      llvm::DIExpression *Expr, unsigned Line,
                                      unsigned Col, llvm::DILocalScope *Scope,
                                      const SILDebugScope *DS) {
  // Set the location/scope of the intrinsic.
  auto *InlinedAt = createInlinedAt(DS);
  auto DL = llvm::DebugLoc::get(Line, Col, Scope, InlinedAt);
  auto *BB = Builder.GetInsertBlock();

  // An alloca may only be described by exactly one dbg.declare.
  if (isa<llvm::AllocaInst>(Storage) && llvm::FindAllocaDbgDeclare(Storage))
    return;
  
  // A dbg.declare is only meaningful if there is a single alloca for
  // the variable that is live throughout the function. With SIL
  // optimizations this is not guaranteed and a variable can end up in
  // two allocas (for example, one function inlined twice).
  if (isa<llvm::AllocaInst>(Storage)) {
    DBuilder.insertDeclare(Storage, Var, Expr, DL, BB);
    return;
  }

  // If the storage is an instruction, insert the dbg.value directly after it.
  if (auto *I = dyn_cast<llvm::Instruction>(Storage)) {
    auto InsPt = std::next(I->getIterator());
    auto E = I->getParent()->end();
    while (InsPt != E && isa<llvm::PHINode>(&*InsPt))
        ++InsPt;
    if (InsPt != E) {
      DBuilder.insertDbgValueIntrinsic(Storage, 0, Var, Expr, DL, &*InsPt);
      return;
    }
  }

  // Otherwise just insert it at the current insertion point.
  DBuilder.insertDbgValueIntrinsic(Storage, 0, Var, Expr, DL, BB);
}

void IRGenDebugInfo::emitGlobalVariableDeclaration(
    llvm::GlobalVariable *Var, StringRef Name, StringRef LinkageName,
    DebugTypeInfo DbgTy, bool IsLocalToUnit, Optional<SILLocation> Loc) {
  if (Opts.DebugInfoKind <= IRGenDebugInfoKind::LineTables)
    return;

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

  auto L = getStartLocation(Loc, SM);
  auto File = getOrCreateFile(L.Filename);

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

StringRef IRGenDebugInfo::getMangledName(DebugTypeInfo DbgTy) {
  if (MetadataTypeDecl && DbgTy.getDecl() == MetadataTypeDecl)
    return BumpAllocatedString(DbgTy.getDecl()->getName().str());

  std::string Name = NewMangling::mangleTypeForDebugger(DbgTy.getType(),
                                                        DbgTy.getDeclContext());
  return BumpAllocatedString(Name);
}

llvm::DIDerivedType *
IRGenDebugInfo::createMemberType(DebugTypeInfo DbgTy, StringRef Name,
                                 unsigned &OffsetInBits, llvm::DIScope *Scope,
                                 llvm::DIFile *File,
                                 llvm::DINode::DIFlags Flags) {
  unsigned SizeOfByte = CI.getTargetInfo().getCharWidth();
  auto *Ty = getOrCreateType(DbgTy);
  auto *DITy = DBuilder.createMemberType(
      Scope, Name, File, 0, SizeOfByte * DbgTy.size.getValue(),
      SizeOfByte * DbgTy.align.getValue(), OffsetInBits, Flags, Ty);
  OffsetInBits += getSizeInBits(Ty);
  OffsetInBits = llvm::alignTo(OffsetInBits,
                                          SizeOfByte * DbgTy.align.getValue());
  return DITy;
}

llvm::DINodeArray IRGenDebugInfo::getTupleElements(
    TupleType *TupleTy, llvm::DIScope *Scope, llvm::DIFile *File,
    llvm::DINode::DIFlags Flags, DeclContext *DeclContext,
    unsigned &SizeInBits) {
  SmallVector<llvm::Metadata *, 16> Elements;
  unsigned OffsetInBits = 0;
  auto genericSig = IGM.getSILTypes().getCurGenericContext();
  for (auto ElemTy : TupleTy->getElementTypes()) {
    auto &elemTI =
      IGM.getTypeInfoForUnlowered(AbstractionPattern(genericSig,
                                                  ElemTy->getCanonicalType()),
                                  ElemTy);
    auto DbgTy = DebugTypeInfo::getFromTypeInfo(DeclContext, ElemTy, elemTI);
    Elements.push_back(
        createMemberType(DbgTy, StringRef(), OffsetInBits, Scope, File, Flags));
  }
  SizeInBits = OffsetInBits;
  return DBuilder.getOrCreateArray(Elements);
}

llvm::DINodeArray
IRGenDebugInfo::getStructMembers(NominalTypeDecl *D, Type BaseTy,
                                 llvm::DIScope *Scope, llvm::DIFile *File,
                                 llvm::DINode::DIFlags Flags,
                                 unsigned &SizeInBits) {
  SmallVector<llvm::Metadata *, 16> Elements;
  unsigned OffsetInBits = 0;
  for (VarDecl *VD : D->getStoredProperties()) {
    auto memberTy =
        BaseTy->getTypeOfMember(IGM.getSwiftModule(), VD, nullptr);

    auto DbgTy = DebugTypeInfo::getFromTypeInfo(
        VD->getDeclContext(), VD->getInterfaceType(),
        IGM.getTypeInfoForUnlowered(IGM.getSILTypes().getAbstractionPattern(VD),
                                    memberTy));
    Elements.push_back(createMemberType(DbgTy, VD->getName().str(),
                                        OffsetInBits, Scope, File, Flags));
  }
  if (OffsetInBits > SizeInBits)
    SizeInBits = OffsetInBits;
  return DBuilder.getOrCreateArray(Elements);
}

llvm::DICompositeType *IRGenDebugInfo::createStructType(
    DebugTypeInfo DbgTy, NominalTypeDecl *Decl, Type BaseTy,
    llvm::DIScope *Scope, llvm::DIFile *File, unsigned Line,
    unsigned SizeInBits, unsigned AlignInBits, llvm::DINode::DIFlags Flags,
    llvm::DIType *DerivedFrom, unsigned RuntimeLang, StringRef UniqueID) {
  StringRef Name = Decl->getName().str();

  // Forward declare this first because types may be recursive.
  auto FwdDecl = llvm::TempDIType(
    DBuilder.createReplaceableCompositeType(
      llvm::dwarf::DW_TAG_structure_type, Name, Scope, File, Line,
        llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags, UniqueID));

#ifndef NDEBUG
  if (UniqueID.empty())
    assert(!Name.empty() && "no mangled name and no human readable name given");
  else
    assert((UniqueID.startswith("_T") ||
              UniqueID.startswith(MANGLING_PREFIX_STR)) &&
           "UID is not a mangled name");
#endif

  auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
  DITypeCache[DbgTy.getType()] = TH;
  auto Members = getStructMembers(Decl, BaseTy, Scope, File, Flags, SizeInBits);
  auto DITy = DBuilder.createStructType(
      Scope, Name, File, Line, SizeInBits, AlignInBits, Flags, DerivedFrom,
      Members, RuntimeLang, nullptr, UniqueID);
  DBuilder.replaceTemporary(std::move(FwdDecl), DITy);
  return DITy;
}

llvm::DINodeArray IRGenDebugInfo::getEnumElements(DebugTypeInfo DbgTy,
                                                  EnumDecl *ED,
                                                  llvm::DIScope *Scope,
                                                  llvm::DIFile *File,
                                                  llvm::DINode::DIFlags Flags) {
  SmallVector<llvm::Metadata *, 16> Elements;

  for (auto *ElemDecl : ED->getAllElements()) {
    // FIXME <rdar://problem/14845818> Support enums.
    // Swift Enums can be both like DWARF enums and discriminated unions.
    DebugTypeInfo ElemDbgTy;
    if (ED->hasRawType())
      // An enum with a raw type (enum E : Int {}), similar to a
      // DWARF enum.
      //
      // The storage occupied by the enum may be smaller than the
      // one of the raw type as long as it is large enough to hold
      // all enum values. Use the raw type for the debug type, but
      // the storage size from the enum.
      ElemDbgTy = DebugTypeInfo(ED, ED->getRawType(), DbgTy.StorageType,
                                DbgTy.size, DbgTy.align);
    else if (auto ArgTy = ElemDecl->getArgumentInterfaceType()) {
      // A discriminated union. This should really be described as a
      // DW_TAG_variant_type. For now only describing the data.
      ArgTy = ElemDecl->getParentEnum()->mapTypeIntoContext(ArgTy);
      auto &TI = IGM.getTypeInfoForUnlowered(ArgTy);
      ElemDbgTy =
          DebugTypeInfo::getFromTypeInfo(ED, ArgTy, TI);
    } else {
      // Discriminated union case without argument. Fallback to Int
      // as the element type; there is no storage here.
      Type IntTy = IGM.Context.getIntDecl()->getDeclaredType();
      ElemDbgTy =
          DebugTypeInfo(ED, IntTy, DbgTy.StorageType, Size(0), Alignment(1));
    }
    unsigned Offset = 0;
    auto MTy = createMemberType(ElemDbgTy, ElemDecl->getName().str(), Offset,
                                Scope, File, Flags);
    Elements.push_back(MTy);
  }
  return DBuilder.getOrCreateArray(Elements);
}

llvm::DICompositeType *IRGenDebugInfo::createEnumType(
    DebugTypeInfo DbgTy, EnumDecl *Decl, StringRef MangledName,
    llvm::DIScope *Scope, llvm::DIFile *File, unsigned Line,
    llvm::DINode::DIFlags Flags) {
  unsigned SizeOfByte = CI.getTargetInfo().getCharWidth();
  unsigned SizeInBits = DbgTy.size.getValue() * SizeOfByte;
  unsigned AlignInBits = DbgTy.align.getValue() * SizeOfByte;

  // FIXME: Is DW_TAG_union_type the right thing here?
  // Consider using a DW_TAG_variant_type instead.
  auto FwdDecl = llvm::TempDIType(
    DBuilder.createReplaceableCompositeType(
      llvm::dwarf::DW_TAG_union_type, MangledName, Scope, File, Line,
        llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
        MangledName));

  auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
  DITypeCache[DbgTy.getType()] = TH;

  auto DITy = DBuilder.createUnionType(
      Scope, Decl->getName().str(), File, Line, SizeInBits, AlignInBits, Flags,
      getEnumElements(DbgTy, Decl, Scope, File, Flags),
      llvm::dwarf::DW_LANG_Swift, MangledName);

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

llvm::DIType *IRGenDebugInfo::getOrCreateDesugaredType(Type Ty,
                                                       DebugTypeInfo DbgTy) {
  DebugTypeInfo BlandDbgTy(DbgTy.getDeclContext(), Ty, DbgTy.StorageType,
                           DbgTy.size, DbgTy.align);
  return getOrCreateType(BlandDbgTy);
}

uint64_t IRGenDebugInfo::getSizeOfBasicType(DebugTypeInfo DbgTy) {
  uint64_t SizeOfByte = CI.getTargetInfo().getCharWidth();
  uint64_t BitWidth = DbgTy.size.getValue() * SizeOfByte;
  llvm::Type *StorageType = DbgTy.StorageType
                                ? DbgTy.StorageType
                                : IGM.DataLayout.getSmallestLegalIntType(
                                      IGM.getLLVMContext(), BitWidth);

  if (StorageType)
    return IGM.DataLayout.getTypeSizeInBits(StorageType);

  // This type is too large to fit in a register.
  assert(BitWidth > IGM.DataLayout.getLargestLegalIntTypeSizeInBits());
  return BitWidth;
}

llvm::DIType *IRGenDebugInfo::createPointerSizedStruct(
    llvm::DIScope *Scope, StringRef Name, llvm::DIFile *File, unsigned Line,
    llvm::DINode::DIFlags Flags, StringRef MangledName) {
  if (Opts.DebugInfoKind > IRGenDebugInfoKind::ASTTypes) {
    auto FwdDecl = DBuilder.createForwardDecl(
        llvm::dwarf::DW_TAG_structure_type, Name, Scope, File, Line,
        llvm::dwarf::DW_LANG_Swift, 0, 0);
    return createPointerSizedStruct(Scope, Name, FwdDecl, File, Line, Flags,
                                    MangledName);
  } else {
    unsigned SizeInBits = CI.getTargetInfo().getPointerWidth(0);
    unsigned AlignInBits = CI.getTargetInfo().getPointerAlign(0);
    return createOpaqueStruct(Scope, Name, File, Line, SizeInBits, AlignInBits,
                              Flags, MangledName);
  }
}

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

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

llvm::DIType *
IRGenDebugInfo::createFunctionPointer(DebugTypeInfo DbgTy, llvm::DIScope *Scope,
                                      unsigned SizeInBits, unsigned AlignInBits,
                                      llvm::DINode::DIFlags Flags,
                                      StringRef MangledName) {
  auto FwdDecl = llvm::TempDINode(DBuilder.createReplaceableCompositeType(
      llvm::dwarf::DW_TAG_subroutine_type, MangledName, Scope, MainFile, 0,
      llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags, MangledName));

  auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
  DITypeCache[DbgTy.getType()] = TH;

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

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

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

llvm::DIType *IRGenDebugInfo::createTuple(DebugTypeInfo DbgTy,
                                          llvm::DIScope *Scope,
                                          unsigned SizeInBits,
                                          unsigned AlignInBits,
                                          llvm::DINode::DIFlags Flags,
                                          StringRef MangledName) {
  TypeBase *BaseTy = DbgTy.getType();
  auto *TupleTy = BaseTy->castTo<TupleType>();
  auto FwdDecl = llvm::TempDINode(DBuilder.createReplaceableCompositeType(
      llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, MainFile, 0,
      llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags, MangledName));

  DITypeCache[DbgTy.getType()] = llvm::TrackingMDNodeRef(FwdDecl.get());

  unsigned RealSize;
  auto Elements = getTupleElements(TupleTy, Scope, MainFile, Flags,
                                   DbgTy.getDeclContext(), RealSize);
  // FIXME: Handle %swift.opaque members and make this into an assertion.
  if (!RealSize)
    RealSize = SizeInBits;

  auto DITy = DBuilder.createStructType(
      Scope, MangledName, MainFile, 0, RealSize, AlignInBits, Flags,
      nullptr, // DerivedFrom
      Elements, llvm::dwarf::DW_LANG_Swift, nullptr, MangledName);

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

llvm::DIType *
IRGenDebugInfo::createOpaqueStruct(llvm::DIScope *Scope, StringRef Name,
                                   llvm::DIFile *File, unsigned Line,
                                   unsigned SizeInBits, unsigned AlignInBits,
                                   llvm::DINode::DIFlags Flags,
                                   StringRef MangledName) {
  return DBuilder.createStructType(
      Scope, Name, File, Line, SizeInBits, AlignInBits, Flags,
      /* DerivedFrom */ nullptr,
      DBuilder.getOrCreateArray(ArrayRef<llvm::Metadata *>()),
      llvm::dwarf::DW_LANG_Swift, nullptr, MangledName);
}

llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
                                         StringRef MangledName,
                                         llvm::DIScope *Scope,
                                         llvm::DIFile *File) {
  // FIXME: For SizeInBits, clang uses the actual size of the type on
  // the target machine instead of the storage size that is alloca'd
  // in the LLVM IR. For all types that are boxed in a struct, we are
  // emitting the storage size of the struct, but it may be necessary
  // to emit the (target!) size of the underlying basic type.
  uint64_t SizeOfByte = CI.getTargetInfo().getCharWidth();
  uint64_t SizeInBits = DbgTy.size.getValue() * SizeOfByte;
  uint64_t AlignInBits = DbgTy.align.getValue() * SizeOfByte;
  unsigned Encoding = 0;
  llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;

  TypeBase *BaseTy = DbgTy.getType();

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

  // Here goes!
  switch (BaseTy->getKind()) {
  case TypeKind::BuiltinInteger: {
    Encoding = llvm::dwarf::DW_ATE_unsigned;
    SizeInBits = getSizeOfBasicType(DbgTy);
    break;
  }

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

  case TypeKind::BuiltinUnknownObject: {
    // The builtin opaque Objective-C pointer type. Useful for pushing
    // an Objective-C type through swift.
    unsigned PtrSize = CI.getTargetInfo().getPointerWidth(0);
    unsigned PtrAlign = CI.getTargetInfo().getPointerAlign(0);
    auto IdTy = DBuilder.createForwardDecl(
      llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, File, 0,
        llvm::dwarf::DW_LANG_ObjC, 0, 0);
    return DBuilder.createPointerType(IdTy, PtrSize, PtrAlign, MangledName);
  }

  case TypeKind::BuiltinNativeObject: {
    unsigned PtrSize = CI.getTargetInfo().getPointerWidth(0);
    unsigned PtrAlign = CI.getTargetInfo().getPointerAlign(0);
    auto PTy = DBuilder.createPointerType(nullptr, PtrSize, PtrAlign,
                                          MangledName);
    return DBuilder.createObjectPointerType(PTy);
  }

  case TypeKind::BuiltinBridgeObject: {
    unsigned PtrSize = CI.getTargetInfo().getPointerWidth(0);
    unsigned PtrAlign = CI.getTargetInfo().getPointerAlign(0);
    auto PTy = DBuilder.createPointerType(nullptr, PtrSize, PtrAlign,
                                          MangledName);
    return DBuilder.createObjectPointerType(PTy);
  }

  case TypeKind::BuiltinRawPointer: {
    unsigned PtrSize = CI.getTargetInfo().getPointerWidth(0);
    unsigned PtrAlign = CI.getTargetInfo().getPointerAlign(0);
    return DBuilder.createPointerType(nullptr, PtrSize, PtrAlign,
                                      MangledName);
  }

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

  }

  // Even builtin swift types usually come boxed in a struct.
  case TypeKind::Struct: {
    auto *StructTy = BaseTy->castTo<StructType>();
    auto *Decl = StructTy->getDecl();
    auto L = getDebugLoc(SM, Decl);
    auto *File = getOrCreateFile(L.Filename);
    if (Opts.DebugInfoKind > IRGenDebugInfoKind::ASTTypes)
      return createStructType(DbgTy, Decl, StructTy, Scope, File, L.Line,
                              SizeInBits, AlignInBits, Flags,
                              nullptr, // DerivedFrom
                              llvm::dwarf::DW_LANG_Swift, MangledName);
    else
      return createOpaqueStruct(Scope, Decl->getName().str(), File, L.Line,
                                SizeInBits, AlignInBits, Flags, MangledName);
  }

  case TypeKind::Class: {
    // Classes are represented as DW_TAG_structure_type. This way the
    // DW_AT_APPLE_runtime_class(DW_LANG_Swift) attribute can be
    // used to differentiate them from C++ and ObjC classes.
    auto *ClassTy = BaseTy->castTo<ClassType>();
    auto *Decl = ClassTy->getDecl();
    auto L = getDebugLoc(SM, Decl);
    if (auto *ClangDecl = Decl->getClangDecl()) {
      auto ClangSrcLoc = ClangDecl->getLocStart();
      clang::SourceManager &ClangSM =
          CI.getClangASTContext().getSourceManager();
      L.Line = ClangSM.getPresumedLineNumber(ClangSrcLoc);
      L.Filename = ClangSM.getBufferName(ClangSrcLoc);

      // Use "__ObjC" as default for implicit decls.
      // FIXME: Do something more clever based on the decl's mangled name.
      std::string FullModuleNameBuffer;
      StringRef ModulePath;
      StringRef ModuleName = "__ObjC";
      if (auto *OwningModule = ClangDecl->getImportedOwningModule())
        ModuleName = OwningModule->getTopLevelModuleName();

      if (auto *SwiftModule = Decl->getParentModule())
        if (auto *ClangModule = SwiftModule->findUnderlyingClangModule()) {
          // FIXME: Clang submodules are not handled here.
          // FIXME: Clang module config macros are not handled here.
          FullModuleNameBuffer = ClangModule->getFullModuleName();
          ModuleName = FullModuleNameBuffer;
          // FIXME: A clang module's Directory is supposed to be the
          // directory containing the module map, but ClangImporter
          // sets it to the module cache directory.
          if (ClangModule->Directory)
            ModulePath = ClangModule->Directory->getName();
        }
      Scope = getOrCreateModule(ModuleName, TheCU, ModuleName, ModulePath);
    }
    assert(SizeInBits == CI.getTargetInfo().getPointerWidth(0));
    return createPointerSizedStruct(Scope, Decl->getNameStr(),
                                    getOrCreateFile(L.Filename), L.Line, Flags,
                                    MangledName);
  }

  case TypeKind::Protocol: {
    auto *ProtocolTy = BaseTy->castTo<ProtocolType>();
    auto *Decl = ProtocolTy->getDecl();
    // FIXME: (LLVM branch) This should probably be a DW_TAG_interface_type.
    auto L = getDebugLoc(SM, Decl);
    auto File = getOrCreateFile(L.Filename);
    return createOpaqueStruct(Scope, Decl ? Decl->getNameStr() : MangledName,
                              File, L.Line, SizeInBits, AlignInBits, Flags,
                              MangledName);
  }

  case TypeKind::ProtocolComposition: {
    auto *Decl = DbgTy.getDecl();
    auto L = getDebugLoc(SM, Decl);
    auto File = getOrCreateFile(L.Filename);

    // FIXME: emit types
    // auto ProtocolCompositionTy = BaseTy->castTo<ProtocolCompositionType>();
    return createOpaqueStruct(Scope, Decl ? Decl->getNameStr() : MangledName,
                              File, L.Line, SizeInBits, AlignInBits, Flags,
                              MangledName);
  }

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

  case TypeKind::BoundGenericStruct: {
    auto *StructTy = BaseTy->castTo<BoundGenericStructType>();
    auto *Decl = StructTy->getDecl();
    auto L = getDebugLoc(SM, Decl);
    return createOpaqueStruct(Scope, Decl ? Decl->getNameStr() : MangledName,
                              File, L.Line, SizeInBits, AlignInBits, Flags,
                              MangledName);
  }

  case TypeKind::BoundGenericClass: {
    auto *ClassTy = BaseTy->castTo<BoundGenericClassType>();
    auto *Decl = ClassTy->getDecl();
    auto L = getDebugLoc(SM, Decl);
    // TODO: We may want to peek at Decl->isObjC() and set this
    // attribute accordingly.
    assert(SizeInBits == CI.getTargetInfo().getPointerWidth(0));
    return createPointerSizedStruct(Scope,
                                    Decl ? Decl->getNameStr() : MangledName,
                                    File, L.Line, Flags, MangledName);
  }

  case TypeKind::Tuple: {
    // Tuples are also represented as structs.
    if (Opts.DebugInfoKind > IRGenDebugInfoKind::ASTTypes)
      return createTuple(DbgTy, Scope, SizeInBits, AlignInBits, Flags,
                         MangledName);
    else
      return createOpaqueStruct(Scope, MangledName, MainFile, 0, SizeInBits,
                                AlignInBits, Flags, MangledName);
  }

  case TypeKind::InOut: {
    // This is an inout type. Naturally we would be emitting them as
    // DW_TAG_reference_type types, but LLDB can deal better with pointer-sized
    // struct that has the appropriate mangled name.
    auto ObjectTy = BaseTy->castTo<InOutType>()->getObjectType();
    if (Opts.DebugInfoKind > IRGenDebugInfoKind::ASTTypes) {
      auto DT = getOrCreateDesugaredType(ObjectTy, DbgTy);
      return createPointerSizedStruct(
          Scope, MangledName, DT, File, 0, Flags,
          MangledName);
    } else
      return createOpaqueStruct(Scope, MangledName, File, 0, SizeInBits,
                                AlignInBits, Flags, MangledName);
  }

  case TypeKind::Archetype: {
    auto *Archetype = BaseTy->castTo<ArchetypeType>();
    auto L = getDebugLoc(SM, Archetype->getAssocType());
    auto Superclass = Archetype->getSuperclass();
    auto DerivedFrom = Superclass.isNull()
                           ? nullptr
                           : getOrCreateDesugaredType(Superclass, DbgTy);
    auto FwdDecl = llvm::TempDIType(
      DBuilder.createReplaceableCompositeType(
        llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, File, L.Line,
          llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
          MangledName));

    // Emit the protocols the archetypes conform to.
    SmallVector<llvm::Metadata *, 4> Protocols;
    for (auto *ProtocolDecl : Archetype->getConformsTo()) {
      auto PTy = IGM.getLoweredType(ProtocolDecl->getInterfaceType())
                     .getSwiftRValueType();
      auto PDbgTy = DebugTypeInfo::getFromTypeInfo(
          DbgTy.getDeclContext(), ProtocolDecl->getInterfaceType(),
          IGM.getTypeInfoForLowered(PTy));
      auto PDITy = getOrCreateType(PDbgTy);
      Protocols.push_back(DBuilder.createInheritance(FwdDecl.get(),
                                                     PDITy, 0, Flags));
    }
    auto DITy = DBuilder.createStructType(
        Scope, MangledName, File, L.Line, SizeInBits, AlignInBits, Flags,
        DerivedFrom, DBuilder.getOrCreateArray(Protocols),
        llvm::dwarf::DW_LANG_Swift, nullptr,
        MangledName);

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

  case TypeKind::ExistentialMetatype:
  case TypeKind::Metatype: {
    // Metatypes are (mostly) singleton type descriptors, often without storage.
    Flags |= llvm::DINode::FlagArtificial;
    auto L = getDebugLoc(SM, DbgTy.getDecl());
    auto File = getOrCreateFile(L.Filename);
    return DBuilder.createStructType(
        Scope, MangledName, File, L.Line, SizeInBits, AlignInBits, Flags,
        nullptr, nullptr, llvm::dwarf::DW_LANG_Swift,
        nullptr, MangledName);
  }

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

  case TypeKind::Enum: {
    auto *EnumTy = BaseTy->castTo<EnumType>();
    auto *Decl = EnumTy->getDecl();
    auto L = getDebugLoc(SM, Decl);
    auto *File = getOrCreateFile(L.Filename);
    if (Opts.DebugInfoKind > IRGenDebugInfoKind::ASTTypes)
      return createEnumType(DbgTy, Decl, MangledName, Scope, File, L.Line,
                            Flags);
    else
      return createOpaqueStruct(Scope, Decl->getName().str(), File, L.Line,
                                SizeInBits, AlignInBits, Flags, MangledName);
  }

  case TypeKind::BoundGenericEnum: {
    auto *EnumTy = BaseTy->castTo<BoundGenericEnumType>();
    auto *Decl = EnumTy->getDecl();
    auto L = getDebugLoc(SM, Decl);
    auto *File = getOrCreateFile(L.Filename);
    if (Opts.DebugInfoKind > IRGenDebugInfoKind::ASTTypes)
      return createEnumType(DbgTy, Decl, MangledName, Scope, File, L.Line,
                            Flags);
    else
      return createOpaqueStruct(Scope, Decl->getName().str(), File, L.Line,
                                SizeInBits, AlignInBits, Flags, MangledName);
  }

  case TypeKind::BuiltinVector: {
    (void)MangledName; // FIXME emit the name somewhere.
    auto *BuiltinVectorTy = BaseTy->castTo<BuiltinVectorType>();
    DebugTypeInfo ElemDbgTy(DbgTy.getDeclContext(),
                            BuiltinVectorTy->getElementType(),
                            DbgTy.StorageType, DbgTy.size, DbgTy.align);
    auto Subscripts = nullptr;
    return DBuilder.createVectorType(BuiltinVectorTy->getNumElements(),
                                     AlignInBits, getOrCreateType(ElemDbgTy),
                                     Subscripts);
  }

  // Reference storage types.
  case TypeKind::UnownedStorage:
  case TypeKind::UnmanagedStorage:
  case TypeKind::WeakStorage: {
    auto *ReferenceTy = cast<ReferenceStorageType>(BaseTy);
    auto CanTy = ReferenceTy->getReferentType();
    auto L = getDebugLoc(SM, DbgTy.getDecl());
    auto File = getOrCreateFile(L.Filename);
    return DBuilder.createTypedef(getOrCreateDesugaredType(CanTy, DbgTy),
                                  MangledName, File, L.Line, File);
  }

  // Sugared types.

  case TypeKind::NameAlias: {

    auto *NameAliasTy = cast<NameAliasType>(BaseTy);
    auto *Decl = NameAliasTy->getDecl();
    auto L = getDebugLoc(SM, Decl);
    auto AliasedTy = NameAliasTy->getSinglyDesugaredType();
    auto File = getOrCreateFile(L.Filename);
    // For NameAlias types, the DeclContext for the aliasED type is
    // in the decl of the alias type.
    DebugTypeInfo AliasedDbgTy(DbgTy.getDeclContext(), AliasedTy,
                               DbgTy.StorageType, DbgTy.size, DbgTy.align);
    return DBuilder.createTypedef(getOrCreateType(AliasedDbgTy), MangledName,
                                  File, L.Line, File);
  }

  case TypeKind::Paren: {
    auto Ty = cast<ParenType>(BaseTy)->getUnderlyingType();
    return getOrCreateDesugaredType(Ty, DbgTy);
  }

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

  case TypeKind::Dictionary: {
    auto *DictionaryTy = cast<DictionaryType>(BaseTy);
    auto *CanTy = DictionaryTy->getDesugaredType();
    return getOrCreateDesugaredType(CanTy, DbgTy);
  }

  case TypeKind::GenericTypeParam: {
    auto *ParamTy = cast<GenericTypeParamType>(BaseTy);
    // FIXME: Provide a more meaningful debug type.
    return DBuilder.createUnspecifiedType(ParamTy->getName().str());
  }
  case TypeKind::DependentMember: {
    auto *MemberTy = cast<DependentMemberType>(BaseTy);
    // FIXME: Provide a more meaningful debug type.
    return DBuilder.createUnspecifiedType(MemberTy->getName().str());
  }

  // The following types exist primarily for internal use by the type
  // checker.
  case TypeKind::Error:
  case TypeKind::Unresolved:
  case TypeKind::LValue:
  case TypeKind::TypeVariable:
  case TypeKind::Module:
  case TypeKind::SILBlockStorage:
  case TypeKind::SILBox:
  case TypeKind::BuiltinUnsafeValueBuffer:

    DEBUG(llvm::errs() << "Unhandled type: "; DbgTy.getType()->dump();
          llvm::errs() << "\n");
    MangledName = "<unknown>";
  }
  return DBuilder.createBasicType(MangledName, SizeInBits, Encoding);
}

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

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

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

  // Look in the cache first.
  if (auto *DITy = getTypeOrNull(DbgTy.getType()))
    return DITy;

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

  // Retrieve the context of the type, as opposed to the DeclContext
  // of the variable.
  //
  // FIXME: Builtin and qualified types in LLVM have no parent
  // scope. TODO: This can be fixed by extending DIBuilder.
  DeclContext *Context = DbgTy.getType()->getNominalOrBoundGenericNominal();
  if (Context)
    Context = Context->getParent();
  llvm::DIScope *Scope = getOrCreateContext(Context);
  llvm::DIType *DITy = createType(DbgTy, MangledName, Scope, getFile(Scope));

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

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

  return DITy;
}

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

  // Finalize all replaceable forward declarations.
  for (auto &Ty : ReplaceMap) {
    llvm::TempMDNode FwdDecl(cast<llvm::MDNode>(Ty.second));
    llvm::Metadata *Replacement;
    if (auto *FullType = getTypeOrNull(Ty.first))
      Replacement = FullType;
    else
      Replacement = Ty.second;
    DBuilder.replaceTemporary(std::move(FwdDecl),
                              cast<llvm::MDNode>(Replacement));
  }
  // Finalize the DIBuilder.
  DBuilder.finalize();
}
