//===- DebugTranslation.cpp - MLIR to LLVM Debug conversion ---------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "DebugTranslation.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "llvm/ADT/SmallVectorExtras.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"

using namespace mlir;
using namespace mlir::LLVM;
using namespace mlir::LLVM::detail;

/// A utility walker that interrupts if the operation has valid debug
/// information.
static WalkResult interruptIfValidLocation(Operation *op) {
  return isa<UnknownLoc>(op->getLoc()) ? WalkResult::advance()
                                       : WalkResult::interrupt();
}

DebugTranslation::DebugTranslation(Operation *module, llvm::Module &llvmModule)
    : debugEmissionIsEnabled(false), llvmModule(llvmModule),
      llvmCtx(llvmModule.getContext()) {
  // If the module has no location information, there is nothing to do.
  if (!module->walk(interruptIfValidLocation).wasInterrupted())
    return;
  debugEmissionIsEnabled = true;
}

static constexpr StringRef kDebugVersionKey = "Debug Info Version";
static constexpr StringRef kCodeViewKey = "CodeView";

void DebugTranslation::addModuleFlagsIfNotPresent() {
  // TODO: The version information should be encoded on the LLVM module itself,
  // not implicitly set here.

  // Mark this module as having debug information.
  if (!llvmModule.getModuleFlag(kDebugVersionKey))
    llvmModule.addModuleFlag(llvm::Module::Warning, kDebugVersionKey,
                             llvm::DEBUG_METADATA_VERSION);

  const llvm::Triple &targetTriple = llvmModule.getTargetTriple();
  if (targetTriple.isKnownWindowsMSVCEnvironment()) {
    // Dwarf debugging files will be generated by default, unless "CodeView"
    // is set explicitly. Windows/MSVC should use CodeView instead.
    if (!llvmModule.getModuleFlag(kCodeViewKey))
      llvmModule.addModuleFlag(llvm::Module::Warning, kCodeViewKey, 1);
  }
}

/// Translate the debug information for the given function.
void DebugTranslation::translate(LLVMFuncOp func, llvm::Function &llvmFunc) {
  if (!debugEmissionIsEnabled)
    return;

  // Look for a sub program attached to the function.
  auto spLoc =
      func.getLoc()->findInstanceOf<FusedLocWith<LLVM::DISubprogramAttr>>();
  if (!spLoc)
    return;
  llvmFunc.setSubprogram(translate(spLoc.getMetadata()));
}

//===----------------------------------------------------------------------===//
// Attributes
//===----------------------------------------------------------------------===//

llvm::DIType *DebugTranslation::translateImpl(DINullTypeAttr attr) {
  // A DINullTypeAttr at the beginning of the subroutine types list models
  // a void result type. If it is at the end, it models a variadic function.
  // Translate the explicit DINullTypeAttr to a nullptr since LLVM IR metadata
  // does not have an explicit void result type nor a variadic type
  // representation.
  return nullptr;
}

llvm::DIExpression *
DebugTranslation::getExpressionAttrOrNull(DIExpressionAttr attr) {
  if (!attr)
    return nullptr;
  return translateExpression(attr);
}

llvm::MDString *DebugTranslation::getMDStringOrNull(StringAttr stringAttr) {
  if (!stringAttr || stringAttr.empty())
    return nullptr;
  return llvm::MDString::get(llvmCtx, stringAttr);
}

llvm::MDTuple *
DebugTranslation::getMDTupleOrNull(ArrayRef<DINodeAttr> elements) {
  if (elements.empty())
    return nullptr;
  SmallVector<llvm::Metadata *> llvmElements =
      llvm::map_to_vector(elements, [&](DINodeAttr attr) -> llvm::Metadata * {
        if (DIAnnotationAttr annAttr = dyn_cast<DIAnnotationAttr>(attr)) {
          llvm::Metadata *ops[2] = {
              llvm::MDString::get(llvmCtx, annAttr.getName()),
              llvm::MDString::get(llvmCtx, annAttr.getValue())};
          return llvm::MDNode::get(llvmCtx, ops);
        }
        return translate(attr);
      });
  return llvm::MDNode::get(llvmCtx, llvmElements);
}

