| 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 "mlir/Support/CyclicReplacerCache.h" |
| 21 | #include "llvm/ADT/MapVector.h" |
| 22 | #include "llvm/IR/DebugInfoMetadata.h" |
| 23 | |
| 24 | namespace mlir { |
| 25 | class Operation; |
| 26 | |
| 27 | namespace LLVM { |
| 28 | class LLVMFuncOp; |
| 29 | |
| 30 | namespace detail { |
| 31 | |
| 32 | class DebugImporter { |
| 33 | public: |
| 34 | DebugImporter(ModuleOp mlirModule, bool dropDICompositeTypeElements); |
| 35 | |
| 36 | /// Translates the given LLVM debug location to an MLIR location. |
| 37 | Location translateLoc(llvm::DILocation *loc); |
| 38 | |
| 39 | /// Translates the LLVM DWARF expression metadata to MLIR. |
| 40 | DIExpressionAttr translateExpression(llvm::DIExpression *node); |
| 41 | |
| 42 | /// Translates the LLVM DWARF global variable expression metadata to MLIR. |
| 43 | DIGlobalVariableExpressionAttr |
| 44 | translateGlobalVariableExpression(llvm::DIGlobalVariableExpression *node); |
| 45 | |
| 46 | /// Translates the debug information for the given function into a Location. |
| 47 | /// Returns UnknownLoc if `func` has no debug information attached to it. |
| 48 | Location translateFuncLocation(llvm::Function *func); |
| 49 | |
| 50 | /// Translates the given LLVM debug metadata to MLIR. |
| 51 | DINodeAttr translate(llvm::DINode *node); |
| 52 | |
| 53 | /// Infers the metadata type and translates it to MLIR. |
| 54 | template <typename DINodeT> |
| 55 | auto translate(DINodeT *node) { |
| 56 | // Infer the MLIR type from the LLVM metadata type. |
| 57 | using MLIRTypeT = decltype(translateImpl(node)); |
| 58 | return cast_or_null<MLIRTypeT>( |
| 59 | translate(node: static_cast<llvm::DINode *>(node))); |
| 60 | } |
| 61 | |
| 62 | private: |
| 63 | /// Translates the given LLVM debug metadata to the corresponding attribute. |
| 64 | DIBasicTypeAttr translateImpl(llvm::DIBasicType *node); |
| 65 | DICompileUnitAttr translateImpl(llvm::DICompileUnit *node); |
| 66 | DICompositeTypeAttr translateImpl(llvm::DICompositeType *node); |
| 67 | DIDerivedTypeAttr translateImpl(llvm::DIDerivedType *node); |
| 68 | DIStringTypeAttr translateImpl(llvm::DIStringType *node); |
| 69 | DIFileAttr translateImpl(llvm::DIFile *node); |
| 70 | DILabelAttr translateImpl(llvm::DILabel *node); |
| 71 | DILexicalBlockAttr translateImpl(llvm::DILexicalBlock *node); |
| 72 | DILexicalBlockFileAttr translateImpl(llvm::DILexicalBlockFile *node); |
| 73 | DIGlobalVariableAttr translateImpl(llvm::DIGlobalVariable *node); |
| 74 | DILocalVariableAttr translateImpl(llvm::DILocalVariable *node); |
| 75 | DIVariableAttr translateImpl(llvm::DIVariable *node); |
| 76 | DIModuleAttr translateImpl(llvm::DIModule *node); |
| 77 | DINamespaceAttr translateImpl(llvm::DINamespace *node); |
| 78 | DIImportedEntityAttr translateImpl(llvm::DIImportedEntity *node); |
| 79 | DIScopeAttr translateImpl(llvm::DIScope *node); |
| 80 | DISubprogramAttr translateImpl(llvm::DISubprogram *node); |
| 81 | DISubrangeAttr translateImpl(llvm::DISubrange *node); |
| 82 | DIGenericSubrangeAttr translateImpl(llvm::DIGenericSubrange *node); |
| 83 | DICommonBlockAttr translateImpl(llvm::DICommonBlock *node); |
| 84 | DISubroutineTypeAttr translateImpl(llvm::DISubroutineType *node); |
| 85 | DITypeAttr translateImpl(llvm::DIType *node); |
| 86 | |
| 87 | /// Constructs a StringAttr from the MDString if it is non-null. Returns a |
| 88 | /// null attribute otherwise. |
| 89 | StringAttr getStringAttrOrNull(llvm::MDString *stringNode); |
| 90 | |
| 91 | /// Get the DistinctAttr used to represent `node` if one was already created |
| 92 | /// for it, or create a new one if not. |
| 93 | DistinctAttr getOrCreateDistinctID(llvm::DINode *node); |
| 94 | |
| 95 | std::optional<DINodeAttr> createRecSelf(llvm::DINode *node); |
| 96 | |
| 97 | /// A mapping between distinct LLVM debug metadata nodes and the corresponding |
| 98 | /// distinct id attribute. |
| 99 | DenseMap<llvm::DINode *, DistinctAttr> nodeToDistinctAttr; |
| 100 | |
| 101 | /// A mapping between DINodes that are recursive, and their assigned recId. |
| 102 | /// This is kept so that repeated occurrences of the same node can reuse the |
| 103 | /// same ID and be deduplicated. |
| 104 | DenseMap<llvm::DINode *, DistinctAttr> nodeToRecId; |
| 105 | |
| 106 | CyclicReplacerCache<llvm::DINode *, DINodeAttr> cache; |
| 107 | |
| 108 | MLIRContext *context; |
| 109 | ModuleOp mlirModule; |
| 110 | |
| 111 | /// An option to control if DICompositeTypes should always be imported without |
| 112 | /// converting their elements. If set, the option avoids the recursive |
| 113 | /// traversal of composite type debug information, which can be expensive for |
| 114 | /// adversarial inputs. |
| 115 | bool dropDICompositeTypeElements; |
| 116 | }; |
| 117 | |
| 118 | } // namespace detail |
| 119 | } // namespace LLVM |
| 120 | } // namespace mlir |
| 121 | |
| 122 | #endif // MLIR_LIB_TARGET_LLVMIR_DEBUGIMPORTER_H_ |
| 123 | |