Skip to content

Commit bc4bedd

Browse files
authored
[mlir][debug] Handle DIImportedEntity. (#103055)
The `DIImporedEntity` can be used to represent imported entities like C++'s namespace with using directive or fortran's moudule with use statement. This PR adds `DIImportedEntityAttr` and 2-way translation from `DIImportedEntity` to `DIImportedEntityAttr` and vice versa. When an entity is imported in a function, the `retainedNodes` field of the `DISubprogram` contains all the imported nodes. See the C++ code and the LLVM IR below. ``` void test() { using namespace n1; ... } !2 = !DINamespace(name: "n1", scope: null) !16 = distinct !DISubprogram(name: "test", ..., retainedNodes: !19) !19 = !{!20} !20 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !16, entity: !2 ...) ``` This PR makes sure that the translation from mlir to `retainedNodes` field happens correctly both ways. To side step the cyclic dependency between `DISubprogramAttr` and `DIImportedEntityAttr`, we have decided to not have `scope` field in the `DIImportedEntityAttr` and it is inferred from the entity which hold the list of `DIImportedEntityAttr`. A `retainedNodes` field has been added in the `DISubprogramAttr` which contains the list of `DIImportedEntityAttr` for that function. This PR currently does not handle entities imported in a global scope but that should be easy to handle in a subsequent PR.
1 parent ad468da commit bc4bedd

File tree

13 files changed

+184
-16
lines changed

13 files changed

+184
-16
lines changed

flang/lib/Optimizer/Transforms/AddDebugInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp,
301301

302302
auto spAttr = mlir::LLVM::DISubprogramAttr::get(
303303
context, id, compilationUnit, Scope, funcName, fullName, funcFileAttr,
304-
line, line, subprogramFlags, subTypeAttr);
304+
line, line, subprogramFlags, subTypeAttr, /*retainedNodes=*/{});
305305
funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr));
306306

307307
// Don't process variables if user asked for line tables only.

mlir/include/mlir-c/Dialect/LLVM.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,8 @@ MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMDISubprogramAttrGet(
316316
MlirContext ctx, MlirAttribute id, MlirAttribute compileUnit,
317317
MlirAttribute scope, MlirAttribute name, MlirAttribute linkageName,
318318
MlirAttribute file, unsigned int line, unsigned int scopeLine,
319-
uint64_t subprogramFlags, MlirAttribute type);
319+
uint64_t subprogramFlags, MlirAttribute type, intptr_t nRetainedNodes,
320+
MlirAttribute const *retainedNodes);
320321

321322
/// Gets the scope from this DISubprogramAttr.
322323
MLIR_CAPI_EXPORTED MlirAttribute
@@ -353,6 +354,12 @@ MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMDIModuleAttrGet(
353354
MlirAttribute name, MlirAttribute configMacros, MlirAttribute includePath,
354355
MlirAttribute apinotes, unsigned int line, bool isDecl);
355356

357+
/// Creates a LLVM DIImportedEntityAttr attribute.
358+
MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMDIImportedEntityAttrGet(
359+
MlirContext ctx, unsigned int tag, MlirAttribute entity, MlirAttribute file,
360+
unsigned int line, MlirAttribute name, intptr_t nElements,
361+
MlirAttribute const *elements);
362+
356363
/// Gets the scope of this DIModuleAttr.
357364
MLIR_CAPI_EXPORTED MlirAttribute
358365
mlirLLVMDIModuleAttrGetScope(MlirAttribute diModule);

mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -565,19 +565,21 @@ def LLVM_DISubprogramAttr : LLVM_Attr<"DISubprogram", "di_subprogram",
565565
OptionalParameter<"unsigned">:$line,
566566
OptionalParameter<"unsigned">:$scopeLine,
567567
OptionalParameter<"DISubprogramFlags">:$subprogramFlags,
568-
OptionalParameter<"DISubroutineTypeAttr">:$type
568+
OptionalParameter<"DISubroutineTypeAttr">:$type,
569+
OptionalArrayRefParameter<"DINodeAttr">:$retainedNodes
569570
);
570571
let builders = [
571572
AttrBuilderWithInferredContext<(ins
572573
"DistinctAttr":$id, "DICompileUnitAttr":$compileUnit,
573574
"DIScopeAttr":$scope, "StringRef":$name, "StringRef":$linkageName,
574575
"DIFileAttr":$file, "unsigned":$line, "unsigned":$scopeLine,
575-
"DISubprogramFlags":$subprogramFlags, "DISubroutineTypeAttr":$type
576+
"DISubprogramFlags":$subprogramFlags, "DISubroutineTypeAttr":$type,
577+
"ArrayRef<DINodeAttr>":$retainedNodes
576578
), [{
577579
MLIRContext *ctx = file.getContext();
578580
return $_get(ctx, id, compileUnit, scope, StringAttr::get(ctx, name),
579581
StringAttr::get(ctx, linkageName), file, line,
580-
scopeLine, subprogramFlags, type);
582+
scopeLine, subprogramFlags, type, retainedNodes);
581583
}]>
582584
];
583585