llvm::DIBasicType *DebugTranslation::translateImpl(DIBasicTypeAttr attr) {
  return llvm::DIBasicType::get(
      llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()),
      attr.getSizeInBits(),
      /*AlignInBits=*/0, attr.getEncoding(), llvm::DINode::FlagZero);
}

llvm::TempDICompileUnit
DebugTranslation::translateTemporaryImpl(DICompileUnitAttr attr) {
  return llvm::DICompileUnit::getTemporary(
      llvmCtx,
      static_cast<llvm::DISourceLanguageName>(attr.getSourceLanguage()),
      /*File=*/nullptr, "", attr.getIsOptimized(),
      /*Flags=*/"", /*RuntimeVersion=*/0,
      /*splitDebugFileName=*/"",
      static_cast<llvm::DICompileUnit::DebugEmissionKind>(
          attr.getEmissionKind()),
      /*EnumTypes=*/nullptr, /*RetainedTypes=*/nullptr,
      /*GlobalVariables=*/nullptr, /*ImportedEntities=*/nullptr,
      /*Macros=*/nullptr,
      /*DWOId=*/0, /*SplitDebugInlining=*/true,
      attr.getIsDebugInfoForProfiling(),
      static_cast<llvm::DICompileUnit::DebugNameTableKind>(
          attr.getNameTableKind()),
      /*RangesBaseAddress=*/false, /*SysRoot=*/"", /*SDK=*/"");
}

llvm::DICompileUnit *DebugTranslation::translateImpl(DICompileUnitAttr attr) {
  if (attr.getId())
    if (auto iter = distinctAttrToNode.find(attr.getId());
        iter != distinctAttrToNode.end())
      return cast<llvm::DICompileUnit>(iter->second);

  llvm::DIBuilder builder(llvmModule);
  llvm::DICompileUnit *cu = builder.createCompileUnit(
      attr.getSourceLanguage(), translate(attr.getFile()),
      attr.getProducer() ? attr.getProducer().getValue() : "",
      attr.getIsOptimized(),
      /*Flags=*/"", /*RV=*/0,
      attr.getSplitDebugFilename() ? attr.getSplitDebugFilename().getValue()
                                   : "",
      static_cast<llvm::DICompileUnit::DebugEmissionKind>(
          attr.getEmissionKind()),
      0, true, attr.getIsDebugInfoForProfiling(),
      static_cast<llvm::DICompileUnit::DebugNameTableKind>(
          attr.getNameTableKind()));

  llvm::SmallVector<llvm::Metadata *> importNodes;
  for (DINodeAttr importNode : attr.getImportedEntities())
    importNodes.push_back(translate(importNode));
  if (!importNodes.empty())
    cu->replaceImportedEntities(llvm::MDTuple::get(llvmCtx, importNodes));

  if (attr.getId())
    distinctAttrToNode.try_emplace(attr.getId(), cu);

  return cu;
}

/// Returns a new `DINodeT` that is either distinct or not, depending on
/// `isDistinct`.
template <class DINodeT, class... Ts>
static DINodeT *getDistinctOrUnique(bool isDistinct, Ts &&...args) {
  if (isDistinct)
    return DINodeT::getDistinct(std::forward<Ts>(args)...);
  return DINodeT::get(std::forward<Ts>(args)...);
}

llvm::TempDICompositeType
DebugTranslation::translateTemporaryImpl(DICompositeTypeAttr attr) {
  return llvm::DICompositeType::getTemporary(
      llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()), nullptr,
      attr.getLine(), nullptr, nullptr, attr.getSizeInBits(),
      attr.getAlignInBits(),
      /*OffsetInBits=*/0,
      /*Flags=*/static_cast<llvm::DINode::DIFlags>(attr.getFlags()),
      /*Elements=*/nullptr, /*RuntimeLang=*/0, /*EnumKind=*/std::nullopt,
      /*VTableHolder=*/nullptr);
}

