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