brintos

brintos / llvm-project-archived public Read only

0
0
Text · 24.4 KiB · e3bcf27 Raw
615 lines · cpp
1//===- DebugTranslation.cpp - MLIR to LLVM Debug conversion ---------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "DebugTranslation.h"10#include "mlir/Dialect/LLVMIR/LLVMDialect.h"11#include "llvm/ADT/TypeSwitch.h"12#include "llvm/IR/Metadata.h"13#include "llvm/IR/Module.h"14#include "llvm/Support/FileSystem.h"15#include "llvm/Support/Path.h"16 17using namespace mlir;18using namespace mlir::LLVM;19using namespace mlir::LLVM::detail;20 21/// A utility walker that interrupts if the operation has valid debug22/// information.23static WalkResult interruptIfValidLocation(Operation *op) {24  return isa<UnknownLoc>(op->getLoc()) ? WalkResult::advance()25                                       : WalkResult::interrupt();26}27 28DebugTranslation::DebugTranslation(Operation *module, llvm::Module &llvmModule)29    : debugEmissionIsEnabled(false), llvmModule(llvmModule),30      llvmCtx(llvmModule.getContext()) {31  // If the module has no location information, there is nothing to do.32  if (!module->walk(interruptIfValidLocation).wasInterrupted())33    return;34  debugEmissionIsEnabled = true;35}36 37static constexpr StringRef kDebugVersionKey = "Debug Info Version";38static constexpr StringRef kCodeViewKey = "CodeView";39 40void DebugTranslation::addModuleFlagsIfNotPresent() {41  // TODO: The version information should be encoded on the LLVM module itself,42  // not implicitly set here.43 44  // Mark this module as having debug information.45  if (!llvmModule.getModuleFlag(kDebugVersionKey))46    llvmModule.addModuleFlag(llvm::Module::Warning, kDebugVersionKey,47                             llvm::DEBUG_METADATA_VERSION);48 49  const llvm::Triple &targetTriple = llvmModule.getTargetTriple();50  if (targetTriple.isKnownWindowsMSVCEnvironment()) {51    // Dwarf debugging files will be generated by default, unless "CodeView"52    // is set explicitly. Windows/MSVC should use CodeView instead.53    if (!llvmModule.getModuleFlag(kCodeViewKey))54      llvmModule.addModuleFlag(llvm::Module::Warning, kCodeViewKey, 1);55  }56}57 58/// Translate the debug information for the given function.59void DebugTranslation::translate(LLVMFuncOp func, llvm::Function &llvmFunc) {60  if (!debugEmissionIsEnabled)61    return;62 63  // Look for a sub program attached to the function.64  auto spLoc =65      func.getLoc()->findInstanceOf<FusedLocWith<LLVM::DISubprogramAttr>>();66  if (!spLoc)67    return;68  llvmFunc.setSubprogram(translate(spLoc.getMetadata()));69}70 71//===----------------------------------------------------------------------===//72// Attributes73//===----------------------------------------------------------------------===//74 75llvm::DIType *DebugTranslation::translateImpl(DINullTypeAttr attr) {76  // A DINullTypeAttr at the beginning of the subroutine types list models77  // a void result type. If it is at the end, it models a variadic function.78  // Translate the explicit DINullTypeAttr to a nullptr since LLVM IR metadata79  // does not have an explicit void result type nor a variadic type80  // representation.81  return nullptr;82}83 84llvm::DIExpression *85DebugTranslation::getExpressionAttrOrNull(DIExpressionAttr attr) {86  if (!attr)87    return nullptr;88  return translateExpression(attr);89}90 91llvm::MDString *DebugTranslation::getMDStringOrNull(StringAttr stringAttr) {92  if (!stringAttr || stringAttr.empty())93    return nullptr;94  return llvm::MDString::get(llvmCtx, stringAttr);95}96 97llvm::MDTuple *98DebugTranslation::getMDTupleOrNull(ArrayRef<DINodeAttr> elements) {99  if (elements.empty())100    return nullptr;101  SmallVector<llvm::Metadata *> llvmElements = llvm::to_vector(102      llvm::map_range(elements, [&](DINodeAttr attr) -> llvm::Metadata * {103        if (DIAnnotationAttr annAttr = dyn_cast<DIAnnotationAttr>(attr)) {104          llvm::Metadata *ops[2] = {105              llvm::MDString::get(llvmCtx, annAttr.getName()),106              llvm::MDString::get(llvmCtx, annAttr.getValue())};107          return llvm::MDNode::get(llvmCtx, ops);108        }109        return translate(attr);110      }));111  return llvm::MDNode::get(llvmCtx, llvmElements);112}113 114llvm::DIBasicType *DebugTranslation::translateImpl(DIBasicTypeAttr attr) {115  return llvm::DIBasicType::get(116      llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()),117      attr.getSizeInBits(),118      /*AlignInBits=*/0, attr.getEncoding(), llvm::DINode::FlagZero);119}120 121llvm::DICompileUnit *DebugTranslation::translateImpl(DICompileUnitAttr attr) {122  llvm::DIBuilder builder(llvmModule);123  return builder.createCompileUnit(124      attr.getSourceLanguage(), translate(attr.getFile()),125      attr.getProducer() ? attr.getProducer().getValue() : "",126      attr.getIsOptimized(),127      /*Flags=*/"", /*RV=*/0,128      attr.getSplitDebugFilename() ? attr.getSplitDebugFilename().getValue()129                                   : "",130      static_cast<llvm::DICompileUnit::DebugEmissionKind>(131          attr.getEmissionKind()),132      0, true, false,133      static_cast<llvm::DICompileUnit::DebugNameTableKind>(134          attr.getNameTableKind()));135}136 137/// Returns a new `DINodeT` that is either distinct or not, depending on138/// `isDistinct`.139template <class DINodeT, class... Ts>140static DINodeT *getDistinctOrUnique(bool isDistinct, Ts &&...args) {141  if (isDistinct)142    return DINodeT::getDistinct(std::forward<Ts>(args)...);143  return DINodeT::get(std::forward<Ts>(args)...);144}145 146llvm::TempDICompositeType147DebugTranslation::translateTemporaryImpl(DICompositeTypeAttr attr) {148  return llvm::DICompositeType::getTemporary(149      llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()), nullptr,150      attr.getLine(), nullptr, nullptr, attr.getSizeInBits(),151      attr.getAlignInBits(),152      /*OffsetInBits=*/0,153      /*Flags=*/static_cast<llvm::DINode::DIFlags>(attr.getFlags()),154      /*Elements=*/nullptr, /*RuntimeLang=*/0, /*EnumKind=*/std::nullopt,155      /*VTableHolder=*/nullptr);156}157 158llvm::TempDISubprogram159DebugTranslation::translateTemporaryImpl(DISubprogramAttr attr) {160  return llvm::DISubprogram::getTemporary(161      llvmCtx, /*Scope=*/nullptr, /*Name=*/{}, /*LinkageName=*/{},162      /*File=*/nullptr, attr.getLine(), /*Type=*/nullptr,163      /*ScopeLine=*/0, /*ContainingType=*/nullptr, /*VirtualIndex=*/0,164      /*ThisAdjustment=*/0, llvm::DINode::FlagZero,165      static_cast<llvm::DISubprogram::DISPFlags>(attr.getSubprogramFlags()),166      /*Unit=*/nullptr);167}168 169llvm::DICompositeType *170DebugTranslation::translateImpl(DICompositeTypeAttr attr) {171  // TODO: Use distinct attributes to model this, once they have landed.172  // Depending on the tag, composite types must be distinct.173  bool isDistinct = false;174  switch (attr.getTag()) {175  case llvm::dwarf::DW_TAG_class_type:176  case llvm::dwarf::DW_TAG_enumeration_type:177  case llvm::dwarf::DW_TAG_structure_type:178  case llvm::dwarf::DW_TAG_union_type:179    isDistinct = true;180  }181 182  return getDistinctOrUnique<llvm::DICompositeType>(183      isDistinct, llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()),184      translate(attr.getFile()), attr.getLine(), translate(attr.getScope()),185      translate(attr.getBaseType()), attr.getSizeInBits(),186      attr.getAlignInBits(),187      /*OffsetInBits=*/0,188      /*Flags=*/static_cast<llvm::DINode::DIFlags>(attr.getFlags()),189      getMDTupleOrNull(attr.getElements()),190      /*RuntimeLang=*/0, /*EnumKind*/ std::nullopt, /*VTableHolder=*/nullptr,191      /*TemplateParams=*/nullptr, /*Identifier=*/nullptr,192      /*Discriminator=*/nullptr,193      getExpressionAttrOrNull(attr.getDataLocation()),194      getExpressionAttrOrNull(attr.getAssociated()),195      getExpressionAttrOrNull(attr.getAllocated()),196      getExpressionAttrOrNull(attr.getRank()));197}198 199llvm::DIDerivedType *DebugTranslation::translateImpl(DIDerivedTypeAttr attr) {200  return llvm::DIDerivedType::get(201      llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()),202      /*File=*/nullptr, /*Line=*/0,203      /*Scope=*/nullptr, translate(attr.getBaseType()), attr.getSizeInBits(),204      attr.getAlignInBits(), attr.getOffsetInBits(),205      attr.getDwarfAddressSpace(), /*PtrAuthData=*/std::nullopt,206      /*Flags=*/llvm::DINode::FlagZero, translate(attr.getExtraData()));207}208 209llvm::DIStringType *DebugTranslation::translateImpl(DIStringTypeAttr attr) {210  return llvm::DIStringType::get(211      llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()),212      translate(attr.getStringLength()),213      getExpressionAttrOrNull(attr.getStringLengthExp()),214      getExpressionAttrOrNull(attr.getStringLocationExp()),215      attr.getSizeInBits(), attr.getAlignInBits(), attr.getEncoding());216}217 218llvm::DIFile *DebugTranslation::translateImpl(DIFileAttr attr) {219  return llvm::DIFile::get(llvmCtx, getMDStringOrNull(attr.getName()),220                           getMDStringOrNull(attr.getDirectory()));221}222 223llvm::DILabel *DebugTranslation::translateImpl(DILabelAttr attr) {224  return llvm::DILabel::get(llvmCtx, translate(attr.getScope()),225                            getMDStringOrNull(attr.getName()),226                            translate(attr.getFile()), attr.getLine(),227                            /*Column=*/0, /*IsArtificial=*/false,228                            /*CoroSuspendIdx=*/std::nullopt);229}230 231llvm::DILexicalBlock *DebugTranslation::translateImpl(DILexicalBlockAttr attr) {232  return llvm::DILexicalBlock::getDistinct(llvmCtx, translate(attr.getScope()),233                                           translate(attr.getFile()),234                                           attr.getLine(), attr.getColumn());235}236 237llvm::DILexicalBlockFile *238DebugTranslation::translateImpl(DILexicalBlockFileAttr attr) {239  return llvm::DILexicalBlockFile::getDistinct(240      llvmCtx, translate(attr.getScope()), translate(attr.getFile()),241      attr.getDiscriminator());242}243 244llvm::DILocalScope *DebugTranslation::translateImpl(DILocalScopeAttr attr) {245  return cast<llvm::DILocalScope>(translate(DINodeAttr(attr)));246}247 248llvm::DIVariable *DebugTranslation::translateImpl(DIVariableAttr attr) {249  return cast<llvm::DIVariable>(translate(DINodeAttr(attr)));250}251 252llvm::DILocalVariable *253DebugTranslation::translateImpl(DILocalVariableAttr attr) {254  return llvm::DILocalVariable::get(255      llvmCtx, translate(attr.getScope()), getMDStringOrNull(attr.getName()),256      translate(attr.getFile()), attr.getLine(), translate(attr.getType()),257      attr.getArg(), static_cast<llvm::DINode::DIFlags>(attr.getFlags()),258      attr.getAlignInBits(),259      /*Annotations=*/nullptr);260}261 262llvm::DIGlobalVariable *263DebugTranslation::translateImpl(DIGlobalVariableAttr attr) {264  return llvm::DIGlobalVariable::getDistinct(265      llvmCtx, translate(attr.getScope()), getMDStringOrNull(attr.getName()),266      getMDStringOrNull(attr.getLinkageName()), translate(attr.getFile()),267      attr.getLine(), translate(attr.getType()), attr.getIsLocalToUnit(),268      attr.getIsDefined(), nullptr, nullptr, attr.getAlignInBits(), nullptr);269}270 271llvm::DINode *272DebugTranslation::translateRecursive(DIRecursiveTypeAttrInterface attr) {273  DistinctAttr recursiveId = attr.getRecId();274  if (auto *iter = recursiveNodeMap.find(recursiveId);275      iter != recursiveNodeMap.end()) {276    return iter->second;277  }278  assert(!attr.getIsRecSelf() && "unbound DI recursive self reference");279 280  auto setRecursivePlaceholder = [&](llvm::DINode *placeholder) {281    recursiveNodeMap.try_emplace(recursiveId, placeholder);282  };283 284  llvm::DINode *result =285      TypeSwitch<DIRecursiveTypeAttrInterface, llvm::DINode *>(attr)286          .Case<DICompositeTypeAttr>([&](auto attr) {287            auto temporary = translateTemporaryImpl(attr);288            setRecursivePlaceholder(temporary.get());289            // Must call `translateImpl` directly instead of `translate` to290            // avoid handling the recursive interface again.291            auto *concrete = translateImpl(attr);292            temporary->replaceAllUsesWith(concrete);293            return concrete;294          })295          .Case<DISubprogramAttr>([&](auto attr) {296            auto temporary = translateTemporaryImpl(attr);297            setRecursivePlaceholder(temporary.get());298            // Must call `translateImpl` directly instead of `translate` to299            // avoid handling the recursive interface again.300            auto *concrete = translateImpl(attr);301            temporary->replaceAllUsesWith(concrete);302            return concrete;303          });304 305  assert(recursiveNodeMap.back().first == recursiveId &&306         "internal inconsistency: unexpected recursive translation stack");307  recursiveNodeMap.pop_back();308 309  return result;310}311 312llvm::DIScope *DebugTranslation::translateImpl(DIScopeAttr attr) {313  return cast<llvm::DIScope>(translate(DINodeAttr(attr)));314}315 316llvm::DISubprogram *DebugTranslation::translateImpl(DISubprogramAttr attr) {317  if (auto iter = distinctAttrToNode.find(attr.getId());318      iter != distinctAttrToNode.end())319    return cast<llvm::DISubprogram>(iter->second);320 321  llvm::DIScope *scope = translate(attr.getScope());322  llvm::DIFile *file = translate(attr.getFile());323  llvm::DIType *type = translate(attr.getType());324  llvm::DICompileUnit *compileUnit = translate(attr.getCompileUnit());325 326  // Check again after recursive calls in case this distinct node recurses back327  // to itself.328  if (auto iter = distinctAttrToNode.find(attr.getId());329      iter != distinctAttrToNode.end())330    return cast<llvm::DISubprogram>(iter->second);331 332  bool isDefinition = static_cast<bool>(attr.getSubprogramFlags() &333                                        LLVM::DISubprogramFlags::Definition);334 335  llvm::DISubprogram *node = getDistinctOrUnique<llvm::DISubprogram>(336      isDefinition, llvmCtx, scope, getMDStringOrNull(attr.getName()),337      getMDStringOrNull(attr.getLinkageName()), file, attr.getLine(), type,338      attr.getScopeLine(),339      /*ContainingType=*/nullptr, /*VirtualIndex=*/0,340      /*ThisAdjustment=*/0, llvm::DINode::FlagZero,341      static_cast<llvm::DISubprogram::DISPFlags>(attr.getSubprogramFlags()),342      compileUnit, /*TemplateParams=*/nullptr, /*Declaration=*/nullptr,343      getMDTupleOrNull(attr.getRetainedNodes()), nullptr,344      getMDTupleOrNull(attr.getAnnotations()));345  if (attr.getId())346    distinctAttrToNode.try_emplace(attr.getId(), node);347  return node;348}349 350llvm::DIModule *DebugTranslation::translateImpl(DIModuleAttr attr) {351  return llvm::DIModule::get(352      llvmCtx, translate(attr.getFile()), translate(attr.getScope()),353      getMDStringOrNull(attr.getName()),354      getMDStringOrNull(attr.getConfigMacros()),355      getMDStringOrNull(attr.getIncludePath()),356      getMDStringOrNull(attr.getApinotes()), attr.getLine(), attr.getIsDecl());357}358 359llvm::DINamespace *DebugTranslation::translateImpl(DINamespaceAttr attr) {360  return llvm::DINamespace::get(llvmCtx, translate(attr.getScope()),361                                getMDStringOrNull(attr.getName()),362                                attr.getExportSymbols());363}364 365llvm::DIImportedEntity *366DebugTranslation::translateImpl(DIImportedEntityAttr attr) {367  return llvm::DIImportedEntity::get(368      llvmCtx, attr.getTag(), translate(attr.getScope()),369      translate(attr.getEntity()), translate(attr.getFile()), attr.getLine(),370      getMDStringOrNull(attr.getName()), getMDTupleOrNull(attr.getElements()));371}372 373llvm::DISubrange *DebugTranslation::translateImpl(DISubrangeAttr attr) {374  auto getMetadataOrNull = [&](Attribute attr) -> llvm::Metadata * {375    if (!attr)376      return nullptr;377 378    llvm::Metadata *metadata =379        llvm::TypeSwitch<Attribute, llvm::Metadata *>(attr)380            .Case([&](IntegerAttr intAttr) {381              return llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(382                  llvm::Type::getInt64Ty(llvmCtx), intAttr.getInt()));383            })384            .Case([&](LLVM::DIExpressionAttr expr) {385              return translateExpression(expr);386            })387            .Case([&](LLVM::DILocalVariableAttr local) {388              return translate(local);389            })390            .Case<>([&](LLVM::DIGlobalVariableAttr global) {391              return translate(global);392            })393            .Default(nullptr);394    return metadata;395  };396  return llvm::DISubrange::get(llvmCtx, getMetadataOrNull(attr.getCount()),397                               getMetadataOrNull(attr.getLowerBound()),398                               getMetadataOrNull(attr.getUpperBound()),399                               getMetadataOrNull(attr.getStride()));400}401 402llvm::DICommonBlock *DebugTranslation::translateImpl(DICommonBlockAttr attr) {403  return llvm::DICommonBlock::get(llvmCtx, translate(attr.getScope()),404                                  translate(attr.getDecl()),405                                  getMDStringOrNull(attr.getName()),406                                  translate(attr.getFile()), attr.getLine());407}408 409llvm::DIGenericSubrange *410DebugTranslation::translateImpl(DIGenericSubrangeAttr attr) {411  auto getMetadataOrNull = [&](Attribute attr) -> llvm::Metadata * {412    if (!attr)413      return nullptr;414 415    llvm::Metadata *metadata =416        llvm::TypeSwitch<Attribute, llvm::Metadata *>(attr)417            .Case([&](LLVM::DIExpressionAttr expr) {418              return translateExpression(expr);419            })420            .Case([&](LLVM::DILocalVariableAttr local) {421              return translate(local);422            })423            .Case([&](LLVM::DIGlobalVariableAttr global) {424              return translate(global);425            })426            .Default(nullptr);427    return metadata;428  };429  return llvm::DIGenericSubrange::get(llvmCtx,430                                      getMetadataOrNull(attr.getCount()),431                                      getMetadataOrNull(attr.getLowerBound()),432                                      getMetadataOrNull(attr.getUpperBound()),433                                      getMetadataOrNull(attr.getStride()));434}435 436llvm::DISubroutineType *437DebugTranslation::translateImpl(DISubroutineTypeAttr attr) {438  // Concatenate the result and argument types into a single array.439  SmallVector<llvm::Metadata *> types;440  for (DITypeAttr type : attr.getTypes())441    types.push_back(translate(type));442  return llvm::DISubroutineType::get(443      llvmCtx, llvm::DINode::FlagZero, attr.getCallingConvention(),444      llvm::DITypeRefArray(llvm::MDNode::get(llvmCtx, types)));445}446 447llvm::DIType *DebugTranslation::translateImpl(DITypeAttr attr) {448  return cast<llvm::DIType>(translate(DINodeAttr(attr)));449}450 451llvm::DINode *DebugTranslation::translate(DINodeAttr attr) {452  if (!attr)453    return nullptr;454  // Check for a cached instance.455  if (llvm::DINode *node = attrToNode.lookup(attr))456    return node;457 458  llvm::DINode *node = nullptr;459  // Recursive types go through a dedicated handler. All other types are460  // dispatched directly to their specific handlers.461  if (auto recTypeAttr = dyn_cast<DIRecursiveTypeAttrInterface>(attr))462    if (recTypeAttr.getRecId())463      node = translateRecursive(recTypeAttr);464 465  if (!node)466    node = TypeSwitch<DINodeAttr, llvm::DINode *>(attr)467               .Case<DIBasicTypeAttr, DICommonBlockAttr, DICompileUnitAttr,468                     DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr,469                     DIGenericSubrangeAttr, DIGlobalVariableAttr,470                     DIImportedEntityAttr, DILabelAttr, DILexicalBlockAttr,471                     DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,472                     DINamespaceAttr, DINullTypeAttr, DIStringTypeAttr,473                     DISubprogramAttr, DISubrangeAttr, DISubroutineTypeAttr>(474                   [&](auto attr) { return translateImpl(attr); });475 476  if (node && !node->isTemporary())477    attrToNode.insert({attr, node});478  return node;479}480 481//===----------------------------------------------------------------------===//482// Locations483//===----------------------------------------------------------------------===//484 485/// Translate the given location to an llvm debug location.486llvm::DILocation *DebugTranslation::translateLoc(Location loc,487                                                 llvm::DILocalScope *scope) {488  if (!debugEmissionIsEnabled)489    return nullptr;490  return translateLoc(loc, scope, /*inlinedAt=*/nullptr);491}492 493llvm::DIExpression *494DebugTranslation::translateExpression(LLVM::DIExpressionAttr attr) {495  SmallVector<uint64_t, 1> ops;496  if (attr) {497    // Append operations their operands to the list.498    for (const DIExpressionElemAttr &op : attr.getOperations()) {499      ops.push_back(op.getOpcode());500      append_range(ops, op.getArguments());501    }502  }503  return llvm::DIExpression::get(llvmCtx, ops);504}505 506llvm::DIGlobalVariableExpression *507DebugTranslation::translateGlobalVariableExpression(508    LLVM::DIGlobalVariableExpressionAttr attr) {509  return llvm::DIGlobalVariableExpression::get(510      llvmCtx, translate(attr.getVar()), translateExpression(attr.getExpr()));511}512 513/// Translate the given location to an llvm DebugLoc.514llvm::DILocation *DebugTranslation::translateLoc(Location loc,515                                                 llvm::DILocalScope *scope,516                                                 llvm::DILocation *inlinedAt) {517  // LLVM doesn't have a representation for unknown.518  if (isa<UnknownLoc>(loc))519    return nullptr;520 521  // Check for a cached instance.522  auto existingIt = locationToLoc.find(std::make_tuple(loc, scope, inlinedAt));523  if (existingIt != locationToLoc.end())524    return existingIt->second;525 526  llvm::DILocation *llvmLoc = nullptr;527  if (auto callLoc = dyn_cast<CallSiteLoc>(loc)) {528    // For callsites, the caller is fed as the inlinedAt for the callee.529    auto *callerLoc = translateLoc(callLoc.getCaller(), scope, inlinedAt);530    // If the caller scope is not translatable, the overall callsite cannot be531    // represented in LLVM (the callee scope may not match the parent function).532    if (!callerLoc) {533      // If there is an inlinedAt scope (an outer caller), skip to that534      // directly. Otherwise, cannot translate.535      if (!inlinedAt)536        return nullptr;537      callerLoc = inlinedAt;538    }539    llvmLoc = translateLoc(callLoc.getCallee(), nullptr, callerLoc);540    // Fallback: Ignore callee if it has no debug scope.541    if (!llvmLoc)542      llvmLoc = callerLoc;543 544  } else if (auto fileLoc = dyn_cast<FileLineColLoc>(loc)) {545    // A scope of a DILocation cannot be null.546    if (!scope)547      return nullptr;548    llvmLoc =549        llvm::DILocation::get(llvmCtx, fileLoc.getLine(), fileLoc.getColumn(),550                              scope, const_cast<llvm::DILocation *>(inlinedAt));551 552  } else if (auto fusedLoc = dyn_cast<FusedLoc>(loc)) {553    ArrayRef<Location> locations = fusedLoc.getLocations();554 555    // Check for a scope encoded with the location.556    if (auto scopedAttr =557            dyn_cast_or_null<LLVM::DILocalScopeAttr>(fusedLoc.getMetadata()))558      scope = translate(scopedAttr);559 560    // For fused locations, merge each of the nodes.561    llvmLoc = translateLoc(locations.front(), scope, inlinedAt);562    for (Location locIt : locations.drop_front()) {563      llvmLoc = llvm::DILocation::getMergedLocation(564          llvmLoc, translateLoc(locIt, scope, inlinedAt));565    }566 567  } else if (auto nameLoc = dyn_cast<NameLoc>(loc)) {568    llvmLoc = translateLoc(nameLoc.getChildLoc(), scope, inlinedAt);569 570  } else if (auto opaqueLoc = dyn_cast<OpaqueLoc>(loc)) {571    llvmLoc = translateLoc(opaqueLoc.getFallbackLocation(), scope, inlinedAt);572  } else {573    llvm_unreachable("unknown location kind");574  }575 576  locationToLoc.try_emplace(std::make_tuple(loc, scope, inlinedAt), llvmLoc);577  return llvmLoc;578}579 580/// Create an llvm debug file for the given file path.581llvm::DIFile *DebugTranslation::translateFile(StringRef fileName) {582  auto *&file = fileMap[fileName];583  if (file)584    return file;585 586  // Make sure the current working directory is up-to-date.587  if (currentWorkingDir.empty())588    llvm::sys::fs::current_path(currentWorkingDir);589 590  StringRef directory = currentWorkingDir;591  SmallString<128> dirBuf;592  SmallString<128> fileBuf;593  if (llvm::sys::path::is_absolute(fileName)) {594    // Strip the common prefix (if it is more than just "/") from current595    // directory and FileName for a more space-efficient encoding.596    auto fileIt = llvm::sys::path::begin(fileName);597    auto fileE = llvm::sys::path::end(fileName);598    auto curDirIt = llvm::sys::path::begin(directory);599    auto curDirE = llvm::sys::path::end(directory);600    for (; curDirIt != curDirE && *curDirIt == *fileIt; ++curDirIt, ++fileIt)601      llvm::sys::path::append(dirBuf, *curDirIt);602    if (std::distance(llvm::sys::path::begin(directory), curDirIt) == 1) {603      // Don't strip the common prefix if it is only the root "/"  since that604      // would make LLVM diagnostic locations confusing.605      directory = StringRef();606    } else {607      for (; fileIt != fileE; ++fileIt)608        llvm::sys::path::append(fileBuf, *fileIt);609      directory = dirBuf;610      fileName = fileBuf;611    }612  }613  return (file = llvm::DIFile::get(llvmCtx, fileName, directory));614}615