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"
24 #define DEBUG_TYPE "flang-lower-type"
26 using Fortran::common::VectorElementCategory
;
28 //===--------------------------------------------------------------------===//
29 // Intrinsic type translation helpers
30 //===--------------------------------------------------------------------===//
32 static mlir::Type
genRealType(mlir::MLIRContext
*context
, int kind
) {
33 if (Fortran::evaluate::IsValidKindOfIntrinsicType(
34 Fortran::common::TypeCategory::Real
, kind
)) {
37 return mlir::FloatType::getF16(context
);
39 return mlir::FloatType::getBF16(context
);
41 return mlir::FloatType::getF32(context
);
43 return mlir::FloatType::getF64(context
);
45 return mlir::FloatType::getF80(context
);
47 return mlir::FloatType::getF128(context
);
50 llvm_unreachable("REAL type translation not implemented");
54 int getIntegerBits() {
55 return Fortran::evaluate::Type
<Fortran::common::TypeCategory::Integer
,
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
);
68 return mlir::IntegerType::get(context
, getIntegerBits
<1>(), signedness
);
70 return mlir::IntegerType::get(context
, getIntegerBits
<2>(), signedness
);
72 return mlir::IntegerType::get(context
, getIntegerBits
<4>(), signedness
);
74 return mlir::IntegerType::get(context
, getIntegerBits
<8>(), signedness
);
76 return mlir::IntegerType::get(context
, getIntegerBits
<16>(), signedness
);
79 llvm_unreachable("INTEGER kind not translated");
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
);
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
);
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
);
106 genFIRType(mlir::MLIRContext
*context
, Fortran::common::TypeCategory tc
,
108 llvm::ArrayRef
<Fortran::lower::LenParameterTy
> lenParameters
) {
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
);
125 llvm_unreachable("unhandled type category");
128 //===--------------------------------------------------------------------===//
129 // Symbol and expression type translation
130 //===--------------------------------------------------------------------===//
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.
140 struct TypeBuilderImpl
{
142 TypeBuilderImpl(Fortran::lower::AbstractConverter
&converter
)
143 : derivedTypeInConstruction
{converter
.getTypeConstructionStack()},
144 converter
{converter
}, context
{&converter
.getMLIRContext()} {}
146 template <typename A
>
147 mlir::Type
genExprType(const A
&expr
) {
148 std::optional
<Fortran::evaluate::DynamicType
> dynamicType
= expr
.GetType();
150 return genTypelessExprType(expr
);
151 Fortran::common::TypeCategory category
= dynamicType
->category();
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());
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
);
167 std::optional
<Fortran::evaluate::Shape
> shapeExpr
=
168 Fortran::evaluate::GetShape(converter
.getFoldingContext(), expr
);
169 fir::SequenceType::Shape shape
;
171 translateShape(shape
, std::move(*shapeExpr
));
173 // Shape static analysis cannot return something useful for the shape.
174 // Use unknown extents.
175 int rank
= expr
.Rank();
177 TODO(converter
.getCurrentLocation(), "assumed rank expression types");
178 for (int dim
= 0; dim
< rank
; ++dim
)
179 shape
.emplace_back(fir::SequenceType::getUnknownExtent());
182 if (!shape
.empty()) {
184 return fir::ClassType::get(fir::SequenceType::get(shape
, baseType
));
185 return fir::SequenceType::get(shape
, baseType
);
188 return fir::ClassType::get(baseType
);
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
);
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
)));
209 template <typename A
>
210 mlir::Type
genTypelessExprType(const A
&expr
) {
211 fir::emitFatalError(converter
.getCurrentLocation(), "not a typeless expr");
214 mlir::Type
genTypelessExprType(const Fortran::lower::SomeExpr
&expr
) {
216 Fortran::common::visitors
{
217 [&](const Fortran::evaluate::BOZLiteralConstant
&) -> mlir::Type
{
218 return mlir::NoneType::get(context
);
220 [&](const Fortran::evaluate::NullPointer
&) -> mlir::Type
{
221 return fir::ReferenceType::get(mlir::NoneType::get(context
));
223 [&](const Fortran::evaluate::ProcedureDesignator
&proc
)
225 return Fortran::lower::translateSignature(proc
, converter
);
227 [&](const Fortran::evaluate::ProcedureRef
&) -> mlir::Type
{
228 return mlir::NoneType::get(context
);
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");
241 mlir::Type
genSymbolType(const Fortran::semantics::Symbol
&symbol
,
242 bool isAlloc
= false, bool isPtr
= false) {
243 mlir::Location loc
= converter
.genLocation(symbol
.name());
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();
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
);
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
=
274 ty
= genDerivedType(*tySpec
);
276 fir::emitFatalError(loc
, "symbol's type must have a type spec");
279 fir::emitFatalError(loc
, "symbol must have a type");
281 bool isPolymorphic
= (Fortran::semantics::IsPolymorphic(symbol
) ||
282 Fortran::semantics::IsUnlimitedPolymorphic(symbol
)) &&
283 !Fortran::semantics::IsAssumedType(symbol
);
284 if (ultimate
.IsObjectArray()) {
286 Fortran::evaluate::GetShape(converter
.getFoldingContext(), ultimate
);
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
);
293 if (Fortran::semantics::IsPointer(symbol
))
294 return fir::wrapInClassOrBoxType(fir::PointerType::get(ty
),
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.
302 return fir::PointerType::get(ty
);
304 return fir::HeapType::get(ty
);
306 return fir::ClassType::get(ty
);
310 /// Does \p component has non deferred lower bounds that are not compile time
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)
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
): {
331 int64_t vecElemCategory
;
333 for (const auto &pair
: tySpec
.parameters()) {
334 if (pair
.first
== "element_category") {
336 Fortran::evaluate::ToInt64(pair
.second
.GetExplicit())
338 } else if (pair
.first
== "element_kind") {
340 Fortran::evaluate::ToInt64(pair
.second
.GetExplicit()).value_or(0);
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");
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
));
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");
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
))
381 if (tySpec
.IsVectorType()) {
382 return genVectorType(tySpec
);
385 const Fortran::semantics::Scope
&derivedScope
= DEREF(tySpec
.GetScope());
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
);
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
>()
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
);
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
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.
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
))
431 cs
.emplace_back(converter
.getRecordTypeFieldName(component
), ty
);
435 mlir::Location loc
= converter
.genLocation(typeSymbol
.name());
436 // (2) The LEN type parameters.
437 for (const auto ¶m
:
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
));
448 rec
.finalize(ps
, cs
);
449 popDerivedTypeInConstruction();
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.
456 LLVM_DEBUG(llvm::dbgs() << "derived type: " << rec
<< '\n');
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
);
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.
469 fir::SequenceType::Extent
470 getCharacterLengthHelper(const Fortran::semantics::Symbol
&symbol
) {
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())))
478 return fir::SequenceType::getUnknownExtent();
481 template <typename T
>
482 void translateLenParameters(
483 llvm::SmallVectorImpl
<Fortran::lower::LenParameterTy
> ¶ms
,
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");
490 Fortran::lower::LenParameterTy
491 getCharacterLength(const Fortran::semantics::Symbol
&symbol
) {
492 const Fortran::semantics::DeclTypeSpec
*type
= symbol
.GetType();
494 type
->category() != Fortran::semantics::DeclTypeSpec::Character
||
495 !type
->AsIntrinsic())
496 llvm::report_fatal_error("not a character symbol");
498 toInt64(Fortran::common::Clone(type
->AsIntrinsic()->kind())).value();
501 return getCharacterLengthHelper
<1>(symbol
);
503 return getCharacterLengthHelper
<2>(symbol
);
505 return getCharacterLengthHelper
<4>(symbol
);
507 llvm_unreachable("unknown character kind");
510 template <typename A
>
511 Fortran::lower::LenParameterTy
getCharacterLength(const A
&expr
) {
512 return fir::SequenceType::getUnknownExtent();
515 template <typename T
>
516 Fortran::lower::LenParameterTy
517 getCharacterLength(const Fortran::evaluate::FunctionRef
<T
> &funcRef
) {
518 if (auto constantLen
= toInt64(funcRef
.LEN()))
520 return fir::SequenceType::getUnknownExtent();
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
>>(
531 if (auto constantLen
= toInt64(charExpr
->LEN()))
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()))
544 return fir::SequenceType::getUnknownExtent();
547 mlir::Type
genVariableType(const Fortran::lower::pft::Variable
&var
) {
548 return genSymbolType(var
.getSymbol(), var
.isHeapAlloc(), var
.isPointer());
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
)
562 void popDerivedTypeInConstruction() {
563 assert(!derivedTypeInConstruction
.empty());
564 derivedTypeInConstruction
.pop_back();
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
;
576 mlir::Type
Fortran::lower::getFIRType(mlir::MLIRContext
*context
,
577 Fortran::common::TypeCategory tc
,
579 llvm::ArrayRef
<LenParameterTy
> params
) {
580 return genFIRType(context
, tc
, kind
, params
);
583 mlir::Type
Fortran::lower::translateDerivedTypeToFIRType(
584 Fortran::lower::AbstractConverter
&converter
,
585 const Fortran::semantics::DerivedTypeSpec
&tySpec
) {
586 return TypeBuilderImpl
{converter
}.genDerivedType(tySpec
);
589 mlir::Type
Fortran::lower::translateSomeExprToFIRType(
590 Fortran::lower::AbstractConverter
&converter
, const SomeExpr
&expr
) {
591 return TypeBuilderImpl
{converter
}.genExprType(expr
);
594 mlir::Type
Fortran::lower::translateSymbolToFIRType(
595 Fortran::lower::AbstractConverter
&converter
, const SymbolRef symbol
) {
596 return TypeBuilderImpl
{converter
}.genSymbolType(symbol
);
599 mlir::Type
Fortran::lower::translateVariableToFIRType(
600 Fortran::lower::AbstractConverter
&converter
,
601 const Fortran::lower::pft::Variable
&var
) {
602 return TypeBuilderImpl
{converter
}.genVariableType(var
);
605 mlir::Type
Fortran::lower::convertReal(mlir::MLIRContext
*context
, int kind
) {
606 return genRealType(context
, kind
);
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
=
614 return Fortran::semantics::CountLenParameters(*derived
) > 0;
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
);
625 const Fortran::semantics::DerivedTypeSpec
&
626 Fortran::lower::ComponentReverseIterator::advanceToParentType() {
627 const Fortran::semantics::Scope
*scope
= currentParentType
->GetScope();
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
;
635 void Fortran::lower::ComponentReverseIterator::setCurrentType(
636 const Fortran::semantics::DerivedTypeSpec
&derived
) {
637 currentParentType
= &derived
;
638 currentTypeDetails
= ¤tParentType
->typeSymbol()
639 .get
<Fortran::semantics::DerivedTypeDetails
>();
640 componentIt
= currentTypeDetails
->componentNames().crbegin();
641 componentItEnd
= currentTypeDetails
->componentNames().crend();
644 using namespace Fortran::evaluate
;
645 using namespace Fortran::common
;
646 FOR_EACH_SPECIFIC_TYPE(template class Fortran::lower::TypeBuilder
, )