MLIR 24.0.0git
DebugImporter.cpp
Go to the documentation of this file.
1//===- DebugImporter.cpp - LLVM to MLIR 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 "DebugImporter.h"
11#include "mlir/IR/Attributes.h"
13#include "mlir/IR/Location.h"
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"
20
21using namespace mlir;
22using namespace mlir::LLVM;
23using namespace mlir::LLVM::detail;
24
25DebugImporter::DebugImporter(ModuleOp mlirModule,
26 bool dropDICompositeTypeElements)
27 : cache([&](llvm::DINode *node) { return createRecSelf(node); }),
28 context(mlirModule.getContext()), mlirModule(mlirModule),
29 dropDICompositeTypeElements(dropDICompositeTypeElements) {}
30
32 llvm::DISubprogram *subprogram = func->getSubprogram();
33 if (!subprogram)
34 return UnknownLoc::get(context);
35
36 // Add a fused location to link the subprogram information.
37 StringAttr fileName = StringAttr::get(context, subprogram->getFilename());
39 {FileLineColLoc::get(fileName, subprogram->getLine(), /*column=*/0)},
40 translate(subprogram), context);
41}
42
43//===----------------------------------------------------------------------===//
44// Attributes
45//===----------------------------------------------------------------------===//
46
47DIBasicTypeAttr DebugImporter::translateImpl(llvm::DIBasicType *node) {
48 return DIBasicTypeAttr::get(context, node->getTag(),
49 getStringAttrOrNull(node->getRawName()),
50 node->getSizeInBits(), node->getEncoding());
51}
52
53DICompileUnitAttr DebugImporter::translateImpl(llvm::DICompileUnit *node) {
54 std::optional<DIEmissionKind> emissionKind =
55 symbolizeDIEmissionKind(node->getEmissionKind());
56 std::optional<DINameTableKind> nameTableKind = symbolizeDINameTableKind(
57 static_cast<
58 std::underlying_type_t<llvm::DICompileUnit::DebugNameTableKind>>(
59 node->getNameTableKind()));
61 if (node->getImportedEntities()) {
62 for (llvm::DIImportedEntity *importedEntity : node->getImportedEntities())
63 if (DINodeAttr nodeAttr =
64 translate(static_cast<llvm::DINode *>(importedEntity)))
65 imports.push_back(nodeAttr);
66 }
67 llvm::DISourceLanguageName sourceLanguage = node->getSourceLanguage();
68 DISourceLanguageNameAttr sourceLanguageAttr;
69 if (sourceLanguage.hasVersionedName()) {
70 sourceLanguageAttr = DISourceLanguageNameAttr::get(
71 context, /*language=*/0, sourceLanguage.getName(),
72 sourceLanguage.getVersion(), sourceLanguage.getDialect());
73 } else {
74 sourceLanguageAttr = DISourceLanguageNameAttr::get(
75 context, sourceLanguage.getName(), /*name=*/0,
76 /*version=*/std::nullopt, sourceLanguage.getDialect());
77 }
78 return DICompileUnitAttr::get(
79 context, /*recId=*/DistinctAttr{}, /*isRecSelf=*/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);
85}
86
87DICompositeTypeAttr DebugImporter::translateImpl(llvm::DICompositeType *node) {
88 std::optional<DIFlags> flags = symbolizeDIFlags(node->getFlags());
89 SmallVector<DINodeAttr> elements;
90
91 // A vector always requires an element.
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");
96 elements.push_back(translate(element));
97 }
98 }
99 // Drop the elements parameter if any of the elements are invalid.
100 if (llvm::is_contained(elements, nullptr))
101 elements.clear();
102 DITypeAttr baseType = translate(node->getBaseType());
103 // Arrays require a base type, otherwise the debug metadata is considered to
104 // be malformed.
105 if (node->getTag() == llvm::dwarf::DW_TAG_array_type && !baseType)
106 return nullptr;
107 return DICompositeTypeAttr::get(
108 context, node->getTag(), getStringAttrOrNull(node->getRawName()),
109 translate(node->getFile()), node->getLine(), translate(node->getScope()),
110 baseType, flags.value_or(DIFlags::Zero), node->getSizeInBits(),
111 node->getAlignInBits(), translateExpression(node->getDataLocationExp()),
112 translateExpression(node->getRankExp()),
113 translateExpression(node->getAllocatedExp()),
114 translateExpression(node->getAssociatedExp()),
115 getStringAttrOrNull(node->getRawIdentifier()),
116 translate(node->getDiscriminator()), elements);
117}
118
119DIDerivedTypeAttr DebugImporter::translateImpl(llvm::DIDerivedType *node) {
120 // Return nullptr if the base type is invalid.
121 DITypeAttr baseType = translate(node->getBaseType());
122 if (node->getBaseType() && !baseType)
123 return nullptr;
124 llvm::Metadata *rawExtraData = node->getExtraData();
125 Attribute extraData;
126 if (auto *extraDataNode = dyn_cast_or_null<llvm::DINode>(rawExtraData)) {
127 extraData = translate(extraDataNode);
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);
135 }
136 }
137 return DIDerivedTypeAttr::get(
138 context, node->getTag(), getStringAttrOrNull(node->getRawName()),
139 translate(node->getFile()), node->getLine(), translate(node->getScope()),
140 baseType, node->getSizeInBits(), node->getAlignInBits(),
141 node->getOffsetInBits(), node->getDWARFAddressSpace(),
142 symbolizeDIFlags(node->getFlags()).value_or(DIFlags::Zero), extraData);
143}
144
145DIStringTypeAttr DebugImporter::translateImpl(llvm::DIStringType *node) {
146 return DIStringTypeAttr::get(
147 context, node->getTag(), getStringAttrOrNull(node->getRawName()),
148 node->getSizeInBits(), node->getAlignInBits(),
149 translate(node->getStringLength()),
150 translateExpression(node->getStringLengthExp()),
151 translateExpression(node->getStringLocationExp()), node->getEncoding(),
152 translate(node->getCharType()));
153}
154
155DIFileAttr DebugImporter::translateImpl(llvm::DIFile *node) {
156 return DIFileAttr::get(context, node->getFilename(), node->getDirectory());
157}
158
159DILabelAttr DebugImporter::translateImpl(llvm::DILabel *node) {
160 // Return nullptr if the scope or type is a cyclic dependency.
161 DIScopeAttr scope = translate(node->getScope());
162 if (node->getScope() && !scope)
163 return nullptr;
164 return DILabelAttr::get(context, scope,
165 getStringAttrOrNull(node->getRawName()),
166 translate(node->getFile()), node->getLine());
167}
168
169DILexicalBlockAttr DebugImporter::translateImpl(llvm::DILexicalBlock *node) {
170 // Return nullptr if the scope or type is a cyclic dependency.
171 DIScopeAttr scope = translate(node->getScope());
172 if (node->getScope() && !scope)
173 return nullptr;
174 return DILexicalBlockAttr::get(context, scope, translate(node->getFile()),
175 node->getLine(), node->getColumn());
176}
177
178DILexicalBlockFileAttr
179DebugImporter::translateImpl(llvm::DILexicalBlockFile *node) {
180 // Return nullptr if the scope or type is a cyclic dependency.
181 DIScopeAttr scope = translate(node->getScope());
182 if (node->getScope() && !scope)
183 return nullptr;
184 return DILexicalBlockFileAttr::get(context, scope, translate(node->getFile()),
185 node->getDiscriminator());
186}
187
188DIGlobalVariableAttr
189DebugImporter::translateImpl(llvm::DIGlobalVariable *node) {
190 // Names of DIGlobalVariables can be empty. MLIR models them as null, instead
191 // of empty strings, so this special handling is necessary.
192 auto convertToStringAttr = [&](StringRef name) -> StringAttr {
193 if (name.empty())
194 return {};
195 return StringAttr::get(context, node->getName());
196 };
197 return DIGlobalVariableAttr::get(
198 context, translate(node->getScope()),
199 convertToStringAttr(node->getName()),
200 convertToStringAttr(node->getLinkageName()), translate(node->getFile()),
201 node->getLine(), translate(node->getType()), node->isLocalToUnit(),
202 node->isDefinition(), node->getAlignInBits());
203}
204
205DILocalVariableAttr DebugImporter::translateImpl(llvm::DILocalVariable *node) {
206 // Return nullptr if the scope or type is a cyclic dependency.
207 DIScopeAttr scope = translate(node->getScope());
208 if (node->getScope() && !scope)
209 return nullptr;
210 return DILocalVariableAttr::get(
211 context, scope, getStringAttrOrNull(node->getRawName()),
212 translate(node->getFile()), node->getLine(), node->getArg(),
213 node->getAlignInBits(), translate(node->getType()),
214 symbolizeDIFlags(node->getFlags()).value_or(DIFlags::Zero));
215}
216
217DIVariableAttr DebugImporter::translateImpl(llvm::DIVariable *node) {
218 return cast<DIVariableAttr>(translate(static_cast<llvm::DINode *>(node)));
219}
220
221DIScopeAttr DebugImporter::translateImpl(llvm::DIScope *node) {
222 return cast<DIScopeAttr>(translate(static_cast<llvm::DINode *>(node)));
223}
224
225DIModuleAttr DebugImporter::translateImpl(llvm::DIModule *node) {
226 return DIModuleAttr::get(
227 context, translate(node->getFile()), translate(node->getScope()),
228 getStringAttrOrNull(node->getRawName()),
229 getStringAttrOrNull(node->getRawConfigurationMacros()),
230 getStringAttrOrNull(node->getRawIncludePath()),
231 getStringAttrOrNull(node->getRawAPINotesFile()), node->getLineNo(),
232 node->getIsDecl());
233}
234
235DINamespaceAttr DebugImporter::translateImpl(llvm::DINamespace *node) {
236 return DINamespaceAttr::get(context, getStringAttrOrNull(node->getRawName()),
237 translate(node->getScope()),
238 node->getExportSymbols());
239}
240
241DIImportedEntityAttr
242DebugImporter::translateImpl(llvm::DIImportedEntity *node) {
243 SmallVector<DINodeAttr> elements;
244 for (llvm::DINode *element : node->getElements()) {
245 assert(element && "expected a non-null element type");
246 elements.push_back(translate(element));
247 }
248
249 return DIImportedEntityAttr::get(
250 context, node->getTag(), translate(node->getScope()),
251 translate(node->getEntity()), translate(node->getFile()), node->getLine(),
252 getStringAttrOrNull(node->getRawName()), elements);
253}
254
255DISubprogramAttr DebugImporter::translateImpl(llvm::DISubprogram *node) {
256 // Only definitions require a distinct identifier.
257 mlir::DistinctAttr id;
258 if (node->isDistinct())
259 id = getOrCreateDistinctID(node);
260
261 // Return nullptr if the scope or type is invalid.
262 DIScopeAttr scope = translate(node->getScope());
263 if (node->getScope() && !scope)
264 return nullptr;
265 std::optional<DISubprogramFlags> subprogramFlags =
266 symbolizeDISubprogramFlags(node->getSubprogram()->getSPFlags());
267 assert(subprogramFlags && "expected valid subprogram flags");
268 DISubroutineTypeAttr type = translate(node->getType());
269 if (node->getType() && !type)
270 return nullptr;
271
272 // Convert the retained nodes but drop all of them if one of them is invalid.
273 SmallVector<Attribute> retainedNodes;
274 auto add = [this, &retainedNodes](llvm::DINode *retainedNode) {
275 retainedNodes.push_back(translate(retainedNode));
276 };
277 auto addGVE = [](llvm::DIGlobalVariableExpression *GVE) {
278 // FIXME Import DIGlobalVariableExpressions from retainedNodes without
279 // duplicating them.
280 };
281 node->forEachRetainedNode(add, add, add, add, addGVE);
282 if (llvm::is_contained(retainedNodes, nullptr))
283 retainedNodes.clear();
284
285 SmallVector<DINodeAttr> annotations;
286 // We currently only support `string` values for annotations on the MLIR side.
287 // Theoretically we could support other primitives, but LLVM is not using
288 // other types in practice.
289 if (llvm::DINodeArray rawAnns = node->getAnnotations(); rawAnns) {
290 for (size_t i = 0, e = rawAnns->getNumOperands(); i < e; ++i) {
291 const llvm::MDTuple *tuple = cast<llvm::MDTuple>(rawAnns->getOperand(i));
292 if (tuple->getNumOperands() != 2)
293 continue;
294 const llvm::MDString *name = cast<llvm::MDString>(tuple->getOperand(0));
295 const llvm::MDString *value =
296 dyn_cast<llvm::MDString>(tuple->getOperand(1));
297 if (name && value) {
298 annotations.push_back(DIAnnotationAttr::get(
299 context, StringAttr::get(context, name->getString()),
300 StringAttr::get(context, value->getString())));
301 }
302 }
303 }
304
305 return DISubprogramAttr::get(context, id, translate(node->getUnit()), scope,
306 getStringAttrOrNull(node->getRawName()),
307 getStringAttrOrNull(node->getRawLinkageName()),
308 translate(node->getFile()), node->getLine(),
309 node->getScopeLine(), *subprogramFlags, type,
310 retainedNodes, annotations);
311}
312
313DISubrangeAttr DebugImporter::translateImpl(llvm::DISubrange *node) {
314 auto getAttrOrNull = [&](llvm::DISubrange::BoundType data) -> Attribute {
315 if (data.isNull())
316 return nullptr;
317 if (auto *constInt = dyn_cast<llvm::ConstantInt *>(data))
318 return IntegerAttr::get(IntegerType::get(context, 64),
319 constInt->getSExtValue());
320 if (auto *expr = dyn_cast<llvm::DIExpression *>(data))
321 return translateExpression(expr);
322 if (auto *var = dyn_cast<llvm::DIVariable *>(data)) {
323 if (auto *local = dyn_cast<llvm::DILocalVariable>(var))
324 return translate(local);
325 if (auto *global = dyn_cast<llvm::DIGlobalVariable>(var))
326 return translate(global);
327 return nullptr;
328 }
329 return nullptr;
330 };
331 Attribute count = getAttrOrNull(node->getCount());
332 Attribute upperBound = getAttrOrNull(node->getUpperBound());
333 // Either count or the upper bound needs to be present. Otherwise, the
334 // metadata is invalid. The conversion might fail due to unsupported DI nodes.
335 if (!count && !upperBound)
336 return {};
337 return DISubrangeAttr::get(context, count,
338 getAttrOrNull(node->getLowerBound()), upperBound,
339 getAttrOrNull(node->getStride()));
340}
341
342DICommonBlockAttr DebugImporter::translateImpl(llvm::DICommonBlock *node) {
343 return DICommonBlockAttr::get(context, translate(node->getScope()),
344 translate(node->getDecl()),
345 getStringAttrOrNull(node->getRawName()),
346 translate(node->getFile()), node->getLineNo());
347}
348
349DIGenericSubrangeAttr
350DebugImporter::translateImpl(llvm::DIGenericSubrange *node) {
351 auto getAttrOrNull =
352 [&](llvm::DIGenericSubrange::BoundType data) -> Attribute {
353 if (data.isNull())
354 return nullptr;
355 if (auto *expr = dyn_cast<llvm::DIExpression *>(data))
356 return translateExpression(expr);
357 if (auto *var = dyn_cast<llvm::DIVariable *>(data)) {
358 if (auto *local = dyn_cast<llvm::DILocalVariable>(var))
359 return translate(local);
360 if (auto *global = dyn_cast<llvm::DIGlobalVariable>(var))
361 return translate(global);
362 return nullptr;
363 }
364 return nullptr;
365 };
366 Attribute count = getAttrOrNull(node->getCount());
367 Attribute upperBound = getAttrOrNull(node->getUpperBound());
368 Attribute lowerBound = getAttrOrNull(node->getLowerBound());
369 Attribute stride = getAttrOrNull(node->getStride());
370 // Either count or the upper bound needs to be present. Otherwise, the
371 // metadata is invalid.
372 if (!count && !upperBound)
373 return {};
374 return DIGenericSubrangeAttr::get(context, count, lowerBound, upperBound,
375 stride);
376}
377
378DISubroutineTypeAttr
379DebugImporter::translateImpl(llvm::DISubroutineType *node) {
380 SmallVector<DITypeAttr> types;
381 for (llvm::DIType *type : node->getTypeArray()) {
382 if (!type) {
383 // A nullptr entry may appear at the beginning or the end of the
384 // subroutine types list modeling either a void result type or the type of
385 // a variadic argument. Translate the nullptr to an explicit
386 // DINullTypeAttr since the attribute list cannot contain a nullptr entry.
387 types.push_back(DINullTypeAttr::get(context));
388 continue;
389 }
390 types.push_back(translate(type));
391 }
392 // Return nullptr if any of the types is invalid.
393 if (llvm::is_contained(types, nullptr))
394 return nullptr;
395 return DISubroutineTypeAttr::get(context, node->getCC(), types);
396}
397
398DITypeAttr DebugImporter::translateImpl(llvm::DIType *node) {
399 return cast<DITypeAttr>(translate(static_cast<llvm::DINode *>(node)));
400}
401
403 if (!node)
404 return nullptr;
405
406 // Check for a cached instance.
407 auto cacheEntry = cache.lookupOrInit(node);
408 if (std::optional<DINodeAttr> result = cacheEntry.get())
409 return *result;
410
411 // Convert the debug metadata if possible.
412 auto translateNode = [this](llvm::DINode *node) -> DINodeAttr {
413 if (auto *casted = dyn_cast<llvm::DIBasicType>(node))
414 return translateImpl(casted);
415 if (auto *casted = dyn_cast<llvm::DICommonBlock>(node))
416 return translateImpl(casted);
417 if (auto *casted = dyn_cast<llvm::DICompileUnit>(node))
418 return translateImpl(casted);
419 if (auto *casted = dyn_cast<llvm::DICompositeType>(node))
420 return translateImpl(casted);
421 if (auto *casted = dyn_cast<llvm::DIDerivedType>(node))
422 return translateImpl(casted);
423 if (auto *casted = dyn_cast<llvm::DIStringType>(node))
424 return translateImpl(casted);
425 if (auto *casted = dyn_cast<llvm::DIFile>(node))
426 return translateImpl(casted);
427 if (auto *casted = dyn_cast<llvm::DIGlobalVariable>(node))
428 return translateImpl(casted);
429 if (auto *casted = dyn_cast<llvm::DIImportedEntity>(node))
430 return translateImpl(casted);
431 if (auto *casted = dyn_cast<llvm::DILabel>(node))
432 return translateImpl(casted);
433 if (auto *casted = dyn_cast<llvm::DILexicalBlock>(node))
434 return translateImpl(casted);
435 if (auto *casted = dyn_cast<llvm::DILexicalBlockFile>(node))
436 return translateImpl(casted);
437 if (auto *casted = dyn_cast<llvm::DILocalVariable>(node))
438 return translateImpl(casted);
439 if (auto *casted = dyn_cast<llvm::DIModule>(node))
440 return translateImpl(casted);
441 if (auto *casted = dyn_cast<llvm::DINamespace>(node))
442 return translateImpl(casted);
443 if (auto *casted = dyn_cast<llvm::DISubprogram>(node))
444 return translateImpl(casted);
445 if (auto *casted = dyn_cast<llvm::DISubrange>(node))
446 return translateImpl(casted);
447 if (auto *casted = dyn_cast<llvm::DIGenericSubrange>(node))
448 return translateImpl(casted);
449 if (auto *casted = dyn_cast<llvm::DISubroutineType>(node))
450 return translateImpl(casted);
451 return nullptr;
452 };
453 if (DINodeAttr attr = translateNode(node)) {
454 // If this node was repeated, lookup its recursive ID and assign it to the
455 // base result.
456 if (cacheEntry.wasRepeated()) {
457 DistinctAttr recId = nodeToRecId.lookup(node);
458 auto recType = cast<DIRecursiveTypeAttrInterface>(attr);
459 attr = cast<DINodeAttr>(recType.withRecId(recId));
460 }
461 cacheEntry.resolve(attr);
462 return attr;
463 }
464 cacheEntry.resolve(nullptr);
465 return nullptr;
466}
467
468/// Get the `getRecSelf` constructor for the translated node if it participates
469/// in CyclicReplacerCache cycle breaking (recursive composite types,
470/// subprograms, or compile units).
471static function_ref<DIRecursiveTypeAttrInterface(DistinctAttr)>
472getRecSelfConstructor(llvm::DINode *node) {
473 using CtorType = function_ref<DIRecursiveTypeAttrInterface(DistinctAttr)>;
475 .Case([&](llvm::DICompositeType *) {
476 return CtorType(DICompositeTypeAttr::getRecSelf);
477 })
478 .Case([&](llvm::DISubprogram *) {
479 return CtorType(DISubprogramAttr::getRecSelf);
480 })
481 .Case([&](llvm::DICompileUnit *) {
482 return CtorType(DICompileUnitAttr::getRecSelf);
483 })
484 .Default(CtorType());
485}
486
487std::optional<DINodeAttr> DebugImporter::createRecSelf(llvm::DINode *node) {
488 auto recSelfCtor = getRecSelfConstructor(node);
489 if (!recSelfCtor)
490 return std::nullopt;
491
492 // The original node may have already been assigned a recursive ID from
493 // a different self-reference. Use that if possible.
494 DistinctAttr recId = nodeToRecId.lookup(node);
495 if (!recId) {
496 recId = DistinctAttr::create(UnitAttr::get(context));
497 nodeToRecId[node] = recId;
498 }
499 DIRecursiveTypeAttrInterface recSelf = recSelfCtor(recId);
500 return cast<DINodeAttr>(recSelf);
501}
502
503//===----------------------------------------------------------------------===//
504// Locations
505//===----------------------------------------------------------------------===//
506
507Location DebugImporter::translateLoc(llvm::DILocation *loc) {
508 if (!loc)
509 return UnknownLoc::get(context);
510
511 // Get the file location of the instruction.
512 Location result = FileLineColLoc::get(context, loc->getFilename(),
513 loc->getLine(), loc->getColumn());
514
515 // Add scope information.
516 assert(loc->getScope() && "expected non-null scope");
518 context);
519
520 // Add call site information, if available.
521 if (llvm::DILocation *inlinedAt = loc->getInlinedAt())
522 result = CallSiteLoc::get(result, translateLoc(inlinedAt));
523
524 return result;
525}
526
527DIExpressionAttr DebugImporter::translateExpression(llvm::DIExpression *node) {
528 if (!node)
529 return nullptr;
530
532
533 // Begin processing the operations.
534 for (const llvm::DIExpression::ExprOperand &op : node->expr_ops()) {
535 SmallVector<uint64_t> operands;
536 operands.reserve(op.getNumArgs());
537 for (const auto &i : llvm::seq(op.getNumArgs()))
538 operands.push_back(op.getArg(i));
539 const auto attr = DIExpressionElemAttr::get(context, op.getOp(), operands);
540 ops.push_back(attr);
541 }
542 return DIExpressionAttr::get(context, ops);
543}
544
546 llvm::DIGlobalVariableExpression *node) {
547 return DIGlobalVariableExpressionAttr::get(
548 context, translate(node->getVariable()),
549 translateExpression(node->getExpression()));
550}
551
552StringAttr DebugImporter::getStringAttrOrNull(llvm::MDString *stringNode) {
553 if (!stringNode)
554 return StringAttr();
555 return StringAttr::get(context, stringNode->getString());
556}
557
558DistinctAttr DebugImporter::getOrCreateDistinctID(llvm::DINode *node) {
559 DistinctAttr &id = nodeToDistinctAttr[node];
560 if (!id)
561 id = DistinctAttr::create(UnitAttr::get(context));
562 return id;
563}
static function_ref< DIRecursiveTypeAttrInterface(DistinctAttr)> getRecSelfConstructor(llvm::DINode *node)
Get the getRecSelf constructor for the translated node if it participates in CyclicReplacerCache cycl...
#define add(a, b)
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)
Definition Location.cpp:157
This class represents a fused location whose metadata is known to be an instance of the given type.
Definition Location.h:149
This class represents the base attribute for all debug info attributes.
Definition LLVMAttrs.h:29
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...
Definition Location.h:76
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition CallGraph.h:227
Include the generated interface declarations.
llvm::TypeSwitch< T, ResultT > TypeSwitch
Definition LLVM.h:147
llvm::function_ref< Fn > function_ref
Definition LLVM.h:155