llvm::TempDISubprogram
DebugTranslation::translateTemporaryImpl(DISubprogramAttr attr) {
  return llvm::DISubprogram::getTemporary(
      llvmCtx, /*Scope=*/nullptr, /*Name=*/{}, /*LinkageName=*/{},
      /*File=*/nullptr, attr.getLine(), /*Type=*/nullptr,
      /*ScopeLine=*/0, /*ContainingType=*/nullptr, /*VirtualIndex=*/0,
      /*ThisAdjustment=*/0, llvm::DINode::FlagZero,
      static_cast<llvm::DISubprogram::DISPFlags>(attr.getSubprogramFlags()),
      /*Unit=*/nullptr);
}

llvm::DICompositeType *
DebugTranslation::translateImpl(DICompositeTypeAttr attr) {
  // TODO: Use distinct attributes to model this, once they have landed.
  // Depending on the tag, composite types must be distinct.
  bool isDistinct = false;
  switch (attr.getTag()) {
  case llvm::dwarf::DW_TAG_class_type:
  case llvm::dwarf::DW_TAG_enumeration_type:
  case llvm::dwarf::DW_TAG_structure_type:
  case llvm::dwarf::DW_TAG_union_type:
    isDistinct = true;
  }

  return getDistinctOrUnique<llvm::DICompositeType>(
      isDistinct, llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()),
      translate(attr.getFile()), attr.getLine(), translate(attr.getScope()),
      translate(attr.getBaseType()), attr.getSizeInBits(),
      attr.getAlignInBits(),
      /*OffsetInBits=*/0,
      /*Flags=*/static_cast<llvm::DINode::DIFlags>(attr.getFlags()),
      getMDTupleOrNull(attr.getElements()),
      /*RuntimeLang=*/0, /*EnumKind*/ std::nullopt, /*VTableHolder=*/nullptr,
      /*TemplateParams=*/nullptr, /*Identifier=*/nullptr,
      /*Discriminator=*/nullptr,
      getExpressionAttrOrNull(attr.getDataLocation()),
      getExpressionAttrOrNull(attr.getAssociated()),
      getExpressionAttrOrNull(attr.getAllocated()),
      getExpressionAttrOrNull(attr.getRank()));
}

llvm::DIDerivedType *DebugTranslation::translateImpl(DIDerivedTypeAttr attr) {
  return llvm::DIDerivedType::get(
      llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()),
      translate(attr.getFile()), attr.getLine(), translate(attr.getScope()),
      translate(attr.getBaseType()), attr.getSizeInBits(),
      attr.getAlignInBits(), attr.getOffsetInBits(),
      attr.getDwarfAddressSpace(), /*PtrAuthData=*/std::nullopt,
      /*Flags=*/static_cast<llvm::DINode::DIFlags>(attr.getFlags()),
      translate(attr.getExtraData()));
}

llvm::DIStringType *DebugTranslation::translateImpl(DIStringTypeAttr attr) {
  return llvm::DIStringType::get(
      llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()),
      translate(attr.getStringLength()),
      getExpressionAttrOrNull(attr.getStringLengthExp()),
      getExpressionAttrOrNull(attr.getStringLocationExp()),
      attr.getSizeInBits(), attr.getAlignInBits(), attr.getEncoding());
}

llvm::DIFile *DebugTranslation::translateImpl(DIFileAttr attr) {
  return llvm::DIFile::get(llvmCtx, getMDStringOrNull(attr.getName()),
                           getMDStringOrNull(attr.getDirectory()));
}

llvm::DILabel *DebugTranslation::translateImpl(DILabelAttr attr) {
  return llvm::DILabel::get(llvmCtx, translate(attr.getScope()),
                            getMDStringOrNull(attr.getName()),
                            translate(attr.getFile()), attr.getLine(),
                            /*Column=*/0, /*IsArtificial=*/false,
                            /*CoroSuspendIdx=*/std::nullopt);
}

llvm::DILexicalBlock *DebugTranslation::translateImpl(DILexicalBlockAttr attr) {
  return llvm::DILexicalBlock::getDistinct(llvmCtx, translate(attr.getScope()),
                                           translate(attr.getFile()),
                                           attr.getLine(), attr.getColumn());
}

llvm::DILexicalBlockFile *
DebugTranslation::translateImpl(DILexicalBlockFileAttr attr) {
  return llvm::DILexicalBlockFile::getDistinct(
      llvmCtx, translate(attr.getScope()), translate(attr.getFile()),
      attr.getDiscriminator());
}

