//===- 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/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;

  // TODO: The version information should be encoded on the LLVM module itself,
  // not implicitly set here.

  // Mark this module as having debug information.
  StringRef debugVersionKey = "Debug Info Version";
  if (!llvmModule.getModuleFlag(debugVersionKey))
    llvmModule.addModuleFlag(llvm::Module::Warning, debugVersionKey,
                             llvm::DEBUG_METADATA_VERSION);

  if (auto targetTripleAttr = module->getDiscardableAttr(
          LLVM::LLVMDialect::getTargetTripleAttrName())) {
    auto targetTriple =
        llvm::Triple(cast<StringAttr>(targetTripleAttr).getValue());
    if (targetTriple.isKnownWindowsMSVCEnvironment()) {
      // Dwarf debugging files will be generated by default, unless "CodeView"
      // is set explicitly. Windows/MSVC should use CodeView instead.
      llvmModule.addModuleFlag(llvm::Module::Warning, "CodeView", 1);
    }
  }
}

/// Finalize the translation of debug information.
void DebugTranslation::finalize() {}

/// 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::MDString *DebugTranslation::getMDStringOrNull(StringAttr stringAttr) {
  if (!stringAttr || stringAttr.empty())
    return nullptr;
  return llvm::MDString::get(llvmCtx, stringAttr);
}

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::DICompileUnit *DebugTranslation::translateImpl(DICompileUnitAttr attr) {
  llvm::DIBuilder builder(llvmModule);
  return builder.createCompileUnit(
      attr.getSourceLanguage(), translate(attr.getFile()),
      attr.getProducer() ? attr.getProducer().getValue() : "",
      attr.getIsOptimized(),
      /*Flags=*/"", /*RV=*/0, /*SplitName=*/{},
      static_cast<llvm::DICompileUnit::DebugEmissionKind>(
          attr.getEmissionKind()),
      0, true, false,
      static_cast<llvm::DICompileUnit::DebugNameTableKind>(
          attr.getNameTableKind()));
}

/// 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,
      /*VTableHolder=*/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;
  }

  SmallVector<llvm::Metadata *> elements;
  for (DINodeAttr member : attr.getElements())
    elements.push_back(translate(member));

  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()),
      llvm::MDNode::get(llvmCtx, elements),
      /*RuntimeLang=*/0, /*VTableHolder=*/nullptr);
}

llvm::DIDerivedType *DebugTranslation::translateImpl(DIDerivedTypeAttr attr) {
  return llvm::DIDerivedType::get(
      llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()),
      /*File=*/nullptr, /*Line=*/0,
      /*Scope=*/nullptr, translate(attr.getBaseType()), attr.getSizeInBits(),
      attr.getAlignInBits(), attr.getOffsetInBits(),
      /*DWARFAddressSpace=*/std::nullopt, /*PtrAuthData=*/std::nullopt,
      /*Flags=*/llvm::DINode::FlagZero, translate(attr.getExtraData()));
}

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());
}

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::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(),
      /*Flags=*/llvm::DINode::FlagZero, 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::DIType *
DebugTranslation::translateRecursive(DIRecursiveTypeAttrInterface attr) {
  DistinctAttr recursiveId = attr.getRecId();
  if (auto *iter = recursiveTypeMap.find(recursiveId);
      iter != recursiveTypeMap.end()) {
    return iter->second;
  } else {
    assert(!attr.isRecSelf() && "unbound DI recursive self type");
  }

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

  llvm::DIType *result =
      TypeSwitch<DIRecursiveTypeAttrInterface, llvm::DIType *>(attr)
          .Case<DICompositeTypeAttr>([&](auto 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;
          });

  assert(recursiveTypeMap.back().first == recursiveId &&
         "internal inconsistency: unexpected recursive translation stack");
  recursiveTypeMap.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);

  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::DISubrange *DebugTranslation::translateImpl(DISubrangeAttr attr) {
  auto getMetadataOrNull = [&](IntegerAttr attr) -> llvm::Metadata * {
    if (!attr)
      return nullptr;
    return llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
        llvm::Type::getInt64Ty(llvmCtx), attr.getInt()));
  };
  return llvm::DISubrange::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::DITypeRefArray(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, DICompileUnitAttr, DICompositeTypeAttr,
                     DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr,
                     DILabelAttr, DILexicalBlockAttr, DILexicalBlockFileAttr,
                     DILocalVariableAttr, DIModuleAttr, DINamespaceAttr,
                     DINullTypeAttr, DISubprogramAttr, DISubrangeAttr,
                     DISubroutineTypeAttr>(
                   [&](auto attr) { return translateImpl(attr); });

  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);
    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));
}
