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