1 //===- DebugTranslation.h - MLIR to LLVM 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 an MLIR debug information and 10 // the corresponding LLVMIR representation. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef MLIR_LIB_TARGET_LLVMIR_DEBUGTRANSLATION_H_ 15 #define MLIR_LIB_TARGET_LLVMIR_DEBUGTRANSLATION_H_ 16 17 #include "mlir/Dialect/LLVMIR/LLVMDialect.h" 18 #include "mlir/IR/Location.h" 19 #include "llvm/ADT/SmallString.h" 20 #include "llvm/ADT/StringMap.h" 21 #include "llvm/IR/DIBuilder.h" 22 23 namespace mlir { 24 class Operation; 25 26 namespace LLVM { 27 class LLVMFuncOp; 28 29 namespace detail { 30 class DebugTranslation { 31 public: 32 DebugTranslation(Operation *module, llvm::Module &llvmModule); 33 34 /// Finalize the translation of debug information. 35 void finalize(); 36 37 /// Translate the given location to an llvm debug location. 38 llvm::DILocation *translateLoc(Location loc, llvm::DILocalScope *scope); 39 40 /// Translates the given DWARF expression metadata to to LLVM. 41 llvm::DIExpression *translateExpression(LLVM::DIExpressionAttr attr); 42 43 /// Translates the given DWARF global variable expression to LLVM. 44 llvm::DIGlobalVariableExpression * 45 translateGlobalVariableExpression(LLVM::DIGlobalVariableExpressionAttr attr); 46 47 /// Translate the debug information for the given function. 48 void translate(LLVMFuncOp func, llvm::Function &llvmFunc); 49 50 /// Translate the given LLVM debug metadata to LLVM. 51 llvm::DINode *translate(DINodeAttr attr); 52 53 /// Translate the given derived LLVM debug metadata to LLVM. 54 template <typename DIAttrT> 55 auto translate(DIAttrT attr) { 56 // Infer the LLVM type from the attribute type. 57 using LLVMTypeT = std::remove_pointer_t<decltype(translateImpl(attr))>; 58 return cast_or_null<LLVMTypeT>(translate(DINodeAttr(attr))); 59 } 60 61 private: 62 /// Translate the given location to an llvm debug location with the given 63 /// scope and inlinedAt parameters. 64 llvm::DILocation *translateLoc(Location loc, llvm::DILocalScope *scope, 65 llvm::DILocation *inlinedAt); 66 67 /// Create an llvm debug file for the given file path. 68 llvm::DIFile *translateFile(StringRef fileName); 69 70 /// Translate the given attribute to the corresponding llvm debug metadata. 71 llvm::DIType *translateImpl(DINullTypeAttr attr); 72 llvm::DIBasicType *translateImpl(DIBasicTypeAttr attr); 73 llvm::DICompileUnit *translateImpl(DICompileUnitAttr attr); 74 llvm::DICompositeType *translateImpl(DICompositeTypeAttr attr); 75 llvm::DIDerivedType *translateImpl(DIDerivedTypeAttr attr); 76 llvm::DIStringType *translateImpl(DIStringTypeAttr attr); 77 llvm::DIFile *translateImpl(DIFileAttr attr); 78 llvm::DIImportedEntity *translateImpl(DIImportedEntityAttr attr); 79 llvm::DILabel *translateImpl(DILabelAttr attr); 80 llvm::DILexicalBlock *translateImpl(DILexicalBlockAttr attr); 81 llvm::DILexicalBlockFile *translateImpl(DILexicalBlockFileAttr attr); 82 llvm::DILocalScope *translateImpl(DILocalScopeAttr attr); 83 llvm::DILocalVariable *translateImpl(DILocalVariableAttr attr); 84 llvm::DIGlobalVariable *translateImpl(DIGlobalVariableAttr attr); 85 llvm::DIVariable *translateImpl(DIVariableAttr attr); 86 llvm::DIModule *translateImpl(DIModuleAttr attr); 87 llvm::DINamespace *translateImpl(DINamespaceAttr attr); 88 llvm::DIScope *translateImpl(DIScopeAttr attr); 89 llvm::DISubprogram *translateImpl(DISubprogramAttr attr); 90 llvm::DIGenericSubrange *translateImpl(DIGenericSubrangeAttr attr); 91 llvm::DISubrange *translateImpl(DISubrangeAttr attr); 92 llvm::DICommonBlock *translateImpl(DICommonBlockAttr attr); 93 llvm::DISubroutineType *translateImpl(DISubroutineTypeAttr attr); 94 llvm::DIType *translateImpl(DITypeAttr attr); 95 96 /// Attributes that support self recursion need to implement an additional 97 /// method to hook into `translateRecursive`. 98 /// - `<temp llvm type> translateTemporaryImpl(<mlir type>)`: 99 /// Create a temporary translation of the DI attr without recursively 100 /// translating any nested DI attrs. 101 llvm::DINode *translateRecursive(DIRecursiveTypeAttrInterface attr); 102 103 /// Translate the given attribute to a temporary llvm debug metadata of the 104 /// corresponding type. 105 llvm::TempDICompositeType translateTemporaryImpl(DICompositeTypeAttr attr); 106 llvm::TempDISubprogram translateTemporaryImpl(DISubprogramAttr attr); 107 108 /// Constructs a string metadata node from the string attribute. Returns 109 /// nullptr if `stringAttr` is null or contains and empty string. 110 llvm::MDString *getMDStringOrNull(StringAttr stringAttr); 111 112 /// Constructs a tuple metadata node from the `elements`. Returns nullptr if 113 /// `elements` is empty. 114 llvm::MDTuple *getMDTupleOrNull(ArrayRef<DINodeAttr> elements); 115 116 /// Constructs a DIExpression metadata node from the DIExpressionAttr. Returns 117 /// nullptr if `DIExpressionAttr` is null. 118 llvm::DIExpression *getExpressionAttrOrNull(DIExpressionAttr attr); 119 120 /// A mapping between mlir location+scope and the corresponding llvm debug 121 /// metadata. 122 DenseMap<std::tuple<Location, llvm::DILocalScope *, const llvm::DILocation *>, 123 llvm::DILocation *> 124 locationToLoc; 125 126 /// A mapping between debug attribute and the corresponding llvm debug 127 /// metadata. 128 DenseMap<Attribute, llvm::DINode *> attrToNode; 129 130 /// A mapping between recursive ID and the translated DINode. 131 llvm::MapVector<DistinctAttr, llvm::DINode *> recursiveNodeMap; 132 133 /// A mapping between a distinct ID and the translated LLVM metadata node. 134 /// This helps identify attrs that should translate into the same LLVM debug 135 /// node. 136 DenseMap<DistinctAttr, llvm::DINode *> distinctAttrToNode; 137 138 /// A mapping between filename and llvm debug file. 139 /// TODO: Change this to DenseMap<Identifier, ...> when we can 140 /// access the Identifier filename in FileLineColLoc. 141 llvm::StringMap<llvm::DIFile *> fileMap; 142 143 /// A string containing the current working directory of the compiler. 144 SmallString<256> currentWorkingDir; 145 146 /// Flag indicating if debug information should be emitted. 147 bool debugEmissionIsEnabled; 148 149 /// Debug information fields. 150 llvm::Module &llvmModule; 151 llvm::LLVMContext &llvmCtx; 152 }; 153 154 } // namespace detail 155 } // namespace LLVM 156 } // namespace mlir 157 158 #endif // MLIR_LIB_TARGET_LLVMIR_DEBUGTRANSLATION_H_ 159