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-exception 6 // 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 17 using namespace mlir; 18 using namespace mlir::LLVM; 19 using namespace mlir::LLVM::detail; 20 21 /// A utility walker that interrupts if the operation has valid debug 22 /// information. 23 static WalkResult interruptIfValidLocation(Operation *op) { 24 return isa<UnknownLoc>(op->getLoc()) ? WalkResult::advance() 25 : WalkResult::interrupt(); 26 } 27 28 DebugTranslation::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 // TODO: The version information should be encoded on the LLVM module itself, 37 // not implicitly set here. 38 39 // Mark this module as having debug information. 40 StringRef debugVersionKey = "Debug Info Version"; 41 if (!llvmModule.getModuleFlag(debugVersionKey)) 42 llvmModule.addModuleFlag(llvm::Module::Warning, debugVersionKey, 43 llvm::DEBUG_METADATA_VERSION); 44 45 if (auto targetTripleAttr = module->getDiscardableAttr( 46 LLVM::LLVMDialect::getTargetTripleAttrName())) { 47 auto targetTriple = 48 llvm::Triple(cast<StringAttr>(targetTripleAttr).getValue()); 49 if (targetTriple.isKnownWindowsMSVCEnvironment()) { 50 // Dwarf debugging files will be generated by default, unless "CodeView" 51 // is set explicitly. Windows/MSVC should use CodeView instead. 52 llvmModule.addModuleFlag(llvm::Module::Warning, "CodeView", 1); 53 } 54 } 55 } 56 57 /// Finalize the translation of debug information. 58 void DebugTranslation::finalize() {} 59 60 /// Translate the debug information for the given function. 61 void DebugTranslation::translate(LLVMFuncOp func, llvm::Function &llvmFunc) { 62 if (!debugEmissionIsEnabled) 63 return; 64 65 // Look for a sub program attached to the function. 66 auto spLoc = 67 func.getLoc()->findInstanceOf<FusedLocWith<LLVM::DISubprogramAttr>>(); 68 if (!spLoc) 69 return; 70 llvmFunc.setSubprogram(translate(spLoc.getMetadata())); 71 } 72 73 //===----------------------------------------------------------------------===// 74 // Attributes 75 //===----------------------------------------------------------------------===// 76 77 llvm::DIType *DebugTranslation::translateImpl(DINullTypeAttr attr) { 78 // A DINullTypeAttr at the beginning of the subroutine types list models 79 // a void result type. If it is at the end, it models a variadic function. 80 // Translate the explicit DINullTypeAttr to a nullptr since LLVM IR metadata 81 // does not have an explicit void result type nor a variadic type 82 // representation. 83 return nullptr; 84 } 85 86 llvm::DIExpression * 87 DebugTranslation::getExpressionAttrOrNull(DIExpressionAttr attr) { 88 if (!attr) 89 return nullptr; 90 return translateExpression(attr); 91 } 92 93 llvm::MDString *DebugTranslation::getMDStringOrNull(StringAttr stringAttr) { 94 if (!stringAttr || stringAttr.empty()) 95 return nullptr; 96 return llvm::MDString::get(llvmCtx, stringAttr); 97 } 98 99 llvm::MDTuple * 100 DebugTranslation::getMDTupleOrNull(ArrayRef<DINodeAttr> elements) { 101 if (elements.empty()) 102 return nullptr; 103 SmallVector<llvm::Metadata *> llvmElements = llvm::to_vector( 104 llvm::map_range(elements, [&](DINodeAttr attr) -> llvm::Metadata * { 105 if (DIAnnotationAttr annAttr = dyn_cast<DIAnnotationAttr>(attr)) { 106 llvm::Metadata *ops[2] = { 107 llvm::MDString::get(llvmCtx, annAttr.getName()), 108 llvm::MDString::get(llvmCtx, annAttr.getValue())}; 109 return llvm::MDNode::get(llvmCtx, ops); 110 } 111 return translate(attr); 112 })); 113 return llvm::MDNode::get(llvmCtx, llvmElements); 114 } 115 116 llvm::DIBasicType *DebugTranslation::translateImpl(DIBasicTypeAttr attr) { 117 return llvm::DIBasicType::get( 118 llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()), 119 attr.getSizeInBits(), 120 /*AlignInBits=*/0, attr.getEncoding(), llvm::DINode::FlagZero); 121 } 122 123 llvm::DICompileUnit *DebugTranslation::translateImpl(DICompileUnitAttr attr) { 124 llvm::DIBuilder builder(llvmModule); 125 return builder.createCompileUnit( 126 attr.getSourceLanguage(), translate(attr.getFile()), 127 attr.getProducer() ? attr.getProducer().getValue() : "", 128 attr.getIsOptimized(), 129 /*Flags=*/"", /*RV=*/0, /*SplitName=*/{}, 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 on 138 /// `isDistinct`. 139 template <class DINodeT, class... Ts> 140 static 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 146 llvm::TempDICompositeType 147 DebugTranslation::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, 155 /*VTableHolder=*/nullptr); 156 } 157 158 llvm::TempDISubprogram 159 DebugTranslation::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 169 llvm::DICompositeType * 170 DebugTranslation::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, /*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 199 llvm::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 209 llvm::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 218 llvm::DIFile *DebugTranslation::translateImpl(DIFileAttr attr) { 219 return llvm::DIFile::get(llvmCtx, getMDStringOrNull(attr.getName()), 220 getMDStringOrNull(attr.getDirectory())); 221 } 222 223 llvm::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 } 228 229 llvm::DILexicalBlock *DebugTranslation::translateImpl(DILexicalBlockAttr attr) { 230 return llvm::DILexicalBlock::getDistinct(llvmCtx, translate(attr.getScope()), 231 translate(attr.getFile()), 232 attr.getLine(), attr.getColumn()); 233 } 234 235 llvm::DILexicalBlockFile * 236 DebugTranslation::translateImpl(DILexicalBlockFileAttr attr) { 237 return llvm::DILexicalBlockFile::getDistinct( 238 llvmCtx, translate(attr.getScope()), translate(attr.getFile()), 239 attr.getDiscriminator()); 240 } 241 242 llvm::DILocalScope *DebugTranslation::translateImpl(DILocalScopeAttr attr) { 243 return cast<llvm::DILocalScope>(translate(DINodeAttr(attr))); 244 } 245 246 llvm::DIVariable *DebugTranslation::translateImpl(DIVariableAttr attr) { 247 return cast<llvm::DIVariable>(translate(DINodeAttr(attr))); 248 } 249 250 llvm::DILocalVariable * 251 DebugTranslation::translateImpl(DILocalVariableAttr attr) { 252 return llvm::DILocalVariable::get( 253 llvmCtx, translate(attr.getScope()), getMDStringOrNull(attr.getName()), 254 translate(attr.getFile()), attr.getLine(), translate(attr.getType()), 255 attr.getArg(), static_cast<llvm::DINode::DIFlags>(attr.getFlags()), 256 attr.getAlignInBits(), 257 /*Annotations=*/nullptr); 258 } 259 260 llvm::DIGlobalVariable * 261 DebugTranslation::translateImpl(DIGlobalVariableAttr attr) { 262 return llvm::DIGlobalVariable::getDistinct( 263 llvmCtx, translate(attr.getScope()), getMDStringOrNull(attr.getName()), 264 getMDStringOrNull(attr.getLinkageName()), translate(attr.getFile()), 265 attr.getLine(), translate(attr.getType()), attr.getIsLocalToUnit(), 266 attr.getIsDefined(), nullptr, nullptr, attr.getAlignInBits(), nullptr); 267 } 268 269 llvm::DINode * 270 DebugTranslation::translateRecursive(DIRecursiveTypeAttrInterface attr) { 271 DistinctAttr recursiveId = attr.getRecId(); 272 if (auto *iter = recursiveNodeMap.find(recursiveId); 273 iter != recursiveNodeMap.end()) { 274 return iter->second; 275 } 276 assert(!attr.getIsRecSelf() && "unbound DI recursive self reference"); 277 278 auto setRecursivePlaceholder = [&](llvm::DINode *placeholder) { 279 recursiveNodeMap.try_emplace(recursiveId, placeholder); 280 }; 281 282 llvm::DINode *result = 283 TypeSwitch<DIRecursiveTypeAttrInterface, llvm::DINode *>(attr) 284 .Case<DICompositeTypeAttr>([&](auto attr) { 285 auto temporary = translateTemporaryImpl(attr); 286 setRecursivePlaceholder(temporary.get()); 287 // Must call `translateImpl` directly instead of `translate` to 288 // avoid handling the recursive interface again. 289 auto *concrete = translateImpl(attr); 290 temporary->replaceAllUsesWith(concrete); 291 return concrete; 292 }) 293 .Case<DISubprogramAttr>([&](auto attr) { 294 auto temporary = translateTemporaryImpl(attr); 295 setRecursivePlaceholder(temporary.get()); 296 // Must call `translateImpl` directly instead of `translate` to 297 // avoid handling the recursive interface again. 298 auto *concrete = translateImpl(attr); 299 temporary->replaceAllUsesWith(concrete); 300 return concrete; 301 }); 302 303 assert(recursiveNodeMap.back().first == recursiveId && 304 "internal inconsistency: unexpected recursive translation stack"); 305 recursiveNodeMap.pop_back(); 306 307 return result; 308 } 309 310 llvm::DIScope *DebugTranslation::translateImpl(DIScopeAttr attr) { 311 return cast<llvm::DIScope>(translate(DINodeAttr(attr))); 312 } 313 314 llvm::DISubprogram *DebugTranslation::translateImpl(DISubprogramAttr attr) { 315 if (auto iter = distinctAttrToNode.find(attr.getId()); 316 iter != distinctAttrToNode.end()) 317 return cast<llvm::DISubprogram>(iter->second); 318 319 llvm::DIScope *scope = translate(attr.getScope()); 320 llvm::DIFile *file = translate(attr.getFile()); 321 llvm::DIType *type = translate(attr.getType()); 322 llvm::DICompileUnit *compileUnit = translate(attr.getCompileUnit()); 323 324 // Check again after recursive calls in case this distinct node recurses back 325 // to itself. 326 if (auto iter = distinctAttrToNode.find(attr.getId()); 327 iter != distinctAttrToNode.end()) 328 return cast<llvm::DISubprogram>(iter->second); 329 330 bool isDefinition = static_cast<bool>(attr.getSubprogramFlags() & 331 LLVM::DISubprogramFlags::Definition); 332 333 llvm::DISubprogram *node = getDistinctOrUnique<llvm::DISubprogram>( 334 isDefinition, llvmCtx, scope, getMDStringOrNull(attr.getName()), 335 getMDStringOrNull(attr.getLinkageName()), file, attr.getLine(), type, 336 attr.getScopeLine(), 337 /*ContainingType=*/nullptr, /*VirtualIndex=*/0, 338 /*ThisAdjustment=*/0, llvm::DINode::FlagZero, 339 static_cast<llvm::DISubprogram::DISPFlags>(attr.getSubprogramFlags()), 340 compileUnit, /*TemplateParams=*/nullptr, /*Declaration=*/nullptr, 341 getMDTupleOrNull(attr.getRetainedNodes()), nullptr, 342 getMDTupleOrNull(attr.getAnnotations())); 343 if (attr.getId()) 344 distinctAttrToNode.try_emplace(attr.getId(), node); 345 return node; 346 } 347 348 llvm::DIModule *DebugTranslation::translateImpl(DIModuleAttr attr) { 349 return llvm::DIModule::get( 350 llvmCtx, translate(attr.getFile()), translate(attr.getScope()), 351 getMDStringOrNull(attr.getName()), 352 getMDStringOrNull(attr.getConfigMacros()), 353 getMDStringOrNull(attr.getIncludePath()), 354 getMDStringOrNull(attr.getApinotes()), attr.getLine(), attr.getIsDecl()); 355 } 356 357 llvm::DINamespace *DebugTranslation::translateImpl(DINamespaceAttr attr) { 358 return llvm::DINamespace::get(llvmCtx, translate(attr.getScope()), 359 getMDStringOrNull(attr.getName()), 360 attr.getExportSymbols()); 361 } 362 363 llvm::DIImportedEntity * 364 DebugTranslation::translateImpl(DIImportedEntityAttr attr) { 365 return llvm::DIImportedEntity::get( 366 llvmCtx, attr.getTag(), translate(attr.getScope()), 367 translate(attr.getEntity()), translate(attr.getFile()), attr.getLine(), 368 getMDStringOrNull(attr.getName()), getMDTupleOrNull(attr.getElements())); 369 } 370 371 llvm::DISubrange *DebugTranslation::translateImpl(DISubrangeAttr attr) { 372 auto getMetadataOrNull = [&](Attribute attr) -> llvm::Metadata * { 373 if (!attr) 374 return nullptr; 375 376 llvm::Metadata *metadata = 377 llvm::TypeSwitch<Attribute, llvm::Metadata *>(attr) 378 .Case([&](IntegerAttr intAttr) { 379 return llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned( 380 llvm::Type::getInt64Ty(llvmCtx), intAttr.getInt())); 381 }) 382 .Case([&](LLVM::DIExpressionAttr expr) { 383 return translateExpression(expr); 384 }) 385 .Case([&](LLVM::DILocalVariableAttr local) { 386 return translate(local); 387 }) 388 .Case<>([&](LLVM::DIGlobalVariableAttr global) { 389 return translate(global); 390 }) 391 .Default([&](Attribute attr) { return nullptr; }); 392 return metadata; 393 }; 394 return llvm::DISubrange::get(llvmCtx, getMetadataOrNull(attr.getCount()), 395 getMetadataOrNull(attr.getLowerBound()), 396 getMetadataOrNull(attr.getUpperBound()), 397 getMetadataOrNull(attr.getStride())); 398 } 399 400 llvm::DICommonBlock *DebugTranslation::translateImpl(DICommonBlockAttr attr) { 401 return llvm::DICommonBlock::get(llvmCtx, translate(attr.getScope()), 402 translate(attr.getDecl()), 403 getMDStringOrNull(attr.getName()), 404 translate(attr.getFile()), attr.getLine()); 405 } 406 407 llvm::DIGenericSubrange * 408 DebugTranslation::translateImpl(DIGenericSubrangeAttr attr) { 409 auto getMetadataOrNull = [&](Attribute attr) -> llvm::Metadata * { 410 if (!attr) 411 return nullptr; 412 413 llvm::Metadata *metadata = 414 llvm::TypeSwitch<Attribute, llvm::Metadata *>(attr) 415 .Case([&](LLVM::DIExpressionAttr expr) { 416 return translateExpression(expr); 417 }) 418 .Case([&](LLVM::DILocalVariableAttr local) { 419 return translate(local); 420 }) 421 .Case<>([&](LLVM::DIGlobalVariableAttr global) { 422 return translate(global); 423 }) 424 .Default([&](Attribute attr) { return nullptr; }); 425 return metadata; 426 }; 427 return llvm::DIGenericSubrange::get(llvmCtx, 428 getMetadataOrNull(attr.getCount()), 429 getMetadataOrNull(attr.getLowerBound()), 430 getMetadataOrNull(attr.getUpperBound()), 431 getMetadataOrNull(attr.getStride())); 432 } 433 434 llvm::DISubroutineType * 435 DebugTranslation::translateImpl(DISubroutineTypeAttr attr) { 436 // Concatenate the result and argument types into a single array. 437 SmallVector<llvm::Metadata *> types; 438 for (DITypeAttr type : attr.getTypes()) 439 types.push_back(translate(type)); 440 return llvm::DISubroutineType::get( 441 llvmCtx, llvm::DINode::FlagZero, attr.getCallingConvention(), 442 llvm::DITypeRefArray(llvm::MDNode::get(llvmCtx, types))); 443 } 444 445 llvm::DIType *DebugTranslation::translateImpl(DITypeAttr attr) { 446 return cast<llvm::DIType>(translate(DINodeAttr(attr))); 447 } 448 449 llvm::DINode *DebugTranslation::translate(DINodeAttr attr) { 450 if (!attr) 451 return nullptr; 452 // Check for a cached instance. 453 if (llvm::DINode *node = attrToNode.lookup(attr)) 454 return node; 455 456 llvm::DINode *node = nullptr; 457 // Recursive types go through a dedicated handler. All other types are 458 // dispatched directly to their specific handlers. 459 if (auto recTypeAttr = dyn_cast<DIRecursiveTypeAttrInterface>(attr)) 460 if (recTypeAttr.getRecId()) 461 node = translateRecursive(recTypeAttr); 462 463 if (!node) 464 node = TypeSwitch<DINodeAttr, llvm::DINode *>(attr) 465 .Case<DIBasicTypeAttr, DICommonBlockAttr, DICompileUnitAttr, 466 DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr, 467 DIGenericSubrangeAttr, DIGlobalVariableAttr, 468 DIImportedEntityAttr, DILabelAttr, DILexicalBlockAttr, 469 DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr, 470 DINamespaceAttr, DINullTypeAttr, DIStringTypeAttr, 471 DISubprogramAttr, DISubrangeAttr, DISubroutineTypeAttr>( 472 [&](auto attr) { return translateImpl(attr); }); 473 474 if (node && !node->isTemporary()) 475 attrToNode.insert({attr, node}); 476 return node; 477 } 478 479 //===----------------------------------------------------------------------===// 480 // Locations 481 //===----------------------------------------------------------------------===// 482 483 /// Translate the given location to an llvm debug location. 484 llvm::DILocation *DebugTranslation::translateLoc(Location loc, 485 llvm::DILocalScope *scope) { 486 if (!debugEmissionIsEnabled) 487 return nullptr; 488 return translateLoc(loc, scope, /*inlinedAt=*/nullptr); 489 } 490 491 llvm::DIExpression * 492 DebugTranslation::translateExpression(LLVM::DIExpressionAttr attr) { 493 SmallVector<uint64_t, 1> ops; 494 if (attr) { 495 // Append operations their operands to the list. 496 for (const DIExpressionElemAttr &op : attr.getOperations()) { 497 ops.push_back(op.getOpcode()); 498 append_range(ops, op.getArguments()); 499 } 500 } 501 return llvm::DIExpression::get(llvmCtx, ops); 502 } 503 504 llvm::DIGlobalVariableExpression * 505 DebugTranslation::translateGlobalVariableExpression( 506 LLVM::DIGlobalVariableExpressionAttr attr) { 507 return llvm::DIGlobalVariableExpression::get( 508 llvmCtx, translate(attr.getVar()), translateExpression(attr.getExpr())); 509 } 510 511 /// Translate the given location to an llvm DebugLoc. 512 llvm::DILocation *DebugTranslation::translateLoc(Location loc, 513 llvm::DILocalScope *scope, 514 llvm::DILocation *inlinedAt) { 515 // LLVM doesn't have a representation for unknown. 516 if (isa<UnknownLoc>(loc)) 517 return nullptr; 518 519 // Check for a cached instance. 520 auto existingIt = locationToLoc.find(std::make_tuple(loc, scope, inlinedAt)); 521 if (existingIt != locationToLoc.end()) 522 return existingIt->second; 523 524 llvm::DILocation *llvmLoc = nullptr; 525 if (auto callLoc = dyn_cast<CallSiteLoc>(loc)) { 526 // For callsites, the caller is fed as the inlinedAt for the callee. 527 auto *callerLoc = translateLoc(callLoc.getCaller(), scope, inlinedAt); 528 // If the caller scope is not translatable, the overall callsite cannot be 529 // represented in LLVM (the callee scope may not match the parent function). 530 if (!callerLoc) { 531 // If there is an inlinedAt scope (an outer caller), skip to that 532 // directly. Otherwise, cannot translate. 533 if (!inlinedAt) 534 return nullptr; 535 callerLoc = inlinedAt; 536 } 537 llvmLoc = translateLoc(callLoc.getCallee(), nullptr, callerLoc); 538 // Fallback: Ignore callee if it has no debug scope. 539 if (!llvmLoc) 540 llvmLoc = callerLoc; 541 542 } else if (auto fileLoc = dyn_cast<FileLineColLoc>(loc)) { 543 // A scope of a DILocation cannot be null. 544 if (!scope) 545 return nullptr; 546 llvmLoc = 547 llvm::DILocation::get(llvmCtx, fileLoc.getLine(), fileLoc.getColumn(), 548 scope, const_cast<llvm::DILocation *>(inlinedAt)); 549 550 } else if (auto fusedLoc = dyn_cast<FusedLoc>(loc)) { 551 ArrayRef<Location> locations = fusedLoc.getLocations(); 552 553 // Check for a scope encoded with the location. 554 if (auto scopedAttr = 555 dyn_cast_or_null<LLVM::DILocalScopeAttr>(fusedLoc.getMetadata())) 556 scope = translate(scopedAttr); 557 558 // For fused locations, merge each of the nodes. 559 llvmLoc = translateLoc(locations.front(), scope, inlinedAt); 560 for (Location locIt : locations.drop_front()) { 561 llvmLoc = llvm::DILocation::getMergedLocation( 562 llvmLoc, translateLoc(locIt, scope, inlinedAt)); 563 } 564 565 } else if (auto nameLoc = dyn_cast<NameLoc>(loc)) { 566 llvmLoc = translateLoc(nameLoc.getChildLoc(), scope, inlinedAt); 567 568 } else if (auto opaqueLoc = dyn_cast<OpaqueLoc>(loc)) { 569 llvmLoc = translateLoc(opaqueLoc.getFallbackLocation(), scope, inlinedAt); 570 } else { 571 llvm_unreachable("unknown location kind"); 572 } 573 574 locationToLoc.try_emplace(std::make_tuple(loc, scope, inlinedAt), llvmLoc); 575 return llvmLoc; 576 } 577 578 /// Create an llvm debug file for the given file path. 579 llvm::DIFile *DebugTranslation::translateFile(StringRef fileName) { 580 auto *&file = fileMap[fileName]; 581 if (file) 582 return file; 583 584 // Make sure the current working directory is up-to-date. 585 if (currentWorkingDir.empty()) 586 llvm::sys::fs::current_path(currentWorkingDir); 587 588 StringRef directory = currentWorkingDir; 589 SmallString<128> dirBuf; 590 SmallString<128> fileBuf; 591 if (llvm::sys::path::is_absolute(fileName)) { 592 // Strip the common prefix (if it is more than just "/") from current 593 // directory and FileName for a more space-efficient encoding. 594 auto fileIt = llvm::sys::path::begin(fileName); 595 auto fileE = llvm::sys::path::end(fileName); 596 auto curDirIt = llvm::sys::path::begin(directory); 597 auto curDirE = llvm::sys::path::end(directory); 598 for (; curDirIt != curDirE && *curDirIt == *fileIt; ++curDirIt, ++fileIt) 599 llvm::sys::path::append(dirBuf, *curDirIt); 600 if (std::distance(llvm::sys::path::begin(directory), curDirIt) == 1) { 601 // Don't strip the common prefix if it is only the root "/" since that 602 // would make LLVM diagnostic locations confusing. 603 directory = StringRef(); 604 } else { 605 for (; fileIt != fileE; ++fileIt) 606 llvm::sys::path::append(fileBuf, *fileIt); 607 directory = dirBuf; 608 fileName = fileBuf; 609 } 610 } 611 return (file = llvm::DIFile::get(llvmCtx, fileName, directory)); 612 } 613