MLIR  19.0.0git
DebugImporter.h
Go to the documentation of this file.
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 
18 #include "mlir/IR/BuiltinOps.h"
19 #include "mlir/IR/MLIRContext.h"
20 #include "llvm/IR/DebugInfoMetadata.h"
21 
22 namespace mlir {
23 class Operation;
24 
25 namespace LLVM {
26 class LLVMFuncOp;
27 
28 namespace detail {
29 
31 public:
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(static_cast<llvm::DINode *>(node)));
58  }
59 
60 private:
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.
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.
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.
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.
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_
An attribute that associates a referenced attribute with a unique identifier.
This class represents the base attribute for all debug info attributes.
Definition: LLVMAttrs.h:27
This class represents a LLVM attribute that describes a debug info scope.
Definition: LLVMAttrs.h:36
This class represents a LLVM attribute that describes a debug info type.
Definition: LLVMAttrs.h:55
DINodeAttr translate(llvm::DINode *node)
Translates the given LLVM debug metadata to MLIR.
DIExpressionAttr translateExpression(llvm::DIExpression *node)
Translates the LLVM DWARF expression metadata to MLIR.
auto translate(DINodeT *node)
Infers the metadata type and translates it to MLIR.
Definition: DebugImporter.h:53
DIGlobalVariableExpressionAttr translateGlobalVariableExpression(llvm::DIGlobalVariableExpression *node)
Translates the LLVM DWARF global variable expression metadata to MLIR.
Location translateLoc(llvm::DILocation *loc)
Translates the given LLVM debug location to an MLIR location.
Location translateFuncLocation(llvm::Function *func)
Translates the debug information for the given function into a Location.
DebugImporter(ModuleOp mlirModule, bool dropDICompositeTypeElements)
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
Include the generated interface declarations.