Skip to content

Commit 0657c86

Browse files
committed
add exporter support for composite type
1 parent 4c03e15 commit 0657c86

File tree

3 files changed

+156
-23
lines changed

3 files changed

+156
-23
lines changed

mlir/lib/Target/LLVMIR/DebugTranslation.cpp

Lines changed: 74 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,8 @@ static DINodeT *getDistinctOrUnique(bool isDistinct, Ts &&...args) {
117117
}
118118

119119
llvm::DICompositeType *
120-
DebugTranslation::translateImpl(DICompositeTypeAttr attr) {
121-
SmallVector<llvm::Metadata *> elements;
122-
for (auto member : attr.getElements())
123-
elements.push_back(translate(member));
124-
120+
DebugTranslation::translateImpl(DICompositeTypeAttr attr,
121+
SetRecursivePlaceholderFn setRec) {
125122
// TODO: Use distinct attributes to model this, once they have landed.
126123
// Depending on the tag, composite types must be distinct.
127124
bool isDistinct = false;
@@ -133,15 +130,26 @@ DebugTranslation::translateImpl(DICompositeTypeAttr attr) {
133130
isDistinct = true;
134131
}
135132

136-
return getDistinctOrUnique<llvm::DICompositeType>(
137-
isDistinct, llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()),
138-
translate(attr.getFile()), attr.getLine(), translate(attr.getScope()),
139-
translate(attr.getBaseType()), attr.getSizeInBits(),
140-
attr.getAlignInBits(),
141-
/*OffsetInBits=*/0,
142-
/*Flags=*/static_cast<llvm::DINode::DIFlags>(attr.getFlags()),
143-
llvm::MDNode::get(llvmCtx, elements),
144-
/*RuntimeLang=*/0, /*VTableHolder=*/nullptr);
133+
llvm::DICompositeType *placeholder =
134+
getDistinctOrUnique<llvm::DICompositeType>(
135+
isDistinct, llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()),
136+
translate(attr.getFile()), attr.getLine(), translate(attr.getScope()),
137+
translate(attr.getBaseType()), attr.getSizeInBits(),
138+
attr.getAlignInBits(),
139+
/*OffsetInBits=*/0,
140+
/*Flags=*/static_cast<llvm::DINode::DIFlags>(attr.getFlags()),
141+
/*Elements=*/nullptr, /*RuntimeLang=*/0, /*VTableHolder=*/nullptr);
142+
143+
if (setRec)
144+
setRec(placeholder);
145+
146+
SmallVector<llvm::Metadata *> elements;
147+
for (auto member : attr.getElements())
148+
elements.push_back(translate(member));
149+
150+
placeholder->replaceElements(llvm::MDNode::get(llvmCtx, elements));
151+
152+
return placeholder;
145153
}
146154

147155
llvm::DIDerivedType *DebugTranslation::translateImpl(DIDerivedTypeAttr attr) {
@@ -200,22 +208,66 @@ DebugTranslation::translateImpl(DIGlobalVariableAttr attr) {
200208
attr.getIsDefined(), nullptr, nullptr, attr.getAlignInBits(), nullptr);
201209
}
202210

211+
llvm::DIType *DebugTranslation::translateImpl(DIRecursiveTypeAttr attr) {
212+
if (attr.isRecSelf()) {
213+
auto *iter = recursiveTypeMap.find(attr.getId());
214+
assert(iter != recursiveTypeMap.end() && "unbound DI recursive self type");
215+
return iter->second;
216+
}
217+
218+
size_t recursiveStackSize = recursiveTypeMap.size();
219+
auto setRecursivePlaceholderFn = [&](llvm::DIType *node) {
220+
auto [iter, inserted] = recursiveTypeMap.try_emplace(attr.getId(), node);
221+
assert(inserted && "illegal reuse of recursive id");
222+
};
223+
224+
llvm::DIType *node =
225+
TypeSwitch<DITypeAttr, llvm::DIType *>(attr.getBaseType())
226+
.Case<DICompositeTypeAttr>([&](auto attr) {
227+
return translateImpl(attr, setRecursivePlaceholderFn);
228+
});
229+
230+
assert((recursiveStackSize + 1 == recursiveTypeMap.size()) &&
231+
"internal inconsistency: unexpected recursive translation stack");
232+
recursiveTypeMap.pop_back();
233+
234+
return node;
235+
}
236+
203237
llvm::DIScope *DebugTranslation::translateImpl(DIScopeAttr attr) {
204238
return cast<llvm::DIScope>(translate(DINodeAttr(attr)));
205239
}
206240

