FLANG
DebugTypeGenerator.h
1//===-- DebugTypeGenerator.h -- type 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// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef FORTRAN_OPTIMIZER_TRANSFORMS_DEBUGTYPEGENERATOR_H
14#define FORTRAN_OPTIMIZER_TRANSFORMS_DEBUGTYPEGENERATOR_H
15
16#include "flang/Optimizer/CodeGen/TypeConverter.h"
17#include "flang/Optimizer/Dialect/FIRCG/CGOps.h"
18#include "flang/Optimizer/Dialect/FIRType.h"
19#include "flang/Optimizer/Dialect/Support/FIRContext.h"
20#include "flang/Optimizer/Dialect/Support/KindMapping.h"
21#include "flang/Optimizer/Support/DataLayout.h"
22#include "llvm/Support/Debug.h"
23
24namespace fir {
25
35public:
36 // Currently, the handling of recursive debug type in mlir has some
37 // limitations that were discussed at the end of the thread for following
38 // PR.
39 // https://github.com/llvm/llvm-project/pull/106571
40 //
41 // Problem could be explained with the following example code:
42 // type t2
43 // type(t1), pointer :: p1
44 // end type
45 // type t1
46 // type(t2), pointer :: p2
47 // end type
48 // In the description below, type_self means a temporary type that is
49 // generated
50 // as a place holder while the members of that type are being processed.
51 //
52 // If we process t1 first then we will have the following structure after
53 // it has been processed.
54 // t1 -> t2 -> t1_self
55 // This is because when we started processing t2, we did not have the
56 // complete t1 but its place holder t1_self.
57 // Now if some entity requires t2, we will already have that in cache and
58 // will return it. But this t2 refers to t1_self and not to t1. In mlir
59 // handling, only those types are allowed to have _self reference which are
60 // wrapped by entity whose reference it is. So t1 -> t2 -> t1_self is ok
61 // because the t1_self reference can be resolved by the outer t1. But
62 // standalone t2 is not because there will be no way to resolve it. Until
63 // this is fixed in mlir, we avoid caching such types. Please see
64 // DebugTranslation::translateRecursive for details on how mlir handles
65 // recursive types.
67 mlir::LLVM::DITypeAttr lookup(mlir::Type);
68 ActiveLevels startTranslating(mlir::Type,
69 mlir::LLVM::DITypeAttr placeHolder = nullptr);
70 void finalize(mlir::Type, mlir::LLVM::DITypeAttr, ActiveLevels &&);
71 void preComponentVisitUpdate();
72 void postComponentVisitUpdate(ActiveLevels &);
73
74private:
75 void insertCacheCleanUp(mlir::Type type, int32_t depth);
76 void cleanUpCache(int32_t depth);
77 // Current depth inside a top level derived type being converted.
78 int32_t derivedTypeDepth = 0;
79 // Cache for already translated derived types with the minimum depth where
80 // this cache entry is valid. Zero means the translation is always valid, "i"
81 // means the type depends its derived type tree parent node at depth "i". Such
82 // types should be cleaned-up from the cache in the post visit of node "i".
83 // Note that any new metadata created for a type with a component in the cache
84 // with validity of "i" shall not be added to the cache with a validity
85 // smaller than "i".
86 llvm::DenseMap<mlir::Type, std::pair<mlir::LLVM::DITypeAttr, ActiveLevels>>
87 typeCache;
88 // List of parent nodes that are being recursively referred to in the
89 // component type that has just been computed.
90 ActiveLevels componentActiveRecursionLevels;
91 // Helper list that maintains the list of nodes that must be deleted from the
92 // cache when going back past listed parent depths.
94 cacheCleanupList;
95};
96
99public:
100 DebugTypeGenerator(mlir::ModuleOp module, mlir::SymbolTable *symbolTable,
101 const mlir::DataLayout &dl);
102
103 mlir::LLVM::DITypeAttr convertType(mlir::Type Ty,
104 mlir::LLVM::DIFileAttr fileAttr,
105 mlir::LLVM::DIScopeAttr scope,
106 fir::cg::XDeclareOp declOp);
107
108private:
109 mlir::LLVM::DITypeAttr convertRecordType(fir::RecordType Ty,
110 mlir::LLVM::DIFileAttr fileAttr,
111 mlir::LLVM::DIScopeAttr scope,
112 fir::cg::XDeclareOp declOp);
113 mlir::LLVM::DITypeAttr convertTupleType(mlir::TupleType Ty,
114 mlir::LLVM::DIFileAttr fileAttr,
115 mlir::LLVM::DIScopeAttr scope,
116 fir::cg::XDeclareOp declOp);
117 mlir::LLVM::DITypeAttr convertSequenceType(fir::SequenceType seqTy,
118 mlir::LLVM::DIFileAttr fileAttr,
119 mlir::LLVM::DIScopeAttr scope,
120 fir::cg::XDeclareOp declOp);
121 mlir::LLVM::DITypeAttr convertVectorType(fir::VectorType vecTy,
122 mlir::LLVM::DIFileAttr fileAttr,
123 mlir::LLVM::DIScopeAttr scope,
124 fir::cg::XDeclareOp declOp);
125
130 mlir::LLVM::DITypeAttr convertBoxedSequenceType(
131 fir::SequenceType seqTy, mlir::LLVM::DIFileAttr fileAttr,
132 mlir::LLVM::DIScopeAttr scope, fir::cg::XDeclareOp declOp,
133 bool genAllocated, bool genAssociated);
134 mlir::LLVM::DITypeAttr convertCharacterType(fir::CharacterType charTy,
135 mlir::LLVM::DIFileAttr fileAttr,
136 mlir::LLVM::DIScopeAttr scope,
137 fir::cg::XDeclareOp declOp,
138 bool hasDescriptor);
139
140 mlir::LLVM::DITypeAttr convertPointerLikeType(mlir::Type elTy,
141 mlir::LLVM::DIFileAttr fileAttr,
142 mlir::LLVM::DIScopeAttr scope,
143 fir::cg::XDeclareOp declOp,
144 bool genAllocated,
145 bool genAssociated);
146 mlir::LLVM::DILocalVariableAttr
147 generateArtificialVariable(mlir::MLIRContext *context, mlir::Value Val,
148 mlir::LLVM::DIFileAttr fileAttr,
149 mlir::LLVM::DIScopeAttr scope,
150 fir::cg::XDeclareOp declOp);
151 std::pair<std::uint64_t, unsigned short>
152 getFieldSizeAndAlign(mlir::Type fieldTy);
153
154 mlir::ModuleOp module;
155 mlir::SymbolTable *symbolTable;
156 const mlir::DataLayout *dataLayout;
157 KindMapping kindMapping;
158 fir::LLVMTypeConverter llvmTypeConverter;
159 std::uint64_t dimsSize;
160 std::uint64_t dimsOffset;
161 std::uint64_t ptrSize;
162 std::uint64_t lenOffset;
163 std::uint64_t rankOffset;
164 std::uint64_t rankSize;
165 DerivedTypeCache derivedTypeCache;
166};
167
168} // namespace fir
169
170static uint32_t getLineFromLoc(mlir::Location loc) {
171 uint32_t line = 1;
172 if (auto fileLoc = mlir::dyn_cast<mlir::FileLineColLoc>(loc))
173 line = fileLoc.getLine();
174 return line;
175}
176
177#endif // FORTRAN_OPTIMIZER_TRANSFORMS_DEBUGTYPEGENERATOR_H
This converts FIR/mlir type to DITypeAttr.
Definition: DebugTypeGenerator.h:98
Definition: DebugTypeGenerator.h:34
Definition: KindMapping.h:48
Definition: TypeConverter.h:50
Definition: AbstractConverter.h:34