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

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