207241
llvm::DISubprogram *DebugTranslation::translateImpl(DISubprogramAttr attr) {
242+
if (auto iter = distinctAttrToNode.find(attr.getId());
243+
iter != distinctAttrToNode.end())
244+
return cast<llvm::DISubprogram>(iter->second);
245+
246+
llvm::DIScope *scope = translate(attr.getScope());
247+
llvm::DIFile *file = translate(attr.getFile());
248+
llvm::DIType *type = translate(attr.getType());
249+
llvm::DICompileUnit *compileUnit = translate(attr.getCompileUnit());
250+
251+
// Check again after recursive calls in case this distinct node recurses back
252+
// to itself.
253+
if (auto iter = distinctAttrToNode.find(attr.getId());
254+
iter != distinctAttrToNode.end())
255+
return cast<llvm::DISubprogram>(iter->second);
256+
208257
bool isDefinition = static_cast<bool>(attr.getSubprogramFlags() &
209258
LLVM::DISubprogramFlags::Definition);
210-
return getDistinctOrUnique<llvm::DISubprogram>(
211-
isDefinition, llvmCtx, translate(attr.getScope()),
212-
getMDStringOrNull(attr.getName()),
213-
getMDStringOrNull(attr.getLinkageName()), translate(attr.getFile()),
214-
attr.getLine(), translate(attr.getType()), attr.getScopeLine(),
259+
llvm::DISubprogram *node = getDistinctOrUnique<llvm::DISubprogram>(
260+
isDefinition, llvmCtx, scope, getMDStringOrNull(attr.getName()),
261+
getMDStringOrNull(attr.getLinkageName()), file, attr.getLine(), type,
262+
attr.getScopeLine(),
215263
/*ContainingType=*/nullptr, /*VirtualIndex=*/0,
216264
/*ThisAdjustment=*/0, llvm::DINode::FlagZero,
217265
static_cast<llvm::DISubprogram::DISPFlags>(attr.getSubprogramFlags()),
218-
translate(attr.getCompileUnit()));
266+
compileUnit);
267+
268+
if (attr.getId())
269+
distinctAttrToNode.try_emplace(attr.getId(), node);
270+
return node;
219271
}
220272

