1 //===-- ConvertType.cpp ---------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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 #include "llvm/TargetParser/Host.h"
24 #include "llvm/TargetParser/Triple.h"
26 #define DEBUG_TYPE "flang-lower-type"
28 using Fortran::common::VectorElementCategory
;
30 //===--------------------------------------------------------------------===//
31 // Intrinsic type translation helpers
32 //===--------------------------------------------------------------------===//
34 static mlir::Type
genRealType(mlir::MLIRContext
*context
, int kind
) {
35 if (Fortran::evaluate::IsValidKindOfIntrinsicType(
36 Fortran::common::TypeCategory::Real
, kind
)) {
39 return mlir::Float16Type::get(context
);
41 return mlir::BFloat16Type::get(context
);
43 return mlir::Float32Type::get(context
);
45 return mlir::Float64Type::get(context
);
47 return mlir::Float80Type::get(context
);
49 return mlir::Float128Type::get(context
);
52 llvm_unreachable("REAL type translation not implemented");
56 int getIntegerBits() {
57 return Fortran::evaluate::Type
<Fortran::common::TypeCategory::Integer
,
60 static mlir::Type
genIntegerType(mlir::MLIRContext
*context
, int kind
,
61 bool isUnsigned
= false) {
62 if (Fortran::evaluate::IsValidKindOfIntrinsicType(
63 Fortran::common::TypeCategory::Integer
, kind
)) {
64 mlir::IntegerType::SignednessSemantics signedness
=
65 (isUnsigned
? mlir::IntegerType::SignednessSemantics::Unsigned
66 : mlir::IntegerType::SignednessSemantics::Signless
);
70 return mlir::IntegerType::get(context
, getIntegerBits
<1>(), signedness
);
72 return mlir::IntegerType::get(context
, getIntegerBits
<2>(), signedness
);
74 return mlir::IntegerType::get(context
, getIntegerBits
<4>(), signedness
);
76 return mlir::IntegerType::get(context
, getIntegerBits
<8>(), signedness
);
78 return mlir::IntegerType::get(context
, getIntegerBits
<16>(), signedness
);
81 llvm_unreachable("INTEGER or UNSIGNED kind not translated");
84 static mlir::Type
genLogicalType(mlir::MLIRContext
*context
, int KIND
) {
85 if (Fortran::evaluate::IsValidKindOfIntrinsicType(
86 Fortran::common::TypeCategory::Logical
, KIND
))
87 return fir::LogicalType::get(context
, KIND
);
91 static mlir::Type
genCharacterType(
92 mlir::MLIRContext
*context
, int KIND
,
93 Fortran::lower::LenParameterTy len
= fir::CharacterType::unknownLen()) {
94 if (Fortran::evaluate::IsValidKindOfIntrinsicType(
95 Fortran::common::TypeCategory::Character
, KIND
))
96 return fir::CharacterType::get(context
, KIND
, len
);
100 static mlir::Type
genComplexType(mlir::MLIRContext
*context
, int KIND
) {
101 return mlir::ComplexType::get(genRealType(context
, KIND
));
105 genFIRType(mlir::MLIRContext
*context
, Fortran::common::TypeCategory tc
,
107 llvm::ArrayRef
<Fortran::lower::LenParameterTy
> lenParameters
) {
109 case Fortran::common::TypeCategory::Real
:
110 return genRealType(context
, kind
);
111 case Fortran::common::TypeCategory::Integer
:
112 return genIntegerType(context
, kind
, false);
113 case Fortran::common::TypeCategory::Unsigned
:
114 return genIntegerType(context
, kind
, true);
115 case Fortran::common::TypeCategory::Complex
:
116 return genComplexType(context
, kind
);
117 case Fortran::common::TypeCategory::Logical
:
118 return genLogicalType(context
, kind
);
119 case Fortran::common::TypeCategory::Character
:
120 if (!lenParameters
.empty())
121 return genCharacterType(context
, kind
, lenParameters
[0]);
122 return genCharacterType(context
, kind
);
126 llvm_unreachable("unhandled type category");
129 //===--------------------------------------------------------------------===//
130 // Symbol and expression type translation
131 //===--------------------------------------------------------------------===//
133 /// TypeBuilderImpl translates expression and symbol type taking into account
134 /// their shape and length parameters. For symbols, attributes such as
135 /// ALLOCATABLE or POINTER are reflected in the fir type.
136 /// It uses evaluate::DynamicType and evaluate::Shape when possible to
137 /// avoid re-implementing type/shape analysis here.
138 /// Do not use the FirOpBuilder from the AbstractConverter to get fir/mlir types
139 /// since it is not guaranteed to exist yet when we lower types.
141 struct TypeBuilderImpl
{
143 TypeBuilderImpl(Fortran::lower::AbstractConverter
&converter
)
144 : derivedTypeInConstruction
{converter
.getTypeConstructionStack()},
145 converter
{converter
}, context
{&converter
.getMLIRContext()} {}
147 template <typename A
>
148 mlir::Type
genExprType(const A
&expr
) {
149 std::optional
<Fortran::evaluate::DynamicType
> dynamicType
= expr
.GetType();
151 return genTypelessExprType(expr
);
152 Fortran::common::TypeCategory category
= dynamicType
->category();
155 bool isPolymorphic
= (dynamicType
->IsPolymorphic() ||
156 dynamicType
->IsUnlimitedPolymorphic()) &&
157 !dynamicType
->IsAssumedType();
158 if (dynamicType
->IsUnlimitedPolymorphic()) {
159 baseType
= mlir::NoneType::get(context
);
160 } else if (category
== Fortran::common::TypeCategory::Derived
) {
161 baseType
= genDerivedType(dynamicType
->GetDerivedTypeSpec());
163 // INTEGER, UNSIGNED, REAL, COMPLEX, CHARACTER, LOGICAL
164 llvm::SmallVector
<Fortran::lower::LenParameterTy
> params
;
165 translateLenParameters(params
, category
, expr
);
166 baseType
= genFIRType(context
, category
, dynamicType
->kind(), params
);
168 std::optional
<Fortran::evaluate::Shape
> shapeExpr
=
169 Fortran::evaluate::GetShape(converter
.getFoldingContext(), expr
);
170 fir::SequenceType::Shape shape
;
172 translateShape(shape
, std::move(*shapeExpr
));
174 // Shape static analysis cannot return something useful for the shape.
175 // Use unknown extents.
176 int rank
= expr
.Rank();
178 TODO(converter
.getCurrentLocation(), "assumed rank expression types");
179 for (int dim
= 0; dim
< rank
; ++dim
)
180 shape
.emplace_back(fir::SequenceType::getUnknownExtent());
183 if (!shape
.empty()) {
185 return fir::ClassType::get(fir::SequenceType::get(shape
, baseType
));
186 return fir::SequenceType::get(shape
, baseType
);
189 return fir::ClassType::get(baseType
);
193 template <typename A
>
194 void translateShape(A
&shape
, Fortran::evaluate::Shape
&&shapeExpr
) {
195 for (Fortran::evaluate::MaybeExtentExpr extentExpr
: shapeExpr
) {
196 fir::SequenceType::Extent extent
= fir::SequenceType::getUnknownExtent();
197 if (std::optional
<std::int64_t> constantExtent
=
198 toInt64(std::move(extentExpr
)))
199 extent
= *constantExtent
;
200 shape
.push_back(extent
);
204 template <typename A
>
205 std::optional
<std::int64_t> toInt64(A
&&expr
) {
206 return Fortran::evaluate::ToInt64(Fortran::evaluate::Fold(
207 converter
.getFoldingContext(), std::move(expr
)));
210 template <typename A
>
211 mlir::Type
genTypelessExprType(const A
&expr
) {
212 fir::emitFatalError(converter
.getCurrentLocation(), "not a typeless expr");
215 mlir::Type
genTypelessExprType(const Fortran::lower::SomeExpr
&expr
) {
216 return Fortran::common::visit(
217 Fortran::common::visitors
{
218 [&](const Fortran::evaluate::BOZLiteralConstant
&) -> mlir::Type
{
219 return mlir::NoneType::get(context
);
221 [&](const Fortran::evaluate::NullPointer
&) -> mlir::Type
{
222 return fir::ReferenceType::get(mlir::NoneType::get(context
));
224 [&](const Fortran::evaluate::ProcedureDesignator
&proc
)
226 return Fortran::lower::translateSignature(proc
, converter
);
228 [&](const Fortran::evaluate::ProcedureRef
&) -> mlir::Type
{
229 return mlir::NoneType::get(context
);
231 [](const auto &x
) -> mlir::Type
{
232 using T
= std::decay_t
<decltype(x
)>;
233 static_assert(!Fortran::common::HasMember
<
234 T
, Fortran::evaluate::TypelessExpression
>,
235 "missing typeless expr handling");
236 llvm::report_fatal_error("not a typeless expression");
242 mlir::Type
genSymbolType(const Fortran::semantics::Symbol
&symbol
,
243 bool isAlloc
= false, bool isPtr
= false) {
244 mlir::Location loc
= converter
.genLocation(symbol
.name());
246 // If the symbol is not the same as the ultimate one (i.e, it is host or use
247 // associated), all the symbol properties are the ones of the ultimate
248 // symbol but the volatile and asynchronous attributes that may differ. To
249 // avoid issues with helper functions that would not follow association
250 // links, the fir type is built based on the ultimate symbol. This relies
251 // on the fact volatile and asynchronous are not reflected in fir types.
252 const Fortran::semantics::Symbol
&ultimate
= symbol
.GetUltimate();
254 if (Fortran::semantics::IsProcedurePointer(ultimate
)) {
255 Fortran::evaluate::ProcedureDesignator
proc(ultimate
);
256 auto procTy
{Fortran::lower::translateSignature(proc
, converter
)};
257 return fir::BoxProcType::get(context
, procTy
);
260 if (const Fortran::semantics::DeclTypeSpec
*type
= ultimate
.GetType()) {
261 if (const Fortran::semantics::IntrinsicTypeSpec
*tySpec
=
262 type
->AsIntrinsic()) {
263 int kind
= toInt64(Fortran::common::Clone(tySpec
->kind())).value();
264 llvm::SmallVector
<Fortran::lower::LenParameterTy
> params
;
265 translateLenParameters(params
, tySpec
->category(), ultimate
);
266 ty
= genFIRType(context
, tySpec
->category(), kind
, params
);
267 } else if (type
->IsUnlimitedPolymorphic()) {
268 ty
= mlir::NoneType::get(context
);
269 } else if (const Fortran::semantics::DerivedTypeSpec
*tySpec
=
271 ty
= genDerivedType(*tySpec
);
273 fir::emitFatalError(loc
, "symbol's type must have a type spec");
276 fir::emitFatalError(loc
, "symbol must have a type");
278 bool isPolymorphic
= (Fortran::semantics::IsPolymorphic(symbol
) ||
279 Fortran::semantics::IsUnlimitedPolymorphic(symbol
)) &&
280 !Fortran::semantics::IsAssumedType(symbol
);
281 if (ultimate
.IsObjectArray()) {
283 Fortran::evaluate::GetShape(converter
.getFoldingContext(), ultimate
);
284 fir::SequenceType::Shape shape
;
285 // If there is no shapExpr, this is an assumed-rank, and the empty shape
286 // will build the desired fir.array<*:T> type.
288 translateShape(shape
, std::move(*shapeExpr
));
289 ty
= fir::SequenceType::get(shape
, ty
);
291 if (Fortran::semantics::IsPointer(symbol
))
292 return fir::wrapInClassOrBoxType(fir::PointerType::get(ty
),
294 if (Fortran::semantics::IsAllocatable(symbol
))
295 return fir::wrapInClassOrBoxType(fir::HeapType::get(ty
), isPolymorphic
);
296 // isPtr and isAlloc are variable that were promoted to be on the
297 // heap or to be pointers, but they do not have Fortran allocatable
298 // or pointer semantics, so do not use box for them.
300 return fir::PointerType::get(ty
);
302 return fir::HeapType::get(ty
);
304 return fir::ClassType::get(ty
);
308 /// Does \p component has non deferred lower bounds that are not compile time
310 static bool componentHasNonDefaultLowerBounds(
311 const Fortran::semantics::Symbol
&component
) {
312 if (const auto *objDetails
=
313 component
.detailsIf
<Fortran::semantics::ObjectEntityDetails
>())
314 for (const Fortran::semantics::ShapeSpec
&bounds
: objDetails
->shape())
315 if (auto lb
= bounds
.lbound().GetExplicit())
316 if (auto constant
= Fortran::evaluate::ToInt64(*lb
))
317 if (!constant
|| *constant
!= 1)
322 mlir::Type
genVectorType(const Fortran::semantics::DerivedTypeSpec
&tySpec
) {
323 assert(tySpec
.scope() && "Missing scope for Vector type");
324 auto vectorSize
{tySpec
.scope()->size()};
325 switch (tySpec
.category()) {
326 SWITCH_COVERS_ALL_CASES
327 case (Fortran::semantics::DerivedTypeSpec::Category::IntrinsicVector
): {
329 int64_t vecElemCategory
;
331 for (const auto &pair
: tySpec
.parameters()) {
332 if (pair
.first
== "element_category") {
334 Fortran::evaluate::ToInt64(pair
.second
.GetExplicit())
336 } else if (pair
.first
== "element_kind") {
338 Fortran::evaluate::ToInt64(pair
.second
.GetExplicit()).value_or(0);
342 assert((vecElemCategory
>= 0 &&
343 static_cast<size_t>(vecElemCategory
) <
344 Fortran::common::VectorElementCategory_enumSize
) &&
345 "Vector element type is not specified");
346 assert(vecElemKind
&& "Vector element kind is not specified");
348 int64_t numOfElements
= vectorSize
/ vecElemKind
;
349 switch (static_cast<VectorElementCategory
>(vecElemCategory
)) {
350 SWITCH_COVERS_ALL_CASES
351 case VectorElementCategory::Integer
:
352 return fir::VectorType::get(numOfElements
,
353 genIntegerType(context
, vecElemKind
));
354 case VectorElementCategory::Unsigned
:
355 return fir::VectorType::get(numOfElements
,
356 genIntegerType(context
, vecElemKind
, true));
357 case VectorElementCategory::Real
:
358 return fir::VectorType::get(numOfElements
,
359 genRealType(context
, vecElemKind
));
363 case (Fortran::semantics::DerivedTypeSpec::Category::PairVector
):
364 case (Fortran::semantics::DerivedTypeSpec::Category::QuadVector
):
365 return fir::VectorType::get(vectorSize
* 8,
366 mlir::IntegerType::get(context
, 1));
367 case (Fortran::semantics::DerivedTypeSpec::Category::DerivedType
):
368 Fortran::common::die("Vector element type not implemented");
372 mlir::Type
genDerivedType(const Fortran::semantics::DerivedTypeSpec
&tySpec
) {
373 std::vector
<std::pair
<std::string
, mlir::Type
>> ps
;
374 std::vector
<std::pair
<std::string
, mlir::Type
>> cs
;
375 if (tySpec
.IsVectorType()) {
376 return genVectorType(tySpec
);
379 const Fortran::semantics::Symbol
&typeSymbol
= tySpec
.typeSymbol();
380 const Fortran::semantics::Scope
&derivedScope
= DEREF(tySpec
.GetScope());
381 if (mlir::Type ty
= getTypeIfDerivedAlreadyInConstruction(derivedScope
))
384 auto rec
= fir::RecordType::get(context
, converter
.mangleName(tySpec
));
385 // Maintain the stack of types for recursive references and to speed-up
386 // the derived type constructions that can be expensive for derived type
387 // with dozens of components/parents (modern Fortran).
388 derivedTypeInConstruction
.try_emplace(&derivedScope
, rec
);
390 auto targetTriple
{llvm::Triple(
391 llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()))};
392 // Always generate packed FIR struct type for bind(c) derived type for AIX
393 if (targetTriple
.getOS() == llvm::Triple::OSType::AIX
&&
394 tySpec
.typeSymbol().attrs().test(Fortran::semantics::Attr::BIND_C
) &&
395 !IsIsoCType(&tySpec
) && !fir::isa_builtin_cdevptr_type(rec
)) {
399 // Gather the record type fields.
400 // (1) The data components.
401 if (converter
.getLoweringOptions().getLowerToHighLevelFIR()) {
402 size_t prev_offset
{0};
403 unsigned padCounter
{0};
404 // In HLFIR the parent component is the first fir.type component.
405 for (const auto &componentName
:
406 typeSymbol
.get
<Fortran::semantics::DerivedTypeDetails
>()
408 auto scopeIter
= derivedScope
.find(componentName
);
409 assert(scopeIter
!= derivedScope
.cend() &&
410 "failed to find derived type component symbol");
411 const Fortran::semantics::Symbol
&component
= scopeIter
->second
.get();
412 mlir::Type ty
= genSymbolType(component
);
413 if (rec
.isPacked()) {
414 auto compSize
{component
.size()};
415 auto compOffset
{component
.offset()};
417 if (prev_offset
< compOffset
) {
418 size_t pad
{compOffset
- prev_offset
};
419 mlir::Type i8Ty
{mlir::IntegerType::get(context
, 8)};
420 fir::SequenceType::Shape shape
{static_cast<int64_t>(pad
)};
421 mlir::Type padTy
{fir::SequenceType::get(shape
, i8Ty
)};
423 cs
.emplace_back("__padding" + std::to_string(padCounter
++), padTy
);
425 prev_offset
+= compSize
;
427 cs
.emplace_back(converter
.getRecordTypeFieldName(component
), ty
);
428 if (rec
.isPacked()) {
429 // For the last component, determine if any padding is needed.
431 typeSymbol
.get
<Fortran::semantics::DerivedTypeDetails
>()
434 auto compEnd
{component
.offset() + component
.size()};
435 if (compEnd
< derivedScope
.size()) {
436 size_t pad
{derivedScope
.size() - compEnd
};
437 mlir::Type i8Ty
{mlir::IntegerType::get(context
, 8)};
438 fir::SequenceType::Shape shape
{static_cast<int64_t>(pad
)};
439 mlir::Type padTy
{fir::SequenceType::get(shape
, i8Ty
)};
440 cs
.emplace_back("__padding" + std::to_string(padCounter
++),
447 for (const auto &component
:
448 Fortran::semantics::OrderedComponentIterator(tySpec
)) {
449 // In the lowering to FIR the parent component does not appear in the
450 // fir.type and its components are inlined at the beginning of the
452 // FIXME: this strategy leads to bugs because padding should be inserted
453 // after the component of the parents so that the next components do not
454 // end-up in the parent storage if the sum of the parent's component
455 // storage size is not a multiple of the parent type storage alignment.
457 // Lowering is assuming non deferred component lower bounds are
458 // always 1. Catch any situations where this is not true for now.
459 if (componentHasNonDefaultLowerBounds(component
))
460 TODO(converter
.genLocation(component
.name()),
461 "derived type components with non default lower bounds");
462 if (IsProcedure(component
))
463 TODO(converter
.genLocation(component
.name()), "procedure components");
464 mlir::Type ty
= genSymbolType(component
);
465 // Do not add the parent component (component of the parents are
466 // added and should be sufficient, the parent component would
467 // duplicate the fields). Note that genSymbolType must be called above
468 // on it so that the dispatch table for the parent type still gets
469 // emitted as needed.
470 if (component
.test(Fortran::semantics::Symbol::Flag::ParentComp
))
472 cs
.emplace_back(converter
.getRecordTypeFieldName(component
), ty
);
476 mlir::Location loc
= converter
.genLocation(typeSymbol
.name());
477 // (2) The LEN type parameters.
478 for (const auto ¶m
:
479 Fortran::semantics::OrderParameterDeclarations(typeSymbol
))
480 if (param
->get
<Fortran::semantics::TypeParamDetails
>().attr() ==
481 Fortran::common::TypeParamAttr::Len
) {
482 TODO(loc
, "parameterized derived types");
483 // TODO: emplace in ps. Beware that param is the symbol in the type
484 // declaration, not instantiation: its kind may not be a constant.
485 // The instantiated symbol in tySpec.scope should be used instead.
486 ps
.emplace_back(param
->name().ToString(), genSymbolType(*param
));
489 rec
.finalize(ps
, cs
);
492 // TODO: this type is a PDT (parametric derived type) with length
493 // parameter. Create the functions to use for allocation, dereferencing,
494 // and address arithmetic here.
496 LLVM_DEBUG(llvm::dbgs() << "derived type: " << rec
<< '\n');
498 // Generate the type descriptor object if any
499 if (const Fortran::semantics::Symbol
*typeInfoSym
=
500 derivedScope
.runtimeDerivedTypeDescription())
501 converter
.registerTypeInfo(loc
, *typeInfoSym
, tySpec
, rec
);
505 // To get the character length from a symbol, make an fold a designator for
506 // the symbol to cover the case where the symbol is an assumed length named
507 // constant and its length comes from its init expression length.
509 fir::SequenceType::Extent
510 getCharacterLengthHelper(const Fortran::semantics::Symbol
&symbol
) {
512 Fortran::evaluate::Type
<Fortran::common::TypeCategory::Character
, Kind
>;
513 auto designator
= Fortran::evaluate::Fold(
514 converter
.getFoldingContext(),
515 Fortran::evaluate::Expr
<TC
>{Fortran::evaluate::Designator
<TC
>{symbol
}});
516 if (auto len
= toInt64(std::move(designator
.LEN())))
518 return fir::SequenceType::getUnknownExtent();
521 template <typename T
>
522 void translateLenParameters(
523 llvm::SmallVectorImpl
<Fortran::lower::LenParameterTy
> ¶ms
,
524 Fortran::common::TypeCategory category
, const T
&exprOrSym
) {
525 if (category
== Fortran::common::TypeCategory::Character
)
526 params
.push_back(getCharacterLength(exprOrSym
));
527 else if (category
== Fortran::common::TypeCategory::Derived
)
528 TODO(converter
.getCurrentLocation(), "derived type length parameters");
530 Fortran::lower::LenParameterTy
531 getCharacterLength(const Fortran::semantics::Symbol
&symbol
) {
532 const Fortran::semantics::DeclTypeSpec
*type
= symbol
.GetType();
534 type
->category() != Fortran::semantics::DeclTypeSpec::Character
||
535 !type
->AsIntrinsic())
536 llvm::report_fatal_error("not a character symbol");
538 toInt64(Fortran::common::Clone(type
->AsIntrinsic()->kind())).value();
541 return getCharacterLengthHelper
<1>(symbol
);
543 return getCharacterLengthHelper
<2>(symbol
);
545 return getCharacterLengthHelper
<4>(symbol
);
547 llvm_unreachable("unknown character kind");
550 template <typename A
>
551 Fortran::lower::LenParameterTy
getCharacterLength(const A
&expr
) {
552 return fir::SequenceType::getUnknownExtent();
555 template <typename T
>
556 Fortran::lower::LenParameterTy
557 getCharacterLength(const Fortran::evaluate::FunctionRef
<T
> &funcRef
) {
558 if (auto constantLen
= toInt64(funcRef
.LEN()))
560 return fir::SequenceType::getUnknownExtent();
563 Fortran::lower::LenParameterTy
564 getCharacterLength(const Fortran::lower::SomeExpr
&expr
) {
565 // Do not use dynamic type length here. We would miss constant
566 // lengths opportunities because dynamic type only has the length
567 // if it comes from a declaration.
568 if (const auto *charExpr
= std::get_if
<
569 Fortran::evaluate::Expr
<Fortran::evaluate::SomeCharacter
>>(
571 if (auto constantLen
= toInt64(charExpr
->LEN()))
573 } else if (auto dynamicType
= expr
.GetType()) {
574 // When generating derived type type descriptor as structure constructor,
575 // semantics wraps designators to data component initialization into
576 // CLASS(*), regardless of their actual type.
577 // GetType() will recover the actual symbol type as the dynamic type, so
578 // getCharacterLength may be reached even if expr is packaged as an
579 // Expr<SomeDerived> instead of an Expr<SomeChar>.
580 // Just use the dynamic type here again to retrieve the length.
581 if (auto constantLen
= toInt64(dynamicType
->GetCharLength()))
584 return fir::SequenceType::getUnknownExtent();
587 mlir::Type
genVariableType(const Fortran::lower::pft::Variable
&var
) {
588 return genSymbolType(var
.getSymbol(), var
.isHeapAlloc(), var
.isPointer());
591 /// Derived type can be recursive. That is, pointer components of a derived
592 /// type `t` have type `t`. This helper returns `t` if it is already being
593 /// lowered to avoid infinite loops.
594 mlir::Type
getTypeIfDerivedAlreadyInConstruction(
595 const Fortran::semantics::Scope
&derivedScope
) const {
596 return derivedTypeInConstruction
.lookup(&derivedScope
);
599 /// Stack derived type being processed to avoid infinite loops in case of
600 /// recursive derived types. The depth of derived types is expected to be
601 /// shallow (<10), so a SmallVector is sufficient.
602 Fortran::lower::TypeConstructionStack
&derivedTypeInConstruction
;
603 Fortran::lower::AbstractConverter
&converter
;
604 mlir::MLIRContext
*context
;
608 mlir::Type
Fortran::lower::getFIRType(mlir::MLIRContext
*context
,
609 Fortran::common::TypeCategory tc
,
611 llvm::ArrayRef
<LenParameterTy
> params
) {
612 return genFIRType(context
, tc
, kind
, params
);
615 mlir::Type
Fortran::lower::translateDerivedTypeToFIRType(
616 Fortran::lower::AbstractConverter
&converter
,
617 const Fortran::semantics::DerivedTypeSpec
&tySpec
) {
618 return TypeBuilderImpl
{converter
}.genDerivedType(tySpec
);
621 mlir::Type
Fortran::lower::translateSomeExprToFIRType(
622 Fortran::lower::AbstractConverter
&converter
, const SomeExpr
&expr
) {
623 return TypeBuilderImpl
{converter
}.genExprType(expr
);
626 mlir::Type
Fortran::lower::translateSymbolToFIRType(
627 Fortran::lower::AbstractConverter
&converter
, const SymbolRef symbol
) {
628 return TypeBuilderImpl
{converter
}.genSymbolType(symbol
);
631 mlir::Type
Fortran::lower::translateVariableToFIRType(
632 Fortran::lower::AbstractConverter
&converter
,
633 const Fortran::lower::pft::Variable
&var
) {
634 return TypeBuilderImpl
{converter
}.genVariableType(var
);
637 mlir::Type
Fortran::lower::convertReal(mlir::MLIRContext
*context
, int kind
) {
638 return genRealType(context
, kind
);
641 bool Fortran::lower::isDerivedTypeWithLenParameters(
642 const Fortran::semantics::Symbol
&sym
) {
643 if (const Fortran::semantics::DeclTypeSpec
*declTy
= sym
.GetType())
644 if (const Fortran::semantics::DerivedTypeSpec
*derived
=
646 return Fortran::semantics::CountLenParameters(*derived
) > 0;
650 template <typename T
>
651 mlir::Type
Fortran::lower::TypeBuilder
<T
>::genType(
652 Fortran::lower::AbstractConverter
&converter
,
653 const Fortran::evaluate::FunctionRef
<T
> &funcRef
) {
654 return TypeBuilderImpl
{converter
}.genExprType(funcRef
);
657 const Fortran::semantics::DerivedTypeSpec
&
658 Fortran::lower::ComponentReverseIterator::advanceToParentType() {
659 const Fortran::semantics::Scope
*scope
= currentParentType
->GetScope();
661 DEREF(scope
).find(currentTypeDetails
->GetParentComponentName().value());
662 assert(parentComp
!= scope
->cend() && "failed to get parent component");
663 setCurrentType(parentComp
->second
->GetType()->derivedTypeSpec());
664 return *currentParentType
;
667 void Fortran::lower::ComponentReverseIterator::setCurrentType(
668 const Fortran::semantics::DerivedTypeSpec
&derived
) {
669 currentParentType
= &derived
;
670 currentTypeDetails
= ¤tParentType
->typeSymbol()
671 .get
<Fortran::semantics::DerivedTypeDetails
>();
672 componentIt
= currentTypeDetails
->componentNames().crbegin();
673 componentItEnd
= currentTypeDetails
->componentNames().crend();
676 using namespace Fortran::evaluate
;
677 using namespace Fortran::common
;
678 FOR_EACH_SPECIFIC_TYPE(template class Fortran::lower::TypeBuilder
, )