llvm::DILocalScope *DebugTranslation::translateImpl(DILocalScopeAttr attr) {
  return cast<llvm::DILocalScope>(translate(DINodeAttr(attr)));
}

llvm::DIVariable *DebugTranslation::translateImpl(DIVariableAttr attr) {
  return cast<llvm::DIVariable>(translate(DINodeAttr(attr)));
}

llvm::DILocalVariable *
DebugTranslation::translateImpl(DILocalVariableAttr attr) {
  return llvm::DILocalVariable::get(
      llvmCtx, translate(attr.getScope()), getMDStringOrNull(attr.getName()),
      translate(attr.getFile()), attr.getLine(), translate(attr.getType()),
      attr.getArg(), static_cast<llvm::DINode::DIFlags>(attr.getFlags()),
      attr.getAlignInBits(),
      /*Annotations=*/nullptr);
}

llvm::DIGlobalVariable *
DebugTranslation::translateImpl(DIGlobalVariableAttr attr) {
  return llvm::DIGlobalVariable::getDistinct(
      llvmCtx, translate(attr.getScope()), getMDStringOrNull(attr.getName()),
      getMDStringOrNull(attr.getLinkageName()), translate(attr.getFile()),
      attr.getLine(), translate(attr.getType()), attr.getIsLocalToUnit(),
      attr.getIsDefined(), nullptr, nullptr, attr.getAlignInBits(), nullptr);
}

llvm::DINode *
DebugTranslation::translateRecursive(DIRecursiveTypeAttrInterface attr) {
  DistinctAttr recursiveId = attr.getRecId();
  if (auto *iter = recursiveNodeMap.find(recursiveId);
      iter != recursiveNodeMap.end()) {
    return iter->second;
  }
  assert(!attr.getIsRecSelf() && "unbound DI recursive self reference");

  auto setRecursivePlaceholder = [&](llvm::DINode *placeholder) {
    recursiveNodeMap.try_emplace(recursiveId, placeholder);
  };

  llvm::DINode *result =
      TypeSwitch<DIRecursiveTypeAttrInterface, llvm::DINode *>(attr)
          .Case([&](DICompositeTypeAttr attr) {
            auto temporary = translateTemporaryImpl(attr);
            setRecursivePlaceholder(temporary.get());
            // Must call `translateImpl` directly instead of `translate` to
            // avoid handling the recursive interface again.
            auto *concrete = translateImpl(attr);
            temporary->replaceAllUsesWith(concrete);
            return concrete;
          })
          .Case([&](DISubprogramAttr attr) {
            auto temporary = translateTemporaryImpl(attr);
            setRecursivePlaceholder(temporary.get());
            // Must call `translateImpl` directly instead of `translate` to
            // avoid handling the recursive interface again.
            auto *concrete = translateImpl(attr);
            temporary->replaceAllUsesWith(concrete);
            return concrete;
          })
          .Case([&](DICompileUnitAttr attr) {
            auto temporary = translateTemporaryImpl(attr);
            setRecursivePlaceholder(temporary.get());
            auto *concrete = translateImpl(attr);
            temporary->replaceAllUsesWith(concrete);
            return concrete;
          });

  assert(recursiveNodeMap.back().first == recursiveId &&
         "internal inconsistency: unexpected recursive translation stack");
  recursiveNodeMap.pop_back();

  return result;
}

llvm::DIScope *DebugTranslation::translateImpl(DIScopeAttr attr) {
  return cast<llvm::DIScope>(translate(DINodeAttr(attr)));
}

