1baa12ddbSEric Schweitz //===-- ConvertType.cpp ---------------------------------------------------===// 2baa12ddbSEric Schweitz // 3baa12ddbSEric Schweitz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4baa12ddbSEric Schweitz // See https://llvm.org/LICENSE.txt for license information. 5baa12ddbSEric Schweitz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6baa12ddbSEric Schweitz // 7baa12ddbSEric Schweitz //===----------------------------------------------------------------------===// 8baa12ddbSEric Schweitz 9baa12ddbSEric Schweitz #include "flang/Lower/ConvertType.h" 102c2e5a5dSValentin Clement #include "flang/Lower/AbstractConverter.h" 119aeb7f03SValentin Clement #include "flang/Lower/CallInterface.h" 129aeb7f03SValentin Clement #include "flang/Lower/ConvertVariable.h" 13589d51eaSValentin Clement #include "flang/Lower/Mangler.h" 14baa12ddbSEric Schweitz #include "flang/Lower/PFTBuilder.h" 15e641c29fSValentin Clement #include "flang/Lower/Support/Utils.h" 165b66cc10SValentin Clement #include "flang/Optimizer/Builder/Todo.h" 17baa12ddbSEric Schweitz #include "flang/Optimizer/Dialect/FIRType.h" 18baa12ddbSEric Schweitz #include "flang/Semantics/tools.h" 19baa12ddbSEric Schweitz #include "flang/Semantics/type.h" 20baa12ddbSEric Schweitz #include "mlir/IR/Builders.h" 2109f7a55fSRiver Riddle #include "mlir/IR/BuiltinTypes.h" 22589d51eaSValentin Clement #include "llvm/Support/Debug.h" 2379e788d0SKelvin Li #include "llvm/TargetParser/Host.h" 2479e788d0SKelvin Li #include "llvm/TargetParser/Triple.h" 25baa12ddbSEric Schweitz 26ad40cc14SValentin Clement #define DEBUG_TYPE "flang-lower-type" 27ad40cc14SValentin Clement 28ef934174SKelvin Li using Fortran::common::VectorElementCategory; 29ef934174SKelvin Li 30ad40cc14SValentin Clement //===--------------------------------------------------------------------===// 31ad40cc14SValentin Clement // Intrinsic type translation helpers 32ad40cc14SValentin Clement //===--------------------------------------------------------------------===// 33ad40cc14SValentin Clement 340a0b3029SValentin Clement static mlir::Type genRealType(mlir::MLIRContext *context, int kind) { 350a0b3029SValentin Clement if (Fortran::evaluate::IsValidKindOfIntrinsicType( 360a0b3029SValentin Clement Fortran::common::TypeCategory::Real, kind)) { 370a0b3029SValentin Clement switch (kind) { 380a0b3029SValentin Clement case 2: 39*f023da12SMatthias Springer return mlir::Float16Type::get(context); 400a0b3029SValentin Clement case 3: 41*f023da12SMatthias Springer return mlir::BFloat16Type::get(context); 420a0b3029SValentin Clement case 4: 43*f023da12SMatthias Springer return mlir::Float32Type::get(context); 440a0b3029SValentin Clement case 8: 45*f023da12SMatthias Springer return mlir::Float64Type::get(context); 460a0b3029SValentin Clement case 10: 47*f023da12SMatthias Springer return mlir::Float80Type::get(context); 480a0b3029SValentin Clement case 16: 49*f023da12SMatthias Springer return mlir::Float128Type::get(context); 500a0b3029SValentin Clement } 510a0b3029SValentin Clement } 520a0b3029SValentin Clement llvm_unreachable("REAL type translation not implemented"); 530a0b3029SValentin Clement } 540a0b3029SValentin Clement 55ad40cc14SValentin Clement template <int KIND> 56ad40cc14SValentin Clement int getIntegerBits() { 57ad40cc14SValentin Clement return Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer, 58ad40cc14SValentin Clement KIND>::Scalar::bits; 59ad40cc14SValentin Clement } 60ef934174SKelvin Li static mlir::Type genIntegerType(mlir::MLIRContext *context, int kind, 61ef934174SKelvin Li bool isUnsigned = false) { 62ad40cc14SValentin Clement if (Fortran::evaluate::IsValidKindOfIntrinsicType( 63ad40cc14SValentin Clement Fortran::common::TypeCategory::Integer, kind)) { 64ef934174SKelvin Li mlir::IntegerType::SignednessSemantics signedness = 65ef934174SKelvin Li (isUnsigned ? mlir::IntegerType::SignednessSemantics::Unsigned 66ef934174SKelvin Li : mlir::IntegerType::SignednessSemantics::Signless); 67ef934174SKelvin Li 68ad40cc14SValentin Clement switch (kind) { 69ad40cc14SValentin Clement case 1: 70ef934174SKelvin Li return mlir::IntegerType::get(context, getIntegerBits<1>(), signedness); 71ad40cc14SValentin Clement case 2: 72ef934174SKelvin Li return mlir::IntegerType::get(context, getIntegerBits<2>(), signedness); 73ad40cc14SValentin Clement case 4: 74ef934174SKelvin Li return mlir::IntegerType::get(context, getIntegerBits<4>(), signedness); 75ad40cc14SValentin Clement case 8: 76ef934174SKelvin Li return mlir::IntegerType::get(context, getIntegerBits<8>(), signedness); 77ad40cc14SValentin Clement case 16: 78ef934174SKelvin Li return mlir::IntegerType::get(context, getIntegerBits<16>(), signedness); 79ad40cc14SValentin Clement } 80ad40cc14SValentin Clement } 81fc97d2e6SPeter Klausler llvm_unreachable("INTEGER or UNSIGNED kind not translated"); 82ad40cc14SValentin Clement } 83ad40cc14SValentin Clement 84ad40cc14SValentin Clement static mlir::Type genLogicalType(mlir::MLIRContext *context, int KIND) { 85ad40cc14SValentin Clement if (Fortran::evaluate::IsValidKindOfIntrinsicType( 86ad40cc14SValentin Clement Fortran::common::TypeCategory::Logical, KIND)) 87ad40cc14SValentin Clement return fir::LogicalType::get(context, KIND); 88ad40cc14SValentin Clement return {}; 89ad40cc14SValentin Clement } 90ad40cc14SValentin Clement 918c22cb84SValentin Clement static mlir::Type genCharacterType( 928c22cb84SValentin Clement mlir::MLIRContext *context, int KIND, 938c22cb84SValentin Clement Fortran::lower::LenParameterTy len = fir::CharacterType::unknownLen()) { 948c22cb84SValentin Clement if (Fortran::evaluate::IsValidKindOfIntrinsicType( 958c22cb84SValentin Clement Fortran::common::TypeCategory::Character, KIND)) 968c22cb84SValentin Clement return fir::CharacterType::get(context, KIND, len); 978c22cb84SValentin Clement return {}; 988c22cb84SValentin Clement } 998c22cb84SValentin Clement 1001ceb1d9bSValentin Clement static mlir::Type genComplexType(mlir::MLIRContext *context, int KIND) { 101c4204c0bSjeanPerier return mlir::ComplexType::get(genRealType(context, KIND)); 1021ceb1d9bSValentin Clement } 1031ceb1d9bSValentin Clement 1048c22cb84SValentin Clement static mlir::Type 1058c22cb84SValentin Clement genFIRType(mlir::MLIRContext *context, Fortran::common::TypeCategory tc, 1068c22cb84SValentin Clement int kind, 1078c22cb84SValentin Clement llvm::ArrayRef<Fortran::lower::LenParameterTy> lenParameters) { 108ad40cc14SValentin Clement switch (tc) { 109ad40cc14SValentin Clement case Fortran::common::TypeCategory::Real: 1100a0b3029SValentin Clement return genRealType(context, kind); 111ad40cc14SValentin Clement case Fortran::common::TypeCategory::Integer: 112fc97d2e6SPeter Klausler return genIntegerType(context, kind, false); 113fc97d2e6SPeter Klausler case Fortran::common::TypeCategory::Unsigned: 114fc97d2e6SPeter Klausler return genIntegerType(context, kind, true); 115ad40cc14SValentin Clement case Fortran::common::TypeCategory::Complex: 1161ceb1d9bSValentin Clement return genComplexType(context, kind); 117ad40cc14SValentin Clement case Fortran::common::TypeCategory::Logical: 118ad40cc14SValentin Clement return genLogicalType(context, kind); 119ad40cc14SValentin Clement case Fortran::common::TypeCategory::Character: 1208c22cb84SValentin Clement if (!lenParameters.empty()) 1218c22cb84SValentin Clement return genCharacterType(context, kind, lenParameters[0]); 1228c22cb84SValentin Clement return genCharacterType(context, kind); 123ad40cc14SValentin Clement default: 124ad40cc14SValentin Clement break; 125ad40cc14SValentin Clement } 126ad40cc14SValentin Clement llvm_unreachable("unhandled type category"); 127baa12ddbSEric Schweitz } 128baa12ddbSEric Schweitz 129307ccf4cSValentin Clement //===--------------------------------------------------------------------===// 130307ccf4cSValentin Clement // Symbol and expression type translation 131307ccf4cSValentin Clement //===--------------------------------------------------------------------===// 132baa12ddbSEric Schweitz 133d71c1de0SJean Perier /// TypeBuilderImpl translates expression and symbol type taking into account 134307ccf4cSValentin Clement /// their shape and length parameters. For symbols, attributes such as 135307ccf4cSValentin Clement /// ALLOCATABLE or POINTER are reflected in the fir type. 136307ccf4cSValentin Clement /// It uses evaluate::DynamicType and evaluate::Shape when possible to 137307ccf4cSValentin Clement /// avoid re-implementing type/shape analysis here. 138307ccf4cSValentin Clement /// Do not use the FirOpBuilder from the AbstractConverter to get fir/mlir types 139307ccf4cSValentin Clement /// since it is not guaranteed to exist yet when we lower types. 140baa12ddbSEric Schweitz namespace { 141d71c1de0SJean Perier struct TypeBuilderImpl { 1429aeb7f03SValentin Clement 143d71c1de0SJean Perier TypeBuilderImpl(Fortran::lower::AbstractConverter &converter) 144c373f581SjeanPerier : derivedTypeInConstruction{converter.getTypeConstructionStack()}, 145c373f581SjeanPerier converter{converter}, context{&converter.getMLIRContext()} {} 146ad40cc14SValentin Clement 147d71c1de0SJean Perier template <typename A> 148d71c1de0SJean Perier mlir::Type genExprType(const A &expr) { 149e641c29fSValentin Clement std::optional<Fortran::evaluate::DynamicType> dynamicType = expr.GetType(); 150e641c29fSValentin Clement if (!dynamicType) 151e641c29fSValentin Clement return genTypelessExprType(expr); 152e641c29fSValentin Clement Fortran::common::TypeCategory category = dynamicType->category(); 153e641c29fSValentin Clement 154e641c29fSValentin Clement mlir::Type baseType; 1551e413b90SValentin Clement bool isPolymorphic = (dynamicType->IsPolymorphic() || 1561e413b90SValentin Clement dynamicType->IsUnlimitedPolymorphic()) && 1571e413b90SValentin Clement !dynamicType->IsAssumedType(); 158c1b7e9c9SValentin Clement if (dynamicType->IsUnlimitedPolymorphic()) { 159c1b7e9c9SValentin Clement baseType = mlir::NoneType::get(context); 160c1b7e9c9SValentin Clement } else if (category == Fortran::common::TypeCategory::Derived) { 161589d51eaSValentin Clement baseType = genDerivedType(dynamicType->GetDerivedTypeSpec()); 162e641c29fSValentin Clement } else { 163fc97d2e6SPeter Klausler // INTEGER, UNSIGNED, REAL, COMPLEX, CHARACTER, LOGICAL 1648c22cb84SValentin Clement llvm::SmallVector<Fortran::lower::LenParameterTy> params; 1658c22cb84SValentin Clement translateLenParameters(params, category, expr); 1668c22cb84SValentin Clement baseType = genFIRType(context, category, dynamicType->kind(), params); 167e641c29fSValentin Clement } 168e641c29fSValentin Clement std::optional<Fortran::evaluate::Shape> shapeExpr = 169e641c29fSValentin Clement Fortran::evaluate::GetShape(converter.getFoldingContext(), expr); 170e641c29fSValentin Clement fir::SequenceType::Shape shape; 171e641c29fSValentin Clement if (shapeExpr) { 172e641c29fSValentin Clement translateShape(shape, std::move(*shapeExpr)); 173e641c29fSValentin Clement } else { 174e641c29fSValentin Clement // Shape static analysis cannot return something useful for the shape. 175e641c29fSValentin Clement // Use unknown extents. 176e641c29fSValentin Clement int rank = expr.Rank(); 177e641c29fSValentin Clement if (rank < 0) 17839377d52SValentin Clement TODO(converter.getCurrentLocation(), "assumed rank expression types"); 179e641c29fSValentin Clement for (int dim = 0; dim < rank; ++dim) 180e641c29fSValentin Clement shape.emplace_back(fir::SequenceType::getUnknownExtent()); 181e641c29fSValentin Clement } 1821e413b90SValentin Clement 1831e413b90SValentin Clement if (!shape.empty()) { 1841e413b90SValentin Clement if (isPolymorphic) 1851e413b90SValentin Clement return fir::ClassType::get(fir::SequenceType::get(shape, baseType)); 186e641c29fSValentin Clement return fir::SequenceType::get(shape, baseType); 1871e413b90SValentin Clement } 1881e413b90SValentin Clement if (isPolymorphic) 1891e413b90SValentin Clement return fir::ClassType::get(baseType); 190e641c29fSValentin Clement return baseType; 191e641c29fSValentin Clement } 192e641c29fSValentin Clement 193ad40cc14SValentin Clement template <typename A> 194c807aa53SValentin Clement void translateShape(A &shape, Fortran::evaluate::Shape &&shapeExpr) { 195c807aa53SValentin Clement for (Fortran::evaluate::MaybeExtentExpr extentExpr : shapeExpr) { 196c807aa53SValentin Clement fir::SequenceType::Extent extent = fir::SequenceType::getUnknownExtent(); 197c807aa53SValentin Clement if (std::optional<std::int64_t> constantExtent = 198c807aa53SValentin Clement toInt64(std::move(extentExpr))) 199c807aa53SValentin Clement extent = *constantExtent; 200c807aa53SValentin Clement shape.push_back(extent); 201c807aa53SValentin Clement } 202c807aa53SValentin Clement } 203c807aa53SValentin Clement 204c807aa53SValentin Clement template <typename A> 205ad40cc14SValentin Clement std::optional<std::int64_t> toInt64(A &&expr) { 206ad40cc14SValentin Clement return Fortran::evaluate::ToInt64(Fortran::evaluate::Fold( 207ad40cc14SValentin Clement converter.getFoldingContext(), std::move(expr))); 208ad40cc14SValentin Clement } 209ad40cc14SValentin Clement 210d71c1de0SJean Perier template <typename A> 211d71c1de0SJean Perier mlir::Type genTypelessExprType(const A &expr) { 212d71c1de0SJean Perier fir::emitFatalError(converter.getCurrentLocation(), "not a typeless expr"); 213d71c1de0SJean Perier } 214d71c1de0SJean Perier 215e641c29fSValentin Clement mlir::Type genTypelessExprType(const Fortran::lower::SomeExpr &expr) { 21677d8cfb3SAlexander Shaposhnikov return Fortran::common::visit( 217e641c29fSValentin Clement Fortran::common::visitors{ 218e641c29fSValentin Clement [&](const Fortran::evaluate::BOZLiteralConstant &) -> mlir::Type { 219e641c29fSValentin Clement return mlir::NoneType::get(context); 220e641c29fSValentin Clement }, 221e641c29fSValentin Clement [&](const Fortran::evaluate::NullPointer &) -> mlir::Type { 222e641c29fSValentin Clement return fir::ReferenceType::get(mlir::NoneType::get(context)); 223e641c29fSValentin Clement }, 224e641c29fSValentin Clement [&](const Fortran::evaluate::ProcedureDesignator &proc) 225e641c29fSValentin Clement -> mlir::Type { 2269aeb7f03SValentin Clement return Fortran::lower::translateSignature(proc, converter); 227e641c29fSValentin Clement }, 228e641c29fSValentin Clement [&](const Fortran::evaluate::ProcedureRef &) -> mlir::Type { 229e641c29fSValentin Clement return mlir::NoneType::get(context); 230e641c29fSValentin Clement }, 231e641c29fSValentin Clement [](const auto &x) -> mlir::Type { 232e641c29fSValentin Clement using T = std::decay_t<decltype(x)>; 233e641c29fSValentin Clement static_assert(!Fortran::common::HasMember< 234e641c29fSValentin Clement T, Fortran::evaluate::TypelessExpression>, 23539377d52SValentin Clement "missing typeless expr handling"); 236e641c29fSValentin Clement llvm::report_fatal_error("not a typeless expression"); 237e641c29fSValentin Clement }, 238e641c29fSValentin Clement }, 239e641c29fSValentin Clement expr.u); 240e641c29fSValentin Clement } 241e641c29fSValentin Clement 242ad40cc14SValentin Clement mlir::Type genSymbolType(const Fortran::semantics::Symbol &symbol, 243ad40cc14SValentin Clement bool isAlloc = false, bool isPtr = false) { 244ad40cc14SValentin Clement mlir::Location loc = converter.genLocation(symbol.name()); 245ad40cc14SValentin Clement mlir::Type ty; 246ad40cc14SValentin Clement // If the symbol is not the same as the ultimate one (i.e, it is host or use 247ad40cc14SValentin Clement // associated), all the symbol properties are the ones of the ultimate 248ad40cc14SValentin Clement // symbol but the volatile and asynchronous attributes that may differ. To 249ad40cc14SValentin Clement // avoid issues with helper functions that would not follow association 250ad40cc14SValentin Clement // links, the fir type is built based on the ultimate symbol. This relies 251ad40cc14SValentin Clement // on the fact volatile and asynchronous are not reflected in fir types. 252ad40cc14SValentin Clement const Fortran::semantics::Symbol &ultimate = symbol.GetUltimate(); 253af09219eSDaniel Chen 254af09219eSDaniel Chen if (Fortran::semantics::IsProcedurePointer(ultimate)) { 255af09219eSDaniel Chen Fortran::evaluate::ProcedureDesignator proc(ultimate); 256af09219eSDaniel Chen auto procTy{Fortran::lower::translateSignature(proc, converter)}; 257af09219eSDaniel Chen return fir::BoxProcType::get(context, procTy); 258af09219eSDaniel Chen } 259af09219eSDaniel Chen 260ad40cc14SValentin Clement if (const Fortran::semantics::DeclTypeSpec *type = ultimate.GetType()) { 261ad40cc14SValentin Clement if (const Fortran::semantics::IntrinsicTypeSpec *tySpec = 262ad40cc14SValentin Clement type->AsIntrinsic()) { 263ad40cc14SValentin Clement int kind = toInt64(Fortran::common::Clone(tySpec->kind())).value(); 2648c22cb84SValentin Clement llvm::SmallVector<Fortran::lower::LenParameterTy> params; 2658c22cb84SValentin Clement translateLenParameters(params, tySpec->category(), ultimate); 2668c22cb84SValentin Clement ty = genFIRType(context, tySpec->category(), kind, params); 2679d99b482SValentin Clement } else if (type->IsUnlimitedPolymorphic()) { 2689d99b482SValentin Clement ty = mlir::NoneType::get(context); 269589d51eaSValentin Clement } else if (const Fortran::semantics::DerivedTypeSpec *tySpec = 270589d51eaSValentin Clement type->AsDerived()) { 271589d51eaSValentin Clement ty = genDerivedType(*tySpec); 272ad40cc14SValentin Clement } else { 273ad40cc14SValentin Clement fir::emitFatalError(loc, "symbol's type must have a type spec"); 274ad40cc14SValentin Clement } 275ad40cc14SValentin Clement } else { 276ad40cc14SValentin Clement fir::emitFatalError(loc, "symbol must have a type"); 277ad40cc14SValentin Clement } 2781e413b90SValentin Clement bool isPolymorphic = (Fortran::semantics::IsPolymorphic(symbol) || 2791e413b90SValentin Clement Fortran::semantics::IsUnlimitedPolymorphic(symbol)) && 2801e413b90SValentin Clement !Fortran::semantics::IsAssumedType(symbol); 281c807aa53SValentin Clement if (ultimate.IsObjectArray()) { 2820c0b2ea9SPeter Klausler auto shapeExpr = 2830c0b2ea9SPeter Klausler Fortran::evaluate::GetShape(converter.getFoldingContext(), ultimate); 284c807aa53SValentin Clement fir::SequenceType::Shape shape; 2854abbf995SjeanPerier // If there is no shapExpr, this is an assumed-rank, and the empty shape 2864abbf995SjeanPerier // will build the desired fir.array<*:T> type. 2874abbf995SjeanPerier if (shapeExpr) 288c807aa53SValentin Clement translateShape(shape, std::move(*shapeExpr)); 289c807aa53SValentin Clement ty = fir::SequenceType::get(shape, ty); 290c807aa53SValentin Clement } 291ad40cc14SValentin Clement if (Fortran::semantics::IsPointer(symbol)) 2921e413b90SValentin Clement return fir::wrapInClassOrBoxType(fir::PointerType::get(ty), 2931e413b90SValentin Clement isPolymorphic); 294ad40cc14SValentin Clement if (Fortran::semantics::IsAllocatable(symbol)) 2951e413b90SValentin Clement return fir::wrapInClassOrBoxType(fir::HeapType::get(ty), isPolymorphic); 296ad40cc14SValentin Clement // isPtr and isAlloc are variable that were promoted to be on the 297ad40cc14SValentin Clement // heap or to be pointers, but they do not have Fortran allocatable 298ad40cc14SValentin Clement // or pointer semantics, so do not use box for them. 299ad40cc14SValentin Clement if (isPtr) 300ad40cc14SValentin Clement return fir::PointerType::get(ty); 301ad40cc14SValentin Clement if (isAlloc) 302ad40cc14SValentin Clement return fir::HeapType::get(ty); 3031e413b90SValentin Clement if (isPolymorphic) 3041e413b90SValentin Clement return fir::ClassType::get(ty); 305ad40cc14SValentin Clement return ty; 306ad40cc14SValentin Clement } 307baa12ddbSEric Schweitz 308589d51eaSValentin Clement /// Does \p component has non deferred lower bounds that are not compile time 309589d51eaSValentin Clement /// constant 1. 310589d51eaSValentin Clement static bool componentHasNonDefaultLowerBounds( 311589d51eaSValentin Clement const Fortran::semantics::Symbol &component) { 312589d51eaSValentin Clement if (const auto *objDetails = 313589d51eaSValentin Clement component.detailsIf<Fortran::semantics::ObjectEntityDetails>()) 314589d51eaSValentin Clement for (const Fortran::semantics::ShapeSpec &bounds : objDetails->shape()) 315589d51eaSValentin Clement if (auto lb = bounds.lbound().GetExplicit()) 316589d51eaSValentin Clement if (auto constant = Fortran::evaluate::ToInt64(*lb)) 317589d51eaSValentin Clement if (!constant || *constant != 1) 318589d51eaSValentin Clement return true; 319589d51eaSValentin Clement return false; 320589d51eaSValentin Clement } 321589d51eaSValentin Clement 322ef934174SKelvin Li mlir::Type genVectorType(const Fortran::semantics::DerivedTypeSpec &tySpec) { 323ef934174SKelvin Li assert(tySpec.scope() && "Missing scope for Vector type"); 324ef934174SKelvin Li auto vectorSize{tySpec.scope()->size()}; 325ef934174SKelvin Li switch (tySpec.category()) { 326ef934174SKelvin Li SWITCH_COVERS_ALL_CASES 327ef934174SKelvin Li case (Fortran::semantics::DerivedTypeSpec::Category::IntrinsicVector): { 328ef934174SKelvin Li int64_t vecElemKind; 329ef934174SKelvin Li int64_t vecElemCategory; 330ef934174SKelvin Li 331ef934174SKelvin Li for (const auto &pair : tySpec.parameters()) { 332ef934174SKelvin Li if (pair.first == "element_category") { 333ef934174SKelvin Li vecElemCategory = 334ef934174SKelvin Li Fortran::evaluate::ToInt64(pair.second.GetExplicit()) 335ef934174SKelvin Li .value_or(-1); 336ef934174SKelvin Li } else if (pair.first == "element_kind") { 337ef934174SKelvin Li vecElemKind = 338ef934174SKelvin Li Fortran::evaluate::ToInt64(pair.second.GetExplicit()).value_or(0); 339ef934174SKelvin Li } 340ef934174SKelvin Li } 341ef934174SKelvin Li 342ef934174SKelvin Li assert((vecElemCategory >= 0 && 343ef934174SKelvin Li static_cast<size_t>(vecElemCategory) < 344ef934174SKelvin Li Fortran::common::VectorElementCategory_enumSize) && 345ef934174SKelvin Li "Vector element type is not specified"); 346ef934174SKelvin Li assert(vecElemKind && "Vector element kind is not specified"); 347ef934174SKelvin Li 348ef934174SKelvin Li int64_t numOfElements = vectorSize / vecElemKind; 349ef934174SKelvin Li switch (static_cast<VectorElementCategory>(vecElemCategory)) { 350ef934174SKelvin Li SWITCH_COVERS_ALL_CASES 351ef934174SKelvin Li case VectorElementCategory::Integer: 352ef934174SKelvin Li return fir::VectorType::get(numOfElements, 353ef934174SKelvin Li genIntegerType(context, vecElemKind)); 354ef934174SKelvin Li case VectorElementCategory::Unsigned: 355ef934174SKelvin Li return fir::VectorType::get(numOfElements, 356ef934174SKelvin Li genIntegerType(context, vecElemKind, true)); 357ef934174SKelvin Li case VectorElementCategory::Real: 358ef934174SKelvin Li return fir::VectorType::get(numOfElements, 359ef934174SKelvin Li genRealType(context, vecElemKind)); 360ef934174SKelvin Li } 361ef934174SKelvin Li break; 362ef934174SKelvin Li } 363ef934174SKelvin Li case (Fortran::semantics::DerivedTypeSpec::Category::PairVector): 364ef934174SKelvin Li case (Fortran::semantics::DerivedTypeSpec::Category::QuadVector): 365ef934174SKelvin Li return fir::VectorType::get(vectorSize * 8, 366ef934174SKelvin Li mlir::IntegerType::get(context, 1)); 367ef934174SKelvin Li case (Fortran::semantics::DerivedTypeSpec::Category::DerivedType): 368ef934174SKelvin Li Fortran::common::die("Vector element type not implemented"); 369ef934174SKelvin Li } 370ef934174SKelvin Li } 371ef934174SKelvin Li 372589d51eaSValentin Clement mlir::Type genDerivedType(const Fortran::semantics::DerivedTypeSpec &tySpec) { 373589d51eaSValentin Clement std::vector<std::pair<std::string, mlir::Type>> ps; 374589d51eaSValentin Clement std::vector<std::pair<std::string, mlir::Type>> cs; 375ef934174SKelvin Li if (tySpec.IsVectorType()) { 376ef934174SKelvin Li return genVectorType(tySpec); 377ef934174SKelvin Li } 378ef934174SKelvin Li 37984564e10SjeanPerier const Fortran::semantics::Symbol &typeSymbol = tySpec.typeSymbol(); 380e45f6e93SjeanPerier const Fortran::semantics::Scope &derivedScope = DEREF(tySpec.GetScope()); 38184564e10SjeanPerier if (mlir::Type ty = getTypeIfDerivedAlreadyInConstruction(derivedScope)) 38284564e10SjeanPerier return ty; 383e45f6e93SjeanPerier 3842c143345SV Donaldson auto rec = fir::RecordType::get(context, converter.mangleName(tySpec)); 38584564e10SjeanPerier // Maintain the stack of types for recursive references and to speed-up 38684564e10SjeanPerier // the derived type constructions that can be expensive for derived type 38784564e10SjeanPerier // with dozens of components/parents (modern Fortran). 38884564e10SjeanPerier derivedTypeInConstruction.try_emplace(&derivedScope, rec); 389589d51eaSValentin Clement 39079e788d0SKelvin Li auto targetTriple{llvm::Triple( 39179e788d0SKelvin Li llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()))}; 39279e788d0SKelvin Li // Always generate packed FIR struct type for bind(c) derived type for AIX 39379e788d0SKelvin Li if (targetTriple.getOS() == llvm::Triple::OSType::AIX && 39479e788d0SKelvin Li tySpec.typeSymbol().attrs().test(Fortran::semantics::Attr::BIND_C) && 395d305fd0bSKelvin Li !IsIsoCType(&tySpec) && !fir::isa_builtin_cdevptr_type(rec)) { 39679e788d0SKelvin Li rec.pack(true); 39779e788d0SKelvin Li } 39879e788d0SKelvin Li 399589d51eaSValentin Clement // Gather the record type fields. 400589d51eaSValentin Clement // (1) The data components. 401e45f6e93SjeanPerier if (converter.getLoweringOptions().getLowerToHighLevelFIR()) { 40279e788d0SKelvin Li size_t prev_offset{0}; 40379e788d0SKelvin Li unsigned padCounter{0}; 404e45f6e93SjeanPerier // In HLFIR the parent component is the first fir.type component. 405e45f6e93SjeanPerier for (const auto &componentName : 406e45f6e93SjeanPerier typeSymbol.get<Fortran::semantics::DerivedTypeDetails>() 407e45f6e93SjeanPerier .componentNames()) { 408e45f6e93SjeanPerier auto scopeIter = derivedScope.find(componentName); 409e45f6e93SjeanPerier assert(scopeIter != derivedScope.cend() && 410e45f6e93SjeanPerier "failed to find derived type component symbol"); 411e45f6e93SjeanPerier const Fortran::semantics::Symbol &component = scopeIter->second.get(); 412e45f6e93SjeanPerier mlir::Type ty = genSymbolType(component); 41379e788d0SKelvin Li if (rec.isPacked()) { 41479e788d0SKelvin Li auto compSize{component.size()}; 41579e788d0SKelvin Li auto compOffset{component.offset()}; 41679e788d0SKelvin Li 41779e788d0SKelvin Li if (prev_offset < compOffset) { 41879e788d0SKelvin Li size_t pad{compOffset - prev_offset}; 41979e788d0SKelvin Li mlir::Type i8Ty{mlir::IntegerType::get(context, 8)}; 42079e788d0SKelvin Li fir::SequenceType::Shape shape{static_cast<int64_t>(pad)}; 42179e788d0SKelvin Li mlir::Type padTy{fir::SequenceType::get(shape, i8Ty)}; 42279e788d0SKelvin Li prev_offset += pad; 42379e788d0SKelvin Li cs.emplace_back("__padding" + std::to_string(padCounter++), padTy); 42479e788d0SKelvin Li } 42579e788d0SKelvin Li prev_offset += compSize; 42679e788d0SKelvin Li } 427e45f6e93SjeanPerier cs.emplace_back(converter.getRecordTypeFieldName(component), ty); 42879e788d0SKelvin Li if (rec.isPacked()) { 42979e788d0SKelvin Li // For the last component, determine if any padding is needed. 43079e788d0SKelvin Li if (componentName == 43179e788d0SKelvin Li typeSymbol.get<Fortran::semantics::DerivedTypeDetails>() 43279e788d0SKelvin Li .componentNames() 43379e788d0SKelvin Li .back()) { 43479e788d0SKelvin Li auto compEnd{component.offset() + component.size()}; 43579e788d0SKelvin Li if (compEnd < derivedScope.size()) { 43679e788d0SKelvin Li size_t pad{derivedScope.size() - compEnd}; 43779e788d0SKelvin Li mlir::Type i8Ty{mlir::IntegerType::get(context, 8)}; 43879e788d0SKelvin Li fir::SequenceType::Shape shape{static_cast<int64_t>(pad)}; 43979e788d0SKelvin Li mlir::Type padTy{fir::SequenceType::get(shape, i8Ty)}; 44079e788d0SKelvin Li cs.emplace_back("__padding" + std::to_string(padCounter++), 44179e788d0SKelvin Li padTy); 44279e788d0SKelvin Li } 44379e788d0SKelvin Li } 44479e788d0SKelvin Li } 445e45f6e93SjeanPerier } 446e45f6e93SjeanPerier } else { 44799a54b83SjeanPerier for (const auto &component : 448589d51eaSValentin Clement Fortran::semantics::OrderedComponentIterator(tySpec)) { 449e45f6e93SjeanPerier // In the lowering to FIR the parent component does not appear in the 450e45f6e93SjeanPerier // fir.type and its components are inlined at the beginning of the 451e45f6e93SjeanPerier // fir.type<>. 452e45f6e93SjeanPerier // FIXME: this strategy leads to bugs because padding should be inserted 453e45f6e93SjeanPerier // after the component of the parents so that the next components do not 454e45f6e93SjeanPerier // end-up in the parent storage if the sum of the parent's component 455e45f6e93SjeanPerier // storage size is not a multiple of the parent type storage alignment. 456e45f6e93SjeanPerier 457e45f6e93SjeanPerier // Lowering is assuming non deferred component lower bounds are 458e45f6e93SjeanPerier // always 1. Catch any situations where this is not true for now. 459e45f6e93SjeanPerier if (componentHasNonDefaultLowerBounds(component)) 46099a54b83SjeanPerier TODO(converter.genLocation(component.name()), 46139377d52SValentin Clement "derived type components with non default lower bounds"); 46299a54b83SjeanPerier if (IsProcedure(component)) 46399a54b83SjeanPerier TODO(converter.genLocation(component.name()), "procedure components"); 46499a54b83SjeanPerier mlir::Type ty = genSymbolType(component); 465589d51eaSValentin Clement // Do not add the parent component (component of the parents are 466589d51eaSValentin Clement // added and should be sufficient, the parent component would 467e45f6e93SjeanPerier // duplicate the fields). Note that genSymbolType must be called above 468e45f6e93SjeanPerier // on it so that the dispatch table for the parent type still gets 469e45f6e93SjeanPerier // emitted as needed. 47099a54b83SjeanPerier if (component.test(Fortran::semantics::Symbol::Flag::ParentComp)) 471589d51eaSValentin Clement continue; 47299a54b83SjeanPerier cs.emplace_back(converter.getRecordTypeFieldName(component), ty); 473589d51eaSValentin Clement } 474e45f6e93SjeanPerier } 475589d51eaSValentin Clement 476be30cd62SjeanPerier mlir::Location loc = converter.genLocation(typeSymbol.name()); 477589d51eaSValentin Clement // (2) The LEN type parameters. 478589d51eaSValentin Clement for (const auto ¶m : 479589d51eaSValentin Clement Fortran::semantics::OrderParameterDeclarations(typeSymbol)) 480589d51eaSValentin Clement if (param->get<Fortran::semantics::TypeParamDetails>().attr() == 481be30cd62SjeanPerier Fortran::common::TypeParamAttr::Len) { 482be30cd62SjeanPerier TODO(loc, "parameterized derived types"); 483be30cd62SjeanPerier // TODO: emplace in ps. Beware that param is the symbol in the type 484be30cd62SjeanPerier // declaration, not instantiation: its kind may not be a constant. 485be30cd62SjeanPerier // The instantiated symbol in tySpec.scope should be used instead. 486589d51eaSValentin Clement ps.emplace_back(param->name().ToString(), genSymbolType(*param)); 487be30cd62SjeanPerier } 488589d51eaSValentin Clement 489589d51eaSValentin Clement rec.finalize(ps, cs); 490589d51eaSValentin Clement 491589d51eaSValentin Clement if (!ps.empty()) { 492be30cd62SjeanPerier // TODO: this type is a PDT (parametric derived type) with length 493be30cd62SjeanPerier // parameter. Create the functions to use for allocation, dereferencing, 494be30cd62SjeanPerier // and address arithmetic here. 495589d51eaSValentin Clement } 496589d51eaSValentin Clement LLVM_DEBUG(llvm::dbgs() << "derived type: " << rec << '\n'); 4979aeb7f03SValentin Clement 4989aeb7f03SValentin Clement // Generate the type descriptor object if any 4999aeb7f03SValentin Clement if (const Fortran::semantics::Symbol *typeInfoSym = 500e45f6e93SjeanPerier derivedScope.runtimeDerivedTypeDescription()) 5014ccd57ddSjeanPerier converter.registerTypeInfo(loc, *typeInfoSym, tySpec, rec); 502589d51eaSValentin Clement return rec; 503589d51eaSValentin Clement } 504589d51eaSValentin Clement 5058c22cb84SValentin Clement // To get the character length from a symbol, make an fold a designator for 5068c22cb84SValentin Clement // the symbol to cover the case where the symbol is an assumed length named 5078c22cb84SValentin Clement // constant and its length comes from its init expression length. 5088c22cb84SValentin Clement template <int Kind> 5098c22cb84SValentin Clement fir::SequenceType::Extent 5108c22cb84SValentin Clement getCharacterLengthHelper(const Fortran::semantics::Symbol &symbol) { 5118c22cb84SValentin Clement using TC = 5128c22cb84SValentin Clement Fortran::evaluate::Type<Fortran::common::TypeCategory::Character, Kind>; 5138c22cb84SValentin Clement auto designator = Fortran::evaluate::Fold( 5148c22cb84SValentin Clement converter.getFoldingContext(), 5158c22cb84SValentin Clement Fortran::evaluate::Expr<TC>{Fortran::evaluate::Designator<TC>{symbol}}); 5168c22cb84SValentin Clement if (auto len = toInt64(std::move(designator.LEN()))) 5178c22cb84SValentin Clement return *len; 5188c22cb84SValentin Clement return fir::SequenceType::getUnknownExtent(); 5198c22cb84SValentin Clement } 5208c22cb84SValentin Clement 5218c22cb84SValentin Clement template <typename T> 5228c22cb84SValentin Clement void translateLenParameters( 5238c22cb84SValentin Clement llvm::SmallVectorImpl<Fortran::lower::LenParameterTy> ¶ms, 5248c22cb84SValentin Clement Fortran::common::TypeCategory category, const T &exprOrSym) { 5258c22cb84SValentin Clement if (category == Fortran::common::TypeCategory::Character) 5268c22cb84SValentin Clement params.push_back(getCharacterLength(exprOrSym)); 5278c22cb84SValentin Clement else if (category == Fortran::common::TypeCategory::Derived) 52839377d52SValentin Clement TODO(converter.getCurrentLocation(), "derived type length parameters"); 5298c22cb84SValentin Clement } 5308c22cb84SValentin Clement Fortran::lower::LenParameterTy 5318c22cb84SValentin Clement getCharacterLength(const Fortran::semantics::Symbol &symbol) { 5328c22cb84SValentin Clement const Fortran::semantics::DeclTypeSpec *type = symbol.GetType(); 5338c22cb84SValentin Clement if (!type || 5348c22cb84SValentin Clement type->category() != Fortran::semantics::DeclTypeSpec::Character || 5358c22cb84SValentin Clement !type->AsIntrinsic()) 5368c22cb84SValentin Clement llvm::report_fatal_error("not a character symbol"); 5378c22cb84SValentin Clement int kind = 5388c22cb84SValentin Clement toInt64(Fortran::common::Clone(type->AsIntrinsic()->kind())).value(); 5398c22cb84SValentin Clement switch (kind) { 5408c22cb84SValentin Clement case 1: 5418c22cb84SValentin Clement return getCharacterLengthHelper<1>(symbol); 5428c22cb84SValentin Clement case 2: 5438c22cb84SValentin Clement return getCharacterLengthHelper<2>(symbol); 5448c22cb84SValentin Clement case 4: 5458c22cb84SValentin Clement return getCharacterLengthHelper<4>(symbol); 5468c22cb84SValentin Clement } 5478c22cb84SValentin Clement llvm_unreachable("unknown character kind"); 5488c22cb84SValentin Clement } 549d71c1de0SJean Perier 550d71c1de0SJean Perier template <typename A> 551d71c1de0SJean Perier Fortran::lower::LenParameterTy getCharacterLength(const A &expr) { 552d71c1de0SJean Perier return fir::SequenceType::getUnknownExtent(); 553d71c1de0SJean Perier } 554da78ae46SJean Perier 555da78ae46SJean Perier template <typename T> 556da78ae46SJean Perier Fortran::lower::LenParameterTy 557da78ae46SJean Perier getCharacterLength(const Fortran::evaluate::FunctionRef<T> &funcRef) { 558da78ae46SJean Perier if (auto constantLen = toInt64(funcRef.LEN())) 559da78ae46SJean Perier return *constantLen; 560da78ae46SJean Perier return fir::SequenceType::getUnknownExtent(); 561da78ae46SJean Perier } 562da78ae46SJean Perier 5638c22cb84SValentin Clement Fortran::lower::LenParameterTy 5648c22cb84SValentin Clement getCharacterLength(const Fortran::lower::SomeExpr &expr) { 5658c22cb84SValentin Clement // Do not use dynamic type length here. We would miss constant 5668c22cb84SValentin Clement // lengths opportunities because dynamic type only has the length 5678c22cb84SValentin Clement // if it comes from a declaration. 568d8d91b2aSJean Perier if (const auto *charExpr = std::get_if< 569d8d91b2aSJean Perier Fortran::evaluate::Expr<Fortran::evaluate::SomeCharacter>>( 570d8d91b2aSJean Perier &expr.u)) { 571d8d91b2aSJean Perier if (auto constantLen = toInt64(charExpr->LEN())) 5728c22cb84SValentin Clement return *constantLen; 573d8d91b2aSJean Perier } else if (auto dynamicType = expr.GetType()) { 574d8d91b2aSJean Perier // When generating derived type type descriptor as structure constructor, 575d8d91b2aSJean Perier // semantics wraps designators to data component initialization into 576d8d91b2aSJean Perier // CLASS(*), regardless of their actual type. 577d8d91b2aSJean Perier // GetType() will recover the actual symbol type as the dynamic type, so 578d8d91b2aSJean Perier // getCharacterLength may be reached even if expr is packaged as an 579d8d91b2aSJean Perier // Expr<SomeDerived> instead of an Expr<SomeChar>. 580d8d91b2aSJean Perier // Just use the dynamic type here again to retrieve the length. 581d8d91b2aSJean Perier if (auto constantLen = toInt64(dynamicType->GetCharLength())) 582d8d91b2aSJean Perier return *constantLen; 583d8d91b2aSJean Perier } 5848c22cb84SValentin Clement return fir::SequenceType::getUnknownExtent(); 5858c22cb84SValentin Clement } 5868c22cb84SValentin Clement 5872c2e5a5dSValentin Clement mlir::Type genVariableType(const Fortran::lower::pft::Variable &var) { 588ad40cc14SValentin Clement return genSymbolType(var.getSymbol(), var.isHeapAlloc(), var.isPointer()); 589baa12ddbSEric Schweitz } 590baa12ddbSEric Schweitz 591589d51eaSValentin Clement /// Derived type can be recursive. That is, pointer components of a derived 592589d51eaSValentin Clement /// type `t` have type `t`. This helper returns `t` if it is already being 593589d51eaSValentin Clement /// lowered to avoid infinite loops. 594589d51eaSValentin Clement mlir::Type getTypeIfDerivedAlreadyInConstruction( 59584564e10SjeanPerier const Fortran::semantics::Scope &derivedScope) const { 59684564e10SjeanPerier return derivedTypeInConstruction.lookup(&derivedScope); 597589d51eaSValentin Clement } 598589d51eaSValentin Clement 599589d51eaSValentin Clement /// Stack derived type being processed to avoid infinite loops in case of 600589d51eaSValentin Clement /// recursive derived types. The depth of derived types is expected to be 601589d51eaSValentin Clement /// shallow (<10), so a SmallVector is sufficient. 602c373f581SjeanPerier Fortran::lower::TypeConstructionStack &derivedTypeInConstruction; 603ad40cc14SValentin Clement Fortran::lower::AbstractConverter &converter; 604baa12ddbSEric Schweitz mlir::MLIRContext *context; 605baa12ddbSEric Schweitz }; 606baa12ddbSEric Schweitz } // namespace 607baa12ddbSEric Schweitz 608dc6a3446SValentin Clement mlir::Type Fortran::lower::getFIRType(mlir::MLIRContext *context, 609dc6a3446SValentin Clement Fortran::common::TypeCategory tc, 6108c22cb84SValentin Clement int kind, 6118c22cb84SValentin Clement llvm::ArrayRef<LenParameterTy> params) { 6128c22cb84SValentin Clement return genFIRType(context, tc, kind, params); 613baa12ddbSEric Schweitz } 614baa12ddbSEric Schweitz 615589d51eaSValentin Clement mlir::Type Fortran::lower::translateDerivedTypeToFIRType( 616589d51eaSValentin Clement Fortran::lower::AbstractConverter &converter, 617589d51eaSValentin Clement const Fortran::semantics::DerivedTypeSpec &tySpec) { 618d71c1de0SJean Perier return TypeBuilderImpl{converter}.genDerivedType(tySpec); 619589d51eaSValentin Clement } 620589d51eaSValentin Clement 621baa12ddbSEric Schweitz mlir::Type Fortran::lower::translateSomeExprToFIRType( 622e641c29fSValentin Clement Fortran::lower::AbstractConverter &converter, const SomeExpr &expr) { 623d71c1de0SJean Perier return TypeBuilderImpl{converter}.genExprType(expr); 624baa12ddbSEric Schweitz } 625baa12ddbSEric Schweitz 626baa12ddbSEric Schweitz mlir::Type Fortran::lower::translateSymbolToFIRType( 6272c2e5a5dSValentin Clement Fortran::lower::AbstractConverter &converter, const SymbolRef symbol) { 628d71c1de0SJean Perier return TypeBuilderImpl{converter}.genSymbolType(symbol); 629baa12ddbSEric Schweitz } 630baa12ddbSEric Schweitz 631baa12ddbSEric Schweitz mlir::Type Fortran::lower::translateVariableToFIRType( 6322c2e5a5dSValentin Clement Fortran::lower::AbstractConverter &converter, 633baa12ddbSEric Schweitz const Fortran::lower::pft::Variable &var) { 634d71c1de0SJean Perier return TypeBuilderImpl{converter}.genVariableType(var); 635baa12ddbSEric Schweitz } 636baa12ddbSEric Schweitz 637baa12ddbSEric Schweitz mlir::Type Fortran::lower::convertReal(mlir::MLIRContext *context, int kind) { 638b3d1f073SValentin Clement return genRealType(context, kind); 639baa12ddbSEric Schweitz } 640d71c1de0SJean Perier 6412d9b4a50SJean Perier bool Fortran::lower::isDerivedTypeWithLenParameters( 6422d9b4a50SJean Perier const Fortran::semantics::Symbol &sym) { 6432d9b4a50SJean Perier if (const Fortran::semantics::DeclTypeSpec *declTy = sym.GetType()) 6442d9b4a50SJean Perier if (const Fortran::semantics::DerivedTypeSpec *derived = 6452d9b4a50SJean Perier declTy->AsDerived()) 6462d9b4a50SJean Perier return Fortran::semantics::CountLenParameters(*derived) > 0; 6472d9b4a50SJean Perier return false; 6482d9b4a50SJean Perier } 6492d9b4a50SJean Perier 650d71c1de0SJean Perier template <typename T> 651d71c1de0SJean Perier mlir::Type Fortran::lower::TypeBuilder<T>::genType( 652d71c1de0SJean Perier Fortran::lower::AbstractConverter &converter, 653d71c1de0SJean Perier const Fortran::evaluate::FunctionRef<T> &funcRef) { 654d71c1de0SJean Perier return TypeBuilderImpl{converter}.genExprType(funcRef); 655d71c1de0SJean Perier } 656d71c1de0SJean Perier 657e45f6e93SjeanPerier const Fortran::semantics::DerivedTypeSpec & 658e45f6e93SjeanPerier Fortran::lower::ComponentReverseIterator::advanceToParentType() { 659e45f6e93SjeanPerier const Fortran::semantics::Scope *scope = currentParentType->GetScope(); 660e45f6e93SjeanPerier auto parentComp = 661e45f6e93SjeanPerier DEREF(scope).find(currentTypeDetails->GetParentComponentName().value()); 662e45f6e93SjeanPerier assert(parentComp != scope->cend() && "failed to get parent component"); 663e45f6e93SjeanPerier setCurrentType(parentComp->second->GetType()->derivedTypeSpec()); 664e45f6e93SjeanPerier return *currentParentType; 665e45f6e93SjeanPerier } 666e45f6e93SjeanPerier 667e45f6e93SjeanPerier void Fortran::lower::ComponentReverseIterator::setCurrentType( 668e45f6e93SjeanPerier const Fortran::semantics::DerivedTypeSpec &derived) { 669e45f6e93SjeanPerier currentParentType = &derived; 670e45f6e93SjeanPerier currentTypeDetails = ¤tParentType->typeSymbol() 671e45f6e93SjeanPerier .get<Fortran::semantics::DerivedTypeDetails>(); 672e45f6e93SjeanPerier componentIt = currentTypeDetails->componentNames().crbegin(); 673e45f6e93SjeanPerier componentItEnd = currentTypeDetails->componentNames().crend(); 674e45f6e93SjeanPerier } 675e45f6e93SjeanPerier 676d71c1de0SJean Perier using namespace Fortran::evaluate; 677d71c1de0SJean Perier using namespace Fortran::common; 678d71c1de0SJean Perier FOR_EACH_SPECIFIC_TYPE(template class Fortran::lower::TypeBuilder, ) 679