Skip to content

Commit c242302

Browse files
zyx-billygysit
andauthored
[MLIR][LLVM] DI Recursive Type fix for recursion via scope of composites (#85850)
Fixes this bug for the previous recursive DI type PR: #80251 (comment). Drawing inspiration from how clang uses DIBuilder to build forward decls, this PR changes how placeholders are created & updated. Instead of requiring each recursive DIType to do in-place mutation, we simply ask for a temporary node as the placeholder, and run RAUW at the end when the concrete node is translated. This has the side effect of simplifying what's needed to add recursion support for a type. Now only one additional method needs to be created for exporting. Concretely, for this PR, `translateImpl` for DICompositeType is back to the state it was before the previous PR, and the only net addition for DICompositeType is `translateTemporaryImpl`. --------- Co-authored-by: Tobias Gysi <[email protected]>
1 parent 4a026b5 commit c242302

File tree

3 files changed

+54
-40
lines changed

3 files changed

+54
-40
lines changed

mlir/lib/Target/LLVMIR/DebugTranslation.cpp

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,20 @@ static DINodeT *getDistinctOrUnique(bool isDistinct, Ts &&...args) {
116116
return DINodeT::get(std::forward<Ts>(args)...);
117117
}
118118

119+
llvm::TempDICompositeType
120+
DebugTranslation::translateTemporaryImpl(DICompositeTypeAttr attr) {
121+
return llvm::DICompositeType::getTemporary(
122+
llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()), nullptr,
123+
attr.getLine(), nullptr, nullptr, attr.getSizeInBits(),
124+
attr.getAlignInBits(),
125+
/*OffsetInBits=*/0,
126+
/*Flags=*/static_cast<llvm::DINode::DIFlags>(attr.getFlags()),
127+
/*Elements=*/nullptr, /*RuntimeLang=*/0,
128+
/*VTableHolder=*/nullptr);
129+
}
130+
119131
llvm::DICompositeType *
120-
DebugTranslation::translateImplGetPlaceholder(DICompositeTypeAttr attr) {
132+
DebugTranslation::translateImpl(DICompositeTypeAttr attr) {
121133
// TODO: Use distinct attributes to model this, once they have landed.
122134
// Depending on the tag, composite types must be distinct.
123135
bool isDistinct = false;
@@ -129,32 +141,19 @@ DebugTranslation::translateImplGetPlaceholder(DICompositeTypeAttr attr) {
129141
isDistinct = true;
130142
}
131143

132-
llvm::TempMDTuple placeholderElements =
133-
llvm::MDNode::getTemporary(llvmCtx, std::nullopt);
144+
SmallVector<llvm::Metadata *> elements;
145+
for (DINodeAttr member : attr.getElements())
146+
elements.push_back(translate(member));
147+
134148
return getDistinctOrUnique<llvm::DICompositeType>(
135149
isDistinct, llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()),
136150
translate(attr.getFile()), attr.getLine(), translate(attr.getScope()),
137151
translate(attr.getBaseType()), attr.getSizeInBits(),
138152
attr.getAlignInBits(),
139153
/*OffsetInBits=*/0,
140154
/*Flags=*/static_cast<llvm::DINode::DIFlags>(attr.getFlags()),
141-
/*Elements=*/placeholderElements.get(), /*RuntimeLang=*/0,
142-
/*VTableHolder=*/nullptr);
143-
}
144-
145-
void DebugTranslation::translateImplFillPlaceholder(
146-
DICompositeTypeAttr attr, llvm::DICompositeType *placeholder) {
147-
SmallVector<llvm::Metadata *> elements;
148-
for (DINodeAttr member : attr.getElements())
149-
elements.push_back(translate(member));
150-
placeholder->replaceElements(llvm::MDNode::get(llvmCtx, elements));
151-
}
152-
153-
llvm::DICompositeType *
154-
DebugTranslation::translateImpl(DICompositeTypeAttr attr) {
155-
llvm::DICompositeType *placeholder = translateImplGetPlaceholder(attr);
156-
translateImplFillPlaceholder(attr, placeholder);
157-
return placeholder;
155+
llvm::MDNode::get(llvmCtx, elements),
156+
/*RuntimeLang=*/0, /*VTableHolder=*/nullptr);
158157
}
159158

