1//===- DebugImporter.h - LLVM to MLIR Debug conversion -------*- C++ -*----===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the translation between LLVMIR debug information and
10// the corresponding MLIR representation.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef MLIR_LIB_TARGET_LLVMIR_DEBUGIMPORTER_H_
15#define MLIR_LIB_TARGET_LLVMIR_DEBUGIMPORTER_H_
16
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"
21
22namespace mlir {
23class Operation;
24
25namespace LLVM {
26class LLVMFuncOp;
27
28namespace detail {
29
30class DebugImporter {
31public:
32 DebugImporter(ModuleOp mlirModule, bool dropDICompositeTypeElements);
33
34 /// Translates the given LLVM debug location to an MLIR location.
35 Location translateLoc(llvm::DILocation *loc);
36
37 /// Translates the LLVM DWARF expression metadata to MLIR.
38 DIExpressionAttr translateExpression(llvm::DIExpression *node);
39
40 /// Translates the LLVM DWARF global variable expression metadata to MLIR.
41 DIGlobalVariableExpressionAttr
42 translateGlobalVariableExpression(llvm::DIGlobalVariableExpression *node);
43
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);
47
48 /// Translates the given LLVM debug metadata to MLIR.
49 DINodeAttr translate(llvm::DINode *node);
50
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(node: static_cast<llvm::DINode *>(node)));
58 }
59
60private:
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);
79
80 /// Constructs a StringAttr from the MDString if it is non-null. Returns a
81 /// null attribute otherwise.
82 StringAttr getStringAttrOrNull(llvm::MDString *stringNode);
83
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);
87
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;
93
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.
97 ///
98 /// Usage:
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
102 /// DINodeAttr.
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.
109 ///
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 {
116 public:
117 RecursionPruner(MLIRContext *context) : context(context) {}
118
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);
125
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,
130 DINodeAttr result);
131
132 /// Pop off a frame from the translation stack after a node is done being
133 /// translated.
134 void popTranslationStack(llvm::DINode *node);
135
136 private:
137 /// Returns the cached result (if exists) or null.
138 /// The cache entry will be removed if not all of its dependent self-refs
139 /// exists.
140 DINodeAttr lookup(llvm::DINode *node);
141
142 MLIRContext *context;
143
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
148 /// recursive attrs.
149 DINodeAttr attr;
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;
153 };
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;
158
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;
170 };
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;
177
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;
182 };
183 RecursionPruner recursionPruner;
184
185 MLIRContext *context;
186 ModuleOp mlirModule;
187
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;
193};
194
195} // namespace detail
196} // namespace LLVM
197} // namespace mlir
198
199#endif // MLIR_LIB_TARGET_LLVMIR_DEBUGIMPORTER_H_
200

source code of mlir/lib/Target/LLVMIR/DebugImporter.h