1 //===- DebugImporter.h - LLVM to MLIR Debug conversion -------*- C++ -*----===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements the translation between LLVMIR debug information and
10 // the corresponding MLIR representation.
12 //===----------------------------------------------------------------------===//
14 #ifndef MLIR_LIB_TARGET_LLVMIR_DEBUGIMPORTER_H_
15 #define MLIR_LIB_TARGET_LLVMIR_DEBUGIMPORTER_H_
17 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
18 #include "mlir/IR/BuiltinOps.h"
19 #include "mlir/IR/MLIRContext.h"
20 #include "llvm/IR/DebugInfoMetadata.h"
32 DebugImporter(ModuleOp mlirModule
, bool dropDICompositeTypeElements
);
34 /// Translates the given LLVM debug location to an MLIR location.
35 Location
translateLoc(llvm::DILocation
*loc
);
37 /// Translates the LLVM DWARF expression metadata to MLIR.
38 DIExpressionAttr
translateExpression(llvm::DIExpression
*node
);
40 /// Translates the LLVM DWARF global variable expression metadata to MLIR.
41 DIGlobalVariableExpressionAttr
42 translateGlobalVariableExpression(llvm::DIGlobalVariableExpression
*node
);
44 /// Translates the debug information for the given function into a Location.
45 /// Returns UnknownLoc if `func` has no debug information attached to it.
46 Location
translateFuncLocation(llvm::Function
*func
);
48 /// Translates the given LLVM debug metadata to MLIR.
49 DINodeAttr
translate(llvm::DINode
*node
);
51 /// Infers the metadata type and translates it to MLIR.
52 template <typename DINodeT
>
53 auto translate(DINodeT
*node
) {
54 // Infer the MLIR type from the LLVM metadata type.
55 using MLIRTypeT
= decltype(translateImpl(node
));
56 return cast_or_null
<MLIRTypeT
>(
57 translate(static_cast<llvm::DINode
*>(node
)));
61 /// Translates the given LLVM debug metadata to the corresponding attribute.
62 DIBasicTypeAttr
translateImpl(llvm::DIBasicType
*node
);
63 DICompileUnitAttr
translateImpl(llvm::DICompileUnit
*node
);
64 DICompositeTypeAttr
translateImpl(llvm::DICompositeType
*node
);
65 DIDerivedTypeAttr
translateImpl(llvm::DIDerivedType
*node
);
66 DIFileAttr
translateImpl(llvm::DIFile
*node
);
67 DILabelAttr
translateImpl(llvm::DILabel
*node
);
68 DILexicalBlockAttr
translateImpl(llvm::DILexicalBlock
*node
);
69 DILexicalBlockFileAttr
translateImpl(llvm::DILexicalBlockFile
*node
);
70 DIGlobalVariableAttr
translateImpl(llvm::DIGlobalVariable
*node
);
71 DILocalVariableAttr
translateImpl(llvm::DILocalVariable
*node
);
72 DIModuleAttr
translateImpl(llvm::DIModule
*node
);
73 DINamespaceAttr
translateImpl(llvm::DINamespace
*node
);
74 DIScopeAttr
translateImpl(llvm::DIScope
*node
);
75 DISubprogramAttr
translateImpl(llvm::DISubprogram
*node
);
76 DISubrangeAttr
translateImpl(llvm::DISubrange
*node
);
77 DISubroutineTypeAttr
translateImpl(llvm::DISubroutineType
*node
);
78 DITypeAttr
translateImpl(llvm::DIType
*node
);
80 /// Constructs a StringAttr from the MDString if it is non-null. Returns a
81 /// null attribute otherwise.
82 StringAttr
getStringAttrOrNull(llvm::MDString
*stringNode
);
84 /// Get the DistinctAttr used to represent `node` if one was already created
85 /// for it, or create a new one if not.
86 DistinctAttr
getOrCreateDistinctID(llvm::DINode
*node
);
88 /// A mapping between LLVM debug metadata and the corresponding attribute.
89 DenseMap
<llvm::DINode
*, DINodeAttr
> nodeToAttr
;
90 /// A mapping between distinct LLVM debug metadata nodes and the corresponding
91 /// distinct id attribute.
92 DenseMap
<llvm::DINode
*, DistinctAttr
> nodeToDistinctAttr
;
94 /// Translation helper for recursive DINodes.
95 /// Works alongside a stack-based DINode translator (the "main translator")
96 /// for gracefully handling DINodes that are recursive.
99 /// - Before translating a node, call `pruneOrPushTranslationStack` to see if
100 /// the pruner can preempt this translation. If this is a node that the
101 /// pruner already knows how to handle, it will return the translated
103 /// - After a node is successfully translated by the main translator, call
104 /// `finalizeTranslation` to save the translated result with the pruner, and
105 /// give it a chance to further modify the result.
106 /// - Regardless of success or failure by the main translator, always call
107 /// `popTranslationStack` at the end of translating a node. This is
108 /// necessary to keep the internal book-keeping in sync.
110 /// This helper maintains an internal cache so that no recursive type will
111 /// be translated more than once by the main translator.
112 /// This internal cache is different from the cache maintained by the main
113 /// translator because it may store nodes that are not self-contained (i.e.
114 /// contain unbounded recursive self-references).
115 class RecursionPruner
{
117 RecursionPruner(MLIRContext
*context
) : context(context
) {}
119 /// If this node is a recursive instance that was previously seen, returns a
120 /// self-reference. If this node was previously cached, returns the cached
121 /// result. Otherwise, returns null attr, and a translation stack frame is
122 /// created for this node. Expects `finalizeTranslation` &
123 /// `popTranslationStack` to be called on this node later.
124 DINodeAttr
pruneOrPushTranslationStack(llvm::DINode
*node
);
126 /// Register the translated result of `node`. Returns the finalized result
127 /// (with recId if recursive) and whether the result is self-contained
128 /// (i.e. contains no unbound self-refs).
129 std::pair
<DINodeAttr
, bool> finalizeTranslation(llvm::DINode
*node
,
132 /// Pop off a frame from the translation stack after a node is done being
134 void popTranslationStack(llvm::DINode
*node
);
137 /// Returns the cached result (if exists) or null.
138 /// The cache entry will be removed if not all of its dependent self-refs
140 DINodeAttr
lookup(llvm::DINode
*node
);
142 MLIRContext
*context
;
144 /// A cached translation that contains the translated attribute as well
145 /// as any unbound self-references that it depends on.
146 struct DependentTranslation
{
147 /// The translated attr. May contain unbound self-references for other
150 /// The set of unbound self-refs that this cached entry refers to. All
151 /// these self-refs must exist for the cached entry to be valid.
152 DenseSet
<DIRecursiveTypeAttrInterface
> unboundSelfRefs
;
154 /// A mapping between LLVM debug metadata and the corresponding attribute.
155 /// Only contains those with unboundSelfRefs. Fully self-contained attrs
156 /// will be cached by the outer main translator.
157 DenseMap
<llvm::DINode
*, DependentTranslation
> dependentCache
;
159 /// Each potentially recursive node will have a TranslationState pushed onto
160 /// the `translationStack` to keep track of whether this node is actually
161 /// recursive (i.e. has self-references inside), and other book-keeping.
162 struct TranslationState
{
163 /// The rec-self if this node is indeed a recursive node (i.e. another
164 /// instance of itself is seen while translating it). Null if this node
165 /// has not been seen again deeper in the translation stack.
166 DIRecursiveTypeAttrInterface recSelf
;
167 /// All the unbound recursive self references in this layer of the
168 /// translation stack.
169 DenseSet
<DIRecursiveTypeAttrInterface
> unboundSelfRefs
;
171 /// A stack that stores the metadata nodes that are being traversed. The
172 /// stack is used to handle cyclic dependencies during metadata translation.
173 /// Each node is pushed with an empty TranslationState. If it is ever seen
174 /// later when the stack is deeper, the node is recursive, and its
175 /// TranslationState is assigned a recSelf.
176 llvm::MapVector
<llvm::DINode
*, TranslationState
> translationStack
;
178 /// A mapping between DINodes that are recursive, and their assigned recId.
179 /// This is kept so that repeated occurrences of the same node can reuse the
180 /// same ID and be deduplicated.
181 DenseMap
<llvm::DINode
*, DistinctAttr
> nodeToRecId
;
183 RecursionPruner recursionPruner
;
185 MLIRContext
*context
;
188 /// An option to control if DICompositeTypes should always be imported without
189 /// converting their elements. If set, the option avoids the recursive
190 /// traversal of composite type debug information, which can be expensive for
191 /// adversarial inputs.
192 bool dropDICompositeTypeElements
;
195 } // namespace detail
199 #endif // MLIR_LIB_TARGET_LLVMIR_DEBUGIMPORTER_H_