LAA: improve code in getStrideFromPointer (NFC) (#124780)
[llvm-project.git] / flang / lib / Lower / ConvertType.cpp
blob2fab520e6c475a305c2b26377f28d5bd05cef5f6
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 //===----------------------------------------------------------------------===//
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)) {
37 switch (kind) {
38 case 2:
39 return mlir::Float16Type::get(context);
40 case 3:
41 return mlir::BFloat16Type::get(context);
42 case 4:
43 return mlir::Float32Type::get(context);
44 case 8:
45 return mlir::Float64Type::get(context);
46 case 10:
47 return mlir::Float80Type::get(context);
48 case 16:
49 return mlir::Float128Type::get(context);
52 llvm_unreachable("REAL type translation not implemented");
55 template <int KIND>
56 int getIntegerBits() {
57 return Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer,
58 KIND>::Scalar::bits;
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);
68 switch (kind) {
69 case 1:
70 return mlir::IntegerType::get(context, getIntegerBits<1>(), signedness);
71 case 2:
72 return mlir::IntegerType::get(context, getIntegerBits<2>(), signedness);
73 case 4:
74 return mlir::IntegerType::get(context, getIntegerBits<4>(), signedness);
75 case 8:
76 return mlir::IntegerType::get(context, getIntegerBits<8>(), signedness);
77 case 16:
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);
88 return {};
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);
97 return {};
100 static mlir::Type genComplexType(mlir::MLIRContext *context, int KIND) {
101 return mlir::ComplexType::get(genRealType(context, KIND));
104 static mlir::Type
105 genFIRType(mlir::MLIRContext *context, Fortran::common::TypeCategory tc,
106 int kind,
107 llvm::ArrayRef<Fortran::lower::LenParameterTy> lenParameters) {
108 switch (tc) {
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);
123 default:
124 break;
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.
140 namespace {
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();
150 if (!dynamicType)
151 return genTypelessExprType(expr);
152 Fortran::common::TypeCategory category = dynamicType->category();
154 mlir::Type baseType;
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());
162 } else {
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;
171 if (shapeExpr) {
172 translateShape(shape, std::move(*shapeExpr));
173 } else {
174 // Shape static analysis cannot return something useful for the shape.
175 // Use unknown extents.
176 int rank = expr.Rank();
177 if (rank < 0)
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()) {
184 if (isPolymorphic)
185 return fir::ClassType::get(fir::SequenceType::get(shape, baseType));
186 return fir::SequenceType::get(shape, baseType);
188 if (isPolymorphic)
189 return fir::ClassType::get(baseType);
190 return 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)
225 -> mlir::Type {
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");
239 expr.u);
242 mlir::Type genSymbolType(const Fortran::semantics::Symbol &symbol,
243 bool isAlloc = false, bool isPtr = false) {
244 mlir::Location loc = converter.genLocation(symbol.name());
245 mlir::Type ty;
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 =
270 type->AsDerived()) {
271 ty = genDerivedType(*tySpec);
272 } else {
273 fir::emitFatalError(loc, "symbol's type must have a type spec");
275 } else {
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()) {
282 auto shapeExpr =
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.
287 if (shapeExpr)
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),
293 isPolymorphic);
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.
299 if (isPtr)
300 return fir::PointerType::get(ty);
301 if (isAlloc)
302 return fir::HeapType::get(ty);
303 if (isPolymorphic)
304 return fir::ClassType::get(ty);
305 return ty;
308 /// Does \p component has non deferred lower bounds that are not compile time
309 /// constant 1.
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)
318 return true;
319 return false;
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): {
328 int64_t vecElemKind;
329 int64_t vecElemCategory;
331 for (const auto &pair : tySpec.parameters()) {
332 if (pair.first == "element_category") {
333 vecElemCategory =
334 Fortran::evaluate::ToInt64(pair.second.GetExplicit())
335 .value_or(-1);
336 } else if (pair.first == "element_kind") {
337 vecElemKind =
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));
361 break;
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))
382 return ty;
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)) {
396 rec.pack(true);
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>()
407 .componentNames()) {
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)};
422 prev_offset += pad;
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.
430 if (componentName ==
431 typeSymbol.get<Fortran::semantics::DerivedTypeDetails>()
432 .componentNames()
433 .back()) {
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++),
441 padTy);
446 } else {
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
451 // fir.type<>.
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))
471 continue;
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 &param :
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);
491 if (!ps.empty()) {
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);
502 return 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.
508 template <int Kind>
509 fir::SequenceType::Extent
510 getCharacterLengthHelper(const Fortran::semantics::Symbol &symbol) {
511 using TC =
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())))
517 return *len;
518 return fir::SequenceType::getUnknownExtent();
521 template <typename T>
522 void translateLenParameters(
523 llvm::SmallVectorImpl<Fortran::lower::LenParameterTy> &params,
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();
533 if (!type ||
534 type->category() != Fortran::semantics::DeclTypeSpec::Character ||
535 !type->AsIntrinsic())
536 llvm::report_fatal_error("not a character symbol");
537 int kind =
538 toInt64(Fortran::common::Clone(type->AsIntrinsic()->kind())).value();
539 switch (kind) {
540 case 1:
541 return getCharacterLengthHelper<1>(symbol);
542 case 2:
543 return getCharacterLengthHelper<2>(symbol);
544 case 4:
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()))
559 return *constantLen;
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>>(
570 &expr.u)) {
571 if (auto constantLen = toInt64(charExpr->LEN()))
572 return *constantLen;
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()))
582 return *constantLen;
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;
606 } // namespace
608 mlir::Type Fortran::lower::getFIRType(mlir::MLIRContext *context,
609 Fortran::common::TypeCategory tc,
610 int kind,
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 =
645 declTy->AsDerived())
646 return Fortran::semantics::CountLenParameters(*derived) > 0;
647 return false;
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();
660 auto parentComp =
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 = &currentParentType->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, )