aboutsummaryrefslogtreecommitdiff
path: root/mlir/lib/Target/LLVMIR/DebugTranslation.h
blob: b690d4820d7b02073ebfcfeec2c12360e1055edd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//===- DebugTranslation.h - MLIR to LLVM Debug conversion -------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the translation between an MLIR debug information and
// the corresponding LLVMIR representation.
//
//===----------------------------------------------------------------------===//

#ifndef MLIR_LIB_TARGET_LLVMIR_DEBUGTRANSLATION_H_
#define MLIR_LIB_TARGET_LLVMIR_DEBUGTRANSLATION_H_

#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/IR/Location.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/IR/DIBuilder.h"

namespace mlir {
class Operation;

namespace LLVM {
class LLVMFuncOp;

namespace detail {
class DebugTranslation {
public:
  DebugTranslation(Operation *module, llvm::Module &llvmModule);

  /// Adds the necessary module flags to the module, if not yet present.
  void addModuleFlagsIfNotPresent();

  /// Translate the given location to an llvm debug location.
  llvm::DILocation *translateLoc(Location loc, llvm::DILocalScope *scope);

  /// Translates the given DWARF expression metadata to to LLVM.
  llvm::DIExpression *translateExpression(LLVM::DIExpressionAttr attr);

  /// Translates the given DWARF global variable expression to LLVM.
  llvm::DIGlobalVariableExpression *
  translateGlobalVariableExpression(LLVM::DIGlobalVariableExpressionAttr attr);

  /// Translate the debug information for the given function.
  void translate(LLVMFuncOp func, llvm::Function &llvmFunc);

  /// Translate the given LLVM debug metadata to LLVM.
  llvm::DINode *translate(DINodeAttr attr);

  /// Translate the given derived LLVM debug metadata to LLVM.
  template <typename DIAttrT>
  auto translate(DIAttrT attr) {
    // Infer the LLVM type from the attribute type.
    using LLVMTypeT = std::remove_pointer_t<decltype(translateImpl(attr))>;
    return cast_or_null<LLVMTypeT>(translate(DINodeAttr(attr)));
  }

private:
  /// Translate the given location to an llvm debug location with the given
  /// scope and inlinedAt parameters.
  llvm::DILocation *translateLoc(Location loc, llvm::DILocalScope *scope,
                                 llvm::DILocation *inlinedAt);

  /// Create an llvm debug file for the given file path.
  llvm::DIFile *translateFile(StringRef fileName);

  /// Translate the given attribute to the corresponding llvm debug metadata.
  llvm::DIType *translateImpl(DINullTypeAttr attr);
  llvm::DIBasicType *translateImpl(DIBasicTypeAttr attr);
  llvm::DICompileUnit *translateImpl(DICompileUnitAttr attr);
  llvm::DICompositeType *translateImpl(DICompositeTypeAttr attr);
  llvm::DIDerivedType *translateImpl(DIDerivedTypeAttr attr);
  llvm::DIStringType *translateImpl(DIStringTypeAttr attr);
  llvm::DIFile *translateImpl(DIFileAttr attr);
  llvm::DIImportedEntity *translateImpl(DIImportedEntityAttr attr);
  llvm::DILabel *translateImpl(DILabelAttr attr);
  llvm::DILexicalBlock *translateImpl(DILexicalBlockAttr attr);
  llvm::DILexicalBlockFile *translateImpl(DILexicalBlockFileAttr attr);
  llvm::DILocalScope *translateImpl(DILocalScopeAttr attr);
  llvm::DILocalVariable *translateImpl(DILocalVariableAttr attr);
  llvm::DIGlobalVariable *translateImpl(DIGlobalVariableAttr attr);
  llvm::DIVariable *translateImpl(DIVariableAttr attr);
  llvm::DIModule *translateImpl(DIModuleAttr attr);
  llvm::DINamespace *translateImpl(DINamespaceAttr attr);
  llvm::DIScope *translateImpl(DIScopeAttr attr);
  llvm::DISubprogram *translateImpl(DISubprogramAttr attr);
  llvm::DIGenericSubrange *translateImpl(DIGenericSubrangeAttr attr);
  llvm::DISubrange *translateImpl(DISubrangeAttr attr);
  llvm::DICommonBlock *translateImpl(DICommonBlockAttr attr);
  llvm::DISubroutineType *translateImpl(DISubroutineTypeAttr attr);
  llvm::DIType *translateImpl(DITypeAttr attr);

  /// Attributes that support self recursion need to implement an additional
  /// method to hook into `translateRecursive`.
  /// - `<temp llvm type> translateTemporaryImpl(<mlir type>)`:
  ///   Create a temporary translation of the DI attr without recursively
  ///   translating any nested DI attrs.
  llvm::DINode *translateRecursive(DIRecursiveTypeAttrInterface attr);

  /// Translate the given attribute to a temporary llvm debug metadata of the
  /// corresponding type.
  llvm::TempDICompositeType translateTemporaryImpl(DICompositeTypeAttr attr);
  llvm::TempDISubprogram translateTemporaryImpl(DISubprogramAttr attr);

  /// Constructs a string metadata node from the string attribute. Returns
  /// nullptr if `stringAttr` is null or contains and empty string.
  llvm::MDString *getMDStringOrNull(StringAttr stringAttr);

  /// Constructs a tuple metadata node from the `elements`. Returns nullptr if
  /// `elements` is empty.
  llvm::MDTuple *getMDTupleOrNull(ArrayRef<DINodeAttr> elements);

  /// Constructs a DIExpression metadata node from the DIExpressionAttr. Returns
  /// nullptr if `DIExpressionAttr` is null.
  llvm::DIExpression *getExpressionAttrOrNull(DIExpressionAttr attr);

  /// A mapping between mlir location+scope and the corresponding llvm debug
  /// metadata.
  DenseMap<std::tuple<Location, llvm::DILocalScope *, const llvm::DILocation *>,
           llvm::DILocation *>
      locationToLoc;

  /// A mapping between debug attribute and the corresponding llvm debug
  /// metadata.
  DenseMap<Attribute, llvm::DINode *> attrToNode;

  /// A mapping between recursive ID and the translated DINode.
  llvm::MapVector<DistinctAttr, llvm::DINode *> recursiveNodeMap;

  /// A mapping between a distinct ID and the translated LLVM metadata node.
  /// This helps identify attrs that should translate into the same LLVM debug
  /// node.
  DenseMap<DistinctAttr, llvm::DINode *> distinctAttrToNode;

  /// A mapping between filename and llvm debug file.
  /// TODO: Change this to DenseMap<Identifier, ...> when we can
  /// access the Identifier filename in FileLineColLoc.
  llvm::StringMap<llvm::DIFile *> fileMap;

  /// A string containing the current working directory of the compiler.
  SmallString<256> currentWorkingDir;

  /// Flag indicating if debug information should be emitted.
  bool debugEmissionIsEnabled;

  /// Debug information fields.
  llvm::Module &llvmModule;
  llvm::LLVMContext &llvmCtx;
};

} // namespace detail
} // namespace LLVM
} // namespace mlir

#endif // MLIR_LIB_TARGET_LLVMIR_DEBUGTRANSLATION_H_