llvm::DISubprogram *DebugTranslation::translateImpl(DISubprogramAttr attr) {
  if (auto iter = distinctAttrToNode.find(attr.getId());
      iter != distinctAttrToNode.end())
    return cast<llvm::DISubprogram>(iter->second);

  llvm::DIScope *scope = translate(attr.getScope());
  llvm::DIFile *file = translate(attr.getFile());
  llvm::DIType *type = translate(attr.getType());
  llvm::DICompileUnit *compileUnit = translate(attr.getCompileUnit());

  // Check again after recursive calls in case this distinct node recurses back
  // to itself.
  if (auto iter = distinctAttrToNode.find(attr.getId());
      iter != distinctAttrToNode.end())
    return cast<llvm::DISubprogram>(iter->second);

  bool isDefinition = static_cast<bool>(attr.getSubprogramFlags() &
                                        LLVM::DISubprogramFlags::Definition);

  llvm::DISubprogram *node = getDistinctOrUnique<llvm::DISubprogram>(
      isDefinition, llvmCtx, scope, getMDStringOrNull(attr.getName()),
      getMDStringOrNull(attr.getLinkageName()), file, attr.getLine(), type,
      attr.getScopeLine(),
      /*ContainingType=*/nullptr, /*VirtualIndex=*/0,
      /*ThisAdjustment=*/0, llvm::DINode::FlagZero,
      static_cast<llvm::DISubprogram::DISPFlags>(attr.getSubprogramFlags()),
      compileUnit, /*TemplateParams=*/nullptr, /*Declaration=*/nullptr,
      getMDTupleOrNull(attr.getRetainedNodes()), nullptr,
      getMDTupleOrNull(attr.getAnnotations()));
  if (attr.getId())
    distinctAttrToNode.try_emplace(attr.getId(), node);
  return node;
}

llvm::DIModule *DebugTranslation::translateImpl(DIModuleAttr attr) {
  return llvm::DIModule::get(
      llvmCtx, translate(attr.getFile()), translate(attr.getScope()),
      getMDStringOrNull(attr.getName()),
      getMDStringOrNull(attr.getConfigMacros()),
      getMDStringOrNull(attr.getIncludePath()),
      getMDStringOrNull(attr.getApinotes()), attr.getLine(), attr.getIsDecl());
}

llvm::DINamespace *DebugTranslation::translateImpl(DINamespaceAttr attr) {
  return llvm::DINamespace::get(llvmCtx, translate(attr.getScope()),
                                getMDStringOrNull(attr.getName()),
                                attr.getExportSymbols());
}

llvm::DIImportedEntity *
DebugTranslation::translateImpl(DIImportedEntityAttr attr) {
  return llvm::DIImportedEntity::get(
      llvmCtx, attr.getTag(), translate(attr.getScope()),
      translate(attr.getEntity()), translate(attr.getFile()), attr.getLine(),
      getMDStringOrNull(attr.getName()), getMDTupleOrNull(attr.getElements()));
}

llvm::DISubrange *DebugTranslation::translateImpl(DISubrangeAttr attr) {
  auto getMetadataOrNull = [&](Attribute attr) -> llvm::Metadata * {
    if (!attr)
      return nullptr;

    llvm::Metadata *metadata =
        llvm::TypeSwitch<Attribute, llvm::Metadata *>(attr)
            .Case([&](IntegerAttr intAttr) {
              return llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
                  llvm::Type::getInt64Ty(llvmCtx), intAttr.getInt()));
            })
            .Case([&](LLVM::DIExpressionAttr expr) {
              return translateExpression(expr);
            })
            .Case([&](LLVM::DILocalVariableAttr local) {
              return translate(local);
            })
            .Case<>([&](LLVM::DIGlobalVariableAttr global) {
              return translate(global);
            })
            .Default(nullptr);
    return metadata;
  };
  return llvm::DISubrange::get(llvmCtx, getMetadataOrNull(attr.getCount()),
                               getMetadataOrNull(attr.getLowerBound()),
                               getMetadataOrNull(attr.getUpperBound()),
                               getMetadataOrNull(attr.getStride()));
}

llvm::DICommonBlock *DebugTranslation::translateImpl(DICommonBlockAttr attr) {
  return llvm::DICommonBlock::get(llvmCtx, translate(attr.getScope()),
                                  translate(attr.getDecl()),
                                  getMDStringOrNull(attr.getName()),
                                  translate(attr.getFile()), attr.getLine());
}