@@ -619,6 +621,29 @@ def LLVM_DINamespaceAttr : LLVM_Attr<"DINamespace", "di_namespace",
619621
let assemblyFormat = "`<` struct(params) `>`";
620622
}
621623

624+
//===----------------------------------------------------------------------===//
625+
// DIImportedEntityAttr
626+
//===----------------------------------------------------------------------===//
627+
628+
def LLVM_DIImportedEntityAttr : LLVM_Attr<"DIImportedEntity", "di_imported_entity",
629+
/*traits=*/[], "DINodeAttr"> {
630+
/// TODO: DIImportedEntity has a 'scope' field which represents the scope where
631+
/// this entity is imported. Currently, we are not adding a 'scope' field in
632+
/// DIImportedEntityAttr to avoid cyclic dependency. As DIImportedEntityAttr
633+
/// entries will be contained inside a scope entity (e.g. DISubprogramAttr),
634+
/// the scope can easily be inferred.
635+
let parameters = (ins
636+
LLVM_DITagParameter:$tag,
637+
"DINodeAttr":$entity,
638+
OptionalParameter<"DIFileAttr">:$file,
639+
OptionalParameter<"unsigned">:$line,
640+
OptionalParameter<"StringAttr">:$name,
641+
OptionalArrayRefParameter<"DINodeAttr">:$elements
642+
);
643+
644+
let assemblyFormat = "`<` struct(params) `>`";
645+
}
646+
622647
//===----------------------------------------------------------------------===//
623648
// DISubrangeAttr
624649
//===----------------------------------------------------------------------===//

mlir/lib/CAPI/Dialect/LLVM.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,14 +293,20 @@ MlirAttribute mlirLLVMDISubprogramAttrGet(
293293
MlirContext ctx, MlirAttribute id, MlirAttribute compileUnit,
294294
MlirAttribute scope, MlirAttribute name, MlirAttribute linkageName,
295295
MlirAttribute file, unsigned int line, unsigned int scopeLine,
296-
uint64_t subprogramFlags, MlirAttribute type) {
296+
uint64_t subprogramFlags, MlirAttribute type, intptr_t nRetainedNodes,
297+
MlirAttribute const *retainedNodes) {
298+
SmallVector<Attribute> nodesStorage;
299+
nodesStorage.reserve(nRetainedNodes);
297300
return wrap(DISubprogramAttr::get(
298301
unwrap(ctx), cast<DistinctAttr>(unwrap(id)),
299302
cast<DICompileUnitAttr>(unwrap(compileUnit)),
300303
cast<DIScopeAttr>(unwrap(scope)), cast<StringAttr>(unwrap(name)),
301304
cast<StringAttr>(unwrap(linkageName)), cast<DIFileAttr>(unwrap(file)),
302305
line, scopeLine, DISubprogramFlags(subprogramFlags),
303-
cast<DISubroutineTypeAttr>(unwrap(type))));
306+
cast<DISubroutineTypeAttr>(unwrap(type)),
307+
llvm::map_to_vector(
308+
unwrapList(nRetainedNodes, retainedNodes, nodesStorage),
309+
[](Attribute a) { return cast<DINodeAttr>(a); })));
304310
}
305311

