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