llvm::DIGenericSubrange *
DebugTranslation::translateImpl(DIGenericSubrangeAttr attr) {
  auto getMetadataOrNull = [&](Attribute attr) -> llvm::Metadata * {
    if (!attr)
      return nullptr;

    llvm::Metadata *metadata =
        llvm::TypeSwitch<Attribute, llvm::Metadata *>(attr)
            .Case([&](LLVM::DIExpressionAttr expr) {
              return translateExpression(expr);
            })
            .Case([&](LLVM::DILocalVariableAttr local) {
              return translate(local);
            })
            .Case([&](LLVM::DIGlobalVariableAttr global) {
              return translate(global);
            })
            .Default(nullptr);
    return metadata;
  };
  return llvm::DIGenericSubrange::get(llvmCtx,
                                      getMetadataOrNull(attr.getCount()),
                                      getMetadataOrNull(attr.getLowerBound()),
                                      getMetadataOrNull(attr.getUpperBound()),
                                      getMetadataOrNull(attr.getStride()));
}

llvm::DISubroutineType *
DebugTranslation::translateImpl(DISubroutineTypeAttr attr) {
  // Concatenate the result and argument types into a single array.
  SmallVector<llvm::Metadata *> types;
  for (DITypeAttr type : attr.getTypes())
    types.push_back(translate(type));
  return llvm::DISubroutineType::get(
      llvmCtx, llvm::DINode::FlagZero, attr.getCallingConvention(),
      llvm::DITypeArray(llvm::MDNode::get(llvmCtx, types)));
}

llvm::DIType *DebugTranslation::translateImpl(DITypeAttr attr) {
  return cast<llvm::DIType>(translate(DINodeAttr(attr)));
}

llvm::DINode *DebugTranslation::translate(DINodeAttr attr) {
  if (!attr)
    return nullptr;
  // Check for a cached instance.
  if (llvm::DINode *node = attrToNode.lookup(attr))
    return node;

  llvm::DINode *node = nullptr;
  // Recursive types go through a dedicated handler. All other types are
  // dispatched directly to their specific handlers.
  if (auto recTypeAttr = dyn_cast<DIRecursiveTypeAttrInterface>(attr))
    if (recTypeAttr.getRecId())
      node = translateRecursive(recTypeAttr);

  if (!node)
    node = TypeSwitch<DINodeAttr, llvm::DINode *>(attr)
               .Case<DIBasicTypeAttr, DICommonBlockAttr, DICompileUnitAttr,
                     DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr,
                     DIGenericSubrangeAttr, DIGlobalVariableAttr,
                     DIImportedEntityAttr, DILabelAttr, DILexicalBlockAttr,
                     DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,
                     DINamespaceAttr, DINullTypeAttr, DIStringTypeAttr,
                     DISubprogramAttr, DISubrangeAttr, DISubroutineTypeAttr>(
                   [&](auto attr) { return translateImpl(attr); });

  if (node && !node->isTemporary())
    attrToNode.insert({attr, node});
  return node;
}

//===----------------------------------------------------------------------===//
// Locations
//===----------------------------------------------------------------------===//

/// Translate the given location to an llvm debug location.
llvm::DILocation *DebugTranslation::translateLoc(Location loc,
                                                 llvm::DILocalScope *scope) {
  if (!debugEmissionIsEnabled)
    return nullptr;
  return translateLoc(loc, scope, /*inlinedAt=*/nullptr);
}

llvm::DIExpression *
DebugTranslation::translateExpression(LLVM::DIExpressionAttr attr) {
  SmallVector<uint64_t, 1> ops;
  if (attr) {
    // Append operations their operands to the list.
    for (const DIExpressionElemAttr &op : attr.getOperations()) {
      ops.push_back(op.getOpcode());
      append_range(ops, op.getArguments());
    }
  }
  return llvm::DIExpression::get(llvmCtx, ops);
}

llvm::DIGlobalVariableExpression *
DebugTranslation::translateGlobalVariableExpression(
    LLVM::DIGlobalVariableExpressionAttr attr) {
  return llvm::DIGlobalVariableExpression::get(
      llvmCtx, translate(attr.getVar()), translateExpression(attr.getExpr()));
}

