@@ -2404,6 +2404,19 @@ class ArrayExprLowering {
2404
2404
return result;
2405
2405
}
2406
2406
2407
+ // / In an explicit space, the context may include an implicit subspace. The
2408
+ // / RHS of the assignment does not necessarily have rank and can be promoted
2409
+ // / from a scalar to an array. In that case, the implicit subscripts must be
2410
+ // / removed.
2411
+ void removeImplicit () {
2412
+ llvm::SmallVector<AccessValue> newIndices;
2413
+ const auto size = indices.size ();
2414
+ for (std::remove_const_t <decltype (size)> i = 0 , j = 0 ; j < size; ++j)
2415
+ if (indices[j].access () != AccessKind::Implicit)
2416
+ newIndices[i++] = indices[j];
2417
+ indices.swap (newIndices);
2418
+ }
2419
+
2407
2420
private:
2408
2421
mlir::Value inArg;
2409
2422
mlir::Value outRes;
@@ -2480,8 +2493,10 @@ class ArrayExprLowering {
2480
2493
auto lambda = [=](IterSpace iters) -> ExtValue {
2481
2494
auto innerArg = iters.innerArgument ();
2482
2495
auto resTy = adjustedArrayElementType (innerArg.getType ());
2496
+ auto cast = builder.createConvert (loc, fir::unwrapSequenceType (resTy),
2497
+ iters.getElement ());
2483
2498
auto arrUpdate = builder.create <fir::ArrayUpdateOp>(
2484
- loc, resTy, innerArg, iters. getElement () , iters.iterVec (),
2499
+ loc, resTy, innerArg, cast , iters.iterVec (),
2485
2500
destination.typeparams ());
2486
2501
return abstractArrayExtValue (arrUpdate);
2487
2502
};
@@ -2530,7 +2545,7 @@ class ArrayExprLowering {
2530
2545
static void lowerAllocatableArrayAssignment (
2531
2546
Fortran::lower::AbstractConverter &converter,
2532
2547
Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
2533
- const fir::MutableBoxValue &lhs,
2548
+ const Fortran::evaluate::Expr<Fortran::evaluate::SomeType> &lhs,
2534
2549
const Fortran::evaluate::Expr<Fortran::evaluate::SomeType> &rhs,
2535
2550
Fortran::lower::ExplicitIterSpace &explicitSpace,
2536
2551
Fortran::lower::ImplicitIterSpace &implicitSpace) {
@@ -2546,11 +2561,15 @@ class ArrayExprLowering {
2546
2561
// / defines the iteration space of the computation and the lhs is
2547
2562
// / resized/reallocated to fit if necessary.
2548
2563
void lowerAllocatableArrayAssignment (
2549
- const fir::MutableBoxValue &mutableBox ,
2564
+ const Fortran::evaluate::Expr<Fortran::evaluate::SomeType> &lhs ,
2550
2565
const Fortran::evaluate::Expr<Fortran::evaluate::SomeType> &rhs) {
2551
2566
// With assignment to allocatable, we want to lower the rhs first and use
2552
2567
// its shape to determine if we need to reallocate, etc.
2553
2568
auto loc = getLoc ();
2569
+ // FIXME: If the lhs is in an explicit iteration space, the assignment may
2570
+ // be to an array of allocatable arrays rather than a single allocatable
2571
+ // array.
2572
+ auto mutableBox = createMutableBox (loc, converter, lhs, symMap);
2554
2573
auto resultTy = converter.genType (rhs);
2555
2574
auto rhsCC = [&]() {
2556
2575
PushSemantics (ConstituentSemantics::RefTransparent);
@@ -2738,8 +2757,11 @@ class ArrayExprLowering {
2738
2757
const Fortran::evaluate::Expr<Fortran::evaluate::SomeType> &exp) {
2739
2758
auto resTy = explicitSpace ? destination->getResult (0 ).getType ()
2740
2759
: converter.genType (exp);
2760
+ bool explicitScalar = explicitSpace && exp.Rank () == 0 ;
2741
2761
return std::visit (
2742
- [&](const auto &e) { return lowerArrayExpression (genarr (e), resTy); },
2762
+ [&](const auto &e) {
2763
+ return lowerArrayExpression (genarr (e), resTy, explicitScalar);
2764
+ },
2743
2765
exp.u );
2744
2766
}
2745
2767
ExtValue lowerArrayExpression (const ExtValue &exv) {
@@ -2766,11 +2788,15 @@ class ArrayExprLowering {
2766
2788
// / Otherwise, \p resultTy is ignored and the expression is evaluated
2767
2789
// / in the destination. \p f is a continuation built from an
2768
2790
// / evaluate::Expr or an ExtendedValue.
2769
- ExtValue lowerArrayExpression (CC f, mlir::Type resultTy) {
2791
+ ExtValue lowerArrayExpression (CC f, mlir::Type resultTy,
2792
+ bool explicitScalar = false ) {
2770
2793
auto loc = getLoc ();
2771
2794
auto [iterSpace, insPt] = genIterSpace (resultTy);
2795
+ auto rhsIterSpace = iterSpace;
2796
+ if (explicitScalar)
2797
+ rhsIterSpace.removeImplicit ();
2772
2798
auto innerArg = iterSpace.innerArgument ();
2773
- auto exv = f (iterSpace );
2799
+ auto exv = f (rhsIterSpace );
2774
2800
mlir::Value upd;
2775
2801
if (ccDest.hasValue ()) {
2776
2802
auto element = fir::getBase (exv);
@@ -3212,17 +3238,21 @@ class ArrayExprLowering {
3212
3238
const Fortran::evaluate::Expr<Fortran::evaluate::SomeType> &e) {
3213
3239
struct Filter : public Fortran ::evaluate::AnyTraverse<
3214
3240
Filter, std::optional<llvm::SmallVector<mlir::Value>>> {
3215
- using Base = Fortran::evaluate::AnyTraverse<
3216
- Filter, std::optional<llvm::SmallVector<mlir::Value>> >;
3241
+ using RT = std::optional<llvm::SmallVector<mlir::Value>>;
3242
+ using Base = Fortran::evaluate::AnyTraverse<Filter, RT >;
3217
3243
using Base::operator ();
3218
3244
3219
- Filter (const llvm::SmallVector<mlir::Value> init)
3220
- : Base(*this ), bounds(init) {}
3245
+ Filter (ArrayExprLowering *const ael) : Base(*this ), ael(ael) {}
3221
3246
3222
- std::optional<llvm::SmallVector<mlir::Value>>
3223
- operator ()(const Fortran::evaluate::ArrayRef &ref) {
3247
+ RT operator ()(const Fortran::evaluate::ArrayRef &ref) {
3224
3248
if ((ref.base ().IsSymbol () || ref.base ().Rank () == 0 ) &&
3225
3249
ref.Rank () > 0 && !ref.subscript ().empty ()) {
3250
+ auto baseTy = ael->raiseBaseType (ref.base ());
3251
+ auto ty = ref.base ().IsSymbol ()
3252
+ ? baseTy
3253
+ : baseTy.cast <fir::RecordType>().getType (
3254
+ toStringRef (ref.GetLastSymbol ().name ()));
3255
+ auto bounds = ael->getShape (ty);
3226
3256
assert (ref.subscript ().size () == bounds.size ());
3227
3257
llvm::SmallVector<mlir::Value> result;
3228
3258
auto bdIter = bounds.begin ();
@@ -3242,15 +3272,24 @@ class ArrayExprLowering {
3242
3272
}
3243
3273
return {};
3244
3274
}
3275
+ RT operator ()(const Fortran::evaluate::Component &cpnt) {
3276
+ if (cpnt.base ().Rank () == 0 && cpnt.Rank () > 0 )
3277
+ return ael->getShape (ael->raiseBaseType (cpnt));
3278
+ return {};
3279
+ }
3280
+ RT operator ()(const Fortran::semantics::Symbol &sym) {
3281
+ if (sym.Rank () > 0 )
3282
+ return ael->getShape (ael->raiseBaseType (sym));
3283
+ return {};
3284
+ }
3245
3285
3246
- llvm::SmallVector<mlir::Value> bounds ;
3286
+ ArrayExprLowering * const ael ;
3247
3287
};
3248
3288
3249
- auto originalShape = getShape (converter.genType (e));
3250
- Filter filter (originalShape);
3289
+ Filter filter (this );
3251
3290
if (auto res = filter (e))
3252
3291
return *res;
3253
- return originalShape ;
3292
+ return {} ;
3254
3293
}
3255
3294
3256
3295
void genMasks () {
@@ -4308,6 +4347,10 @@ class ArrayExprLowering {
4308
4347
return false ;
4309
4348
}
4310
4349
4350
+ // / Set of helper member functions for generating the type of a particular
4351
+ // / component along a path. We cannot use the `converter` here because it is
4352
+ // / not possible to uplift an arbitrary component list to a generic
4353
+ // / `Fortran::evaluate::Expr`.
4311
4354
mlir::Type raiseBaseType (const Fortran::evaluate::Component &x) {
4312
4355
auto baseTy = raiseBaseType (x.base ());
4313
4356
auto recTy = baseTy.cast <fir::RecordType>();
@@ -4320,10 +4363,13 @@ class ArrayExprLowering {
4320
4363
LLVM_DEBUG (llvm::dbgs () << " base type s " << rv << ' \n ' );
4321
4364
return rv;
4322
4365
}
4366
+ mlir::Type raiseBaseType (const Fortran::evaluate::NamedEntity &n) {
4367
+ return n.IsSymbol () ? raiseBaseType (n.GetLastSymbol ())
4368
+ : raiseBaseType (n.GetComponent ());
4369
+ }
4323
4370
mlir::Type raiseBaseType (const Fortran::evaluate::ArrayRef &x) {
4324
4371
auto &base = x.base ();
4325
- mlir::Type baseTy = base.IsSymbol () ? raiseBaseType (base.GetLastSymbol ())
4326
- : raiseBaseType (base.GetComponent ());
4372
+ mlir::Type baseTy = raiseBaseType (base);
4327
4373
auto seqTy = baseTy.cast <fir::SequenceType>();
4328
4374
auto rv = seqTy.getEleTy ();
4329
4375
LLVM_DEBUG (llvm::dbgs () << " base type a " << rv << ' \n ' );
@@ -5700,12 +5746,12 @@ void Fortran::lower::createAnyMaskedArrayAssignment(
5700
5746
5701
5747
void Fortran::lower::createAllocatableArrayAssignment (
5702
5748
Fortran::lower::AbstractConverter &converter,
5703
- const fir::MutableBoxValue &lhs,
5749
+ const Fortran::evaluate::Expr<Fortran::evaluate::SomeType> &lhs,
5704
5750
const Fortran::evaluate::Expr<Fortran::evaluate::SomeType> &rhs,
5705
5751
Fortran::lower::ExplicitIterSpace &explicitSpace,
5706
5752
Fortran::lower::ImplicitIterSpace &implicitSpace,
5707
5753
Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx) {
5708
- LLVM_DEBUG (llvm::dbgs () << " defining array: " << lhs << ' \n ' ;
5754
+ LLVM_DEBUG (lhs. AsFortran ( llvm::dbgs () << " defining array: " ) << ' \n ' ;
5709
5755
rhs.AsFortran (llvm::dbgs () << " assign expression: " )
5710
5756
<< " given the explicit iteration space:\n "
5711
5757
<< explicitSpace << " \n and implied mask conditions:\n "
@@ -5733,7 +5779,7 @@ fir::ExtendedValue Fortran::lower::createSomeArrayBox(
5733
5779
stmtCtx, expr);
5734
5780
}
5735
5781
5736
- fir::MutableBoxValue Fortran::lower::createSomeMutableBox (
5782
+ fir::MutableBoxValue Fortran::lower::createMutableBox (
5737
5783
mlir::Location loc, Fortran::lower::AbstractConverter &converter,
5738
5784
const Fortran::evaluate::Expr<Fortran::evaluate::SomeType> &expr,
5739
5785
Fortran::lower::SymMap &symMap) {
0 commit comments