1 //===-- ConvertExprToHLFIR.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 // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "flang/Lower/ConvertExprToHLFIR.h" 14 #include "flang/Evaluate/shape.h" 15 #include "flang/Lower/AbstractConverter.h" 16 #include "flang/Lower/Allocatable.h" 17 #include "flang/Lower/CallInterface.h" 18 #include "flang/Lower/ConvertArrayConstructor.h" 19 #include "flang/Lower/ConvertCall.h" 20 #include "flang/Lower/ConvertConstant.h" 21 #include "flang/Lower/ConvertProcedureDesignator.h" 22 #include "flang/Lower/ConvertType.h" 23 #include "flang/Lower/ConvertVariable.h" 24 #include "flang/Lower/StatementContext.h" 25 #include "flang/Lower/SymbolMap.h" 26 #include "flang/Optimizer/Builder/Complex.h" 27 #include "flang/Optimizer/Builder/IntrinsicCall.h" 28 #include "flang/Optimizer/Builder/MutableBox.h" 29 #include "flang/Optimizer/Builder/Runtime/Character.h" 30 #include "flang/Optimizer/Builder/Runtime/Derived.h" 31 #include "flang/Optimizer/Builder/Runtime/Pointer.h" 32 #include "flang/Optimizer/Builder/Todo.h" 33 #include "flang/Optimizer/HLFIR/HLFIROps.h" 34 #include "llvm/ADT/TypeSwitch.h" 35 #include <optional> 36 37 namespace { 38 39 /// Lower Designators to HLFIR. 40 class HlfirDesignatorBuilder { 41 private: 42 /// Internal entry point on the rightest part of a evaluate::Designator. 43 template <typename T> 44 hlfir::EntityWithAttributes 45 genLeafPartRef(const T &designatorNode, 46 bool vectorSubscriptDesignatorToValue) { 47 hlfir::EntityWithAttributes result = gen(designatorNode); 48 if (vectorSubscriptDesignatorToValue) 49 return turnVectorSubscriptedDesignatorIntoValue(result); 50 return result; 51 } 52 53 hlfir::EntityWithAttributes 54 genDesignatorExpr(const Fortran::lower::SomeExpr &designatorExpr, 55 bool vectorSubscriptDesignatorToValue = true); 56 57 public: 58 HlfirDesignatorBuilder(mlir::Location loc, 59 Fortran::lower::AbstractConverter &converter, 60 Fortran::lower::SymMap &symMap, 61 Fortran::lower::StatementContext &stmtCtx) 62 : converter{converter}, symMap{symMap}, stmtCtx{stmtCtx}, loc{loc} {} 63 64 /// Public entry points to lower a Designator<T> (given its .u member, to 65 /// avoid the template arguments which does not matter here). 66 /// This lowers a designator to an hlfir variable SSA value (that can be 67 /// assigned to), except for vector subscripted designators that are 68 /// lowered by default to hlfir.expr value since they cannot be 69 /// represented as HLFIR variable SSA values. 70 71 // Character designators variant contains substrings 72 using CharacterDesignators = 73 decltype(Fortran::evaluate::Designator<Fortran::evaluate::Type< 74 Fortran::evaluate::TypeCategory::Character, 1>>::u); 75 hlfir::EntityWithAttributes 76 gen(const CharacterDesignators &designatorVariant, 77 bool vectorSubscriptDesignatorToValue = true) { 78 return std::visit( 79 [&](const auto &x) -> hlfir::EntityWithAttributes { 80 return genLeafPartRef(x, vectorSubscriptDesignatorToValue); 81 }, 82 designatorVariant); 83 } 84 // Character designators variant contains complex parts 85 using RealDesignators = 86 decltype(Fortran::evaluate::Designator<Fortran::evaluate::Type< 87 Fortran::evaluate::TypeCategory::Real, 4>>::u); 88 hlfir::EntityWithAttributes 89 gen(const RealDesignators &designatorVariant, 90 bool vectorSubscriptDesignatorToValue = true) { 91 return std::visit( 92 [&](const auto &x) -> hlfir::EntityWithAttributes { 93 return genLeafPartRef(x, vectorSubscriptDesignatorToValue); 94 }, 95 designatorVariant); 96 } 97 // All other designators are similar 98 using OtherDesignators = 99 decltype(Fortran::evaluate::Designator<Fortran::evaluate::Type< 100 Fortran::evaluate::TypeCategory::Integer, 4>>::u); 101 hlfir::EntityWithAttributes 102 gen(const OtherDesignators &designatorVariant, 103 bool vectorSubscriptDesignatorToValue = true) { 104 return std::visit( 105 [&](const auto &x) -> hlfir::EntityWithAttributes { 106 return genLeafPartRef(x, vectorSubscriptDesignatorToValue); 107 }, 108 designatorVariant); 109 } 110 111 hlfir::EntityWithAttributes 112 genNamedEntity(const Fortran::evaluate::NamedEntity &namedEntity, 113 bool vectorSubscriptDesignatorToValue = true) { 114 if (namedEntity.IsSymbol()) 115 return genLeafPartRef( 116 Fortran::evaluate::SymbolRef{namedEntity.GetLastSymbol()}, 117 vectorSubscriptDesignatorToValue); 118 return genLeafPartRef(namedEntity.GetComponent(), 119 vectorSubscriptDesignatorToValue); 120 } 121 122 /// Public entry point to lower a vector subscripted designator to 123 /// an hlfir::ElementalAddrOp. 124 hlfir::ElementalAddrOp convertVectorSubscriptedExprToElementalAddr( 125 const Fortran::lower::SomeExpr &designatorExpr); 126 127 mlir::Value genComponentShape(const Fortran::semantics::Symbol &componentSym, 128 mlir::Type fieldType) { 129 // For pointers and allocatable components, the 130 // shape is deferred and should not be loaded now to preserve 131 // pointer/allocatable aspects. 132 if (componentSym.Rank() == 0 || 133 Fortran::semantics::IsAllocatableOrObjectPointer(&componentSym)) 134 return mlir::Value{}; 135 136 fir::FirOpBuilder &builder = getBuilder(); 137 mlir::Location loc = getLoc(); 138 mlir::Type idxTy = builder.getIndexType(); 139 llvm::SmallVector<mlir::Value> extents; 140 auto seqTy = hlfir::getFortranElementOrSequenceType(fieldType) 141 .cast<fir::SequenceType>(); 142 for (auto extent : seqTy.getShape()) { 143 if (extent == fir::SequenceType::getUnknownExtent()) { 144 // We have already generated invalid hlfir.declare 145 // without the type parameters and probably invalid storage 146 // for the variable (e.g. fir.alloca without type parameters). 147 // So this TODO here is a little bit late, but it matches 148 // the non-HLFIR path. 149 TODO(loc, "array component shape depending on length parameters"); 150 } 151 extents.push_back(builder.createIntegerConstant(loc, idxTy, extent)); 152 } 153 if (!hasNonDefaultLowerBounds(componentSym)) 154 return builder.create<fir::ShapeOp>(loc, extents); 155 156 llvm::SmallVector<mlir::Value> lbounds; 157 if (const auto *objDetails = 158 componentSym.detailsIf<Fortran::semantics::ObjectEntityDetails>()) 159 for (const Fortran::semantics::ShapeSpec &bounds : objDetails->shape()) 160 if (auto lb = bounds.lbound().GetExplicit()) 161 if (auto constant = Fortran::evaluate::ToInt64(*lb)) 162 lbounds.push_back( 163 builder.createIntegerConstant(loc, idxTy, *constant)); 164 assert(extents.size() == lbounds.size() && 165 "extents and lower bounds must match"); 166 return builder.genShape(loc, lbounds, extents); 167 } 168 169 fir::FortranVariableOpInterface 170 gen(const Fortran::evaluate::DataRef &dataRef) { 171 return std::visit( 172 Fortran::common::visitors{[&](const auto &x) { return gen(x); }}, 173 dataRef.u); 174 } 175 176 private: 177 /// Struct that is filled while visiting a part-ref (in the "visit" member 178 /// function) before the top level "gen" generates an hlfir.declare for the 179 /// part ref. It contains the lowered pieces of the part-ref that will 180 /// become the operands of an hlfir.declare. 181 struct PartInfo { 182 std::optional<hlfir::Entity> base; 183 std::string componentName{}; 184 mlir::Value componentShape; 185 hlfir::DesignateOp::Subscripts subscripts; 186 std::optional<bool> complexPart; 187 mlir::Value resultShape; 188 llvm::SmallVector<mlir::Value> typeParams; 189 llvm::SmallVector<mlir::Value, 2> substring; 190 }; 191 192 // Given the value type of a designator (T or fir.array<T>) and the front-end 193 // node for the designator, compute the memory type (fir.class, fir.ref, or 194 // fir.box)... 195 template <typename T> 196 mlir::Type computeDesignatorType(mlir::Type resultValueType, 197 PartInfo &partInfo, 198 const T &designatorNode) { 199 // Get base's shape if its a sequence type with no previously computed 200 // result shape 201 if (partInfo.base && resultValueType.isa<fir::SequenceType>() && 202 !partInfo.resultShape) 203 partInfo.resultShape = 204 hlfir::genShape(getLoc(), getBuilder(), *partInfo.base); 205 // Dynamic type of polymorphic base must be kept if the designator is 206 // polymorphic. 207 if (isPolymorphic(designatorNode)) 208 return fir::ClassType::get(resultValueType); 209 // Character scalar with dynamic length needs a fir.boxchar to hold the 210 // designator length. 211 auto charType = resultValueType.dyn_cast<fir::CharacterType>(); 212 if (charType && charType.hasDynamicLen()) 213 return fir::BoxCharType::get(charType.getContext(), charType.getFKind()); 214 // Arrays with non default lower bounds or dynamic length or dynamic extent 215 // need a fir.box to hold the dynamic or lower bound information. 216 if (fir::hasDynamicSize(resultValueType) || 217 hasNonDefaultLowerBounds(partInfo)) 218 return fir::BoxType::get(resultValueType); 219 // Non simply contiguous ref require a fir.box to carry the byte stride. 220 if (resultValueType.isa<fir::SequenceType>() && 221 !Fortran::evaluate::IsSimplyContiguous( 222 designatorNode, getConverter().getFoldingContext())) 223 return fir::BoxType::get(resultValueType); 224 // Other designators can be handled as raw addresses. 225 return fir::ReferenceType::get(resultValueType); 226 } 227 228 template <typename T> 229 static bool isPolymorphic(const T &designatorNode) { 230 if constexpr (!std::is_same_v<T, Fortran::evaluate::Substring>) { 231 return Fortran::semantics::IsPolymorphic(designatorNode.GetLastSymbol()); 232 } 233 return false; 234 } 235 236 template <typename T> 237 /// Generate an hlfir.designate for a part-ref given a filled PartInfo and the 238 /// FIR type for this part-ref. 239 fir::FortranVariableOpInterface genDesignate(mlir::Type resultValueType, 240 PartInfo &partInfo, 241 const T &designatorNode) { 242 mlir::Type designatorType = 243 computeDesignatorType(resultValueType, partInfo, designatorNode); 244 return genDesignate(designatorType, partInfo, /*attributes=*/{}); 245 } 246 fir::FortranVariableOpInterface 247 genDesignate(mlir::Type designatorType, PartInfo &partInfo, 248 fir::FortranVariableFlagsAttr attributes) { 249 fir::FirOpBuilder &builder = getBuilder(); 250 // Once a part with vector subscripts has been lowered, the following 251 // hlfir.designator (for the parts on the right of the designator) must 252 // be lowered inside the hlfir.elemental_addr because they depend on the 253 // hlfir.elemental_addr indices. 254 // All the subsequent Fortran indices however, should be lowered before 255 // the hlfir.elemental_addr because they should only be evaluated once, 256 // hence, the insertion point is restored outside of the 257 // hlfir.elemental_addr after generating the hlfir.designate. Example: in 258 // "X(VECTOR)%COMP(FOO(), BAR())", the calls to bar() and foo() must be 259 // generated outside of the hlfir.elemental, but the related hlfir.designate 260 // that depends on the scalar hlfir.designate of X(VECTOR) that was 261 // generated inside the hlfir.elemental_addr should be generated in the 262 // hlfir.elemental_addr. 263 if (auto elementalAddrOp = getVectorSubscriptElementAddrOp()) 264 builder.setInsertionPointToEnd(&elementalAddrOp->getBody().front()); 265 auto designate = builder.create<hlfir::DesignateOp>( 266 getLoc(), designatorType, partInfo.base.value().getBase(), 267 partInfo.componentName, partInfo.componentShape, partInfo.subscripts, 268 partInfo.substring, partInfo.complexPart, partInfo.resultShape, 269 partInfo.typeParams, attributes); 270 if (auto elementalAddrOp = getVectorSubscriptElementAddrOp()) 271 builder.setInsertionPoint(*elementalAddrOp); 272 return mlir::cast<fir::FortranVariableOpInterface>( 273 designate.getOperation()); 274 } 275 276 fir::FortranVariableOpInterface 277 gen(const Fortran::evaluate::SymbolRef &symbolRef) { 278 if (std::optional<fir::FortranVariableOpInterface> varDef = 279 getSymMap().lookupVariableDefinition(symbolRef)) { 280 if (symbolRef->test(Fortran::semantics::Symbol::Flag::CrayPointee)) { 281 // The pointee is represented with a descriptor inheriting 282 // the shape and type parameters of the pointee. 283 // We have to update the base_addr to point to the current 284 // value of the Cray pointer variable. 285 fir::FirOpBuilder &builder = getBuilder(); 286 fir::FortranVariableOpInterface ptrVar = 287 gen(Fortran::lower::getCrayPointer(symbolRef)); 288 mlir::Value ptrAddr = ptrVar.getBase(); 289 290 // Reinterpret the reference to a Cray pointer so that 291 // we have a pointer-compatible value after loading 292 // the Cray pointer value. 293 mlir::Type refPtrType = builder.getRefType( 294 fir::PointerType::get(fir::dyn_cast_ptrEleTy(ptrAddr.getType()))); 295 mlir::Value cast = builder.createConvert(loc, refPtrType, ptrAddr); 296 mlir::Value ptrVal = builder.create<fir::LoadOp>(loc, cast); 297 298 // Update the base_addr to the value of the Cray pointer. 299 // This is a hacky way to do the update, and it may harm 300 // performance around Cray pointer references. 301 // TODO: we should introduce an operation that updates 302 // just the base_addr of the given box. The CodeGen 303 // will just convert it into a single store. 304 fir::runtime::genPointerAssociateScalar(builder, loc, varDef->getBase(), 305 ptrVal); 306 } 307 return *varDef; 308 } 309 TODO(getLoc(), "lowering symbol to HLFIR"); 310 } 311 312 fir::FortranVariableOpInterface 313 gen(const Fortran::evaluate::Component &component) { 314 if (Fortran::semantics::IsAllocatableOrPointer(component.GetLastSymbol())) 315 return genWholeAllocatableOrPointerComponent(component); 316 PartInfo partInfo; 317 mlir::Type resultType = visit(component, partInfo); 318 return genDesignate(resultType, partInfo, component); 319 } 320 321 fir::FortranVariableOpInterface 322 gen(const Fortran::evaluate::ArrayRef &arrayRef) { 323 PartInfo partInfo; 324 mlir::Type resultType = visit(arrayRef, partInfo); 325 return genDesignate(resultType, partInfo, arrayRef); 326 } 327 328 fir::FortranVariableOpInterface 329 gen(const Fortran::evaluate::CoarrayRef &coarrayRef) { 330 TODO(getLoc(), "coarray: lowering a reference to a coarray object"); 331 } 332 333 mlir::Type visit(const Fortran::evaluate::CoarrayRef &, PartInfo &) { 334 TODO(getLoc(), "coarray: lowering a reference to a coarray object"); 335 } 336 337 fir::FortranVariableOpInterface 338 gen(const Fortran::evaluate::ComplexPart &complexPart) { 339 PartInfo partInfo; 340 fir::factory::Complex cmplxHelper(getBuilder(), getLoc()); 341 342 bool complexBit = 343 complexPart.part() == Fortran::evaluate::ComplexPart::Part::IM; 344 partInfo.complexPart = {complexBit}; 345 346 mlir::Type resultType = visit(complexPart.complex(), partInfo); 347 348 // Determine complex part type 349 mlir::Type base = hlfir::getFortranElementType(resultType); 350 mlir::Type cmplxValueType = cmplxHelper.getComplexPartType(base); 351 mlir::Type designatorType = changeElementType(resultType, cmplxValueType); 352 353 return genDesignate(designatorType, partInfo, complexPart); 354 } 355 356 fir::FortranVariableOpInterface 357 gen(const Fortran::evaluate::Substring &substring) { 358 PartInfo partInfo; 359 mlir::Type baseStringType = std::visit( 360 [&](const auto &x) { return visit(x, partInfo); }, substring.parent()); 361 assert(partInfo.typeParams.size() == 1 && "expect base string length"); 362 // Compute the substring lower and upper bound. 363 partInfo.substring.push_back(genSubscript(substring.lower())); 364 if (Fortran::evaluate::MaybeExtentExpr upperBound = substring.upper()) 365 partInfo.substring.push_back(genSubscript(*upperBound)); 366 else 367 partInfo.substring.push_back(partInfo.typeParams[0]); 368 fir::FirOpBuilder &builder = getBuilder(); 369 mlir::Location loc = getLoc(); 370 mlir::Type idxTy = builder.getIndexType(); 371 partInfo.substring[0] = 372 builder.createConvert(loc, idxTy, partInfo.substring[0]); 373 partInfo.substring[1] = 374 builder.createConvert(loc, idxTy, partInfo.substring[1]); 375 // Try using constant length if available. mlir::arith folding would 376 // most likely be able to fold "max(ub-lb+1,0)" too, but getting 377 // the constant length in the FIR types would be harder. 378 std::optional<int64_t> cstLen = 379 Fortran::evaluate::ToInt64(Fortran::evaluate::Fold( 380 getConverter().getFoldingContext(), substring.LEN())); 381 if (cstLen) { 382 partInfo.typeParams[0] = 383 builder.createIntegerConstant(loc, idxTy, *cstLen); 384 } else { 385 // Compute "len = max(ub-lb+1,0)" (Fortran 2018 9.4.1). 386 mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1); 387 auto boundsDiff = builder.create<mlir::arith::SubIOp>( 388 loc, partInfo.substring[1], partInfo.substring[0]); 389 auto rawLen = builder.create<mlir::arith::AddIOp>(loc, boundsDiff, one); 390 partInfo.typeParams[0] = 391 fir::factory::genMaxWithZero(builder, loc, rawLen); 392 } 393 auto kind = hlfir::getFortranElementType(baseStringType) 394 .cast<fir::CharacterType>() 395 .getFKind(); 396 auto newCharTy = fir::CharacterType::get( 397 baseStringType.getContext(), kind, 398 cstLen ? *cstLen : fir::CharacterType::unknownLen()); 399 mlir::Type resultType = changeElementType(baseStringType, newCharTy); 400 return genDesignate(resultType, partInfo, substring); 401 } 402 403 static mlir::Type changeElementType(mlir::Type type, mlir::Type newEleTy) { 404 return llvm::TypeSwitch<mlir::Type, mlir::Type>(type) 405 .Case<fir::SequenceType>([&](fir::SequenceType seqTy) -> mlir::Type { 406 return fir::SequenceType::get(seqTy.getShape(), newEleTy); 407 }) 408 .Case<fir::PointerType, fir::HeapType, fir::ReferenceType, 409 fir::BoxType>([&](auto t) -> mlir::Type { 410 using FIRT = decltype(t); 411 return FIRT::get(changeElementType(t.getEleTy(), newEleTy)); 412 }) 413 .Default([newEleTy](mlir::Type t) -> mlir::Type { return newEleTy; }); 414 } 415 416 fir::FortranVariableOpInterface genWholeAllocatableOrPointerComponent( 417 const Fortran::evaluate::Component &component) { 418 // Generate whole allocatable or pointer component reference. The 419 // hlfir.designate result will be a pointer/allocatable. 420 PartInfo partInfo; 421 mlir::Type componentType = visitComponentImpl(component, partInfo).second; 422 mlir::Type designatorType = fir::ReferenceType::get(componentType); 423 fir::FortranVariableFlagsAttr attributes = 424 Fortran::lower::translateSymbolAttributes(getBuilder().getContext(), 425 component.GetLastSymbol()); 426 return genDesignate(designatorType, partInfo, attributes); 427 } 428 429 mlir::Type visit(const Fortran::evaluate::DataRef &dataRef, 430 PartInfo &partInfo) { 431 return std::visit([&](const auto &x) { return visit(x, partInfo); }, 432 dataRef.u); 433 } 434 435 mlir::Type 436 visit(const Fortran::evaluate::StaticDataObject::Pointer &staticObject, 437 PartInfo &partInfo) { 438 fir::FirOpBuilder &builder = getBuilder(); 439 mlir::Location loc = getLoc(); 440 std::optional<std::string> string = staticObject->AsString(); 441 // TODO: see if StaticDataObject can be replaced by something based on 442 // Constant<T> to avoid dealing with endianness here for KIND>1. 443 // This will also avoid making string copies here. 444 if (!string) 445 TODO(loc, "StaticDataObject::Pointer substring with kind > 1"); 446 fir::ExtendedValue exv = 447 fir::factory::createStringLiteral(builder, getLoc(), *string); 448 auto flags = fir::FortranVariableFlagsAttr::get( 449 builder.getContext(), fir::FortranVariableFlagsEnum::parameter); 450 partInfo.base = hlfir::genDeclare(loc, builder, exv, ".stringlit", flags); 451 partInfo.typeParams.push_back(fir::getLen(exv)); 452 return partInfo.base->getElementOrSequenceType(); 453 } 454 455 mlir::Type visit(const Fortran::evaluate::SymbolRef &symbolRef, 456 PartInfo &partInfo) { 457 // A symbol is only visited if there is a following array, substring, or 458 // complex reference. If the entity is a pointer or allocatable, this 459 // reference designates the target, so the pointer, allocatable must be 460 // dereferenced here. 461 partInfo.base = 462 hlfir::derefPointersAndAllocatables(loc, getBuilder(), gen(symbolRef)); 463 hlfir::genLengthParameters(loc, getBuilder(), *partInfo.base, 464 partInfo.typeParams); 465 return partInfo.base->getElementOrSequenceType(); 466 } 467 468 mlir::Type visit(const Fortran::evaluate::ArrayRef &arrayRef, 469 PartInfo &partInfo) { 470 mlir::Type baseType; 471 if (const auto *component = arrayRef.base().UnwrapComponent()) { 472 // Pointers and allocatable components must be dereferenced since the 473 // array ref designates the target (this is done in "visit"). Other 474 // components need special care to deal with the array%array_comp(indices) 475 // case. 476 if (Fortran::semantics::IsAllocatableOrObjectPointer( 477 &component->GetLastSymbol())) 478 baseType = visit(*component, partInfo); 479 else 480 baseType = hlfir::getFortranElementOrSequenceType( 481 visitComponentImpl(*component, partInfo).second); 482 } else { 483 baseType = visit(arrayRef.base().GetLastSymbol(), partInfo); 484 } 485 486 fir::FirOpBuilder &builder = getBuilder(); 487 mlir::Location loc = getLoc(); 488 mlir::Type idxTy = builder.getIndexType(); 489 llvm::SmallVector<std::pair<mlir::Value, mlir::Value>> bounds; 490 auto getBaseBounds = [&](unsigned i) { 491 if (bounds.empty()) { 492 if (partInfo.componentName.empty()) { 493 bounds = hlfir::genBounds(loc, builder, partInfo.base.value()); 494 } else { 495 assert( 496 partInfo.componentShape && 497 "implicit array section bounds must come from component shape"); 498 bounds = hlfir::genBounds(loc, builder, partInfo.componentShape); 499 } 500 assert(!bounds.empty() && 501 "failed to compute implicit array section bounds"); 502 } 503 return bounds[i]; 504 }; 505 auto frontEndResultShape = 506 Fortran::evaluate::GetShape(converter.getFoldingContext(), arrayRef); 507 auto tryGettingExtentFromFrontEnd = 508 [&](unsigned dim) -> std::pair<mlir::Value, fir::SequenceType::Extent> { 509 // Use constant extent if possible. The main advantage to do this now 510 // is to get the best FIR array types as possible while lowering. 511 if (frontEndResultShape) 512 if (auto maybeI64 = 513 Fortran::evaluate::ToInt64(frontEndResultShape->at(dim))) 514 return {builder.createIntegerConstant(loc, idxTy, *maybeI64), 515 *maybeI64}; 516 return {mlir::Value{}, fir::SequenceType::getUnknownExtent()}; 517 }; 518 llvm::SmallVector<mlir::Value> resultExtents; 519 fir::SequenceType::Shape resultTypeShape; 520 bool sawVectorSubscripts = false; 521 for (auto subscript : llvm::enumerate(arrayRef.subscript())) { 522 if (const auto *triplet = 523 std::get_if<Fortran::evaluate::Triplet>(&subscript.value().u)) { 524 mlir::Value lb, ub; 525 if (const auto &lbExpr = triplet->lower()) 526 lb = genSubscript(*lbExpr); 527 else 528 lb = getBaseBounds(subscript.index()).first; 529 if (const auto &ubExpr = triplet->upper()) 530 ub = genSubscript(*ubExpr); 531 else 532 ub = getBaseBounds(subscript.index()).second; 533 lb = builder.createConvert(loc, idxTy, lb); 534 ub = builder.createConvert(loc, idxTy, ub); 535 mlir::Value stride = genSubscript(triplet->stride()); 536 stride = builder.createConvert(loc, idxTy, stride); 537 auto [extentValue, shapeExtent] = 538 tryGettingExtentFromFrontEnd(resultExtents.size()); 539 resultTypeShape.push_back(shapeExtent); 540 if (!extentValue) 541 extentValue = 542 builder.genExtentFromTriplet(loc, lb, ub, stride, idxTy); 543 resultExtents.push_back(extentValue); 544 partInfo.subscripts.emplace_back( 545 hlfir::DesignateOp::Triplet{lb, ub, stride}); 546 } else { 547 const auto &expr = 548 std::get<Fortran::evaluate::IndirectSubscriptIntegerExpr>( 549 subscript.value().u) 550 .value(); 551 hlfir::Entity subscript = genSubscript(expr); 552 partInfo.subscripts.push_back(subscript); 553 if (expr.Rank() > 0) { 554 sawVectorSubscripts = true; 555 auto [extentValue, shapeExtent] = 556 tryGettingExtentFromFrontEnd(resultExtents.size()); 557 resultTypeShape.push_back(shapeExtent); 558 if (!extentValue) 559 extentValue = hlfir::genExtent(loc, builder, subscript, /*dim=*/0); 560 resultExtents.push_back(extentValue); 561 } 562 } 563 } 564 assert(resultExtents.size() == resultTypeShape.size() && 565 "inconsistent hlfir.designate shape"); 566 567 // For vector subscripts, create an hlfir.elemental_addr and continue 568 // lowering the designator inside it as if it was addressing an element of 569 // the vector subscripts. 570 if (sawVectorSubscripts) 571 return createVectorSubscriptElementAddrOp(partInfo, baseType, 572 resultExtents); 573 574 mlir::Type resultType = baseType.cast<fir::SequenceType>().getEleTy(); 575 if (!resultTypeShape.empty()) { 576 // Ranked array section. The result shape comes from the array section 577 // subscripts. 578 resultType = fir::SequenceType::get(resultTypeShape, resultType); 579 assert(!partInfo.resultShape && 580 "Fortran designator can only have one ranked part"); 581 partInfo.resultShape = builder.genShape(loc, resultExtents); 582 } else if (!partInfo.componentName.empty() && 583 partInfo.base.value().isArray()) { 584 // This is an array%array_comp(indices) reference. Keep the 585 // shape of the base array and not the array_comp. 586 auto compBaseTy = partInfo.base->getElementOrSequenceType(); 587 resultType = changeElementType(compBaseTy, resultType); 588 assert(!partInfo.resultShape && "should not have been computed already"); 589 partInfo.resultShape = hlfir::genShape(loc, builder, *partInfo.base); 590 } 591 return resultType; 592 } 593 594 static bool 595 hasNonDefaultLowerBounds(const Fortran::semantics::Symbol &componentSym) { 596 if (const auto *objDetails = 597 componentSym.detailsIf<Fortran::semantics::ObjectEntityDetails>()) 598 for (const Fortran::semantics::ShapeSpec &bounds : objDetails->shape()) 599 if (auto lb = bounds.lbound().GetExplicit()) 600 if (auto constant = Fortran::evaluate::ToInt64(*lb)) 601 if (!constant || *constant != 1) 602 return true; 603 return false; 604 } 605 static bool hasNonDefaultLowerBounds(const PartInfo &partInfo) { 606 return partInfo.resultShape && 607 (partInfo.resultShape.getType().isa<fir::ShiftType>() || 608 partInfo.resultShape.getType().isa<fir::ShapeShiftType>()); 609 } 610 611 mlir::Type visit(const Fortran::evaluate::Component &component, 612 PartInfo &partInfo) { 613 if (Fortran::semantics::IsAllocatableOrPointer(component.GetLastSymbol())) { 614 // In a visit, the following reference will address the target. Insert 615 // the dereference here. 616 partInfo.base = genWholeAllocatableOrPointerComponent(component); 617 partInfo.base = hlfir::derefPointersAndAllocatables(loc, getBuilder(), 618 *partInfo.base); 619 hlfir::genLengthParameters(loc, getBuilder(), *partInfo.base, 620 partInfo.typeParams); 621 return partInfo.base->getElementOrSequenceType(); 622 } 623 // This function must be called from contexts where the component is not the 624 // base of an ArrayRef. In these cases, the component cannot be an array 625 // if the base is an array. The code below determines the shape of the 626 // component reference if any. 627 auto [baseType, componentType] = visitComponentImpl(component, partInfo); 628 mlir::Type componentBaseType = 629 hlfir::getFortranElementOrSequenceType(componentType); 630 if (partInfo.base.value().isArray()) { 631 // For array%scalar_comp, the result shape is 632 // the one of the base. Compute it here. Note that the lower bounds of the 633 // base are not the ones of the resulting reference (that are default 634 // ones). 635 partInfo.resultShape = hlfir::genShape(loc, getBuilder(), *partInfo.base); 636 assert(!partInfo.componentShape && 637 "Fortran designators can only have one ranked part"); 638 return changeElementType(baseType, componentBaseType); 639 } 640 641 if (partInfo.complexPart && partInfo.componentShape) { 642 // Treat ...array_comp%im/re as ...array_comp(:,:,...)%im/re 643 // so that the codegen has the full slice triples for the component 644 // readily available. 645 fir::FirOpBuilder &builder = getBuilder(); 646 mlir::Type idxTy = builder.getIndexType(); 647 mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1); 648 649 llvm::SmallVector<mlir::Value> resultExtents; 650 // Collect <lb, ub> pairs from the component shape. 651 auto bounds = hlfir::genBounds(loc, builder, partInfo.componentShape); 652 for (auto &boundPair : bounds) { 653 // The default subscripts are <lb, ub, 1>: 654 partInfo.subscripts.emplace_back(hlfir::DesignateOp::Triplet{ 655 boundPair.first, boundPair.second, one}); 656 auto extentValue = builder.genExtentFromTriplet( 657 loc, boundPair.first, boundPair.second, one, idxTy); 658 resultExtents.push_back(extentValue); 659 } 660 // The result shape is: <max((ub - lb + 1) / 1, 0), ...>. 661 partInfo.resultShape = builder.genShape(loc, resultExtents); 662 return componentBaseType; 663 } 664 665 // scalar%array_comp or scalar%scalar. In any case the shape of this 666 // part-ref is coming from the component. 667 partInfo.resultShape = partInfo.componentShape; 668 partInfo.componentShape = {}; 669 return componentBaseType; 670 } 671 672 // Returns the <BaseType, ComponentType> pair, computes partInfo.base, 673 // partInfo.componentShape and partInfo.typeParams, but does not set the 674 // partInfo.resultShape yet. The result shape will be computed after 675 // processing a following ArrayRef, if any, and in "visit" otherwise. 676 std::pair<mlir::Type, mlir::Type> 677 visitComponentImpl(const Fortran::evaluate::Component &component, 678 PartInfo &partInfo) { 679 fir::FirOpBuilder &builder = getBuilder(); 680 // Break the Designator visit here: if the base is an array-ref, a 681 // coarray-ref, or another component, this creates another hlfir.designate 682 // for it. hlfir.designate is not meant to represent more than one 683 // part-ref. 684 partInfo.base = gen(component.base()); 685 // If the base is an allocatable/pointer, dereference it here since the 686 // component ref designates its target. 687 partInfo.base = 688 hlfir::derefPointersAndAllocatables(loc, builder, *partInfo.base); 689 assert(partInfo.typeParams.empty() && "should not have been computed yet"); 690 691 hlfir::genLengthParameters(getLoc(), getBuilder(), *partInfo.base, 692 partInfo.typeParams); 693 mlir::Type baseType = partInfo.base->getElementOrSequenceType(); 694 695 // Lower the information about the component (type, length parameters and 696 // shape). 697 const Fortran::semantics::Symbol &componentSym = component.GetLastSymbol(); 698 partInfo.componentName = converter.getRecordTypeFieldName(componentSym); 699 auto recordType = 700 hlfir::getFortranElementType(baseType).cast<fir::RecordType>(); 701 if (recordType.isDependentType()) 702 TODO(getLoc(), "Designate derived type with length parameters in HLFIR"); 703 mlir::Type fieldType = recordType.getType(partInfo.componentName); 704 assert(fieldType && "component name is not known"); 705 mlir::Type fieldBaseType = 706 hlfir::getFortranElementOrSequenceType(fieldType); 707 partInfo.componentShape = genComponentShape(componentSym, fieldBaseType); 708 709 mlir::Type fieldEleType = hlfir::getFortranElementType(fieldBaseType); 710 if (fir::isRecordWithTypeParameters(fieldEleType)) 711 TODO(loc, 712 "lower a component that is a parameterized derived type to HLFIR"); 713 if (auto charTy = fieldEleType.dyn_cast<fir::CharacterType>()) { 714 mlir::Location loc = getLoc(); 715 mlir::Type idxTy = builder.getIndexType(); 716 if (charTy.hasConstantLen()) 717 partInfo.typeParams.push_back( 718 builder.createIntegerConstant(loc, idxTy, charTy.getLen())); 719 else if (!Fortran::semantics::IsAllocatableOrObjectPointer(&componentSym)) 720 TODO(loc, "compute character length of automatic character component " 721 "in a PDT"); 722 // Otherwise, the length of the component is deferred and will only 723 // be read when the component is dereferenced. 724 } 725 return {baseType, fieldType}; 726 } 727 728 // Compute: "lb + (i-1)*step". 729 mlir::Value computeTripletPosition(mlir::Location loc, 730 fir::FirOpBuilder &builder, 731 hlfir::DesignateOp::Triplet &triplet, 732 mlir::Value oneBasedIndex) { 733 mlir::Type idxTy = builder.getIndexType(); 734 mlir::Value lb = builder.createConvert(loc, idxTy, std::get<0>(triplet)); 735 mlir::Value step = builder.createConvert(loc, idxTy, std::get<2>(triplet)); 736 mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1); 737 oneBasedIndex = builder.createConvert(loc, idxTy, oneBasedIndex); 738 mlir::Value zeroBased = 739 builder.create<mlir::arith::SubIOp>(loc, oneBasedIndex, one); 740 mlir::Value offset = 741 builder.create<mlir::arith::MulIOp>(loc, zeroBased, step); 742 return builder.create<mlir::arith::AddIOp>(loc, lb, offset); 743 } 744 745 /// Create an hlfir.element_addr operation to deal with vector subscripted 746 /// entities. This transforms the current vector subscripted array-ref into a 747 /// a scalar array-ref that is addressing the vector subscripted part given 748 /// the one based indices of the hlfir.element_addr. 749 /// The rest of the designator lowering will continue lowering any further 750 /// parts inside the hlfir.elemental as a scalar reference. 751 /// At the end of the designator lowering, the hlfir.elemental_addr will 752 /// be turned into an hlfir.elemental value, unless the caller of this 753 /// utility requested to get the hlfir.elemental_addr instead of lowering 754 /// the designator to an mlir::Value. 755 mlir::Type createVectorSubscriptElementAddrOp( 756 PartInfo &partInfo, mlir::Type baseType, 757 llvm::ArrayRef<mlir::Value> resultExtents) { 758 fir::FirOpBuilder &builder = getBuilder(); 759 mlir::Value shape = builder.genShape(loc, resultExtents); 760 // The type parameters to be added on the hlfir.elemental_addr are the ones 761 // of the whole designator (not the ones of the vector subscripted part). 762 // These are not yet known and will be added when finalizing the designator 763 // lowering. 764 auto elementalAddrOp = 765 builder.create<hlfir::ElementalAddrOp>(loc, shape, 766 /*isUnordered=*/true); 767 setVectorSubscriptElementAddrOp(elementalAddrOp); 768 builder.setInsertionPointToEnd(&elementalAddrOp.getBody().front()); 769 mlir::Region::BlockArgListType indices = elementalAddrOp.getIndices(); 770 auto indicesIterator = indices.begin(); 771 auto getNextOneBasedIndex = [&]() -> mlir::Value { 772 assert(indicesIterator != indices.end() && "ill formed ElementalAddrOp"); 773 return *(indicesIterator++); 774 }; 775 // Transform the designator into a scalar designator computing the vector 776 // subscripted entity element address given one based indices (for the shape 777 // of the vector subscripted designator). 778 for (hlfir::DesignateOp::Subscript &subscript : partInfo.subscripts) { 779 if (auto *triplet = 780 std::get_if<hlfir::DesignateOp::Triplet>(&subscript)) { 781 // subscript = (lb + (i-1)*step) 782 mlir::Value scalarSubscript = computeTripletPosition( 783 loc, builder, *triplet, getNextOneBasedIndex()); 784 subscript = scalarSubscript; 785 } else { 786 hlfir::Entity valueSubscript{std::get<mlir::Value>(subscript)}; 787 if (valueSubscript.isScalar()) 788 continue; 789 // subscript = vector(i + (vector_lb-1)) 790 hlfir::Entity scalarSubscript = hlfir::getElementAt( 791 loc, builder, valueSubscript, {getNextOneBasedIndex()}); 792 scalarSubscript = 793 hlfir::loadTrivialScalar(loc, builder, scalarSubscript); 794 subscript = scalarSubscript; 795 } 796 } 797 builder.setInsertionPoint(elementalAddrOp); 798 return baseType.cast<fir::SequenceType>().getEleTy(); 799 } 800 801 /// Yield the designator for the final part-ref inside the 802 /// hlfir.elemental_addr. 803 void finalizeElementAddrOp(hlfir::ElementalAddrOp elementalAddrOp, 804 hlfir::EntityWithAttributes elementAddr) { 805 fir::FirOpBuilder &builder = getBuilder(); 806 builder.setInsertionPointToEnd(&elementalAddrOp.getBody().front()); 807 // For polymorphic entities, it will be needed to add a mold on the 808 // hlfir.elemental so that we are able to create temporary storage 809 // for it using the dynamic type. It seems that a reference to the mold 810 // entity can be created by evaluating the hlfir.elemental_addr 811 // for a single index. The evaluation should be legal as long as 812 // the hlfir.elemental_addr has no side effects, otherwise, 813 // it is not clear how to get the mold reference. 814 if (elementAddr.isPolymorphic()) 815 TODO(loc, "vector subscripted polymorphic entity in HLFIR"); 816 builder.create<hlfir::YieldOp>(loc, elementAddr); 817 builder.setInsertionPointAfter(elementalAddrOp); 818 } 819 820 /// If the lowered designator has vector subscripts turn it into an 821 /// ElementalOp, otherwise, return the lowered designator. This should 822 /// only be called if the user did not request to get the 823 /// hlfir.elemental_addr. In Fortran, vector subscripted designators are only 824 /// writable on the left-hand side of an assignment and in input IO 825 /// statements. Otherwise, they are not variables (cannot be modified, their 826 /// value is taken at the place they appear). 827 hlfir::EntityWithAttributes turnVectorSubscriptedDesignatorIntoValue( 828 hlfir::EntityWithAttributes loweredDesignator) { 829 std::optional<hlfir::ElementalAddrOp> elementalAddrOp = 830 getVectorSubscriptElementAddrOp(); 831 if (!elementalAddrOp) 832 return loweredDesignator; 833 finalizeElementAddrOp(*elementalAddrOp, loweredDesignator); 834 // This vector subscript designator is only being read, transform the 835 // hlfir.elemental_addr into an hlfir.elemental. The content of the 836 // hlfir.elemental_addr is cloned, and the resulting address is loaded to 837 // get the new element value. 838 fir::FirOpBuilder &builder = getBuilder(); 839 mlir::Location loc = getLoc(); 840 mlir::Value elemental = 841 hlfir::cloneToElementalOp(loc, builder, *elementalAddrOp); 842 (*elementalAddrOp)->erase(); 843 setVectorSubscriptElementAddrOp(std::nullopt); 844 fir::FirOpBuilder *bldr = &builder; 845 getStmtCtx().attachCleanup( 846 [=]() { bldr->create<hlfir::DestroyOp>(loc, elemental); }); 847 return hlfir::EntityWithAttributes{elemental}; 848 } 849 850 /// Lower a subscript expression. If it is a scalar subscript that is a 851 /// variable, it is loaded into an integer value. If it is an array (for 852 /// vector subscripts) it is dereferenced if this is an allocatable or 853 /// pointer. 854 template <typename T> 855 hlfir::Entity genSubscript(const Fortran::evaluate::Expr<T> &expr); 856 857 const std::optional<hlfir::ElementalAddrOp> & 858 getVectorSubscriptElementAddrOp() const { 859 return vectorSubscriptElementAddrOp; 860 } 861 void setVectorSubscriptElementAddrOp( 862 std::optional<hlfir::ElementalAddrOp> elementalAddrOp) { 863 vectorSubscriptElementAddrOp = elementalAddrOp; 864 } 865 866 mlir::Location getLoc() const { return loc; } 867 Fortran::lower::AbstractConverter &getConverter() { return converter; } 868 fir::FirOpBuilder &getBuilder() { return converter.getFirOpBuilder(); } 869 Fortran::lower::SymMap &getSymMap() { return symMap; } 870 Fortran::lower::StatementContext &getStmtCtx() { return stmtCtx; } 871 872 Fortran::lower::AbstractConverter &converter; 873 Fortran::lower::SymMap &symMap; 874 Fortran::lower::StatementContext &stmtCtx; 875 // If there is a vector subscript, an elementalAddrOp is created 876 // to compute the address of the designator elements. 877 std::optional<hlfir::ElementalAddrOp> vectorSubscriptElementAddrOp{}; 878 mlir::Location loc; 879 }; 880 881 hlfir::EntityWithAttributes HlfirDesignatorBuilder::genDesignatorExpr( 882 const Fortran::lower::SomeExpr &designatorExpr, 883 bool vectorSubscriptDesignatorToValue) { 884 // Expr<SomeType> plumbing to unwrap Designator<T> and call 885 // gen(Designator<T>.u). 886 return std::visit( 887 [&](const auto &x) -> hlfir::EntityWithAttributes { 888 using T = std::decay_t<decltype(x)>; 889 if constexpr (Fortran::common::HasMember< 890 T, Fortran::lower::CategoryExpression>) { 891 if constexpr (T::Result::category == 892 Fortran::common::TypeCategory::Derived) { 893 return gen(std::get<Fortran::evaluate::Designator< 894 Fortran::evaluate::SomeDerived>>(x.u) 895 .u, 896 vectorSubscriptDesignatorToValue); 897 } else { 898 return std::visit( 899 [&](const auto &preciseKind) { 900 using TK = 901 typename std::decay_t<decltype(preciseKind)>::Result; 902 return gen( 903 std::get<Fortran::evaluate::Designator<TK>>(preciseKind.u) 904 .u, 905 vectorSubscriptDesignatorToValue); 906 }, 907 x.u); 908 } 909 } else { 910 fir::emitFatalError(loc, "unexpected typeless Designator"); 911 } 912 }, 913 designatorExpr.u); 914 } 915 916 hlfir::ElementalAddrOp 917 HlfirDesignatorBuilder::convertVectorSubscriptedExprToElementalAddr( 918 const Fortran::lower::SomeExpr &designatorExpr) { 919 920 hlfir::EntityWithAttributes elementAddrEntity = genDesignatorExpr( 921 designatorExpr, /*vectorSubscriptDesignatorToValue=*/false); 922 assert(getVectorSubscriptElementAddrOp().has_value() && 923 "expected vector subscripts"); 924 hlfir::ElementalAddrOp elementalAddrOp = *getVectorSubscriptElementAddrOp(); 925 // Now that the type parameters have been computed, add then to the 926 // hlfir.elemental_addr. 927 fir::FirOpBuilder &builder = getBuilder(); 928 llvm::SmallVector<mlir::Value, 1> lengths; 929 hlfir::genLengthParameters(loc, builder, elementAddrEntity, lengths); 930 if (!lengths.empty()) 931 elementalAddrOp.getTypeparamsMutable().assign(lengths); 932 // Create the hlfir.yield terminator inside the hlfir.elemental_body. 933 builder.setInsertionPointToEnd(&elementalAddrOp.getBody().front()); 934 builder.create<hlfir::YieldOp>(loc, elementAddrEntity); 935 builder.setInsertionPointAfter(elementalAddrOp); 936 // Reset the HlfirDesignatorBuilder state, in case it is used on a new 937 // designator. 938 setVectorSubscriptElementAddrOp(std::nullopt); 939 return elementalAddrOp; 940 } 941 942 //===--------------------------------------------------------------------===// 943 // Binary Operation implementation 944 //===--------------------------------------------------------------------===// 945 946 template <typename T> 947 struct BinaryOp {}; 948 949 #undef GENBIN 950 #define GENBIN(GenBinEvOp, GenBinTyCat, GenBinFirOp) \ 951 template <int KIND> \ 952 struct BinaryOp<Fortran::evaluate::GenBinEvOp<Fortran::evaluate::Type< \ 953 Fortran::common::TypeCategory::GenBinTyCat, KIND>>> { \ 954 using Op = Fortran::evaluate::GenBinEvOp<Fortran::evaluate::Type< \ 955 Fortran::common::TypeCategory::GenBinTyCat, KIND>>; \ 956 static hlfir::EntityWithAttributes gen(mlir::Location loc, \ 957 fir::FirOpBuilder &builder, \ 958 const Op &, hlfir::Entity lhs, \ 959 hlfir::Entity rhs) { \ 960 return hlfir::EntityWithAttributes{ \ 961 builder.create<GenBinFirOp>(loc, lhs, rhs)}; \ 962 } \ 963 }; 964 965 GENBIN(Add, Integer, mlir::arith::AddIOp) 966 GENBIN(Add, Real, mlir::arith::AddFOp) 967 GENBIN(Add, Complex, fir::AddcOp) 968 GENBIN(Subtract, Integer, mlir::arith::SubIOp) 969 GENBIN(Subtract, Real, mlir::arith::SubFOp) 970 GENBIN(Subtract, Complex, fir::SubcOp) 971 GENBIN(Multiply, Integer, mlir::arith::MulIOp) 972 GENBIN(Multiply, Real, mlir::arith::MulFOp) 973 GENBIN(Multiply, Complex, fir::MulcOp) 974 GENBIN(Divide, Integer, mlir::arith::DivSIOp) 975 GENBIN(Divide, Real, mlir::arith::DivFOp) 976 977 template <int KIND> 978 struct BinaryOp<Fortran::evaluate::Divide< 979 Fortran::evaluate::Type<Fortran::common::TypeCategory::Complex, KIND>>> { 980 using Op = Fortran::evaluate::Divide< 981 Fortran::evaluate::Type<Fortran::common::TypeCategory::Complex, KIND>>; 982 static hlfir::EntityWithAttributes gen(mlir::Location loc, 983 fir::FirOpBuilder &builder, const Op &, 984 hlfir::Entity lhs, hlfir::Entity rhs) { 985 mlir::Type ty = Fortran::lower::getFIRType( 986 builder.getContext(), Fortran::common::TypeCategory::Complex, KIND, 987 /*params=*/std::nullopt); 988 return hlfir::EntityWithAttributes{ 989 fir::genDivC(builder, loc, ty, lhs, rhs)}; 990 } 991 }; 992 993 template <Fortran::common::TypeCategory TC, int KIND> 994 struct BinaryOp<Fortran::evaluate::Power<Fortran::evaluate::Type<TC, KIND>>> { 995 using Op = Fortran::evaluate::Power<Fortran::evaluate::Type<TC, KIND>>; 996 static hlfir::EntityWithAttributes gen(mlir::Location loc, 997 fir::FirOpBuilder &builder, const Op &, 998 hlfir::Entity lhs, hlfir::Entity rhs) { 999 mlir::Type ty = Fortran::lower::getFIRType(builder.getContext(), TC, KIND, 1000 /*params=*/std::nullopt); 1001 return hlfir::EntityWithAttributes{fir::genPow(builder, loc, ty, lhs, rhs)}; 1002 } 1003 }; 1004 1005 template <Fortran::common::TypeCategory TC, int KIND> 1006 struct BinaryOp< 1007 Fortran::evaluate::RealToIntPower<Fortran::evaluate::Type<TC, KIND>>> { 1008 using Op = 1009 Fortran::evaluate::RealToIntPower<Fortran::evaluate::Type<TC, KIND>>; 1010 static hlfir::EntityWithAttributes gen(mlir::Location loc, 1011 fir::FirOpBuilder &builder, const Op &, 1012 hlfir::Entity lhs, hlfir::Entity rhs) { 1013 mlir::Type ty = Fortran::lower::getFIRType(builder.getContext(), TC, KIND, 1014 /*params=*/std::nullopt); 1015 return hlfir::EntityWithAttributes{fir::genPow(builder, loc, ty, lhs, rhs)}; 1016 } 1017 }; 1018 1019 template <Fortran::common::TypeCategory TC, int KIND> 1020 struct BinaryOp< 1021 Fortran::evaluate::Extremum<Fortran::evaluate::Type<TC, KIND>>> { 1022 using Op = Fortran::evaluate::Extremum<Fortran::evaluate::Type<TC, KIND>>; 1023 static hlfir::EntityWithAttributes gen(mlir::Location loc, 1024 fir::FirOpBuilder &builder, 1025 const Op &op, hlfir::Entity lhs, 1026 hlfir::Entity rhs) { 1027 llvm::SmallVector<mlir::Value, 2> args{lhs, rhs}; 1028 fir::ExtendedValue res = op.ordering == Fortran::evaluate::Ordering::Greater 1029 ? fir::genMax(builder, loc, args) 1030 : fir::genMin(builder, loc, args); 1031 return hlfir::EntityWithAttributes{fir::getBase(res)}; 1032 } 1033 }; 1034 1035 // evaluate::Extremum is only created by the front-end when building compiler 1036 // generated expressions (like when folding LEN() or shape/bounds inquiries). 1037 // MIN and MAX are represented as evaluate::ProcedureRef and are not going 1038 // through here. So far the frontend does not generate character Extremum so 1039 // there is no way to test it. 1040 template <int KIND> 1041 struct BinaryOp<Fortran::evaluate::Extremum< 1042 Fortran::evaluate::Type<Fortran::common::TypeCategory::Character, KIND>>> { 1043 using Op = Fortran::evaluate::Extremum< 1044 Fortran::evaluate::Type<Fortran::common::TypeCategory::Character, KIND>>; 1045 static hlfir::EntityWithAttributes gen(mlir::Location loc, 1046 fir::FirOpBuilder &, const Op &, 1047 hlfir::Entity, hlfir::Entity) { 1048 fir::emitFatalError(loc, "Fortran::evaluate::Extremum are unexpected"); 1049 } 1050 static void genResultTypeParams(mlir::Location loc, fir::FirOpBuilder &, 1051 hlfir::Entity, hlfir::Entity, 1052 llvm::SmallVectorImpl<mlir::Value> &) { 1053 fir::emitFatalError(loc, "Fortran::evaluate::Extremum are unexpected"); 1054 } 1055 }; 1056 1057 /// Convert parser's INTEGER relational operators to MLIR. 1058 static mlir::arith::CmpIPredicate 1059 translateRelational(Fortran::common::RelationalOperator rop) { 1060 switch (rop) { 1061 case Fortran::common::RelationalOperator::LT: 1062 return mlir::arith::CmpIPredicate::slt; 1063 case Fortran::common::RelationalOperator::LE: 1064 return mlir::arith::CmpIPredicate::sle; 1065 case Fortran::common::RelationalOperator::EQ: 1066 return mlir::arith::CmpIPredicate::eq; 1067 case Fortran::common::RelationalOperator::NE: 1068 return mlir::arith::CmpIPredicate::ne; 1069 case Fortran::common::RelationalOperator::GT: 1070 return mlir::arith::CmpIPredicate::sgt; 1071 case Fortran::common::RelationalOperator::GE: 1072 return mlir::arith::CmpIPredicate::sge; 1073 } 1074 llvm_unreachable("unhandled INTEGER relational operator"); 1075 } 1076 1077 /// Convert parser's REAL relational operators to MLIR. 1078 /// The choice of order (O prefix) vs unorder (U prefix) follows Fortran 2018 1079 /// requirements in the IEEE context (table 17.1 of F2018). This choice is 1080 /// also applied in other contexts because it is easier and in line with 1081 /// other Fortran compilers. 1082 /// FIXME: The signaling/quiet aspect of the table 17.1 requirement is not 1083 /// fully enforced. FIR and LLVM `fcmp` instructions do not give any guarantee 1084 /// whether the comparison will signal or not in case of quiet NaN argument. 1085 static mlir::arith::CmpFPredicate 1086 translateFloatRelational(Fortran::common::RelationalOperator rop) { 1087 switch (rop) { 1088 case Fortran::common::RelationalOperator::LT: 1089 return mlir::arith::CmpFPredicate::OLT; 1090 case Fortran::common::RelationalOperator::LE: 1091 return mlir::arith::CmpFPredicate::OLE; 1092 case Fortran::common::RelationalOperator::EQ: 1093 return mlir::arith::CmpFPredicate::OEQ; 1094 case Fortran::common::RelationalOperator::NE: 1095 return mlir::arith::CmpFPredicate::UNE; 1096 case Fortran::common::RelationalOperator::GT: 1097 return mlir::arith::CmpFPredicate::OGT; 1098 case Fortran::common::RelationalOperator::GE: 1099 return mlir::arith::CmpFPredicate::OGE; 1100 } 1101 llvm_unreachable("unhandled REAL relational operator"); 1102 } 1103 1104 template <int KIND> 1105 struct BinaryOp<Fortran::evaluate::Relational< 1106 Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer, KIND>>> { 1107 using Op = Fortran::evaluate::Relational< 1108 Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer, KIND>>; 1109 static hlfir::EntityWithAttributes gen(mlir::Location loc, 1110 fir::FirOpBuilder &builder, 1111 const Op &op, hlfir::Entity lhs, 1112 hlfir::Entity rhs) { 1113 auto cmp = builder.create<mlir::arith::CmpIOp>( 1114 loc, translateRelational(op.opr), lhs, rhs); 1115 return hlfir::EntityWithAttributes{cmp}; 1116 } 1117 }; 1118 1119 template <int KIND> 1120 struct BinaryOp<Fortran::evaluate::Relational< 1121 Fortran::evaluate::Type<Fortran::common::TypeCategory::Real, KIND>>> { 1122 using Op = Fortran::evaluate::Relational< 1123 Fortran::evaluate::Type<Fortran::common::TypeCategory::Real, KIND>>; 1124 static hlfir::EntityWithAttributes gen(mlir::Location loc, 1125 fir::FirOpBuilder &builder, 1126 const Op &op, hlfir::Entity lhs, 1127 hlfir::Entity rhs) { 1128 auto cmp = builder.create<mlir::arith::CmpFOp>( 1129 loc, translateFloatRelational(op.opr), lhs, rhs); 1130 return hlfir::EntityWithAttributes{cmp}; 1131 } 1132 }; 1133 1134 template <int KIND> 1135 struct BinaryOp<Fortran::evaluate::Relational< 1136 Fortran::evaluate::Type<Fortran::common::TypeCategory::Complex, KIND>>> { 1137 using Op = Fortran::evaluate::Relational< 1138 Fortran::evaluate::Type<Fortran::common::TypeCategory::Complex, KIND>>; 1139 static hlfir::EntityWithAttributes gen(mlir::Location loc, 1140 fir::FirOpBuilder &builder, 1141 const Op &op, hlfir::Entity lhs, 1142 hlfir::Entity rhs) { 1143 auto cmp = builder.create<fir::CmpcOp>( 1144 loc, translateFloatRelational(op.opr), lhs, rhs); 1145 return hlfir::EntityWithAttributes{cmp}; 1146 } 1147 }; 1148 1149 template <int KIND> 1150 struct BinaryOp<Fortran::evaluate::Relational< 1151 Fortran::evaluate::Type<Fortran::common::TypeCategory::Character, KIND>>> { 1152 using Op = Fortran::evaluate::Relational< 1153 Fortran::evaluate::Type<Fortran::common::TypeCategory::Character, KIND>>; 1154 static hlfir::EntityWithAttributes gen(mlir::Location loc, 1155 fir::FirOpBuilder &builder, 1156 const Op &op, hlfir::Entity lhs, 1157 hlfir::Entity rhs) { 1158 auto [lhsExv, lhsCleanUp] = 1159 hlfir::translateToExtendedValue(loc, builder, lhs); 1160 auto [rhsExv, rhsCleanUp] = 1161 hlfir::translateToExtendedValue(loc, builder, rhs); 1162 auto cmp = fir::runtime::genCharCompare( 1163 builder, loc, translateRelational(op.opr), lhsExv, rhsExv); 1164 if (lhsCleanUp) 1165 (*lhsCleanUp)(); 1166 if (rhsCleanUp) 1167 (*rhsCleanUp)(); 1168 return hlfir::EntityWithAttributes{cmp}; 1169 } 1170 }; 1171 1172 template <int KIND> 1173 struct BinaryOp<Fortran::evaluate::LogicalOperation<KIND>> { 1174 using Op = Fortran::evaluate::LogicalOperation<KIND>; 1175 static hlfir::EntityWithAttributes gen(mlir::Location loc, 1176 fir::FirOpBuilder &builder, 1177 const Op &op, hlfir::Entity lhs, 1178 hlfir::Entity rhs) { 1179 mlir::Type i1Type = builder.getI1Type(); 1180 mlir::Value i1Lhs = builder.createConvert(loc, i1Type, lhs); 1181 mlir::Value i1Rhs = builder.createConvert(loc, i1Type, rhs); 1182 switch (op.logicalOperator) { 1183 case Fortran::evaluate::LogicalOperator::And: 1184 return hlfir::EntityWithAttributes{ 1185 builder.create<mlir::arith::AndIOp>(loc, i1Lhs, i1Rhs)}; 1186 case Fortran::evaluate::LogicalOperator::Or: 1187 return hlfir::EntityWithAttributes{ 1188 builder.create<mlir::arith::OrIOp>(loc, i1Lhs, i1Rhs)}; 1189 case Fortran::evaluate::LogicalOperator::Eqv: 1190 return hlfir::EntityWithAttributes{builder.create<mlir::arith::CmpIOp>( 1191 loc, mlir::arith::CmpIPredicate::eq, i1Lhs, i1Rhs)}; 1192 case Fortran::evaluate::LogicalOperator::Neqv: 1193 return hlfir::EntityWithAttributes{builder.create<mlir::arith::CmpIOp>( 1194 loc, mlir::arith::CmpIPredicate::ne, i1Lhs, i1Rhs)}; 1195 case Fortran::evaluate::LogicalOperator::Not: 1196 // lib/evaluate expression for .NOT. is Fortran::evaluate::Not<KIND>. 1197 llvm_unreachable(".NOT. is not a binary operator"); 1198 } 1199 llvm_unreachable("unhandled logical operation"); 1200 } 1201 }; 1202 1203 template <int KIND> 1204 struct BinaryOp<Fortran::evaluate::ComplexConstructor<KIND>> { 1205 using Op = Fortran::evaluate::ComplexConstructor<KIND>; 1206 static hlfir::EntityWithAttributes gen(mlir::Location loc, 1207 fir::FirOpBuilder &builder, const Op &, 1208 hlfir::Entity lhs, hlfir::Entity rhs) { 1209 mlir::Value res = 1210 fir::factory::Complex{builder, loc}.createComplex(KIND, lhs, rhs); 1211 return hlfir::EntityWithAttributes{res}; 1212 } 1213 }; 1214 1215 template <int KIND> 1216 struct BinaryOp<Fortran::evaluate::SetLength<KIND>> { 1217 using Op = Fortran::evaluate::SetLength<KIND>; 1218 static hlfir::EntityWithAttributes gen(mlir::Location loc, 1219 fir::FirOpBuilder &builder, const Op &, 1220 hlfir::Entity string, 1221 hlfir::Entity length) { 1222 return hlfir::EntityWithAttributes{ 1223 builder.create<hlfir::SetLengthOp>(loc, string, length)}; 1224 } 1225 static void 1226 genResultTypeParams(mlir::Location, fir::FirOpBuilder &, hlfir::Entity, 1227 hlfir::Entity rhs, 1228 llvm::SmallVectorImpl<mlir::Value> &resultTypeParams) { 1229 resultTypeParams.push_back(rhs); 1230 } 1231 }; 1232 1233 template <int KIND> 1234 struct BinaryOp<Fortran::evaluate::Concat<KIND>> { 1235 using Op = Fortran::evaluate::Concat<KIND>; 1236 hlfir::EntityWithAttributes gen(mlir::Location loc, 1237 fir::FirOpBuilder &builder, const Op &, 1238 hlfir::Entity lhs, hlfir::Entity rhs) { 1239 assert(len && "genResultTypeParams must have been called"); 1240 auto concat = 1241 builder.create<hlfir::ConcatOp>(loc, mlir::ValueRange{lhs, rhs}, len); 1242 return hlfir::EntityWithAttributes{concat.getResult()}; 1243 } 1244 void 1245 genResultTypeParams(mlir::Location loc, fir::FirOpBuilder &builder, 1246 hlfir::Entity lhs, hlfir::Entity rhs, 1247 llvm::SmallVectorImpl<mlir::Value> &resultTypeParams) { 1248 llvm::SmallVector<mlir::Value> lengths; 1249 hlfir::genLengthParameters(loc, builder, lhs, lengths); 1250 hlfir::genLengthParameters(loc, builder, rhs, lengths); 1251 assert(lengths.size() == 2 && "lacks rhs or lhs length"); 1252 mlir::Type idxType = builder.getIndexType(); 1253 mlir::Value lhsLen = builder.createConvert(loc, idxType, lengths[0]); 1254 mlir::Value rhsLen = builder.createConvert(loc, idxType, lengths[1]); 1255 len = builder.create<mlir::arith::AddIOp>(loc, lhsLen, rhsLen); 1256 resultTypeParams.push_back(len); 1257 } 1258 1259 private: 1260 mlir::Value len{}; 1261 }; 1262 1263 //===--------------------------------------------------------------------===// 1264 // Unary Operation implementation 1265 //===--------------------------------------------------------------------===// 1266 1267 template <typename T> 1268 struct UnaryOp {}; 1269 1270 template <int KIND> 1271 struct UnaryOp<Fortran::evaluate::Not<KIND>> { 1272 using Op = Fortran::evaluate::Not<KIND>; 1273 static hlfir::EntityWithAttributes gen(mlir::Location loc, 1274 fir::FirOpBuilder &builder, const Op &, 1275 hlfir::Entity lhs) { 1276 mlir::Value one = builder.createBool(loc, true); 1277 mlir::Value val = builder.createConvert(loc, builder.getI1Type(), lhs); 1278 return hlfir::EntityWithAttributes{ 1279 builder.create<mlir::arith::XOrIOp>(loc, val, one)}; 1280 } 1281 }; 1282 1283 template <int KIND> 1284 struct UnaryOp<Fortran::evaluate::Negate< 1285 Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer, KIND>>> { 1286 using Op = Fortran::evaluate::Negate< 1287 Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer, KIND>>; 1288 static hlfir::EntityWithAttributes gen(mlir::Location loc, 1289 fir::FirOpBuilder &builder, const Op &, 1290 hlfir::Entity lhs) { 1291 // Like LLVM, integer negation is the binary op "0 - value" 1292 mlir::Type type = Fortran::lower::getFIRType( 1293 builder.getContext(), Fortran::common::TypeCategory::Integer, KIND, 1294 /*params=*/std::nullopt); 1295 mlir::Value zero = builder.createIntegerConstant(loc, type, 0); 1296 return hlfir::EntityWithAttributes{ 1297 builder.create<mlir::arith::SubIOp>(loc, zero, lhs)}; 1298 } 1299 }; 1300 1301 template <int KIND> 1302 struct UnaryOp<Fortran::evaluate::Negate< 1303 Fortran::evaluate::Type<Fortran::common::TypeCategory::Real, KIND>>> { 1304 using Op = Fortran::evaluate::Negate< 1305 Fortran::evaluate::Type<Fortran::common::TypeCategory::Real, KIND>>; 1306 static hlfir::EntityWithAttributes gen(mlir::Location loc, 1307 fir::FirOpBuilder &builder, const Op &, 1308 hlfir::Entity lhs) { 1309 return hlfir::EntityWithAttributes{ 1310 builder.create<mlir::arith::NegFOp>(loc, lhs)}; 1311 } 1312 }; 1313 1314 template <int KIND> 1315 struct UnaryOp<Fortran::evaluate::Negate< 1316 Fortran::evaluate::Type<Fortran::common::TypeCategory::Complex, KIND>>> { 1317 using Op = Fortran::evaluate::Negate< 1318 Fortran::evaluate::Type<Fortran::common::TypeCategory::Complex, KIND>>; 1319 static hlfir::EntityWithAttributes gen(mlir::Location loc, 1320 fir::FirOpBuilder &builder, const Op &, 1321 hlfir::Entity lhs) { 1322 return hlfir::EntityWithAttributes{builder.create<fir::NegcOp>(loc, lhs)}; 1323 } 1324 }; 1325 1326 template <int KIND> 1327 struct UnaryOp<Fortran::evaluate::ComplexComponent<KIND>> { 1328 using Op = Fortran::evaluate::ComplexComponent<KIND>; 1329 static hlfir::EntityWithAttributes gen(mlir::Location loc, 1330 fir::FirOpBuilder &builder, 1331 const Op &op, hlfir::Entity lhs) { 1332 mlir::Value res = fir::factory::Complex{builder, loc}.extractComplexPart( 1333 lhs, op.isImaginaryPart); 1334 return hlfir::EntityWithAttributes{res}; 1335 } 1336 }; 1337 1338 template <typename T> 1339 struct UnaryOp<Fortran::evaluate::Parentheses<T>> { 1340 using Op = Fortran::evaluate::Parentheses<T>; 1341 static hlfir::EntityWithAttributes gen(mlir::Location loc, 1342 fir::FirOpBuilder &builder, 1343 const Op &op, hlfir::Entity lhs) { 1344 if (lhs.isVariable()) 1345 return hlfir::EntityWithAttributes{ 1346 builder.create<hlfir::AsExprOp>(loc, lhs)}; 1347 return hlfir::EntityWithAttributes{ 1348 builder.create<hlfir::NoReassocOp>(loc, lhs.getType(), lhs)}; 1349 } 1350 1351 static void 1352 genResultTypeParams(mlir::Location loc, fir::FirOpBuilder &builder, 1353 hlfir::Entity lhs, 1354 llvm::SmallVectorImpl<mlir::Value> &resultTypeParams) { 1355 hlfir::genLengthParameters(loc, builder, lhs, resultTypeParams); 1356 } 1357 }; 1358 1359 template <Fortran::common::TypeCategory TC1, int KIND, 1360 Fortran::common::TypeCategory TC2> 1361 struct UnaryOp< 1362 Fortran::evaluate::Convert<Fortran::evaluate::Type<TC1, KIND>, TC2>> { 1363 using Op = 1364 Fortran::evaluate::Convert<Fortran::evaluate::Type<TC1, KIND>, TC2>; 1365 static hlfir::EntityWithAttributes gen(mlir::Location loc, 1366 fir::FirOpBuilder &builder, const Op &, 1367 hlfir::Entity lhs) { 1368 if constexpr (TC1 == Fortran::common::TypeCategory::Character && 1369 TC2 == TC1) { 1370 return hlfir::convertCharacterKind(loc, builder, lhs, KIND); 1371 } 1372 mlir::Type type = Fortran::lower::getFIRType(builder.getContext(), TC1, 1373 KIND, /*params=*/std::nullopt); 1374 mlir::Value res = builder.convertWithSemantics(loc, type, lhs); 1375 return hlfir::EntityWithAttributes{res}; 1376 } 1377 1378 static void 1379 genResultTypeParams(mlir::Location loc, fir::FirOpBuilder &builder, 1380 hlfir::Entity lhs, 1381 llvm::SmallVectorImpl<mlir::Value> &resultTypeParams) { 1382 hlfir::genLengthParameters(loc, builder, lhs, resultTypeParams); 1383 } 1384 }; 1385 1386 /// Lower Expr to HLFIR. 1387 class HlfirBuilder { 1388 public: 1389 HlfirBuilder(mlir::Location loc, Fortran::lower::AbstractConverter &converter, 1390 Fortran::lower::SymMap &symMap, 1391 Fortran::lower::StatementContext &stmtCtx) 1392 : converter{converter}, symMap{symMap}, stmtCtx{stmtCtx}, loc{loc} {} 1393 1394 template <typename T> 1395 hlfir::EntityWithAttributes gen(const Fortran::evaluate::Expr<T> &expr) { 1396 if (const Fortran::lower::ExprToValueMap *map = 1397 getConverter().getExprOverrides()) { 1398 if constexpr (std::is_same_v<T, Fortran::evaluate::SomeType>) { 1399 if (auto match = map->find(&expr); match != map->end()) 1400 return hlfir::EntityWithAttributes{match->second}; 1401 } else { 1402 Fortran::lower::SomeExpr someExpr = toEvExpr(expr); 1403 if (auto match = map->find(&someExpr); match != map->end()) 1404 return hlfir::EntityWithAttributes{match->second}; 1405 } 1406 } 1407 return std::visit([&](const auto &x) { return gen(x); }, expr.u); 1408 } 1409 1410 private: 1411 hlfir::EntityWithAttributes 1412 gen(const Fortran::evaluate::BOZLiteralConstant &expr) { 1413 TODO(getLoc(), "BOZ"); 1414 } 1415 1416 hlfir::EntityWithAttributes gen(const Fortran::evaluate::NullPointer &expr) { 1417 auto nullop = getBuilder().create<hlfir::NullOp>(getLoc()); 1418 return mlir::cast<fir::FortranVariableOpInterface>(nullop.getOperation()); 1419 } 1420 1421 hlfir::EntityWithAttributes 1422 gen(const Fortran::evaluate::ProcedureDesignator &proc) { 1423 return Fortran::lower::convertProcedureDesignatorToHLFIR( 1424 getLoc(), getConverter(), proc, getSymMap(), getStmtCtx()); 1425 } 1426 1427 hlfir::EntityWithAttributes gen(const Fortran::evaluate::ProcedureRef &expr) { 1428 TODO( 1429 getLoc(), 1430 "lowering function references that return procedure pointers to HLFIR"); 1431 } 1432 1433 template <typename T> 1434 hlfir::EntityWithAttributes 1435 gen(const Fortran::evaluate::Designator<T> &designator) { 1436 return HlfirDesignatorBuilder(getLoc(), getConverter(), getSymMap(), 1437 getStmtCtx()) 1438 .gen(designator.u); 1439 } 1440 1441 template <typename T> 1442 hlfir::EntityWithAttributes 1443 gen(const Fortran::evaluate::FunctionRef<T> &expr) { 1444 mlir::Type resType = 1445 Fortran::lower::TypeBuilder<T>::genType(getConverter(), expr); 1446 auto result = Fortran::lower::convertCallToHLFIR( 1447 getLoc(), getConverter(), expr, resType, getSymMap(), getStmtCtx()); 1448 assert(result.has_value()); 1449 return *result; 1450 } 1451 1452 template <typename T> 1453 hlfir::EntityWithAttributes gen(const Fortran::evaluate::Constant<T> &expr) { 1454 mlir::Location loc = getLoc(); 1455 fir::FirOpBuilder &builder = getBuilder(); 1456 fir::ExtendedValue exv = Fortran::lower::convertConstant( 1457 converter, loc, expr, /*outlineBigConstantInReadOnlyMemory=*/true); 1458 if (const auto *scalarBox = exv.getUnboxed()) 1459 if (fir::isa_trivial(scalarBox->getType())) 1460 return hlfir::EntityWithAttributes(*scalarBox); 1461 if (auto addressOf = fir::getBase(exv).getDefiningOp<fir::AddrOfOp>()) { 1462 auto flags = fir::FortranVariableFlagsAttr::get( 1463 builder.getContext(), fir::FortranVariableFlagsEnum::parameter); 1464 return hlfir::genDeclare( 1465 loc, builder, exv, 1466 addressOf.getSymbol().getRootReference().getValue(), flags); 1467 } 1468 fir::emitFatalError(loc, "Constant<T> was lowered to unexpected format"); 1469 } 1470 1471 template <typename T> 1472 hlfir::EntityWithAttributes 1473 gen(const Fortran::evaluate::ArrayConstructor<T> &arrayCtor) { 1474 return Fortran::lower::ArrayConstructorBuilder<T>::gen( 1475 getLoc(), getConverter(), arrayCtor, getSymMap(), getStmtCtx()); 1476 } 1477 1478 template <typename D, typename R, typename O> 1479 hlfir::EntityWithAttributes 1480 gen(const Fortran::evaluate::Operation<D, R, O> &op) { 1481 auto &builder = getBuilder(); 1482 mlir::Location loc = getLoc(); 1483 const int rank = op.Rank(); 1484 UnaryOp<D> unaryOp; 1485 auto left = hlfir::loadTrivialScalar(loc, builder, gen(op.left())); 1486 llvm::SmallVector<mlir::Value, 1> typeParams; 1487 if constexpr (R::category == Fortran::common::TypeCategory::Character) { 1488 unaryOp.genResultTypeParams(loc, builder, left, typeParams); 1489 } 1490 if (rank == 0) 1491 return unaryOp.gen(loc, builder, op.derived(), left); 1492 1493 // Elemental expression. 1494 mlir::Type elementType; 1495 if constexpr (R::category == Fortran::common::TypeCategory::Derived) { 1496 if (op.derived().GetType().IsUnlimitedPolymorphic()) 1497 elementType = mlir::NoneType::get(builder.getContext()); 1498 else 1499 elementType = Fortran::lower::translateDerivedTypeToFIRType( 1500 getConverter(), op.derived().GetType().GetDerivedTypeSpec()); 1501 } else { 1502 elementType = 1503 Fortran::lower::getFIRType(builder.getContext(), R::category, R::kind, 1504 /*params=*/std::nullopt); 1505 } 1506 mlir::Value shape = hlfir::genShape(loc, builder, left); 1507 auto genKernel = [&op, &left, &unaryOp]( 1508 mlir::Location l, fir::FirOpBuilder &b, 1509 mlir::ValueRange oneBasedIndices) -> hlfir::Entity { 1510 auto leftElement = hlfir::getElementAt(l, b, left, oneBasedIndices); 1511 auto leftVal = hlfir::loadTrivialScalar(l, b, leftElement); 1512 return unaryOp.gen(l, b, op.derived(), leftVal); 1513 }; 1514 mlir::Value elemental = hlfir::genElementalOp( 1515 loc, builder, elementType, shape, typeParams, genKernel, 1516 /*isUnordered=*/true, left.isPolymorphic() ? left : mlir::Value{}); 1517 fir::FirOpBuilder *bldr = &builder; 1518 getStmtCtx().attachCleanup( 1519 [=]() { bldr->create<hlfir::DestroyOp>(loc, elemental); }); 1520 return hlfir::EntityWithAttributes{elemental}; 1521 } 1522 1523 template <typename D, typename R, typename LO, typename RO> 1524 hlfir::EntityWithAttributes 1525 gen(const Fortran::evaluate::Operation<D, R, LO, RO> &op) { 1526 auto &builder = getBuilder(); 1527 mlir::Location loc = getLoc(); 1528 const int rank = op.Rank(); 1529 BinaryOp<D> binaryOp; 1530 auto left = hlfir::loadTrivialScalar(loc, builder, gen(op.left())); 1531 auto right = hlfir::loadTrivialScalar(loc, builder, gen(op.right())); 1532 llvm::SmallVector<mlir::Value, 1> typeParams; 1533 if constexpr (R::category == Fortran::common::TypeCategory::Character) { 1534 binaryOp.genResultTypeParams(loc, builder, left, right, typeParams); 1535 } 1536 if (rank == 0) 1537 return binaryOp.gen(loc, builder, op.derived(), left, right); 1538 1539 // Elemental expression. 1540 mlir::Type elementType = 1541 Fortran::lower::getFIRType(builder.getContext(), R::category, R::kind, 1542 /*params=*/std::nullopt); 1543 // TODO: "merge" shape, get cst shape from front-end if possible. 1544 mlir::Value shape; 1545 if (left.isArray()) { 1546 shape = hlfir::genShape(loc, builder, left); 1547 } else { 1548 assert(right.isArray() && "must have at least one array operand"); 1549 shape = hlfir::genShape(loc, builder, right); 1550 } 1551 auto genKernel = [&op, &left, &right, &binaryOp]( 1552 mlir::Location l, fir::FirOpBuilder &b, 1553 mlir::ValueRange oneBasedIndices) -> hlfir::Entity { 1554 auto leftElement = hlfir::getElementAt(l, b, left, oneBasedIndices); 1555 auto rightElement = hlfir::getElementAt(l, b, right, oneBasedIndices); 1556 auto leftVal = hlfir::loadTrivialScalar(l, b, leftElement); 1557 auto rightVal = hlfir::loadTrivialScalar(l, b, rightElement); 1558 return binaryOp.gen(l, b, op.derived(), leftVal, rightVal); 1559 }; 1560 mlir::Value elemental = hlfir::genElementalOp(loc, builder, elementType, 1561 shape, typeParams, genKernel, 1562 /*isUnordered=*/true); 1563 fir::FirOpBuilder *bldr = &builder; 1564 getStmtCtx().attachCleanup( 1565 [=]() { bldr->create<hlfir::DestroyOp>(loc, elemental); }); 1566 return hlfir::EntityWithAttributes{elemental}; 1567 } 1568 1569 hlfir::EntityWithAttributes 1570 gen(const Fortran::evaluate::Relational<Fortran::evaluate::SomeType> &op) { 1571 return std::visit([&](const auto &x) { return gen(x); }, op.u); 1572 } 1573 1574 hlfir::EntityWithAttributes gen(const Fortran::evaluate::TypeParamInquiry &) { 1575 TODO(getLoc(), "lowering type parameter inquiry to HLFIR"); 1576 } 1577 1578 hlfir::EntityWithAttributes 1579 gen(const Fortran::evaluate::DescriptorInquiry &desc) { 1580 mlir::Location loc = getLoc(); 1581 auto &builder = getBuilder(); 1582 hlfir::EntityWithAttributes entity = 1583 HlfirDesignatorBuilder(getLoc(), getConverter(), getSymMap(), 1584 getStmtCtx()) 1585 .genNamedEntity(desc.base()); 1586 using ResTy = Fortran::evaluate::DescriptorInquiry::Result; 1587 mlir::Type resultType = 1588 getConverter().genType(ResTy::category, ResTy::kind); 1589 auto castResult = [&](mlir::Value v) { 1590 return hlfir::EntityWithAttributes{ 1591 builder.createConvert(loc, resultType, v)}; 1592 }; 1593 switch (desc.field()) { 1594 case Fortran::evaluate::DescriptorInquiry::Field::Len: 1595 return castResult(hlfir::genCharLength(loc, builder, entity)); 1596 case Fortran::evaluate::DescriptorInquiry::Field::LowerBound: 1597 return castResult( 1598 hlfir::genLBound(loc, builder, entity, desc.dimension())); 1599 case Fortran::evaluate::DescriptorInquiry::Field::Extent: 1600 return castResult( 1601 hlfir::genExtent(loc, builder, entity, desc.dimension())); 1602 case Fortran::evaluate::DescriptorInquiry::Field::Rank: 1603 TODO(loc, "rank inquiry on assumed rank"); 1604 case Fortran::evaluate::DescriptorInquiry::Field::Stride: 1605 // So far the front end does not generate this inquiry. 1606 TODO(loc, "stride inquiry"); 1607 } 1608 llvm_unreachable("unknown descriptor inquiry"); 1609 } 1610 1611 hlfir::EntityWithAttributes 1612 gen(const Fortran::evaluate::ImpliedDoIndex &var) { 1613 mlir::Value value = symMap.lookupImpliedDo(toStringRef(var.name)); 1614 if (!value) 1615 fir::emitFatalError(getLoc(), "ac-do-variable has no binding"); 1616 // The index value generated by the implied-do has Index type, 1617 // while computations based on it inside the loop body are using 1618 // the original data type. So we need to cast it appropriately. 1619 mlir::Type varTy = getConverter().genType(toEvExpr(var)); 1620 value = getBuilder().createConvert(getLoc(), varTy, value); 1621 return hlfir::EntityWithAttributes{value}; 1622 } 1623 1624 static bool 1625 isDerivedTypeWithLenParameters(const Fortran::semantics::Symbol &sym) { 1626 if (const Fortran::semantics::DeclTypeSpec *declTy = sym.GetType()) 1627 if (const Fortran::semantics::DerivedTypeSpec *derived = 1628 declTy->AsDerived()) 1629 return Fortran::semantics::CountLenParameters(*derived) > 0; 1630 return false; 1631 } 1632 1633 // Construct an entity holding the value specified by the 1634 // StructureConstructor. The initialization of the temporary entity 1635 // is done component by component with the help of HLFIR operations 1636 // DesignateOp and AssignOp. 1637 hlfir::EntityWithAttributes 1638 gen(const Fortran::evaluate::StructureConstructor &ctor) { 1639 mlir::Location loc = getLoc(); 1640 fir::FirOpBuilder &builder = getBuilder(); 1641 mlir::Type ty = translateSomeExprToFIRType(converter, toEvExpr(ctor)); 1642 auto recTy = ty.cast<fir::RecordType>(); 1643 1644 if (recTy.isDependentType()) 1645 TODO(loc, "structure constructor for derived type with length parameters " 1646 "in HLFIR"); 1647 1648 // Allocate scalar temporary that will be initialized 1649 // with the values specified by the constructor. 1650 mlir::Value storagePtr = builder.createTemporary(loc, recTy); 1651 auto varOp = hlfir::EntityWithAttributes{builder.create<hlfir::DeclareOp>( 1652 loc, storagePtr, "ctor.temp", /*shape=*/nullptr, 1653 /*typeparams=*/mlir::ValueRange{}, fir::FortranVariableFlagsAttr{})}; 1654 1655 // Initialize any components that need initialization. 1656 mlir::Value box = builder.createBox(loc, fir::ExtendedValue{varOp}); 1657 fir::runtime::genDerivedTypeInitialize(builder, loc, box); 1658 1659 // StructureConstructor values may relate to name of components in parent 1660 // types. These components cannot be addressed directly, the parent 1661 // components must be addressed first. The loop below creates all the 1662 // required chains of hlfir.designate to address the parent components so 1663 // that the StructureConstructor can later be lowered by addressing these 1664 // parent components if needed. Note: the front-end orders the components in 1665 // structure constructors. The code below relies on the component to appear 1666 // in order. 1667 using ValueAndParent = std::tuple<const Fortran::lower::SomeExpr &, 1668 const Fortran::semantics::Symbol &, 1669 hlfir::EntityWithAttributes>; 1670 llvm::SmallVector<ValueAndParent> valuesAndParents; 1671 Fortran::lower::ComponentReverseIterator compIterator( 1672 ctor.result().derivedTypeSpec()); 1673 hlfir::EntityWithAttributes currentParent = varOp; 1674 for (const auto &value : llvm::reverse(ctor.values())) { 1675 const Fortran::semantics::Symbol &compSym = *value.first; 1676 while (!compIterator.lookup(compSym.name())) { 1677 const auto &parentType = compIterator.advanceToParentType(); 1678 llvm::StringRef parentName = toStringRef(parentType.name()); 1679 auto baseRecTy = mlir::cast<fir::RecordType>( 1680 hlfir::getFortranElementType(currentParent.getType())); 1681 auto parentCompType = baseRecTy.getType(parentName); 1682 assert(parentCompType && "failed to retrieve parent component type"); 1683 mlir::Type designatorType = builder.getRefType(parentCompType); 1684 mlir::Value newParent = builder.create<hlfir::DesignateOp>( 1685 loc, designatorType, currentParent, parentName, 1686 /*compShape=*/mlir::Value{}, hlfir::DesignateOp::Subscripts{}, 1687 /*substring=*/mlir::ValueRange{}, 1688 /*complexPart=*/std::nullopt, 1689 /*shape=*/mlir::Value{}, /*typeParams=*/mlir::ValueRange{}, 1690 fir::FortranVariableFlagsAttr{}); 1691 currentParent = hlfir::EntityWithAttributes{newParent}; 1692 } 1693 valuesAndParents.emplace_back( 1694 ValueAndParent{value.second.value(), compSym, currentParent}); 1695 } 1696 1697 HlfirDesignatorBuilder designatorBuilder(loc, converter, symMap, stmtCtx); 1698 for (const auto &iter : llvm::reverse(valuesAndParents)) { 1699 auto &sym = std::get<const Fortran::semantics::Symbol &>(iter); 1700 auto &expr = std::get<const Fortran::lower::SomeExpr &>(iter); 1701 auto &baseOp = std::get<hlfir::EntityWithAttributes>(iter); 1702 std::string name = converter.getRecordTypeFieldName(sym); 1703 1704 // Generate DesignateOp for the component. 1705 // The designator's result type is just a reference to the component type, 1706 // because the whole component is being designated. 1707 auto baseRecTy = mlir::cast<fir::RecordType>( 1708 hlfir::getFortranElementType(baseOp.getType())); 1709 auto compType = baseRecTy.getType(name); 1710 assert(compType && "failed to retrieve component type"); 1711 mlir::Value compShape = 1712 designatorBuilder.genComponentShape(sym, compType); 1713 mlir::Type designatorType = builder.getRefType(compType); 1714 1715 mlir::Type fieldElemType = hlfir::getFortranElementType(compType); 1716 llvm::SmallVector<mlir::Value, 1> typeParams; 1717 if (auto charType = mlir::dyn_cast<fir::CharacterType>(fieldElemType)) { 1718 if (charType.hasConstantLen()) { 1719 mlir::Type idxType = builder.getIndexType(); 1720 typeParams.push_back( 1721 builder.createIntegerConstant(loc, idxType, charType.getLen())); 1722 } else { 1723 TODO(loc, "dynamic character length in structure constructor"); 1724 } 1725 } 1726 1727 // Convert component symbol attributes to variable attributes. 1728 fir::FortranVariableFlagsAttr attrs = 1729 Fortran::lower::translateSymbolAttributes(builder.getContext(), sym); 1730 1731 // Get the component designator. 1732 auto lhs = builder.create<hlfir::DesignateOp>( 1733 loc, designatorType, baseOp, name, compShape, 1734 hlfir::DesignateOp::Subscripts{}, 1735 /*substring=*/mlir::ValueRange{}, 1736 /*complexPart=*/std::nullopt, 1737 /*shape=*/compShape, typeParams, attrs); 1738 1739 if (attrs && bitEnumContainsAny(attrs.getFlags(), 1740 fir::FortranVariableFlagsEnum::pointer)) { 1741 if (Fortran::semantics::IsProcedure(sym)) 1742 TODO(loc, "procedure pointer component in structure constructor"); 1743 // Pointer component construction is just a copy of the box contents. 1744 fir::ExtendedValue lhsExv = 1745 hlfir::translateToExtendedValue(loc, builder, lhs); 1746 auto *toBox = lhsExv.getBoxOf<fir::MutableBoxValue>(); 1747 if (!toBox) 1748 fir::emitFatalError(loc, "pointer component designator could not be " 1749 "lowered to mutable box"); 1750 Fortran::lower::associateMutableBox(converter, loc, *toBox, expr, 1751 /*lbounds=*/std::nullopt, stmtCtx); 1752 continue; 1753 } 1754 1755 // Use generic assignment for all the other cases. 1756 bool allowRealloc = 1757 attrs && 1758 bitEnumContainsAny(attrs.getFlags(), 1759 fir::FortranVariableFlagsEnum::allocatable); 1760 // If the component is allocatable, then we have to check 1761 // whether the RHS value is allocatable or not. 1762 // If it is not allocatable, then AssignOp can be used directly. 1763 // If it is allocatable, then using AssignOp for unallocated RHS 1764 // will cause illegal dereference. When an unallocated allocatable 1765 // value is used to construct an allocatable component, the component 1766 // must just stay unallocated (see Fortran 2018 7.5.10 point 7). 1767 1768 // If the component is allocatable and RHS is NULL() expression, then 1769 // we can just skip it: the LHS must remain unallocated with its 1770 // defined rank. 1771 if (allowRealloc && 1772 Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>(expr)) 1773 continue; 1774 1775 bool keepLhsLength = false; 1776 if (allowRealloc) 1777 if (const Fortran::semantics::DeclTypeSpec *declType = sym.GetType()) 1778 keepLhsLength = 1779 declType->category() == 1780 Fortran::semantics::DeclTypeSpec::Category::Character && 1781 !declType->characterTypeSpec().length().isDeferred(); 1782 // Handle special case when the initializer expression is 1783 // '{%SET_LENGTH(x,const_kind)}'. In structure constructor, 1784 // SET_LENGTH is used for initializers of non-allocatable character 1785 // components so that the front-end can better 1786 // fold and work with these structure constructors. 1787 // Here, they are just noise since the assignment semantics will deal 1788 // with any length mismatch, and creating an extra temp with the lhs 1789 // length is useless. 1790 // TODO: should this be moved into an hlfir.assign + hlfir.set_length 1791 // pattern rewrite? 1792 hlfir::Entity rhs = gen(expr); 1793 if (auto set_length = rhs.getDefiningOp<hlfir::SetLengthOp>()) 1794 rhs = hlfir::Entity{set_length.getString()}; 1795 1796 // lambda to generate `lhs = rhs` and deal with potential rhs implicit 1797 // cast 1798 auto genAssign = [&] { 1799 rhs = hlfir::loadTrivialScalar(loc, builder, rhs); 1800 auto rhsCastAndCleanup = 1801 hlfir::genTypeAndKindConvert(loc, builder, rhs, lhs.getType(), 1802 /*preserveLowerBounds=*/allowRealloc); 1803 builder.create<hlfir::AssignOp>(loc, rhsCastAndCleanup.first, lhs, 1804 allowRealloc, 1805 allowRealloc ? keepLhsLength : false, 1806 /*temporary_lhs=*/true); 1807 if (rhsCastAndCleanup.second) 1808 (*rhsCastAndCleanup.second)(); 1809 }; 1810 1811 if (!allowRealloc || !rhs.isMutableBox()) { 1812 genAssign(); 1813 continue; 1814 } 1815 1816 auto [rhsExv, cleanup] = 1817 hlfir::translateToExtendedValue(loc, builder, rhs); 1818 assert(!cleanup && "unexpected cleanup"); 1819 auto *fromBox = rhsExv.getBoxOf<fir::MutableBoxValue>(); 1820 if (!fromBox) 1821 fir::emitFatalError(loc, "allocatable entity could not be lowered " 1822 "to mutable box"); 1823 mlir::Value isAlloc = 1824 fir::factory::genIsAllocatedOrAssociatedTest(builder, loc, *fromBox); 1825 builder.genIfThen(loc, isAlloc).genThen(genAssign).end(); 1826 } 1827 1828 return varOp; 1829 } 1830 1831 mlir::Location getLoc() const { return loc; } 1832 Fortran::lower::AbstractConverter &getConverter() { return converter; } 1833 fir::FirOpBuilder &getBuilder() { return converter.getFirOpBuilder(); } 1834 Fortran::lower::SymMap &getSymMap() { return symMap; } 1835 Fortran::lower::StatementContext &getStmtCtx() { return stmtCtx; } 1836 1837 Fortran::lower::AbstractConverter &converter; 1838 Fortran::lower::SymMap &symMap; 1839 Fortran::lower::StatementContext &stmtCtx; 1840 mlir::Location loc; 1841 }; 1842 1843 template <typename T> 1844 hlfir::Entity 1845 HlfirDesignatorBuilder::genSubscript(const Fortran::evaluate::Expr<T> &expr) { 1846 auto loweredExpr = 1847 HlfirBuilder(getLoc(), getConverter(), getSymMap(), getStmtCtx()) 1848 .gen(expr); 1849 fir::FirOpBuilder &builder = getBuilder(); 1850 // Skip constant conversions that litters designators and makes generated 1851 // IR harder to read: directly use index constants for constant subscripts. 1852 mlir::Type idxTy = builder.getIndexType(); 1853 if (!loweredExpr.isArray() && loweredExpr.getType() != idxTy) 1854 if (auto cstIndex = fir::getIntIfConstant(loweredExpr)) 1855 return hlfir::EntityWithAttributes{ 1856 builder.createIntegerConstant(getLoc(), idxTy, *cstIndex)}; 1857 return hlfir::loadTrivialScalar(loc, builder, loweredExpr); 1858 } 1859 1860 } // namespace 1861 1862 hlfir::EntityWithAttributes Fortran::lower::convertExprToHLFIR( 1863 mlir::Location loc, Fortran::lower::AbstractConverter &converter, 1864 const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &symMap, 1865 Fortran::lower::StatementContext &stmtCtx) { 1866 return HlfirBuilder(loc, converter, symMap, stmtCtx).gen(expr); 1867 } 1868 1869 fir::ExtendedValue Fortran::lower::convertToBox( 1870 mlir::Location loc, Fortran::lower::AbstractConverter &converter, 1871 hlfir::Entity entity, Fortran::lower::StatementContext &stmtCtx, 1872 mlir::Type fortranType) { 1873 fir::FirOpBuilder &builder = converter.getFirOpBuilder(); 1874 auto [exv, cleanup] = hlfir::convertToBox(loc, builder, entity, fortranType); 1875 if (cleanup) 1876 stmtCtx.attachCleanup(*cleanup); 1877 return exv; 1878 } 1879 1880 fir::ExtendedValue Fortran::lower::convertExprToBox( 1881 mlir::Location loc, Fortran::lower::AbstractConverter &converter, 1882 const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &symMap, 1883 Fortran::lower::StatementContext &stmtCtx) { 1884 hlfir::EntityWithAttributes loweredExpr = 1885 HlfirBuilder(loc, converter, symMap, stmtCtx).gen(expr); 1886 return convertToBox(loc, converter, loweredExpr, stmtCtx, 1887 converter.genType(expr)); 1888 } 1889 1890 fir::ExtendedValue Fortran::lower::convertToAddress( 1891 mlir::Location loc, Fortran::lower::AbstractConverter &converter, 1892 hlfir::Entity entity, Fortran::lower::StatementContext &stmtCtx, 1893 mlir::Type fortranType) { 1894 fir::FirOpBuilder &builder = converter.getFirOpBuilder(); 1895 auto [exv, cleanup] = 1896 hlfir::convertToAddress(loc, builder, entity, fortranType); 1897 if (cleanup) 1898 stmtCtx.attachCleanup(*cleanup); 1899 return exv; 1900 } 1901 1902 fir::ExtendedValue Fortran::lower::convertExprToAddress( 1903 mlir::Location loc, Fortran::lower::AbstractConverter &converter, 1904 const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &symMap, 1905 Fortran::lower::StatementContext &stmtCtx) { 1906 hlfir::EntityWithAttributes loweredExpr = 1907 HlfirBuilder(loc, converter, symMap, stmtCtx).gen(expr); 1908 return convertToAddress(loc, converter, loweredExpr, stmtCtx, 1909 converter.genType(expr)); 1910 } 1911 1912 fir::ExtendedValue Fortran::lower::convertToValue( 1913 mlir::Location loc, Fortran::lower::AbstractConverter &converter, 1914 hlfir::Entity entity, Fortran::lower::StatementContext &stmtCtx) { 1915 auto &builder = converter.getFirOpBuilder(); 1916 auto [exv, cleanup] = hlfir::convertToValue(loc, builder, entity); 1917 if (cleanup) 1918 stmtCtx.attachCleanup(*cleanup); 1919 return exv; 1920 } 1921 1922 fir::ExtendedValue Fortran::lower::convertExprToValue( 1923 mlir::Location loc, Fortran::lower::AbstractConverter &converter, 1924 const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &symMap, 1925 Fortran::lower::StatementContext &stmtCtx) { 1926 hlfir::EntityWithAttributes loweredExpr = 1927 HlfirBuilder(loc, converter, symMap, stmtCtx).gen(expr); 1928 return convertToValue(loc, converter, loweredExpr, stmtCtx); 1929 } 1930 1931 fir::ExtendedValue Fortran::lower::convertDataRefToValue( 1932 mlir::Location loc, Fortran::lower::AbstractConverter &converter, 1933 const Fortran::evaluate::DataRef &dataRef, Fortran::lower::SymMap &symMap, 1934 Fortran::lower::StatementContext &stmtCtx) { 1935 fir::FortranVariableOpInterface loweredExpr = 1936 HlfirDesignatorBuilder(loc, converter, symMap, stmtCtx).gen(dataRef); 1937 return convertToValue(loc, converter, loweredExpr, stmtCtx); 1938 } 1939 1940 fir::MutableBoxValue Fortran::lower::convertExprToMutableBox( 1941 mlir::Location loc, Fortran::lower::AbstractConverter &converter, 1942 const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &symMap) { 1943 // Pointers and Allocatable cannot be temporary expressions. Temporaries may 1944 // be created while lowering it (e.g. if any indices expression of a 1945 // designator create temporaries), but they can be destroyed before using the 1946 // lowered pointer or allocatable; 1947 Fortran::lower::StatementContext localStmtCtx; 1948 hlfir::EntityWithAttributes loweredExpr = 1949 HlfirBuilder(loc, converter, symMap, localStmtCtx).gen(expr); 1950 fir::ExtendedValue exv = Fortran::lower::translateToExtendedValue( 1951 loc, converter.getFirOpBuilder(), loweredExpr, localStmtCtx); 1952 auto *mutableBox = exv.getBoxOf<fir::MutableBoxValue>(); 1953 assert(mutableBox && "expression could not be lowered to mutable box"); 1954 return *mutableBox; 1955 } 1956 1957 hlfir::ElementalAddrOp 1958 Fortran::lower::convertVectorSubscriptedExprToElementalAddr( 1959 mlir::Location loc, Fortran::lower::AbstractConverter &converter, 1960 const Fortran::lower::SomeExpr &designatorExpr, 1961 Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx) { 1962 return HlfirDesignatorBuilder(loc, converter, symMap, stmtCtx) 1963 .convertVectorSubscriptedExprToElementalAddr(designatorExpr); 1964 } 1965