xref: /llvm-project/flang/lib/Lower/ConvertType.cpp (revision c373f58134997a6d037f0143f13f97451278700f)
1 //===-- ConvertType.cpp ---------------------------------------------------===//
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 #include "flang/Lower/ConvertType.h"
10 #include "flang/Lower/AbstractConverter.h"
11 #include "flang/Lower/CallInterface.h"
12 #include "flang/Lower/ConvertVariable.h"
13 #include "flang/Lower/Mangler.h"
14 #include "flang/Lower/PFTBuilder.h"
15 #include "flang/Lower/Support/Utils.h"
16 #include "flang/Optimizer/Builder/Todo.h"
17 #include "flang/Optimizer/Dialect/FIRType.h"
18 #include "flang/Semantics/tools.h"
19 #include "flang/Semantics/type.h"
20 #include "mlir/IR/Builders.h"
21 #include "mlir/IR/BuiltinTypes.h"
22 #include "llvm/Support/Debug.h"
23 
24 #define DEBUG_TYPE "flang-lower-type"
25 
26 using Fortran::common::VectorElementCategory;
27 
28 //===--------------------------------------------------------------------===//
29 // Intrinsic type translation helpers
30 //===--------------------------------------------------------------------===//
31 
32 static mlir::Type genRealType(mlir::MLIRContext *context, int kind) {
33   if (Fortran::evaluate::IsValidKindOfIntrinsicType(
34           Fortran::common::TypeCategory::Real, kind)) {
35     switch (kind) {
36     case 2:
37       return mlir::FloatType::getF16(context);
38     case 3:
39       return mlir::FloatType::getBF16(context);
40     case 4:
41       return mlir::FloatType::getF32(context);
42     case 8:
43       return mlir::FloatType::getF64(context);
44     case 10:
45       return mlir::FloatType::getF80(context);
46     case 16:
47       return mlir::FloatType::getF128(context);
48     }
49   }
50   llvm_unreachable("REAL type translation not implemented");
51 }
52 
53 template <int KIND>
54 int getIntegerBits() {
55   return Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer,
56                                  KIND>::Scalar::bits;
57 }
58 static mlir::Type genIntegerType(mlir::MLIRContext *context, int kind,
59                                  bool isUnsigned = false) {
60   if (Fortran::evaluate::IsValidKindOfIntrinsicType(
61           Fortran::common::TypeCategory::Integer, kind)) {
62     mlir::IntegerType::SignednessSemantics signedness =
63         (isUnsigned ? mlir::IntegerType::SignednessSemantics::Unsigned
64                     : mlir::IntegerType::SignednessSemantics::Signless);
65 
66     switch (kind) {
67     case 1:
68       return mlir::IntegerType::get(context, getIntegerBits<1>(), signedness);
69     case 2:
70       return mlir::IntegerType::get(context, getIntegerBits<2>(), signedness);
71     case 4:
72       return mlir::IntegerType::get(context, getIntegerBits<4>(), signedness);
73     case 8:
74       return mlir::IntegerType::get(context, getIntegerBits<8>(), signedness);
75     case 16:
76       return mlir::IntegerType::get(context, getIntegerBits<16>(), signedness);
77     }
78   }
79   llvm_unreachable("INTEGER kind not translated");
80 }
81 
82 static mlir::Type genLogicalType(mlir::MLIRContext *context, int KIND) {
83   if (Fortran::evaluate::IsValidKindOfIntrinsicType(
84           Fortran::common::TypeCategory::Logical, KIND))
85     return fir::LogicalType::get(context, KIND);
86   return {};
87 }
88 
89 static mlir::Type genCharacterType(
90     mlir::MLIRContext *context, int KIND,
91     Fortran::lower::LenParameterTy len = fir::CharacterType::unknownLen()) {
92   if (Fortran::evaluate::IsValidKindOfIntrinsicType(
93           Fortran::common::TypeCategory::Character, KIND))
94     return fir::CharacterType::get(context, KIND, len);
95   return {};
96 }
97 
98 static mlir::Type genComplexType(mlir::MLIRContext *context, int KIND) {
99   if (Fortran::evaluate::IsValidKindOfIntrinsicType(
100           Fortran::common::TypeCategory::Complex, KIND))
101     return fir::ComplexType::get(context, KIND);
102   return {};
103 }
104 
105 static mlir::Type
106 genFIRType(mlir::MLIRContext *context, Fortran::common::TypeCategory tc,
107            int kind,
108            llvm::ArrayRef<Fortran::lower::LenParameterTy> lenParameters) {
109   switch (tc) {
110   case Fortran::common::TypeCategory::Real:
111     return genRealType(context, kind);
112   case Fortran::common::TypeCategory::Integer:
113     return genIntegerType(context, kind);
114   case Fortran::common::TypeCategory::Complex:
115     return genComplexType(context, kind);
116   case Fortran::common::TypeCategory::Logical:
117     return genLogicalType(context, kind);
118   case Fortran::common::TypeCategory::Character:
119     if (!lenParameters.empty())
120       return genCharacterType(context, kind, lenParameters[0]);
121     return genCharacterType(context, kind);
122   default:
123     break;
124   }
125   llvm_unreachable("unhandled type category");
126 }
127 
128 //===--------------------------------------------------------------------===//
129 // Symbol and expression type translation
130 //===--------------------------------------------------------------------===//
131 
132 /// TypeBuilderImpl translates expression and symbol type taking into account
133 /// their shape and length parameters. For symbols, attributes such as
134 /// ALLOCATABLE or POINTER are reflected in the fir type.
135 /// It uses evaluate::DynamicType and evaluate::Shape when possible to
136 /// avoid re-implementing type/shape analysis here.
137 /// Do not use the FirOpBuilder from the AbstractConverter to get fir/mlir types
138 /// since it is not guaranteed to exist yet when we lower types.
139 namespace {
140 struct TypeBuilderImpl {
141 
142   TypeBuilderImpl(Fortran::lower::AbstractConverter &converter)
143       : derivedTypeInConstruction{converter.getTypeConstructionStack()},
144         converter{converter}, context{&converter.getMLIRContext()} {}
145 
146   template <typename A>
147   mlir::Type genExprType(const A &expr) {
148     std::optional<Fortran::evaluate::DynamicType> dynamicType = expr.GetType();
149     if (!dynamicType)
150       return genTypelessExprType(expr);
151     Fortran::common::TypeCategory category = dynamicType->category();
152 
153     mlir::Type baseType;
154     bool isPolymorphic = (dynamicType->IsPolymorphic() ||
155                           dynamicType->IsUnlimitedPolymorphic()) &&
156                          !dynamicType->IsAssumedType();
157     if (dynamicType->IsUnlimitedPolymorphic()) {
158       baseType = mlir::NoneType::get(context);
159     } else if (category == Fortran::common::TypeCategory::Derived) {
160       baseType = genDerivedType(dynamicType->GetDerivedTypeSpec());
161     } else {
162       // LOGICAL, INTEGER, REAL, COMPLEX, CHARACTER
163       llvm::SmallVector<Fortran::lower::LenParameterTy> params;
164       translateLenParameters(params, category, expr);
165       baseType = genFIRType(context, category, dynamicType->kind(), params);
166     }
167     std::optional<Fortran::evaluate::Shape> shapeExpr =
168         Fortran::evaluate::GetShape(converter.getFoldingContext(), expr);
169     fir::SequenceType::Shape shape;
170     if (shapeExpr) {
171       translateShape(shape, std::move(*shapeExpr));
172     } else {
173       // Shape static analysis cannot return something useful for the shape.
174       // Use unknown extents.
175       int rank = expr.Rank();
176       if (rank < 0)
177         TODO(converter.getCurrentLocation(), "assumed rank expression types");
178       for (int dim = 0; dim < rank; ++dim)
179         shape.emplace_back(fir::SequenceType::getUnknownExtent());
180     }
181 
182     if (!shape.empty()) {
183       if (isPolymorphic)
184         return fir::ClassType::get(fir::SequenceType::get(shape, baseType));
185       return fir::SequenceType::get(shape, baseType);
186     }
187     if (isPolymorphic)
188       return fir::ClassType::get(baseType);
189     return baseType;
190   }
191 
192   template <typename A>
193   void translateShape(A &shape, Fortran::evaluate::Shape &&shapeExpr) {
194     for (Fortran::evaluate::MaybeExtentExpr extentExpr : shapeExpr) {
195       fir::SequenceType::Extent extent = fir::SequenceType::getUnknownExtent();
196       if (std::optional<std::int64_t> constantExtent =
197               toInt64(std::move(extentExpr)))
198         extent = *constantExtent;
199       shape.push_back(extent);
200     }
201   }
202 
203   template <typename A>
204   std::optional<std::int64_t> toInt64(A &&expr) {
205     return Fortran::evaluate::ToInt64(Fortran::evaluate::Fold(
206         converter.getFoldingContext(), std::move(expr)));
207   }
208 
209   template <typename A>
210   mlir::Type genTypelessExprType(const A &expr) {
211     fir::emitFatalError(converter.getCurrentLocation(), "not a typeless expr");
212   }
213 
214   mlir::Type genTypelessExprType(const Fortran::lower::SomeExpr &expr) {
215     return std::visit(
216         Fortran::common::visitors{
217             [&](const Fortran::evaluate::BOZLiteralConstant &) -> mlir::Type {
218               return mlir::NoneType::get(context);
219             },
220             [&](const Fortran::evaluate::NullPointer &) -> mlir::Type {
221               return fir::ReferenceType::get(mlir::NoneType::get(context));
222             },
223             [&](const Fortran::evaluate::ProcedureDesignator &proc)
224                 -> mlir::Type {
225               return Fortran::lower::translateSignature(proc, converter);
226             },
227             [&](const Fortran::evaluate::ProcedureRef &) -> mlir::Type {
228               return mlir::NoneType::get(context);
229             },
230             [](const auto &x) -> mlir::Type {
231               using T = std::decay_t<decltype(x)>;
232               static_assert(!Fortran::common::HasMember<
233                                 T, Fortran::evaluate::TypelessExpression>,
234                             "missing typeless expr handling");
235               llvm::report_fatal_error("not a typeless expression");
236             },
237         },
238         expr.u);
239   }
240 
241   mlir::Type genSymbolType(const Fortran::semantics::Symbol &symbol,
242                            bool isAlloc = false, bool isPtr = false) {
243     mlir::Location loc = converter.genLocation(symbol.name());
244     mlir::Type ty;
245     // If the symbol is not the same as the ultimate one (i.e, it is host or use
246     // associated), all the symbol properties are the ones of the ultimate
247     // symbol but the volatile and asynchronous attributes that may differ. To
248     // avoid issues with helper functions that would not follow association
249     // links, the fir type is built based on the ultimate symbol. This relies
250     // on the fact volatile and asynchronous are not reflected in fir types.
251     const Fortran::semantics::Symbol &ultimate = symbol.GetUltimate();
252 
253     if (Fortran::semantics::IsProcedurePointer(ultimate)) {
254       Fortran::evaluate::ProcedureDesignator proc(ultimate);
255       auto procTy{Fortran::lower::translateSignature(proc, converter)};
256       return fir::BoxProcType::get(context, procTy);
257     }
258 
259     if (const Fortran::semantics::DeclTypeSpec *type = ultimate.GetType()) {
260       if (const Fortran::semantics::IntrinsicTypeSpec *tySpec =
261               type->AsIntrinsic()) {
262         int kind = toInt64(Fortran::common::Clone(tySpec->kind())).value();
263         llvm::SmallVector<Fortran::lower::LenParameterTy> params;
264         translateLenParameters(params, tySpec->category(), ultimate);
265         ty = genFIRType(context, tySpec->category(), kind, params);
266       } else if (type->IsPolymorphic() &&
267                  !converter.getLoweringOptions().getPolymorphicTypeImpl()) {
268         // TODO is kept under experimental flag until feature is complete.
269         TODO(loc, "support for polymorphic types");
270       } else if (type->IsUnlimitedPolymorphic()) {
271         ty = mlir::NoneType::get(context);
272       } else if (const Fortran::semantics::DerivedTypeSpec *tySpec =
273                      type->AsDerived()) {
274         ty = genDerivedType(*tySpec);
275       } else {
276         fir::emitFatalError(loc, "symbol's type must have a type spec");
277       }
278     } else {
279       fir::emitFatalError(loc, "symbol must have a type");
280     }
281     bool isPolymorphic = (Fortran::semantics::IsPolymorphic(symbol) ||
282                           Fortran::semantics::IsUnlimitedPolymorphic(symbol)) &&
283                          !Fortran::semantics::IsAssumedType(symbol);
284     if (ultimate.IsObjectArray()) {
285       auto shapeExpr =
286           Fortran::evaluate::GetShape(converter.getFoldingContext(), ultimate);
287       if (!shapeExpr)
288         TODO(loc, "assumed rank symbol type");
289       fir::SequenceType::Shape shape;
290       translateShape(shape, std::move(*shapeExpr));
291       ty = fir::SequenceType::get(shape, ty);
292     }
293     if (Fortran::semantics::IsPointer(symbol))
294       return fir::wrapInClassOrBoxType(fir::PointerType::get(ty),
295                                        isPolymorphic);
296     if (Fortran::semantics::IsAllocatable(symbol))
297       return fir::wrapInClassOrBoxType(fir::HeapType::get(ty), isPolymorphic);
298     // isPtr and isAlloc are variable that were promoted to be on the
299     // heap or to be pointers, but they do not have Fortran allocatable
300     // or pointer semantics, so do not use box for them.
301     if (isPtr)
302       return fir::PointerType::get(ty);
303     if (isAlloc)
304       return fir::HeapType::get(ty);
305     if (isPolymorphic)
306       return fir::ClassType::get(ty);
307     return ty;
308   }
309 
310   /// Does \p component has non deferred lower bounds that are not compile time
311   /// constant 1.
312   static bool componentHasNonDefaultLowerBounds(
313       const Fortran::semantics::Symbol &component) {
314     if (const auto *objDetails =
315             component.detailsIf<Fortran::semantics::ObjectEntityDetails>())
316       for (const Fortran::semantics::ShapeSpec &bounds : objDetails->shape())
317         if (auto lb = bounds.lbound().GetExplicit())
318           if (auto constant = Fortran::evaluate::ToInt64(*lb))
319             if (!constant || *constant != 1)
320               return true;
321     return false;
322   }
323 
324   mlir::Type genVectorType(const Fortran::semantics::DerivedTypeSpec &tySpec) {
325     assert(tySpec.scope() && "Missing scope for Vector type");
326     auto vectorSize{tySpec.scope()->size()};
327     switch (tySpec.category()) {
328       SWITCH_COVERS_ALL_CASES
329     case (Fortran::semantics::DerivedTypeSpec::Category::IntrinsicVector): {
330       int64_t vecElemKind;
331       int64_t vecElemCategory;
332 
333       for (const auto &pair : tySpec.parameters()) {
334         if (pair.first == "element_category") {
335           vecElemCategory =
336               Fortran::evaluate::ToInt64(pair.second.GetExplicit())
337                   .value_or(-1);
338         } else if (pair.first == "element_kind") {
339           vecElemKind =
340               Fortran::evaluate::ToInt64(pair.second.GetExplicit()).value_or(0);
341         }
342       }
343 
344       assert((vecElemCategory >= 0 &&
345               static_cast<size_t>(vecElemCategory) <
346                   Fortran::common::VectorElementCategory_enumSize) &&
347              "Vector element type is not specified");
348       assert(vecElemKind && "Vector element kind is not specified");
349 
350       int64_t numOfElements = vectorSize / vecElemKind;
351       switch (static_cast<VectorElementCategory>(vecElemCategory)) {
352         SWITCH_COVERS_ALL_CASES
353       case VectorElementCategory::Integer:
354         return fir::VectorType::get(numOfElements,
355                                     genIntegerType(context, vecElemKind));
356       case VectorElementCategory::Unsigned:
357         return fir::VectorType::get(numOfElements,
358                                     genIntegerType(context, vecElemKind, true));
359       case VectorElementCategory::Real:
360         return fir::VectorType::get(numOfElements,
361                                     genRealType(context, vecElemKind));
362       }
363       break;
364     }
365     case (Fortran::semantics::DerivedTypeSpec::Category::PairVector):
366     case (Fortran::semantics::DerivedTypeSpec::Category::QuadVector):
367       return fir::VectorType::get(vectorSize * 8,
368                                   mlir::IntegerType::get(context, 1));
369     case (Fortran::semantics::DerivedTypeSpec::Category::DerivedType):
370       Fortran::common::die("Vector element type not implemented");
371     }
372   }
373 
374   mlir::Type genDerivedType(const Fortran::semantics::DerivedTypeSpec &tySpec) {
375     std::vector<std::pair<std::string, mlir::Type>> ps;
376     std::vector<std::pair<std::string, mlir::Type>> cs;
377     const Fortran::semantics::Symbol &typeSymbol = tySpec.typeSymbol();
378     if (mlir::Type ty = getTypeIfDerivedAlreadyInConstruction(typeSymbol))
379       return ty;
380 
381     if (tySpec.IsVectorType()) {
382       return genVectorType(tySpec);
383     }
384 
385     const Fortran::semantics::Scope &derivedScope = DEREF(tySpec.GetScope());
386 
387     auto rec = fir::RecordType::get(context, converter.mangleName(tySpec));
388     // Maintain the stack of types for recursive references.
389     derivedTypeInConstruction.emplace_back(typeSymbol, rec);
390 
391     // Gather the record type fields.
392     // (1) The data components.
393     if (converter.getLoweringOptions().getLowerToHighLevelFIR()) {
394       // In HLFIR the parent component is the first fir.type component.
395       for (const auto &componentName :
396            typeSymbol.get<Fortran::semantics::DerivedTypeDetails>()
397                .componentNames()) {
398         auto scopeIter = derivedScope.find(componentName);
399         assert(scopeIter != derivedScope.cend() &&
400                "failed to find derived type component symbol");
401         const Fortran::semantics::Symbol &component = scopeIter->second.get();
402         mlir::Type ty = genSymbolType(component);
403         cs.emplace_back(converter.getRecordTypeFieldName(component), ty);
404       }
405     } else {
406       for (const auto &component :
407            Fortran::semantics::OrderedComponentIterator(tySpec)) {
408         // In the lowering to FIR the parent component does not appear in the
409         // fir.type and its components are inlined at the beginning of the
410         // fir.type<>.
411         // FIXME: this strategy leads to bugs because padding should be inserted
412         // after the component of the parents so that the next components do not
413         // end-up in the parent storage if the sum of the parent's component
414         // storage size is not a multiple of the parent type storage alignment.
415 
416         // Lowering is assuming non deferred component lower bounds are
417         // always 1. Catch any situations where this is not true for now.
418         if (componentHasNonDefaultLowerBounds(component))
419           TODO(converter.genLocation(component.name()),
420                "derived type components with non default lower bounds");
421         if (IsProcedure(component))
422           TODO(converter.genLocation(component.name()), "procedure components");
423         mlir::Type ty = genSymbolType(component);
424         // Do not add the parent component (component of the parents are
425         // added and should be sufficient, the parent component would
426         // duplicate the fields). Note that genSymbolType must be called above
427         // on it so that the dispatch table for the parent type still gets
428         // emitted as needed.
429         if (component.test(Fortran::semantics::Symbol::Flag::ParentComp))
430           continue;
431         cs.emplace_back(converter.getRecordTypeFieldName(component), ty);
432       }
433     }
434 
435     mlir::Location loc = converter.genLocation(typeSymbol.name());
436     // (2) The LEN type parameters.
437     for (const auto &param :
438          Fortran::semantics::OrderParameterDeclarations(typeSymbol))
439       if (param->get<Fortran::semantics::TypeParamDetails>().attr() ==
440           Fortran::common::TypeParamAttr::Len) {
441         TODO(loc, "parameterized derived types");
442         // TODO: emplace in ps. Beware that param is the symbol in the type
443         // declaration, not instantiation: its kind may not be a constant.
444         // The instantiated symbol in tySpec.scope should be used instead.
445         ps.emplace_back(param->name().ToString(), genSymbolType(*param));
446       }
447 
448     rec.finalize(ps, cs);
449     popDerivedTypeInConstruction();
450 
451     if (!ps.empty()) {
452       // TODO: this type is a PDT (parametric derived type) with length
453       // parameter. Create the functions to use for allocation, dereferencing,
454       // and address arithmetic here.
455     }
456     LLVM_DEBUG(llvm::dbgs() << "derived type: " << rec << '\n');
457 
458     // Generate the type descriptor object if any
459     if (const Fortran::semantics::Symbol *typeInfoSym =
460             derivedScope.runtimeDerivedTypeDescription())
461       converter.registerTypeInfo(loc, *typeInfoSym, tySpec, rec);
462     return rec;
463   }
464 
465   // To get the character length from a symbol, make an fold a designator for
466   // the symbol to cover the case where the symbol is an assumed length named
467   // constant and its length comes from its init expression length.
468   template <int Kind>
469   fir::SequenceType::Extent
470   getCharacterLengthHelper(const Fortran::semantics::Symbol &symbol) {
471     using TC =
472         Fortran::evaluate::Type<Fortran::common::TypeCategory::Character, Kind>;
473     auto designator = Fortran::evaluate::Fold(
474         converter.getFoldingContext(),
475         Fortran::evaluate::Expr<TC>{Fortran::evaluate::Designator<TC>{symbol}});
476     if (auto len = toInt64(std::move(designator.LEN())))
477       return *len;
478     return fir::SequenceType::getUnknownExtent();
479   }
480 
481   template <typename T>
482   void translateLenParameters(
483       llvm::SmallVectorImpl<Fortran::lower::LenParameterTy> &params,
484       Fortran::common::TypeCategory category, const T &exprOrSym) {
485     if (category == Fortran::common::TypeCategory::Character)
486       params.push_back(getCharacterLength(exprOrSym));
487     else if (category == Fortran::common::TypeCategory::Derived)
488       TODO(converter.getCurrentLocation(), "derived type length parameters");
489   }
490   Fortran::lower::LenParameterTy
491   getCharacterLength(const Fortran::semantics::Symbol &symbol) {
492     const Fortran::semantics::DeclTypeSpec *type = symbol.GetType();
493     if (!type ||
494         type->category() != Fortran::semantics::DeclTypeSpec::Character ||
495         !type->AsIntrinsic())
496       llvm::report_fatal_error("not a character symbol");
497     int kind =
498         toInt64(Fortran::common::Clone(type->AsIntrinsic()->kind())).value();
499     switch (kind) {
500     case 1:
501       return getCharacterLengthHelper<1>(symbol);
502     case 2:
503       return getCharacterLengthHelper<2>(symbol);
504     case 4:
505       return getCharacterLengthHelper<4>(symbol);
506     }
507     llvm_unreachable("unknown character kind");
508   }
509 
510   template <typename A>
511   Fortran::lower::LenParameterTy getCharacterLength(const A &expr) {
512     return fir::SequenceType::getUnknownExtent();
513   }
514 
515   template <typename T>
516   Fortran::lower::LenParameterTy
517   getCharacterLength(const Fortran::evaluate::FunctionRef<T> &funcRef) {
518     if (auto constantLen = toInt64(funcRef.LEN()))
519       return *constantLen;
520     return fir::SequenceType::getUnknownExtent();
521   }
522 
523   Fortran::lower::LenParameterTy
524   getCharacterLength(const Fortran::lower::SomeExpr &expr) {
525     // Do not use dynamic type length here. We would miss constant
526     // lengths opportunities because dynamic type only has the length
527     // if it comes from a declaration.
528     if (const auto *charExpr = std::get_if<
529             Fortran::evaluate::Expr<Fortran::evaluate::SomeCharacter>>(
530             &expr.u)) {
531       if (auto constantLen = toInt64(charExpr->LEN()))
532         return *constantLen;
533     } else if (auto dynamicType = expr.GetType()) {
534       // When generating derived type type descriptor as structure constructor,
535       // semantics wraps designators to data component initialization into
536       // CLASS(*), regardless of their actual type.
537       // GetType() will recover the actual symbol type as the dynamic type, so
538       // getCharacterLength may be reached even if expr is packaged as an
539       // Expr<SomeDerived> instead of an Expr<SomeChar>.
540       // Just use the dynamic type here again to retrieve the length.
541       if (auto constantLen = toInt64(dynamicType->GetCharLength()))
542         return *constantLen;
543     }
544     return fir::SequenceType::getUnknownExtent();
545   }
546 
547   mlir::Type genVariableType(const Fortran::lower::pft::Variable &var) {
548     return genSymbolType(var.getSymbol(), var.isHeapAlloc(), var.isPointer());
549   }
550 
551   /// Derived type can be recursive. That is, pointer components of a derived
552   /// type `t` have type `t`. This helper returns `t` if it is already being
553   /// lowered to avoid infinite loops.
554   mlir::Type getTypeIfDerivedAlreadyInConstruction(
555       const Fortran::lower::SymbolRef derivedSym) const {
556     for (const auto &[sym, type] : derivedTypeInConstruction)
557       if (sym == derivedSym)
558         return type;
559     return {};
560   }
561 
562   void popDerivedTypeInConstruction() {
563     assert(!derivedTypeInConstruction.empty());
564     derivedTypeInConstruction.pop_back();
565   }
566 
567   /// Stack derived type being processed to avoid infinite loops in case of
568   /// recursive derived types. The depth of derived types is expected to be
569   /// shallow (<10), so a SmallVector is sufficient.
570   Fortran::lower::TypeConstructionStack &derivedTypeInConstruction;
571   Fortran::lower::AbstractConverter &converter;
572   mlir::MLIRContext *context;
573 };
574 } // namespace
575 
576 mlir::Type Fortran::lower::getFIRType(mlir::MLIRContext *context,
577                                       Fortran::common::TypeCategory tc,
578                                       int kind,
579                                       llvm::ArrayRef<LenParameterTy> params) {
580   return genFIRType(context, tc, kind, params);
581 }
582 
583 mlir::Type Fortran::lower::translateDerivedTypeToFIRType(
584     Fortran::lower::AbstractConverter &converter,
585     const Fortran::semantics::DerivedTypeSpec &tySpec) {
586   return TypeBuilderImpl{converter}.genDerivedType(tySpec);
587 }
588 
589 mlir::Type Fortran::lower::translateSomeExprToFIRType(
590     Fortran::lower::AbstractConverter &converter, const SomeExpr &expr) {
591   return TypeBuilderImpl{converter}.genExprType(expr);
592 }
593 
594 mlir::Type Fortran::lower::translateSymbolToFIRType(
595     Fortran::lower::AbstractConverter &converter, const SymbolRef symbol) {
596   return TypeBuilderImpl{converter}.genSymbolType(symbol);
597 }
598 
599 mlir::Type Fortran::lower::translateVariableToFIRType(
600     Fortran::lower::AbstractConverter &converter,
601     const Fortran::lower::pft::Variable &var) {
602   return TypeBuilderImpl{converter}.genVariableType(var);
603 }
604 
605 mlir::Type Fortran::lower::convertReal(mlir::MLIRContext *context, int kind) {
606   return genRealType(context, kind);
607 }
608 
609 bool Fortran::lower::isDerivedTypeWithLenParameters(
610     const Fortran::semantics::Symbol &sym) {
611   if (const Fortran::semantics::DeclTypeSpec *declTy = sym.GetType())
612     if (const Fortran::semantics::DerivedTypeSpec *derived =
613             declTy->AsDerived())
614       return Fortran::semantics::CountLenParameters(*derived) > 0;
615   return false;
616 }
617 
618 template <typename T>
619 mlir::Type Fortran::lower::TypeBuilder<T>::genType(
620     Fortran::lower::AbstractConverter &converter,
621     const Fortran::evaluate::FunctionRef<T> &funcRef) {
622   return TypeBuilderImpl{converter}.genExprType(funcRef);
623 }
624 
625 const Fortran::semantics::DerivedTypeSpec &
626 Fortran::lower::ComponentReverseIterator::advanceToParentType() {
627   const Fortran::semantics::Scope *scope = currentParentType->GetScope();
628   auto parentComp =
629       DEREF(scope).find(currentTypeDetails->GetParentComponentName().value());
630   assert(parentComp != scope->cend() && "failed to get parent component");
631   setCurrentType(parentComp->second->GetType()->derivedTypeSpec());
632   return *currentParentType;
633 }
634 
635 void Fortran::lower::ComponentReverseIterator::setCurrentType(
636     const Fortran::semantics::DerivedTypeSpec &derived) {
637   currentParentType = &derived;
638   currentTypeDetails = &currentParentType->typeSymbol()
639                             .get<Fortran::semantics::DerivedTypeDetails>();
640   componentIt = currentTypeDetails->componentNames().crbegin();
641   componentItEnd = currentTypeDetails->componentNames().crend();
642 }
643 
644 using namespace Fortran::evaluate;
645 using namespace Fortran::common;
646 FOR_EACH_SPECIFIC_TYPE(template class Fortran::lower::TypeBuilder, )
647