14#include "llvm/ADT/STLExtras.h"
15#include "llvm/ADT/TypeSwitch.h"
16#include "llvm/BinaryFormat/Dwarf.h"
17#include "llvm/IR/Constants.h"
18#include "llvm/IR/DebugInfoMetadata.h"
19#include "llvm/IR/Metadata.h"
26 bool dropDICompositeTypeElements)
27 : cache([&](
llvm::DINode *node) {
return createRecSelf(node); }),
28 context(mlirModule.getContext()), mlirModule(mlirModule),
29 dropDICompositeTypeElements(dropDICompositeTypeElements) {}
32 llvm::DISubprogram *subprogram =
func->getSubprogram();
34 return UnknownLoc::get(context);
37 StringAttr fileName = StringAttr::get(context, subprogram->getFilename());
47DIBasicTypeAttr DebugImporter::translateImpl(llvm::DIBasicType *node) {
48 return DIBasicTypeAttr::get(context, node->getTag(),
49 getStringAttrOrNull(node->getRawName()),
50 node->getSizeInBits(), node->getEncoding());
53DICompileUnitAttr DebugImporter::translateImpl(llvm::DICompileUnit *node) {
54 std::optional<DIEmissionKind> emissionKind =
55 symbolizeDIEmissionKind(node->getEmissionKind());
56 std::optional<DINameTableKind> nameTableKind = symbolizeDINameTableKind(
58 std::underlying_type_t<llvm::DICompileUnit::DebugNameTableKind>
>(
59 node->getNameTableKind()));
61 if (node->getImportedEntities()) {
62 for (llvm::DIImportedEntity *importedEntity : node->getImportedEntities())
64 translate(
static_cast<llvm::DINode *
>(importedEntity)))
65 imports.push_back(nodeAttr);
67 llvm::DISourceLanguageName sourceLanguage = node->getSourceLanguage();
68 DISourceLanguageNameAttr sourceLanguageAttr;
69 if (sourceLanguage.hasVersionedName()) {
70 sourceLanguageAttr = DISourceLanguageNameAttr::get(
71 context, 0, sourceLanguage.getName(),
72 sourceLanguage.getVersion(), sourceLanguage.getDialect());
74 sourceLanguageAttr = DISourceLanguageNameAttr::get(
75 context, sourceLanguage.getName(), 0,
76 std::nullopt, sourceLanguage.getDialect());
78 return DICompileUnitAttr::get(
79 context, DistinctAttr{},
false,
80 getOrCreateDistinctID(node), sourceLanguageAttr,
81 translate(node->getFile()), getStringAttrOrNull(node->getRawProducer()),
82 node->isOptimized(), emissionKind.value(),
83 node->isDebugInfoForProfiling(), nameTableKind.value(),
84 getStringAttrOrNull(node->getRawSplitDebugFilename()), imports);
87DICompositeTypeAttr DebugImporter::translateImpl(llvm::DICompositeType *node) {
88 std::optional<DIFlags> flags = symbolizeDIFlags(node->getFlags());
89 SmallVector<DINodeAttr> elements;
92 bool isVectorType = flags && bitEnumContainsAll(*flags, DIFlags::Vector);
93 if (isVectorType || !dropDICompositeTypeElements) {
94 for (llvm::DINode *element : node->getElements()) {
95 assert(element &&
"expected a non-null element type");
100 if (llvm::is_contained(elements,
nullptr))
102 DITypeAttr baseType =
translate(node->getBaseType());
105 if (node->getTag() == llvm::dwarf::DW_TAG_array_type && !baseType)
107 return DICompositeTypeAttr::get(
108 context, node->getTag(), getStringAttrOrNull(node->getRawName()),
110 baseType, flags.value_or(DIFlags::Zero), node->getSizeInBits(),
115 getStringAttrOrNull(node->getRawIdentifier()),
116 translate(node->getDiscriminator()), elements);
119DIDerivedTypeAttr DebugImporter::translateImpl(llvm::DIDerivedType *node) {
121 DITypeAttr baseType =
translate(node->getBaseType());
122 if (node->getBaseType() && !baseType)
124 llvm::Metadata *rawExtraData = node->getExtraData();
126 if (
auto *extraDataNode = dyn_cast_or_null<llvm::DINode>(rawExtraData)) {
128 }
else if (
auto *constantAsMetadata =
129 dyn_cast_or_null<llvm::ConstantAsMetadata>(rawExtraData)) {
130 if (
auto *constantInt =
131 dyn_cast<llvm::ConstantInt>(constantAsMetadata->getValue())) {
132 const APInt &value = constantInt->getValue();
133 extraData = IntegerAttr::get(
134 IntegerType::get(context, value.getBitWidth()), value);
137 return DIDerivedTypeAttr::get(
138 context, node->getTag(), getStringAttrOrNull(node->getRawName()),
140 baseType, node->getSizeInBits(), node->getAlignInBits(),
141 node->getOffsetInBits(), node->getDWARFAddressSpace(),
142 symbolizeDIFlags(node->getFlags()).value_or(DIFlags::Zero), extraData);
145DIStringTypeAttr DebugImporter::translateImpl(llvm::DIStringType *node) {
146 return DIStringTypeAttr::get(
147 context, node->getTag(), getStringAttrOrNull(node->getRawName()),
148 node->getSizeInBits(), node->getAlignInBits(),
154DIFileAttr DebugImporter::translateImpl(llvm::DIFile *node) {
155 return DIFileAttr::get(context, node->getFilename(), node->getDirectory());
158DILabelAttr DebugImporter::translateImpl(llvm::DILabel *node) {
160 DIScopeAttr scope =
translate(node->getScope());
161 if (node->getScope() && !scope)
163 return DILabelAttr::get(context, scope,
164 getStringAttrOrNull(node->getRawName()),
165 translate(node->getFile()), node->getLine());
168DILexicalBlockAttr DebugImporter::translateImpl(llvm::DILexicalBlock *node) {
170 DIScopeAttr scope =
translate(node->getScope());
171 if (node->getScope() && !scope)
173 return DILexicalBlockAttr::get(context, scope,
translate(node->getFile()),
174 node->getLine(), node->getColumn());
177DILexicalBlockFileAttr
178DebugImporter::translateImpl(llvm::DILexicalBlockFile *node) {
180 DIScopeAttr scope =
translate(node->getScope());
181 if (node->getScope() && !scope)
183 return DILexicalBlockFileAttr::get(context, scope,
translate(node->getFile()),
184 node->getDiscriminator());
188DebugImporter::translateImpl(llvm::DIGlobalVariable *node) {
191 auto convertToStringAttr = [&](StringRef name) -> StringAttr {
194 return StringAttr::get(context, node->getName());
196 return DIGlobalVariableAttr::get(
198 convertToStringAttr(node->getName()),
199 convertToStringAttr(node->getLinkageName()),
translate(node->getFile()),
200 node->getLine(),
translate(node->getType()), node->isLocalToUnit(),
201 node->isDefinition(), node->getAlignInBits());
204DILocalVariableAttr DebugImporter::translateImpl(llvm::DILocalVariable *node) {
206 DIScopeAttr scope =
translate(node->getScope());
207 if (node->getScope() && !scope)
209 return DILocalVariableAttr::get(
210 context, scope, getStringAttrOrNull(node->getRawName()),
211 translate(node->getFile()), node->getLine(), node->getArg(),
212 node->getAlignInBits(),
translate(node->getType()),
213 symbolizeDIFlags(node->getFlags()).value_or(DIFlags::Zero));
216DIVariableAttr DebugImporter::translateImpl(llvm::DIVariable *node) {
217 return cast<DIVariableAttr>(
translate(
static_cast<llvm::DINode *
>(node)));
220DIScopeAttr DebugImporter::translateImpl(llvm::DIScope *node) {
221 return cast<DIScopeAttr>(
translate(
static_cast<llvm::DINode *
>(node)));
224DIModuleAttr DebugImporter::translateImpl(llvm::DIModule *node) {
225 return DIModuleAttr::get(
227 getStringAttrOrNull(node->getRawName()),
228 getStringAttrOrNull(node->getRawConfigurationMacros()),
229 getStringAttrOrNull(node->getRawIncludePath()),
230 getStringAttrOrNull(node->getRawAPINotesFile()), node->getLineNo(),
234DINamespaceAttr DebugImporter::translateImpl(llvm::DINamespace *node) {
235 return DINamespaceAttr::get(context, getStringAttrOrNull(node->getRawName()),
237 node->getExportSymbols());
241DebugImporter::translateImpl(llvm::DIImportedEntity *node) {
242 SmallVector<DINodeAttr> elements;
243 for (llvm::DINode *element : node->getElements()) {
244 assert(element &&
"expected a non-null element type");
248 return DIImportedEntityAttr::get(
249 context, node->getTag(),
translate(node->getScope()),
251 getStringAttrOrNull(node->getRawName()), elements);
254DISubprogramAttr DebugImporter::translateImpl(llvm::DISubprogram *node) {
256 mlir::DistinctAttr id;
257 if (node->isDistinct())
258 id = getOrCreateDistinctID(node);
261 DIScopeAttr scope =
translate(node->getScope());
262 if (node->getScope() && !scope)
264 std::optional<DISubprogramFlags> subprogramFlags =
265 symbolizeDISubprogramFlags(node->getSubprogram()->getSPFlags());
266 assert(subprogramFlags &&
"expected valid subprogram flags");
267 DISubroutineTypeAttr type =
translate(node->getType());
268 if (node->getType() && !type)
272 SmallVector<Attribute> retainedNodes;
273 auto add = [
this, &retainedNodes](llvm::DINode *retainedNode) {
274 retainedNodes.push_back(
translate(retainedNode));
276 auto addGVE = [](llvm::DIGlobalVariableExpression *GVE) {
281 if (llvm::is_contained(retainedNodes,
nullptr))
282 retainedNodes.clear();
284 SmallVector<DINodeAttr> annotations;
288 if (llvm::DINodeArray rawAnns = node->getAnnotations(); rawAnns) {
289 for (
size_t i = 0, e = rawAnns->getNumOperands(); i < e; ++i) {
290 const llvm::MDTuple *tuple = cast<llvm::MDTuple>(rawAnns->getOperand(i));
291 if (tuple->getNumOperands() != 2)
293 const llvm::MDString *name = cast<llvm::MDString>(tuple->getOperand(0));
294 const llvm::MDString *value =
295 dyn_cast<llvm::MDString>(tuple->getOperand(1));
297 annotations.push_back(DIAnnotationAttr::get(
298 context, StringAttr::get(context, name->getString()),
299 StringAttr::get(context, value->getString())));
304 return DISubprogramAttr::get(context,
id,
translate(node->getUnit()), scope,
305 getStringAttrOrNull(node->getRawName()),
306 getStringAttrOrNull(node->getRawLinkageName()),
307 translate(node->getFile()), node->getLine(),
308 node->getScopeLine(), *subprogramFlags, type,
309 retainedNodes, annotations);
312DISubrangeAttr DebugImporter::translateImpl(llvm::DISubrange *node) {
313 auto getAttrOrNull = [&](llvm::DISubrange::BoundType data) -> Attribute {
316 if (
auto *constInt = dyn_cast<llvm::ConstantInt *>(data))
317 return IntegerAttr::get(IntegerType::get(context, 64),
318 constInt->getSExtValue());
319 if (
auto *expr = dyn_cast<llvm::DIExpression *>(data))
321 if (
auto *var = dyn_cast<llvm::DIVariable *>(data)) {
322 if (
auto *local = dyn_cast<llvm::DILocalVariable>(var))
324 if (
auto *global = dyn_cast<llvm::DIGlobalVariable>(var))
330 Attribute count = getAttrOrNull(node->getCount());
331 Attribute upperBound = getAttrOrNull(node->getUpperBound());
334 if (!count && !upperBound)
336 return DISubrangeAttr::get(context, count,
337 getAttrOrNull(node->getLowerBound()), upperBound,
338 getAttrOrNull(node->getStride()));
341DICommonBlockAttr DebugImporter::translateImpl(llvm::DICommonBlock *node) {
342 return DICommonBlockAttr::get(context,
translate(node->getScope()),
344 getStringAttrOrNull(node->getRawName()),
345 translate(node->getFile()), node->getLineNo());
349DebugImporter::translateImpl(llvm::DIGenericSubrange *node) {
351 [&](llvm::DIGenericSubrange::BoundType data) -> Attribute {
354 if (
auto *expr = dyn_cast<llvm::DIExpression *>(data))
356 if (
auto *var = dyn_cast<llvm::DIVariable *>(data)) {
357 if (
auto *local = dyn_cast<llvm::DILocalVariable>(var))
359 if (
auto *global = dyn_cast<llvm::DIGlobalVariable>(var))
365 Attribute count = getAttrOrNull(node->getCount());
366 Attribute upperBound = getAttrOrNull(node->getUpperBound());
367 Attribute lowerBound = getAttrOrNull(node->getLowerBound());
368 Attribute stride = getAttrOrNull(node->getStride());
371 if (!count && !upperBound)
373 return DIGenericSubrangeAttr::get(context, count, lowerBound, upperBound,
378DebugImporter::translateImpl(llvm::DISubroutineType *node) {
379 SmallVector<DITypeAttr> types;
380 for (llvm::DIType *type : node->getTypeArray()) {
386 types.push_back(DINullTypeAttr::get(context));
392 if (llvm::is_contained(types,
nullptr))
394 return DISubroutineTypeAttr::get(context, node->getCC(), types);
397DITypeAttr DebugImporter::translateImpl(llvm::DIType *node) {
398 return cast<DITypeAttr>(
translate(
static_cast<llvm::DINode *
>(node)));
406 auto cacheEntry = cache.lookupOrInit(node);
407 if (std::optional<DINodeAttr>
result = cacheEntry.get())
411 auto translateNode = [
this](llvm::DINode *node) ->
DINodeAttr {
412 if (
auto *casted = dyn_cast<llvm::DIBasicType>(node))
413 return translateImpl(casted);
414 if (
auto *casted = dyn_cast<llvm::DICommonBlock>(node))
415 return translateImpl(casted);
416 if (
auto *casted = dyn_cast<llvm::DICompileUnit>(node))
417 return translateImpl(casted);
418 if (
auto *casted = dyn_cast<llvm::DICompositeType>(node))
419 return translateImpl(casted);
420 if (
auto *casted = dyn_cast<llvm::DIDerivedType>(node))
421 return translateImpl(casted);
422 if (
auto *casted = dyn_cast<llvm::DIStringType>(node))
423 return translateImpl(casted);
424 if (
auto *casted = dyn_cast<llvm::DIFile>(node))
425 return translateImpl(casted);
426 if (
auto *casted = dyn_cast<llvm::DIGlobalVariable>(node))
427 return translateImpl(casted);
428 if (
auto *casted = dyn_cast<llvm::DIImportedEntity>(node))
429 return translateImpl(casted);
430 if (
auto *casted = dyn_cast<llvm::DILabel>(node))
431 return translateImpl(casted);
432 if (
auto *casted = dyn_cast<llvm::DILexicalBlock>(node))
433 return translateImpl(casted);
434 if (
auto *casted = dyn_cast<llvm::DILexicalBlockFile>(node))
435 return translateImpl(casted);
436 if (
auto *casted = dyn_cast<llvm::DILocalVariable>(node))
437 return translateImpl(casted);
438 if (
auto *casted = dyn_cast<llvm::DIModule>(node))
439 return translateImpl(casted);
440 if (
auto *casted = dyn_cast<llvm::DINamespace>(node))
441 return translateImpl(casted);
442 if (
auto *casted = dyn_cast<llvm::DISubprogram>(node))
443 return translateImpl(casted);
444 if (
auto *casted = dyn_cast<llvm::DISubrange>(node))
445 return translateImpl(casted);
446 if (
auto *casted = dyn_cast<llvm::DIGenericSubrange>(node))
447 return translateImpl(casted);
448 if (
auto *casted = dyn_cast<llvm::DISubroutineType>(node))
449 return translateImpl(casted);
455 if (cacheEntry.wasRepeated()) {
457 auto recType = cast<DIRecursiveTypeAttrInterface>(attr);
458 attr = cast<DINodeAttr>(recType.withRecId(recId));
460 cacheEntry.resolve(attr);
463 cacheEntry.resolve(
nullptr);
474 .Case([&](llvm::DICompositeType *) {
475 return CtorType(DICompositeTypeAttr::getRecSelf);
477 .Case([&](llvm::DISubprogram *) {
478 return CtorType(DISubprogramAttr::getRecSelf);
480 .Case([&](llvm::DICompileUnit *) {
481 return CtorType(DICompileUnitAttr::getRecSelf);
483 .Default(CtorType());
486std::optional<DINodeAttr> DebugImporter::createRecSelf(llvm::DINode *node) {
493 DistinctAttr recId = nodeToRecId.lookup(node);
496 nodeToRecId[node] = recId;
498 DIRecursiveTypeAttrInterface recSelf = recSelfCtor(recId);
499 return cast<DINodeAttr>(recSelf);
508 return UnknownLoc::get(context);
512 loc->getLine(), loc->getColumn());
515 assert(loc->getScope() &&
"expected non-null scope");
520 if (llvm::DILocation *inlinedAt = loc->getInlinedAt())
533 for (
const llvm::DIExpression::ExprOperand &op : node->expr_ops()) {
535 operands.reserve(op.getNumArgs());
536 for (
const auto &i : llvm::seq(op.getNumArgs()))
537 operands.push_back(op.getArg(i));
538 const auto attr = DIExpressionElemAttr::get(context, op.getOp(), operands);
541 return DIExpressionAttr::get(context, ops);
545 llvm::DIGlobalVariableExpression *node) {
546 return DIGlobalVariableExpressionAttr::get(
551StringAttr DebugImporter::getStringAttrOrNull(llvm::MDString *stringNode) {
554 return StringAttr::get(context, stringNode->getString());
557DistinctAttr DebugImporter::getOrCreateDistinctID(llvm::DINode *node) {
static function_ref< DIRecursiveTypeAttrInterface(DistinctAttr)> getRecSelfConstructor(llvm::DINode *node)
Get the getRecSelf constructor for the translated node if it participates in CyclicReplacerCache cycl...
An attribute that associates a referenced attribute with a unique identifier.
static DistinctAttr create(Attribute referencedAttr)
Creates a distinct attribute that associates a referenced attribute with a unique identifier.
static FileLineColLoc get(StringAttr filename, unsigned line, unsigned column)
This class represents a fused location whose metadata is known to be an instance of the given type.
This class represents the base attribute for all debug info attributes.
DINodeAttr translate(llvm::DINode *node)
Translates the given LLVM debug metadata to MLIR.
DIExpressionAttr translateExpression(llvm::DIExpression *node)
Translates the LLVM DWARF expression metadata to MLIR.
DIGlobalVariableExpressionAttr translateGlobalVariableExpression(llvm::DIGlobalVariableExpression *node)
Translates the LLVM DWARF global variable expression metadata to MLIR.
Location translateLoc(llvm::DILocation *loc)
Translates the given LLVM debug location to an MLIR location.
Location translateFuncLocation(llvm::Function *func)
Translates the debug information for the given function into a Location.
DebugImporter(ModuleOp mlirModule, bool dropDICompositeTypeElements)
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Include the generated interface declarations.
llvm::TypeSwitch< T, ResultT > TypeSwitch
llvm::function_ref< Fn > function_ref