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