/// Translate the given location to an llvm DebugLoc.
llvm::DILocation *DebugTranslation::translateLoc(Location loc,
                                                 llvm::DILocalScope *scope,
                                                 llvm::DILocation *inlinedAt) {
  // LLVM doesn't have a representation for unknown.
  if (isa<UnknownLoc>(loc))
    return nullptr;

  // Check for a cached instance.
  auto existingIt = locationToLoc.find(std::make_tuple(loc, scope, inlinedAt));
  if (existingIt != locationToLoc.end())
    return existingIt->second;

  llvm::DILocation *llvmLoc = nullptr;
  if (auto callLoc = dyn_cast<CallSiteLoc>(loc)) {
    // For callsites, the caller is fed as the inlinedAt for the callee.
    auto *callerLoc = translateLoc(callLoc.getCaller(), scope, inlinedAt);
    // If the caller scope is not translatable, the overall callsite cannot be
    // represented in LLVM (the callee scope may not match the parent function).
    if (!callerLoc) {
      // If there is an inlinedAt scope (an outer caller), skip to that
      // directly. Otherwise, cannot translate.
      if (!inlinedAt)
        return nullptr;
      callerLoc = inlinedAt;
    }
    llvmLoc = translateLoc(callLoc.getCallee(), nullptr, callerLoc);
    // Fallback: Ignore callee if it has no debug scope.
    if (!llvmLoc)
      llvmLoc = callerLoc;

  } else if (auto fileLoc = dyn_cast<FileLineColLoc>(loc)) {
    // A scope of a DILocation cannot be null.
    if (!scope)
      return nullptr;
    llvmLoc =
        llvm::DILocation::get(llvmCtx, fileLoc.getLine(), fileLoc.getColumn(),
                              scope, const_cast<llvm::DILocation *>(inlinedAt));

  } else if (auto fusedLoc = dyn_cast<FusedLoc>(loc)) {
    ArrayRef<Location> locations = fusedLoc.getLocations();

    // Check for a scope encoded with the location.
    if (auto scopedAttr =
            dyn_cast_or_null<LLVM::DILocalScopeAttr>(fusedLoc.getMetadata()))
      scope = translate(scopedAttr);

    // For fused locations, merge each of the nodes.
    llvmLoc = translateLoc(locations.front(), scope, inlinedAt);
    for (Location locIt : locations.drop_front()) {
      llvmLoc = llvm::DILocation::getMergedLocation(
          llvmLoc, translateLoc(locIt, scope, inlinedAt));
    }

  } else if (auto nameLoc = dyn_cast<NameLoc>(loc)) {
    llvmLoc = translateLoc(nameLoc.getChildLoc(), scope, inlinedAt);

  } else if (auto opaqueLoc = dyn_cast<OpaqueLoc>(loc)) {
    llvmLoc = translateLoc(opaqueLoc.getFallbackLocation(), scope, inlinedAt);
  } else {
    llvm_unreachable("unknown location kind");
  }

  locationToLoc.try_emplace(std::make_tuple(loc, scope, inlinedAt), llvmLoc);
  return llvmLoc;
}

/// Create an llvm debug file for the given file path.
llvm::DIFile *DebugTranslation::translateFile(StringRef fileName) {
  auto *&file = fileMap[fileName];
  if (file)
    return file;

  // Make sure the current working directory is up-to-date.
  if (currentWorkingDir.empty())
    llvm::sys::fs::current_path(currentWorkingDir);

  StringRef directory = currentWorkingDir;
  SmallString<128> dirBuf;
  SmallString<128> fileBuf;
  if (llvm::sys::path::is_absolute(fileName)) {
    // Strip the common prefix (if it is more than just "/") from current
    // directory and FileName for a more space-efficient encoding.
    auto fileIt = llvm::sys::path::begin(fileName);
    auto fileE = llvm::sys::path::end(fileName);
    auto curDirIt = llvm::sys::path::begin(directory);
    auto curDirE = llvm::sys::path::end(directory);
    for (; curDirIt != curDirE && *curDirIt == *fileIt; ++curDirIt, ++fileIt)
      llvm::sys::path::append(dirBuf, *curDirIt);
    if (std::distance(llvm::sys::path::begin(directory), curDirIt) == 1) {
      // Don't strip the common prefix if it is only the root "/"  since that
      // would make LLVM diagnostic locations confusing.
      directory = StringRef();
    } else {
      for (; fileIt != fileE; ++fileIt)
        llvm::sys::path::append(fileBuf, *fileIt);
      directory = dirBuf;
      fileName = fileBuf;
    }
  }
  return (file = llvm::DIFile::get(llvmCtx, fileName, directory));
}
