@@ -1753,6 +1753,59 @@ convertToArrayBoxValue(mlir::Location loc, fir::FirOpBuilder &builder,
1753
1753
return fir::ArrayBoxValue (val, extents);
1754
1754
}
1755
1755
1756
+ // ===----------------------------------------------------------------------===//
1757
+ //
1758
+ // Lowering of scalar expressions in an explicit iteration space context.
1759
+ //
1760
+ // ===----------------------------------------------------------------------===//
1761
+
1762
+ // Shared code for creating a copy of a derived type element. This function is
1763
+ // called from a continuation.
1764
+ inline static fir::ArrayAmendOp
1765
+ createDerivedArrayAmend (mlir::Location loc, fir::ArrayLoadOp destLoad,
1766
+ fir::FirOpBuilder &builder, fir::ArrayAccessOp destAcc,
1767
+ const fir::ExtendedValue &elementExv, mlir::Type eleTy,
1768
+ mlir::Value innerArg) {
1769
+ if (destLoad.getTypeparams ().empty ()) {
1770
+ fir::factory::genRecordAssignment (builder, loc, destAcc, elementExv);
1771
+ } else {
1772
+ auto boxTy = fir::BoxType::get (eleTy);
1773
+ auto toBox = builder.create <fir::EmboxOp>(loc, boxTy, destAcc.getResult (),
1774
+ mlir::Value{}, mlir::Value{},
1775
+ destLoad.getTypeparams ());
1776
+ auto fromBox = builder.create <fir::EmboxOp>(
1777
+ loc, boxTy, fir::getBase (elementExv), mlir::Value{}, mlir::Value{},
1778
+ destLoad.getTypeparams ());
1779
+ fir::factory::genRecordAssignment (builder, loc, fir::BoxValue (toBox),
1780
+ fir::BoxValue (fromBox));
1781
+ }
1782
+ return builder.create <fir::ArrayAmendOp>(loc, innerArg.getType (), innerArg,
1783
+ destAcc);
1784
+ }
1785
+
1786
+ inline static fir::ArrayAmendOp
1787
+ createCharArrayAmend (mlir::Location loc, fir::FirOpBuilder &builder,
1788
+ fir::ArrayAccessOp dstOp, mlir::Value &dstLen,
1789
+ const fir::ExtendedValue &srcExv, mlir::Value innerArg,
1790
+ llvm::ArrayRef<mlir::Value> bounds) {
1791
+ fir::CharBoxValue dstChar (dstOp, dstLen);
1792
+ fir::factory::CharacterExprHelper helper{builder, loc};
1793
+ if (!bounds.empty ()) {
1794
+ dstChar = helper.createSubstring (dstChar, bounds);
1795
+ fir::factory::genCharacterCopy (fir::getBase (srcExv), fir::getLen (srcExv),
1796
+ dstChar.getAddr (), dstChar.getLen (), builder,
1797
+ loc);
1798
+ // Update the LEN to the substring's LEN.
1799
+ dstLen = dstChar.getLen ();
1800
+ }
1801
+ // For a CHARACTER, we generate the element assignment loops inline.
1802
+ helper.createAssign (fir::ExtendedValue{dstChar}, srcExv);
1803
+ // Mark this array element as amended.
1804
+ mlir::Type ty = innerArg.getType ();
1805
+ auto amend = builder.create <fir::ArrayAmendOp>(loc, ty, innerArg, dstOp);
1806
+ return amend;
1807
+ }
1808
+
1756
1809
// ===----------------------------------------------------------------------===//
1757
1810
//
1758
1811
// Lowering of array expressions.
@@ -2435,8 +2488,37 @@ class ArrayExprLowering {
2435
2488
TODO (getLoc (), " genarr Component" );
2436
2489
}
2437
2490
2491
+ // / Array reference with subscripts. If this has rank > 0, this is a form
2492
+ // / of an array section (slice).
2493
+ // /
2494
+ // / There are two "slicing" primitives that may be applied on a dimension by
2495
+ // / dimension basis: (1) triple notation and (2) vector addressing. Since
2496
+ // / dimensions can be selectively sliced, some dimensions may contain
2497
+ // / regular scalar expressions and those dimensions do not participate in
2498
+ // / the array expression evaluation.
2438
2499
CC genarr (const Fortran::evaluate::ArrayRef &x, ComponentPath &components) {
2439
- TODO (getLoc (), " genar ArrayRef" );
2500
+ if (explicitSpaceIsActive ()) {
2501
+ TODO (getLoc (), " genarr ArrayRef explicitSpace" );
2502
+ } else {
2503
+ if (Fortran::lower::isRankedArrayAccess (x)) {
2504
+ components.reversePath .push_back (&x);
2505
+ return genImplicitArrayAccess (x.base (), components);
2506
+ }
2507
+ }
2508
+ bool atEnd = pathIsEmpty (components);
2509
+ components.reversePath .push_back (&x);
2510
+ auto result = genarr (x.base (), components);
2511
+ if (components.applied )
2512
+ return result;
2513
+ mlir::Location loc = getLoc ();
2514
+ if (atEnd) {
2515
+ if (x.Rank () == 0 )
2516
+ return genAsScalar (x);
2517
+ fir::emitFatalError (loc, " expected scalar" );
2518
+ }
2519
+ return [=](IterSpace) -> ExtValue {
2520
+ fir::emitFatalError (loc, " reached arrayref with path" );
2521
+ };
2440
2522
}
2441
2523
2442
2524
CC genarr (const Fortran::evaluate::CoarrayRef &x, ComponentPath &components) {
@@ -2454,6 +2536,10 @@ class ArrayExprLowering {
2454
2536
x.u );
2455
2537
}
2456
2538
2539
+ bool pathIsEmpty (const ComponentPath &components) {
2540
+ return components.reversePath .empty ();
2541
+ }
2542
+
2457
2543
CC genarr (const Fortran::evaluate::ComplexPart &x,
2458
2544
ComponentPath &components) {
2459
2545
TODO (getLoc (), " genarr ComplexPart" );
@@ -2666,7 +2752,30 @@ class ArrayExprLowering {
2666
2752
mlir::Type arrTy = innerArg.getType ();
2667
2753
mlir::Type eleTy = fir::applyPathToType (arrTy, iterSpace.iterVec ());
2668
2754
if (isAdjustedArrayElementType (eleTy)) {
2669
- TODO (loc, " isAdjustedArrayElementType" );
2755
+ // The elemental update is in the memref domain. Under this semantics,
2756
+ // we must always copy the computed new element from its location in
2757
+ // memory into the destination array.
2758
+ mlir::Type resRefTy = builder.getRefType (eleTy);
2759
+ // Get a reference to the array element to be amended.
2760
+ auto arrayOp = builder.create <fir::ArrayAccessOp>(
2761
+ loc, resRefTy, innerArg, iterSpace.iterVec (),
2762
+ destination.getTypeparams ());
2763
+ if (auto charTy = eleTy.dyn_cast <fir::CharacterType>()) {
2764
+ llvm::SmallVector<mlir::Value> substringBounds;
2765
+ populateBounds (substringBounds, substring);
2766
+ mlir::Value dstLen = fir::factory::genLenOfCharacter (
2767
+ builder, loc, destination, iterSpace.iterVec (), substringBounds);
2768
+ fir::ArrayAmendOp amend = createCharArrayAmend (
2769
+ loc, builder, arrayOp, dstLen, exv, innerArg, substringBounds);
2770
+ return abstractArrayExtValue (amend, dstLen);
2771
+ }
2772
+ if (fir::isa_derived (eleTy)) {
2773
+ fir::ArrayAmendOp amend = createDerivedArrayAmend (
2774
+ loc, destination, builder, arrayOp, exv, eleTy, innerArg);
2775
+ return abstractArrayExtValue (amend /* FIXME: typeparams?*/ );
2776
+ }
2777
+ assert (eleTy.isa <fir::SequenceType>() && " must be an array" );
2778
+ TODO (loc, " array (as element) assignment" );
2670
2779
}
2671
2780
// By value semantics. The element is being assigned by value.
2672
2781
mlir::Value ele = builder.createConvert (loc, eleTy, fir::getBase (exv));
@@ -2987,3 +3096,15 @@ void Fortran::lower::createAllocatableArrayAssignment(
2987
3096
ArrayExprLowering::lowerAllocatableArrayAssignment (
2988
3097
converter, symMap, stmtCtx, lhs, rhs, explicitSpace, implicitSpace);
2989
3098
}
3099
+
3100
+ mlir::Value Fortran::lower::genMaxWithZero (fir::FirOpBuilder &builder,
3101
+ mlir::Location loc,
3102
+ mlir::Value value) {
3103
+ mlir::Value zero = builder.createIntegerConstant (loc, value.getType (), 0 );
3104
+ if (mlir::Operation *definingOp = value.getDefiningOp ())
3105
+ if (auto cst = mlir::dyn_cast<mlir::arith::ConstantOp>(definingOp))
3106
+ if (auto intAttr = cst.getValue ().dyn_cast <mlir::IntegerAttr>())
3107
+ return intAttr.getInt () < 0 ? zero : value;
3108
+ return Fortran::lower::genMax (builder, loc,
3109
+ llvm::SmallVector<mlir::Value>{value, zero});
3110
+ }
0 commit comments