306312
MlirAttribute mlirLLVMDISubprogramAttrGetScope(MlirAttribute diSubprogram) {
@@ -345,3 +351,16 @@ MlirAttribute mlirLLVMDIModuleAttrGet(MlirContext ctx, MlirAttribute file,
345351
MlirAttribute mlirLLVMDIModuleAttrGetScope(MlirAttribute diModule) {
346352
return wrap(cast<DIModuleAttr>(unwrap(diModule)).getScope());
347353
}
354+
355+
MlirAttribute mlirLLVMDIImportedEntityAttrGet(
356+
MlirContext ctx, unsigned int tag, MlirAttribute entity, MlirAttribute file,
357+
unsigned int line, MlirAttribute name, intptr_t nElements,
358+
MlirAttribute const *elements) {
359+
SmallVector<Attribute> elementsStorage;
360+
elementsStorage.reserve(nElements);
361+
return wrap(DIImportedEntityAttr::get(
362+
unwrap(ctx), tag, cast<DINodeAttr>(unwrap(entity)),
363+
cast<DIFileAttr>(unwrap(file)), line, cast<StringAttr>(unwrap(name)),
364+
llvm::map_to_vector(unwrapList(nElements, elements, elementsStorage),
365+
[](Attribute a) { return cast<DINodeAttr>(a); })));
366+
}

mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,11 @@ void LLVMDialect::registerAttributes() {
5858
bool DINodeAttr::classof(Attribute attr) {
5959
return llvm::isa<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
6060
DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr,
61-
DILabelAttr, DILexicalBlockAttr, DILexicalBlockFileAttr,
62-
DILocalVariableAttr, DIModuleAttr, DINamespaceAttr,
63-
DINullTypeAttr, DIStringTypeAttr, DISubprogramAttr,
64-
DISubrangeAttr, DISubroutineTypeAttr>(attr);
61+
DIImportedEntityAttr, DILabelAttr, DILexicalBlockAttr,
62+
DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,
63+
DINamespaceAttr, DINullTypeAttr, DIStringTypeAttr,
64+
DISubprogramAttr, DISubrangeAttr, DISubroutineTypeAttr>(
65+
attr);
6566
}
6667

6768
//===----------------------------------------------------------------------===//

mlir/lib/Dialect/LLVMIR/Transforms/DIScopeForLLVMFuncOp.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ static void addScopeToFunction(LLVM::LLVMFuncOp llvmFunc,
7979
context, id, compileUnitAttr, fileAttr, funcNameAttr, funcNameAttr,
8080
fileAttr,
8181
/*line=*/line,
82-
/*scopeline=*/col, subprogramFlags, subroutineTypeAttr);
82+
/*scopeline=*/col, subprogramFlags, subroutineTypeAttr,
83+
/*retainedNodes=*/{});
8384
llvmFunc->setLoc(FusedLoc::get(context, {loc}, subprogramAttr));
8485
}
8586

mlir/lib/Target/LLVMIR/DebugImporter.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,20 @@ DINamespaceAttr DebugImporter::translateImpl(llvm::DINamespace *node) {
208208
node->getExportSymbols());
209209
}
210210

211+
DIImportedEntityAttr
212+
DebugImporter::translateImpl(llvm::DIImportedEntity *node) {
213+
SmallVector<DINodeAttr> elements;
214+
for (llvm::DINode *element : node->getElements()) {
215+
assert(element && "expected a non-null element type");
216+
elements.push_back(translate(element));
217+
}
218+
219+
return DIImportedEntityAttr::get(
220+
context, node->getTag(), translate(node->getEntity()),
221+
translate(node->getFile()), node->getLine(),
222+
getStringAttrOrNull(node->getRawName()), elements);
223+
}
224+
211225
DISubprogramAttr DebugImporter::translateImpl(llvm::DISubprogram *node) {
212226
// Only definitions require a distinct identifier.
213227
mlir::DistinctAttr id;
@@ -223,11 +237,17 @@ DISubprogramAttr DebugImporter::translateImpl(llvm::DISubprogram *node) {
223237
DISubroutineTypeAttr type = translate(node->getType());
224238
if (node->getType() && !type)
225239
return nullptr;
240+
241+
SmallVector<DINodeAttr> retainedNodes;
242+
for (llvm::DINode *retainedNode : node->getRetainedNodes())
243+
retainedNodes.push_back(translate(retainedNode));
244+
226245
return DISubprogramAttr::get(context, id, translate(node->getUnit()), scope,
227246
getStringAttrOrNull(node->getRawName()),
228247
getStringAttrOrNull(node->getRawLinkageName()),
229248
translate(node->getFile()), node->getLine(),
230-
node->getScopeLine(), *subprogramFlags, type);
249+
node->getScopeLine(), *subprogramFlags, type,
250+
retainedNodes);
231251
}
232252