221273
llvm::DIModule *DebugTranslation::translateImpl(DIModuleAttr attr) {
@@ -274,8 +326,8 @@ llvm::DINode *DebugTranslation::translate(DINodeAttr attr) {
274326
DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr,
275327
DILabelAttr, DILexicalBlockAttr, DILexicalBlockFileAttr,
276328
DILocalVariableAttr, DIModuleAttr, DINamespaceAttr,
277-
DINullTypeAttr, DISubprogramAttr, DISubrangeAttr,
278-
DISubroutineTypeAttr>(
329+
DINullTypeAttr, DIRecursiveTypeAttr, DISubprogramAttr,
330+
DISubrangeAttr, DISubroutineTypeAttr>(
279331
[&](auto attr) { return translateImpl(attr); });
280332
attrToNode.insert({attr, node});
281333
return node;

mlir/lib/Target/LLVMIR/DebugTranslation.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,22 @@ class DebugTranslation {
6868
llvm::DIFile *translateFile(StringRef fileName);
6969

7070
/// Translate the given attribute to the corresponding llvm debug metadata.
71+
///
72+
/// For attributes corresponding to DITypes that can be recursive (i.e.
73+
/// supports replacing subelements), an additional optional argument with type
74+
/// `SetRecursivePlaceholderFn` should be supported.
75+
/// The translation impl for recursive support must follow these three steps:
76+
/// 1. Produce a placeholder version of the translated node without calling
77+
/// `translate` on any subelements of the MLIR attr.
78+
/// 2. Call the SetRecursivePlaceholderFn with the placeholder node.
79+
/// 3. Translate subelements recursively using `translate` and fill the
80+
/// original placeholder.
81+
using SetRecursivePlaceholderFn = llvm::function_ref<void(llvm::DIType *)>;
7182
llvm::DIType *translateImpl(DINullTypeAttr attr);
7283
llvm::DIBasicType *translateImpl(DIBasicTypeAttr attr);
7384
llvm::DICompileUnit *translateImpl(DICompileUnitAttr attr);
74-
llvm::DICompositeType *translateImpl(DICompositeTypeAttr attr);
85+
llvm::DICompositeType *translateImpl(DICompositeTypeAttr attr,
86+
SetRecursivePlaceholderFn setRec = {});
7587
llvm::DIDerivedType *translateImpl(DIDerivedTypeAttr attr);
7688
llvm::DIFile *translateImpl(DIFileAttr attr);
7789
llvm::DILabel *translateImpl(DILabelAttr attr);
@@ -82,6 +94,7 @@ class DebugTranslation {
8294
llvm::DIGlobalVariable *translateImpl(DIGlobalVariableAttr attr);
8395
llvm::DIModule *translateImpl(DIModuleAttr attr);
8496
llvm::DINamespace *translateImpl(DINamespaceAttr attr);
97+
llvm::DIType *translateImpl(DIRecursiveTypeAttr attr);
8598
llvm::DIScope *translateImpl(DIScopeAttr attr);
8699
llvm::DISubprogram *translateImpl(DISubprogramAttr attr);
87100
llvm::DISubrange *translateImpl(DISubrangeAttr attr);
@@ -102,6 +115,14 @@ class DebugTranslation {
102115
/// metadata.
103116
DenseMap<Attribute, llvm::DINode *> attrToNode;
104117

118+
/// A mapping from DIRecursiveTypeAttr id to the translated DIType.
119+
llvm::MapVector<DistinctAttr, llvm::DIType *> recursiveTypeMap;
120+
121+
/// A mapping between distinct ID attr for DI nodes that require distinction
122+
/// and the translate LLVM metadata node. This helps identify attrs that
123+
/// should translate into the same LLVM debug node.
124+
DenseMap<DistinctAttr, llvm::DINode *> distinctAttrToNode;
125+
105126
/// A mapping between filename and llvm debug file.
106127
/// TODO: Change this to DenseMap<Identifier, ...> when we can
107128
/// access the Identifier filename in FileLineColLoc.

mlir/test/Target/LLVMIR/llvmir-debug.mlir

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,3 +342,63 @@ llvm.func @func_line_tables() {
342342
llvm.func @func_debug_directives() {
343343
llvm.return
344344
} loc(fused<#di_subprogram_2>["foo2.mlir":0:0])
345+
346+
// -----
347+
348+
// Ensure recursive types with multiple external references work.
349+
350+
// Common base nodes.
351+
#di_file = #llvm.di_file<"test.mlir" in "/">
352+
#di_null_type = #llvm.di_null_type
353+
#di_compile_unit = #llvm.di_compile_unit<id = distinct[1]<>, sourceLanguage = DW_LANG_C, file = #di_file, isOptimized = false, emissionKind = None>
354+
355+
// Recursive type itself.
356+
#di_rec_self = #llvm.di_recursive_type<id = distinct[0]<>>
357+
#di_ptr_inner = #llvm.di_derived_type<tag = DW_TAG_pointer_type, baseType = #di_rec_self, sizeInBits = 64>
358+
#di_subroutine_inner = #llvm.di_subroutine_type<types = #di_null_type, #di_ptr_inner>
359+
#di_subprogram_inner = #llvm.di_subprogram<
360+
id = distinct[2]<>,
361+
compileUnit = #di_compile_unit,
362+
scope = #di_rec_self,
363+
name = "class_method",
364+
file = #di_file,
365+
subprogramFlags = Definition,
366+
type = #di_subroutine_inner>
367+
#di_struct = #llvm.di_composite_type<
368+
tag = DW_TAG_class_type,
369+
name = "class_name",
370+
file = #di_file,
371+
line = 42,
372+
flags = "TypePassByReference|NonTrivial",
373+
elements = #di_subprogram_inner>
374+
#di_rec_struct = #llvm.di_recursive_type<id = distinct[0]<>, baseType = #di_struct>
375+
376+
// Outer types referencing the entire recursive type.
377+
#di_ptr_outer = #llvm.di_derived_type<tag = DW_TAG_pointer_type, baseType = #di_rec_struct, sizeInBits = 64>
378+
#di_subroutine_outer = #llvm.di_subroutine_type<types = #di_null_type, #di_ptr_outer>
379+
#di_subprogram_outer = #llvm.di_subprogram<
380+
id = distinct[2]<>,
381+
compileUnit = #di_compile_unit,
382+
scope = #di_rec_struct,
383+
name = "class_method",
384+
file = #di_file,
385+
subprogramFlags = Definition,
386+
type = #di_subroutine_outer>
387+
388+
#loc3 = loc(fused<#di_subprogram_outer>["test.mlir":1:1])
389+
390+
// CHECK: @class_method
391+
// CHECK: ret void, !dbg ![[LOC:.*]]
392+
393+
// CHECK: ![[CU:.*]] = distinct !DICompileUnit(
394+
// CHECK: ![[SP:.*]] = distinct !DISubprogram(name: "class_method", scope: ![[STRUCT:.*]], file: !{{.*}}, type: ![[SUBROUTINE:.*]], spFlags: DISPFlagDefinition, unit: ![[CU]])
395+
// CHECK: ![[STRUCT]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "class_name", {{.*}}, elements: ![[ELEMS:.*]])
396+
// CHECK: ![[ELEMS]] = !{![[SP]]}
397+
// CHECK: ![[SUBROUTINE]] = !DISubroutineType(types: ![[SUBROUTINE_ELEMS:.*]])
398+
// CHECK: ![[SUBROUTINE_ELEMS]] = !{null, ![[PTR:.*]]}
399+
// CHECK: ![[PTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[STRUCT]], size: 64)
400+
// CHECK: ![[LOC]] = !DILocation(line: 1, column: 1, scope: ![[SP]])
401+
402+
llvm.func @class_method() {
403+
llvm.return loc(#loc3)
404+
} loc(#loc3)

0 commit comments

Comments
 (0)