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
23namespace fir {
24
34public:
35 // Currently, the handling of recursive debug type in mlir has some
36 // limitations that were discussed at the end of the thread for following
37 // PR.
38 // https://github.com/llvm/llvm-project/pull/106571
39 //
40 // Problem could be explained with the following example code:
41 // type t2
42 // type(t1), pointer :: p1
43 // end type
44 // type t1
45 // type(t2), pointer :: p2
46 // end type
47 // In the description below, type_self means a temporary type that is
48 // generated
49 // as a place holder while the members of that type are being processed.
50 //
51 // If we process t1 first then we will have the following structure after
52 // it has been processed.
53 // t1 -> t2 -> t1_self
54 // This is because when we started processing t2, we did not have the
55 // complete t1 but its place holder t1_self.
56 // Now if some entity requires t2, we will already have that in cache and
57 // will return it. But this t2 refers to t1_self and not to t1. In mlir
58 // handling, only those types are allowed to have _self reference which are
59 // wrapped by entity whose reference it is. So t1 -> t2 -> t1_self is ok
60 // because the t1_self reference can be resolved by the outer t1. But
61 // standalone t2 is not because there will be no way to resolve it. Until
62 // this is fixed in mlir, we avoid caching such types. Please see
63 // DebugTranslation::translateRecursive for details on how mlir handles
64 // recursive types.
65 using ActiveLevels = llvm::SmallVector<int32_t, 1>;
66 mlir::LLVM::DITypeAttr lookup(mlir::Type);
67 ActiveLevels startTranslating(mlir::Type,
68 mlir::LLVM::DITypeAttr placeHolder = nullptr);
69 void finalize(mlir::Type, mlir::LLVM::DITypeAttr, ActiveLevels &&);
70 void preComponentVisitUpdate();
71 void postComponentVisitUpdate(ActiveLevels &);
72
73private:
74 void insertCacheCleanUp(mlir::Type type, int32_t depth);
75 void cleanUpCache(int32_t depth);
76 // Current depth inside a top level derived type being converted.
77 int32_t derivedTypeDepth = 0;
78 // Cache for already translated derived types with the minimum depth where
79 // this cache entry is valid. Zero means the translation is always valid, "i"
80 // means the type depends its derived type tree parent node at depth "i". Such
81 // types should be cleaned-up from the cache in the post visit of node "i".
82 // Note that any new metadata created for a type with a component in the cache
83 // with validity of "i" shall not be added to the cache with a validity
84 // smaller than "i".
85 llvm::DenseMap<mlir::Type, std::pair<mlir::LLVM::DITypeAttr, ActiveLevels>>
86 typeCache;
87 // List of parent nodes that are being recursively referred to in the
88 // component type that has just been computed.
89 ActiveLevels componentActiveRecursionLevels;
90 // Helper list that maintains the list of nodes that must be deleted from the
91 // cache when going back past listed parent depths.
93 cacheCleanupList;
94};
95
97class DebugTypeGenerator {
98public:
99 DebugTypeGenerator(mlir::ModuleOp module, mlir::SymbolTable *symbolTable,
100 const mlir::DataLayout &dl);
101
102 mlir::LLVM::DITypeAttr convertType(mlir::Type Ty,
103 mlir::LLVM::DIFileAttr fileAttr,
104 mlir::LLVM::DIScopeAttr scope,
105 fir::cg::XDeclareOp declOp);
106
107private:
108 mlir::LLVM::DITypeAttr convertRecordType(fir::RecordType Ty,
109 mlir::LLVM::DIFileAttr fileAttr,
110 mlir::LLVM::DIScopeAttr scope,
111 fir::cg::XDeclareOp declOp);
112 mlir::LLVM::DITypeAttr convertTupleType(mlir::TupleType Ty,
113 mlir::LLVM::DIFileAttr fileAttr,
114 mlir::LLVM::DIScopeAttr scope,
115 fir::cg::XDeclareOp declOp);
116 mlir::LLVM::DITypeAttr convertSequenceType(fir::SequenceType seqTy,
117 mlir::LLVM::DIFileAttr fileAttr,
118 mlir::LLVM::DIScopeAttr scope,
119 fir::cg::XDeclareOp declOp);
120 mlir::LLVM::DITypeAttr convertVectorType(fir::VectorType vecTy,
121 mlir::LLVM::DIFileAttr fileAttr,
122 mlir::LLVM::DIScopeAttr scope,
123 fir::cg::XDeclareOp declOp);
124
129 mlir::LLVM::DITypeAttr convertBoxedSequenceType(
130 fir::SequenceType seqTy, mlir::LLVM::DIFileAttr fileAttr,
131 mlir::LLVM::DIScopeAttr scope, fir::cg::XDeclareOp declOp,
132 bool genAllocated, bool genAssociated);
133 mlir::LLVM::DITypeAttr convertCharacterType(fir::CharacterType charTy,
134 mlir::LLVM::DIFileAttr fileAttr,
135 mlir::LLVM::DIScopeAttr scope,
136 fir::cg::XDeclareOp declOp,
137 bool hasDescriptor,
138 bool genStringLocation = true);
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
Definition DebugTypeGenerator.h:33
Definition KindMapping.h:48
Definition TypeConverter.h:49
Definition OpenACC.h:20
Definition AbstractConverter.h:37