233253
DISubrangeAttr DebugImporter::translateImpl(llvm::DISubrange *node) {
@@ -308,6 +328,8 @@ DINodeAttr DebugImporter::translate(llvm::DINode *node) {
308328
return translateImpl(casted);
309329
if (auto *casted = dyn_cast<llvm::DIGlobalVariable>(node))
310330
return translateImpl(casted);
331+
if (auto *casted = dyn_cast<llvm::DIImportedEntity>(node))
332+
return translateImpl(casted);
311333
if (auto *casted = dyn_cast<llvm::DILabel>(node))
312334
return translateImpl(casted);
313335
if (auto *casted = dyn_cast<llvm::DILexicalBlock>(node))

mlir/lib/Target/LLVMIR/DebugImporter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class DebugImporter {
7575
DIVariableAttr translateImpl(llvm::DIVariable *node);
7676
DIModuleAttr translateImpl(llvm::DIModule *node);
7777
DINamespaceAttr translateImpl(llvm::DINamespace *node);
78+
DIImportedEntityAttr translateImpl(llvm::DIImportedEntity *node);
7879
DIScopeAttr translateImpl(llvm::DIScope *node);
7980
DISubprogramAttr translateImpl(llvm::DISubprogram *node);
8081
DISubrangeAttr translateImpl(llvm::DISubrange *node);

mlir/lib/Target/LLVMIR/DebugTranslation.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,19 @@ llvm::DISubprogram *DebugTranslation::translateImpl(DISubprogramAttr attr) {
306306
static_cast<llvm::DISubprogram::DISPFlags>(attr.getSubprogramFlags()),
307307
compileUnit);
308308

309+
// DIImportedEntity requires scope information which DIImportedEntityAttr does
310+
// not have. This is why we translate DIImportedEntityAttr after we have
311+
// created DISubprogram as we can use it as the scope.
312+
SmallVector<llvm::Metadata *> retainedNodes;
313+
for (DINodeAttr nodeAttr : attr.getRetainedNodes()) {
314+
if (auto importedAttr = dyn_cast<DIImportedEntityAttr>(nodeAttr)) {
315+
llvm::DINode *dn = translate(importedAttr, node);
316+
retainedNodes.push_back(dn);
317+
}
318+
}
319+
if (!retainedNodes.empty())
320+
node->replaceRetainedNodes(llvm::MDTuple::get(llvmCtx, retainedNodes));
321+
309322
if (attr.getId())
310323
distinctAttrToNode.try_emplace(attr.getId(), node);
311324
return node;
@@ -326,6 +339,18 @@ llvm::DINamespace *DebugTranslation::translateImpl(DINamespaceAttr attr) {
326339
attr.getExportSymbols());
327340
}
328341

342+
llvm::DIImportedEntity *DebugTranslation::translate(DIImportedEntityAttr attr,
343+
llvm::DIScope *scope) {
344+
SmallVector<llvm::Metadata *> elements;
345+
for (DINodeAttr member : attr.getElements())
346+
elements.push_back(translate(member));
347+
348+
return llvm::DIImportedEntity::get(
349+
llvmCtx, attr.getTag(), scope, translate(attr.getEntity()),
350+
translate(attr.getFile()), attr.getLine(),
351+
getMDStringOrNull(attr.getName()), llvm::MDNode::get(llvmCtx, elements));
352+
}
353+
329354
llvm::DISubrange *DebugTranslation::translateImpl(DISubrangeAttr attr) {
330355
auto getMetadataOrNull = [&](Attribute attr) -> llvm::Metadata * {
331356
if (!attr)

mlir/lib/Target/LLVMIR/DebugTranslation.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ class DebugTranslation {
9090
llvm::DISubroutineType *translateImpl(DISubroutineTypeAttr attr);
9191
llvm::DIType *translateImpl(DITypeAttr attr);
9292

93+
/// Currently, DIImportedEntityAttr does not have a scope field to avoid a
94+
/// cyclic dependency. The scope information is obtained from the entity
95+
/// which holds the list of DIImportedEntityAttr. This requires that scope
96+
/// information be passed to translate function.
97+
llvm::DIImportedEntity *translate(DIImportedEntityAttr attr, llvm::DIScope *);
98+
9399
/// Attributes that support self recursion need to implement an additional
94100
/// method to hook into `translateRecursive`.
95101
/// - `<temp llvm type> translateTemporaryImpl(<mlir type>)`:

0 commit comments

Comments
 (0)