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();
38 StringAttr fileName =
StringAttr::get(context, subprogram->getFilename());
49 DIBasicTypeAttr DebugImporter::translateImpl(llvm::DIBasicType *node) {
51 node->getSizeInBits(), node->getEncoding());
54 DICompileUnitAttr DebugImporter::translateImpl(llvm::DICompileUnit *node) {
55 std::optional<DIEmissionKind> emissionKind =
56 symbolizeDIEmissionKind(node->getEmissionKind());
57 std::optional<DINameTableKind> nameTableKind = symbolizeDINameTableKind(
59 std::underlying_type_t<llvm::DICompileUnit::DebugNameTableKind>
>(
60 node->getNameTableKind()));
62 context, getOrCreateDistinctID(node),
63 node->getSourceLanguage().getUnversionedName(),
64 translate(node->getFile()), getStringAttrOrNull(node->getRawProducer()),
65 node->isOptimized(), emissionKind.value(), nameTableKind.value(),
66 getStringAttrOrNull(node->getRawSplitDebugFilename()));
69 DICompositeTypeAttr DebugImporter::translateImpl(llvm::DICompositeType *node) {
70 std::optional<DIFlags> flags = symbolizeDIFlags(node->getFlags());
74 bool isVectorType = flags && bitEnumContainsAll(*flags, DIFlags::Vector);
75 if (isVectorType || !dropDICompositeTypeElements) {
76 for (llvm::DINode *element : node->getElements()) {
77 assert(element &&
"expected a non-null element type");
82 if (llvm::is_contained(elements,
nullptr))
87 if (node->getTag() == llvm::dwarf::DW_TAG_array_type && !baseType)
90 context, node->getTag(), getStringAttrOrNull(node->getRawName()),
92 baseType, flags.value_or(DIFlags::Zero), node->getSizeInBits(),
99 DIDerivedTypeAttr DebugImporter::translateImpl(llvm::DIDerivedType *node) {
102 if (node->getBaseType() && !baseType)
105 translate(dyn_cast_or_null<llvm::DINode>(node->getExtraData()));
107 context, node->getTag(), getStringAttrOrNull(node->getRawName()),
108 baseType, node->getSizeInBits(), node->getAlignInBits(),
109 node->getOffsetInBits(), node->getDWARFAddressSpace(), extraData);
112 DIStringTypeAttr DebugImporter::translateImpl(llvm::DIStringType *node) {
114 context, node->getTag(), getStringAttrOrNull(node->getRawName()),
115 node->getSizeInBits(), node->getAlignInBits(),
121 DIFileAttr DebugImporter::translateImpl(llvm::DIFile *node) {
122 return DIFileAttr::get(context, node->getFilename(), node->getDirectory());
125 DILabelAttr DebugImporter::translateImpl(llvm::DILabel *node) {
128 if (node->getScope() && !scope)
131 getStringAttrOrNull(node->getRawName()),
132 translate(node->getFile()), node->getLine());
135 DILexicalBlockAttr DebugImporter::translateImpl(llvm::DILexicalBlock *node) {
138 if (node->getScope() && !scope)
141 node->getLine(), node->getColumn());
144 DILexicalBlockFileAttr
145 DebugImporter::translateImpl(llvm::DILexicalBlockFile *node) {
148 if (node->getScope() && !scope)
151 node->getDiscriminator());
155 DebugImporter::translateImpl(llvm::DIGlobalVariable *node) {
158 auto convertToStringAttr = [&](StringRef name) -> StringAttr {
165 convertToStringAttr(node->getName()),
166 convertToStringAttr(node->getLinkageName()),
translate(node->getFile()),
167 node->getLine(),
translate(node->getType()), node->isLocalToUnit(),
168 node->isDefinition(), node->getAlignInBits());
171 DILocalVariableAttr DebugImporter::translateImpl(llvm::DILocalVariable *node) {
174 if (node->getScope() && !scope)
177 context, scope, getStringAttrOrNull(node->getRawName()),
178 translate(node->getFile()), node->getLine(), node->getArg(),
179 node->getAlignInBits(),
translate(node->getType()),
180 symbolizeDIFlags(node->getFlags()).value_or(DIFlags::Zero));
183 DIVariableAttr DebugImporter::translateImpl(llvm::DIVariable *node) {
184 return cast<DIVariableAttr>(
translate(
static_cast<llvm::DINode *
>(node)));
187 DIScopeAttr DebugImporter::translateImpl(llvm::DIScope *node) {
188 return cast<DIScopeAttr>(
translate(
static_cast<llvm::DINode *
>(node)));
191 DIModuleAttr DebugImporter::translateImpl(llvm::DIModule *node) {
194 getStringAttrOrNull(node->getRawName()),
195 getStringAttrOrNull(node->getRawConfigurationMacros()),
196 getStringAttrOrNull(node->getRawIncludePath()),
197 getStringAttrOrNull(node->getRawAPINotesFile()), node->getLineNo(),
201 DINamespaceAttr DebugImporter::translateImpl(llvm::DINamespace *node) {
204 node->getExportSymbols());
208 DebugImporter::translateImpl(llvm::DIImportedEntity *node) {
210 for (llvm::DINode *element : node->getElements()) {
211 assert(element &&
"expected a non-null element type");
216 context, node->getTag(),
translate(node->getScope()),
218 getStringAttrOrNull(node->getRawName()), elements);
221 DISubprogramAttr DebugImporter::translateImpl(llvm::DISubprogram *node) {
224 if (node->isDistinct())
225 id = getOrCreateDistinctID(node);
229 if (node->getScope() && !scope)
231 std::optional<DISubprogramFlags> subprogramFlags =
232 symbolizeDISubprogramFlags(node->getSubprogram()->getSPFlags());
233 assert(subprogramFlags &&
"expected valid subprogram flags");
234 DISubroutineTypeAttr type =
translate(node->getType());
235 if (node->getType() && !type)
240 for (llvm::DINode *retainedNode : node->getRetainedNodes())
241 retainedNodes.push_back(
translate(retainedNode));
242 if (llvm::is_contained(retainedNodes,
nullptr))
243 retainedNodes.clear();
249 if (llvm::DINodeArray rawAnns = node->getAnnotations(); rawAnns) {
250 for (
size_t i = 0, e = rawAnns->getNumOperands(); i < e; ++i) {
251 const llvm::MDTuple *tuple = cast<llvm::MDTuple>(rawAnns->getOperand(i));
252 if (tuple->getNumOperands() != 2)
254 const llvm::MDString *name = cast<llvm::MDString>(tuple->getOperand(0));
255 const llvm::MDString *value =
256 dyn_cast<llvm::MDString>(tuple->getOperand(1));
266 getStringAttrOrNull(node->getRawName()),
267 getStringAttrOrNull(node->getRawLinkageName()),
268 translate(node->getFile()), node->getLine(),
269 node->getScopeLine(), *subprogramFlags, type,
270 retainedNodes, annotations);
273 DISubrangeAttr DebugImporter::translateImpl(llvm::DISubrange *node) {
277 if (
auto *constInt = dyn_cast<llvm::ConstantInt *>(data))
279 constInt->getSExtValue());
280 if (
auto *expr = dyn_cast<llvm::DIExpression *>(data))
282 if (
auto *var = dyn_cast<llvm::DIVariable *>(data)) {
283 if (
auto *local = dyn_cast<llvm::DILocalVariable>(var))
285 if (
auto *global = dyn_cast<llvm::DIGlobalVariable>(var))
291 Attribute count = getAttrOrNull(node->getCount());
292 Attribute upperBound = getAttrOrNull(node->getUpperBound());
295 if (!count && !upperBound)
298 getAttrOrNull(node->getLowerBound()), upperBound,
299 getAttrOrNull(node->getStride()));
302 DICommonBlockAttr DebugImporter::translateImpl(llvm::DICommonBlock *node) {
305 getStringAttrOrNull(node->getRawName()),
306 translate(node->getFile()), node->getLineNo());
309 DIGenericSubrangeAttr
310 DebugImporter::translateImpl(llvm::DIGenericSubrange *node) {
315 if (
auto *expr = dyn_cast<llvm::DIExpression *>(data))
317 if (
auto *var = dyn_cast<llvm::DIVariable *>(data)) {
318 if (
auto *local = dyn_cast<llvm::DILocalVariable>(var))
320 if (
auto *global = dyn_cast<llvm::DIGlobalVariable>(var))
326 Attribute count = getAttrOrNull(node->getCount());
327 Attribute upperBound = getAttrOrNull(node->getUpperBound());
328 Attribute lowerBound = getAttrOrNull(node->getLowerBound());
329 Attribute stride = getAttrOrNull(node->getStride());
332 if (!count && !upperBound)
339 DebugImporter::translateImpl(llvm::DISubroutineType *node) {
341 for (llvm::DIType *type : node->getTypeArray()) {
353 if (llvm::is_contained(types,
nullptr))
358 DITypeAttr DebugImporter::translateImpl(llvm::DIType *node) {
359 return cast<DITypeAttr>(
translate(
static_cast<llvm::DINode *
>(node)));
367 auto cacheEntry = cache.lookupOrInit(node);
368 if (std::optional<DINodeAttr> result = cacheEntry.get())
372 auto translateNode = [
this](llvm::DINode *node) ->
DINodeAttr {
373 if (
auto *casted = dyn_cast<llvm::DIBasicType>(node))
374 return translateImpl(casted);
375 if (
auto *casted = dyn_cast<llvm::DICommonBlock>(node))
376 return translateImpl(casted);
377 if (
auto *casted = dyn_cast<llvm::DICompileUnit>(node))
378 return translateImpl(casted);
379 if (
auto *casted = dyn_cast<llvm::DICompositeType>(node))
380 return translateImpl(casted);
381 if (
auto *casted = dyn_cast<llvm::DIDerivedType>(node))
382 return translateImpl(casted);
383 if (
auto *casted = dyn_cast<llvm::DIStringType>(node))
384 return translateImpl(casted);
385 if (
auto *casted = dyn_cast<llvm::DIFile>(node))
386 return translateImpl(casted);
387 if (
auto *casted = dyn_cast<llvm::DIGlobalVariable>(node))
388 return translateImpl(casted);
389 if (
auto *casted = dyn_cast<llvm::DIImportedEntity>(node))
390 return translateImpl(casted);
391 if (
auto *casted = dyn_cast<llvm::DILabel>(node))
392 return translateImpl(casted);
393 if (
auto *casted = dyn_cast<llvm::DILexicalBlock>(node))
394 return translateImpl(casted);
395 if (
auto *casted = dyn_cast<llvm::DILexicalBlockFile>(node))
396 return translateImpl(casted);
397 if (
auto *casted = dyn_cast<llvm::DILocalVariable>(node))
398 return translateImpl(casted);
399 if (
auto *casted = dyn_cast<llvm::DIModule>(node))
400 return translateImpl(casted);
401 if (
auto *casted = dyn_cast<llvm::DINamespace>(node))
402 return translateImpl(casted);
403 if (
auto *casted = dyn_cast<llvm::DISubprogram>(node))
404 return translateImpl(casted);
405 if (
auto *casted = dyn_cast<llvm::DISubrange>(node))
406 return translateImpl(casted);
407 if (
auto *casted = dyn_cast<llvm::DIGenericSubrange>(node))
408 return translateImpl(casted);
409 if (
auto *casted = dyn_cast<llvm::DISubroutineType>(node))
410 return translateImpl(casted);
416 if (cacheEntry.wasRepeated()) {
418 auto recType = cast<DIRecursiveTypeAttrInterface>(attr);
419 attr = cast<DINodeAttr>(recType.withRecId(recId));
421 cacheEntry.resolve(attr);
424 cacheEntry.resolve(
nullptr);
434 .Case([&](llvm::DICompositeType *) {
435 return CtorType(DICompositeTypeAttr::getRecSelf);
437 .Case([&](llvm::DISubprogram *) {
438 return CtorType(DISubprogramAttr::getRecSelf);
440 .Default(CtorType());
443 std::optional<DINodeAttr> DebugImporter::createRecSelf(llvm::DINode *node) {
453 nodeToRecId[node] = recId;
455 DIRecursiveTypeAttrInterface recSelf = recSelfCtor(recId);
456 return cast<DINodeAttr>(recSelf);
469 loc->getLine(), loc->getColumn());
472 assert(loc->getScope() &&
"expected non-null scope");
477 if (llvm::DILocation *inlinedAt = loc->getInlinedAt())
490 for (
const llvm::DIExpression::ExprOperand &op : node->expr_ops()) {
492 operands.reserve(op.getNumArgs());
493 for (
const auto &i : llvm::seq(op.getNumArgs()))
494 operands.push_back(op.getArg(i));
502 llvm::DIGlobalVariableExpression *node) {
508 StringAttr DebugImporter::getStringAttrOrNull(llvm::MDString *stringNode) {
514 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.
static FileLineColLoc get(StringAttr filename, unsigned line, unsigned column)
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...