14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/ADT/ScopeExit.h"
16 #include "llvm/ADT/SetOperations.h"
17 #include "llvm/ADT/TypeSwitch.h"
18 #include "llvm/BinaryFormat/Dwarf.h"
19 #include "llvm/IR/Constants.h"
20 #include "llvm/IR/DebugInfoMetadata.h"
21 #include "llvm/IR/Metadata.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Support/ErrorHandling.h"
30 bool dropDICompositeTypeElements)
31 : cache([&](
llvm::DINode *node) {
return createRecSelf(node); }),
32 context(mlirModule.getContext()), mlirModule(mlirModule),
33 dropDICompositeTypeElements(dropDICompositeTypeElements) {}
36 llvm::DISubprogram *subprogram = func->getSubprogram();
42 StringAttr fileName =
StringAttr::get(context, subprogram->getFilename());
53 DIBasicTypeAttr DebugImporter::translateImpl(llvm::DIBasicType *node) {
55 node->getSizeInBits(), node->getEncoding());
58 DICompileUnitAttr DebugImporter::translateImpl(llvm::DICompileUnit *node) {
59 std::optional<DIEmissionKind> emissionKind =
60 symbolizeDIEmissionKind(node->getEmissionKind());
61 std::optional<DINameTableKind> nameTableKind = symbolizeDINameTableKind(
63 std::underlying_type_t<llvm::DICompileUnit::DebugNameTableKind>
>(
64 node->getNameTableKind()));
66 context, getOrCreateDistinctID(node), node->getSourceLanguage(),
67 translate(node->getFile()), getStringAttrOrNull(node->getRawProducer()),
68 node->isOptimized(), emissionKind.value(), nameTableKind.value());
71 DICompositeTypeAttr DebugImporter::translateImpl(llvm::DICompositeType *node) {
72 std::optional<DIFlags> flags = symbolizeDIFlags(node->getFlags());
76 bool isVectorType = flags && bitEnumContainsAll(*flags, DIFlags::Vector);
77 if (isVectorType || !dropDICompositeTypeElements) {
78 for (llvm::DINode *element : node->getElements()) {
79 assert(element &&
"expected a non-null element type");
84 if (llvm::is_contained(elements,
nullptr))
89 if (node->getTag() == llvm::dwarf::DW_TAG_array_type && !baseType)
92 context, node->getTag(), getStringAttrOrNull(node->getRawName()),
94 baseType, flags.value_or(DIFlags::Zero), node->getSizeInBits(),
95 node->getAlignInBits(), elements,
102 DIDerivedTypeAttr DebugImporter::translateImpl(llvm::DIDerivedType *node) {
105 if (node->getBaseType() && !baseType)
108 translate(dyn_cast_or_null<llvm::DINode>(node->getExtraData()));
110 context, node->getTag(), getStringAttrOrNull(node->getRawName()),
111 baseType, node->getSizeInBits(), node->getAlignInBits(),
112 node->getOffsetInBits(), node->getDWARFAddressSpace(), extraData);
115 DIStringTypeAttr DebugImporter::translateImpl(llvm::DIStringType *node) {
117 context, node->getTag(), getStringAttrOrNull(node->getRawName()),
118 node->getSizeInBits(), node->getAlignInBits(),
124 DIFileAttr DebugImporter::translateImpl(llvm::DIFile *node) {
125 return DIFileAttr::get(context, node->getFilename(), node->getDirectory());
128 DILabelAttr DebugImporter::translateImpl(llvm::DILabel *node) {
131 if (node->getScope() && !scope)
134 getStringAttrOrNull(node->getRawName()),
135 translate(node->getFile()), node->getLine());
138 DILexicalBlockAttr DebugImporter::translateImpl(llvm::DILexicalBlock *node) {
141 if (node->getScope() && !scope)
144 node->getLine(), node->getColumn());
147 DILexicalBlockFileAttr
148 DebugImporter::translateImpl(llvm::DILexicalBlockFile *node) {
151 if (node->getScope() && !scope)
154 node->getDiscriminator());
158 DebugImporter::translateImpl(llvm::DIGlobalVariable *node) {
161 auto convertToStringAttr = [&](StringRef name) -> StringAttr {
168 convertToStringAttr(node->getName()),
169 convertToStringAttr(node->getLinkageName()),
translate(node->getFile()),
170 node->getLine(),
translate(node->getType()), node->isLocalToUnit(),
171 node->isDefinition(), node->getAlignInBits());
174 DILocalVariableAttr DebugImporter::translateImpl(llvm::DILocalVariable *node) {
177 if (node->getScope() && !scope)
180 context, scope, getStringAttrOrNull(node->getRawName()),
181 translate(node->getFile()), node->getLine(), node->getArg(),
182 node->getAlignInBits(),
translate(node->getType()),
183 symbolizeDIFlags(node->getFlags()).value_or(DIFlags::Zero));
186 DIVariableAttr DebugImporter::translateImpl(llvm::DIVariable *node) {
187 return cast<DIVariableAttr>(
translate(
static_cast<llvm::DINode *
>(node)));
190 DIScopeAttr DebugImporter::translateImpl(llvm::DIScope *node) {
191 return cast<DIScopeAttr>(
translate(
static_cast<llvm::DINode *
>(node)));
194 DIModuleAttr DebugImporter::translateImpl(llvm::DIModule *node) {
197 getStringAttrOrNull(node->getRawName()),
198 getStringAttrOrNull(node->getRawConfigurationMacros()),
199 getStringAttrOrNull(node->getRawIncludePath()),
200 getStringAttrOrNull(node->getRawAPINotesFile()), node->getLineNo(),
204 DINamespaceAttr DebugImporter::translateImpl(llvm::DINamespace *node) {
207 node->getExportSymbols());
211 DebugImporter::translateImpl(llvm::DIImportedEntity *node) {
213 for (llvm::DINode *element : node->getElements()) {
214 assert(element &&
"expected a non-null element type");
219 context, node->getTag(),
translate(node->getScope()),
221 getStringAttrOrNull(node->getRawName()), elements);
224 DISubprogramAttr DebugImporter::translateImpl(llvm::DISubprogram *node) {
227 if (node->isDistinct())
228 id = getOrCreateDistinctID(node);
232 if (node->getScope() && !scope)
234 std::optional<DISubprogramFlags> subprogramFlags =
235 symbolizeDISubprogramFlags(node->getSubprogram()->getSPFlags());
236 assert(subprogramFlags &&
"expected valid subprogram flags");
237 DISubroutineTypeAttr type =
translate(node->getType());
238 if (node->getType() && !type)
243 for (llvm::DINode *retainedNode : node->getRetainedNodes())
244 retainedNodes.push_back(
translate(retainedNode));
245 if (llvm::is_contained(retainedNodes,
nullptr))
246 retainedNodes.clear();
249 getStringAttrOrNull(node->getRawName()),
250 getStringAttrOrNull(node->getRawLinkageName()),
251 translate(node->getFile()), node->getLine(),
252 node->getScopeLine(), *subprogramFlags, type,
256 DISubrangeAttr DebugImporter::translateImpl(llvm::DISubrange *node) {
260 if (
auto *constInt = dyn_cast<llvm::ConstantInt *>(data))
262 constInt->getSExtValue());
263 if (
auto *expr = dyn_cast<llvm::DIExpression *>(data))
265 if (
auto *var = dyn_cast<llvm::DIVariable *>(data)) {
266 if (
auto *local = dyn_cast<llvm::DILocalVariable>(var))
268 if (
auto *global = dyn_cast<llvm::DIGlobalVariable>(var))
274 Attribute count = getAttrOrNull(node->getCount());
275 Attribute upperBound = getAttrOrNull(node->getUpperBound());
278 if (!count && !upperBound)
281 getAttrOrNull(node->getLowerBound()), upperBound,
282 getAttrOrNull(node->getStride()));
286 DebugImporter::translateImpl(llvm::DISubroutineType *node) {
288 for (llvm::DIType *type : node->getTypeArray()) {
300 if (llvm::is_contained(types,
nullptr))
305 DITypeAttr DebugImporter::translateImpl(llvm::DIType *node) {
306 return cast<DITypeAttr>(
translate(
static_cast<llvm::DINode *
>(node)));
314 auto cacheEntry = cache.lookupOrInit(node);
315 if (std::optional<DINodeAttr> result = cacheEntry.get())
319 auto translateNode = [
this](llvm::DINode *node) ->
DINodeAttr {
320 if (
auto *casted = dyn_cast<llvm::DIBasicType>(node))
321 return translateImpl(casted);
322 if (
auto *casted = dyn_cast<llvm::DICompileUnit>(node))
323 return translateImpl(casted);
324 if (
auto *casted = dyn_cast<llvm::DICompositeType>(node))
325 return translateImpl(casted);
326 if (
auto *casted = dyn_cast<llvm::DIDerivedType>(node))
327 return translateImpl(casted);
328 if (
auto *casted = dyn_cast<llvm::DIStringType>(node))
329 return translateImpl(casted);
330 if (
auto *casted = dyn_cast<llvm::DIFile>(node))
331 return translateImpl(casted);
332 if (
auto *casted = dyn_cast<llvm::DIGlobalVariable>(node))
333 return translateImpl(casted);
334 if (
auto *casted = dyn_cast<llvm::DIImportedEntity>(node))
335 return translateImpl(casted);
336 if (
auto *casted = dyn_cast<llvm::DILabel>(node))
337 return translateImpl(casted);
338 if (
auto *casted = dyn_cast<llvm::DILexicalBlock>(node))
339 return translateImpl(casted);
340 if (
auto *casted = dyn_cast<llvm::DILexicalBlockFile>(node))
341 return translateImpl(casted);
342 if (
auto *casted = dyn_cast<llvm::DILocalVariable>(node))
343 return translateImpl(casted);
344 if (
auto *casted = dyn_cast<llvm::DIModule>(node))
345 return translateImpl(casted);
346 if (
auto *casted = dyn_cast<llvm::DINamespace>(node))
347 return translateImpl(casted);
348 if (
auto *casted = dyn_cast<llvm::DISubprogram>(node))
349 return translateImpl(casted);
350 if (
auto *casted = dyn_cast<llvm::DISubrange>(node))
351 return translateImpl(casted);
352 if (
auto *casted = dyn_cast<llvm::DISubroutineType>(node))
353 return translateImpl(casted);
359 if (cacheEntry.wasRepeated()) {
361 auto recType = cast<DIRecursiveTypeAttrInterface>(attr);
362 attr = cast<DINodeAttr>(recType.withRecId(recId));
364 cacheEntry.resolve(attr);
367 cacheEntry.resolve(
nullptr);
377 .Case([&](llvm::DICompositeType *) {
378 return CtorType(DICompositeTypeAttr::getRecSelf);
380 .Case([&](llvm::DISubprogram *) {
381 return CtorType(DISubprogramAttr::getRecSelf);
383 .Default(CtorType());
386 std::optional<DINodeAttr> DebugImporter::createRecSelf(llvm::DINode *node) {
396 nodeToRecId[node] = recId;
398 DIRecursiveTypeAttrInterface recSelf = recSelfCtor(recId);
399 return cast<DINodeAttr>(recSelf);
412 loc->getLine(), loc->getColumn());
415 assert(loc->getScope() &&
"expected non-null scope");
420 if (llvm::DILocation *inlinedAt = loc->getInlinedAt())
433 for (
const llvm::DIExpression::ExprOperand &op : node->expr_ops()) {
435 operands.reserve(op.getNumArgs());
436 for (
const auto &i : llvm::seq(op.getNumArgs()))
437 operands.push_back(op.getArg(i));
445 llvm::DIGlobalVariableExpression *node) {
451 StringAttr DebugImporter::getStringAttrOrNull(llvm::MDString *stringNode) {
457 DistinctAttr DebugImporter::getOrCreateDistinctID(llvm::DINode *node) {
static function_ref< DIRecursiveTypeAttrInterface(DistinctAttr)> getRecSelfConstructor(llvm::DINode *node)
Get the getRecSelf constructor for the translated type of node if its translated DITypeAttr supports ...
Attributes are known-constant values of operations.
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.
This class represents the base attribute for all debug info attributes.
This class represents a LLVM attribute that describes a debug info scope.
This class represents a LLVM attribute that describes a debug info type.
This class represents a LLVM attribute that describes a debug info variable.
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.
BoundType
The type of bound: equal, lower bound or upper bound.
Include the generated interface declarations.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...