160159
llvm::DIDerivedType *DebugTranslation::translateImpl(DIDerivedTypeAttr attr) {
@@ -234,10 +233,13 @@ DebugTranslation::translateRecursive(DIRecursiveTypeAttrInterface attr) {
234233
llvm::DIType *result =
235234
TypeSwitch<DIRecursiveTypeAttrInterface, llvm::DIType *>(attr)
236235
.Case<DICompositeTypeAttr>([&](auto attr) {
237-
auto *placeholder = translateImplGetPlaceholder(attr);
238-
setRecursivePlaceholder(placeholder);
239-
translateImplFillPlaceholder(attr, placeholder);
240-
return placeholder;
236+
auto temporary = translateTemporaryImpl(attr);
237+
setRecursivePlaceholder(temporary.get());
238+
// Must call `translateImpl` directly instead of `translate` to
239+
// avoid handling the recursive interface again.
240+
auto *concrete = translateImpl(attr);
241+
temporary->replaceAllUsesWith(concrete);
242+
return concrete;
241243
});
242244

243245
assert(recursiveTypeMap.back().first == recursiveId &&

mlir/lib/Target/LLVMIR/DebugTranslation.h

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -88,23 +88,16 @@ class DebugTranslation {
8888
llvm::DISubroutineType *translateImpl(DISubroutineTypeAttr attr);
8989
llvm::DIType *translateImpl(DITypeAttr attr);
9090

91-
/// Attributes that support self recursion need to implement two methods and
92-
/// hook into the `translateImpl` overload for `DIRecursiveTypeAttr`.
93-
/// - `<llvm type> translateImplGetPlaceholder(<mlir type>)`:
94-
/// Translate the DI attr without translating any potentially recursive
95-
/// nested DI attrs.
96-
/// - `void translateImplFillPlaceholder(<mlir type>, <llvm type>)`:
97-
/// Given the placeholder returned by `translateImplGetPlaceholder`, fill
98-
/// any holes by recursively translating nested DI attrs. This method must
99-
/// mutate the placeholder that is passed in, instead of creating a new one.
91+
/// Attributes that support self recursion need to implement an additional
92+
/// method to hook into `translateRecursive`.
93+
/// - `<temp llvm type> translateTemporaryImpl(<mlir type>)`:
94+
/// Create a temporary translation of the DI attr without recursively
95+
/// translating any nested DI attrs.
10096
llvm::DIType *translateRecursive(DIRecursiveTypeAttrInterface attr);
10197

102-
/// Get a placeholder DICompositeType without recursing into the elements.
103-
llvm::DICompositeType *translateImplGetPlaceholder(DICompositeTypeAttr attr);
104-
/// Completes the DICompositeType `placeholder` by recursively translating the
105-
/// elements.
106-
void translateImplFillPlaceholder(DICompositeTypeAttr attr,
107-
llvm::DICompositeType *placeholder);
98+
/// Translate the given attribute to a temporary llvm debug metadata of the
99+
/// corresponding type.
100+
llvm::TempDICompositeType translateTemporaryImpl(DICompositeTypeAttr attr);
108101

109102
/// Constructs a string metadata node from the string attribute. Returns
110103
/// nullptr if `stringAttr` is null or contains and empty string.
@@ -121,7 +114,6 @@ class DebugTranslation {
121114
DenseMap<Attribute, llvm::DINode *> attrToNode;
122115

123116
/// A mapping between recursive ID and the translated DIType.
124-
/// DIType.
125117
llvm::MapVector<DistinctAttr, llvm::DIType *> recursiveTypeMap;
126118

127119
/// A mapping between a distinct ID and the translated LLVM metadata node.

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,3 +402,23 @@ llvm.func @func_debug_directives() {
402402
llvm.func @class_method() {
403403
llvm.return loc(#loc3)
404404
} loc(#loc3)
405+
406+
// -----
407+
408+
// Ensures composite types with a recursive scope work.
409+
410+
#di_composite_type_self = #llvm.di_composite_type<tag = DW_TAG_null, recId = distinct[0]<>>
411+
#di_file = #llvm.di_file<"test.mlir" in "/">
412+
#di_subroutine_type = #llvm.di_subroutine_type<types = #di_composite_type_self>
413+
#di_subprogram = #llvm.di_subprogram<scope = #di_file, file = #di_file, subprogramFlags = Optimized, type = #di_subroutine_type>
414+
#di_composite_type = #llvm.di_composite_type<tag = DW_TAG_class_type, recId = distinct[0]<>, scope = #di_subprogram>
415+
#di_global_variable = #llvm.di_global_variable<file = #di_file, line = 1, type = #di_composite_type>
416+
#di_global_variable_expression = #llvm.di_global_variable_expression<var = #di_global_variable>
417+
418+
llvm.mlir.global @global_variable() {dbg_expr = #di_global_variable_expression} : !llvm.struct<()>
419+
420+
// CHECK: distinct !DIGlobalVariable({{.*}}type: ![[COMP:[0-9]+]],
421+
// CHECK: ![[COMP]] = distinct !DICompositeType({{.*}}scope: ![[SCOPE:[0-9]+]],
422+
// CHECK: ![[SCOPE]] = !DISubprogram({{.*}}type: ![[SUBROUTINE:[0-9]+]],
423+
// CHECK: ![[SUBROUTINE]] = !DISubroutineType(types: ![[SR_TYPES:[0-9]+]])
424+
// CHECK: ![[SR_TYPES]] = !{![[COMP]]}

0 commit comments

Comments
 (0)