@@ -5632,16 +5632,47 @@ class ArrayExprLowering {
5632
5632
// / Target agnostic computation of the size of an element in the array.
5633
5633
// / Returns the size in bytes with type `index` or a null Value if the element
5634
5634
// / size is not constant.
5635
- mlir::Value computeElementSize (mlir::Type eleTy, mlir::Type eleRefTy,
5636
- mlir::Type resRefTy) {
5637
- if (fir::hasDynamicSize (eleTy))
5638
- return {};
5635
+ mlir::Value computeElementSize (const ExtValue &exv, mlir::Type eleTy,
5636
+ mlir::Type resTy) {
5639
5637
auto loc = getLoc ();
5640
5638
auto idxTy = builder.getIndexType ();
5639
+ auto multiplier = builder.createIntegerConstant (loc, idxTy, 1 );
5640
+ if (fir::hasDynamicSize (eleTy)) {
5641
+ if (auto charTy = eleTy.dyn_cast <fir::CharacterType>()) {
5642
+ // Array of char with dynamic length parameter. Downcast to an array
5643
+ // of singleton char, and scale by the len type parameter from
5644
+ // `exv`.
5645
+ exv.match (
5646
+ [&](const fir::CharBoxValue &cb) { multiplier = cb.getLen (); },
5647
+ [&](const fir::CharArrayBoxValue &cb) { multiplier = cb.getLen (); },
5648
+ [&](const fir::BoxValue &box) {
5649
+ multiplier = fir::factory::CharacterExprHelper (builder, loc)
5650
+ .readLengthFromBox (box.getAddr ());
5651
+ },
5652
+ [&](const fir::MutableBoxValue &box) {
5653
+ multiplier = fir::factory::CharacterExprHelper (builder, loc)
5654
+ .readLengthFromBox (box.getAddr ());
5655
+ },
5656
+ [&](const auto &) {
5657
+ fir::emitFatalError (loc,
5658
+ " array constructor element has unknown size" );
5659
+ });
5660
+ auto newEleTy = fir::CharacterType::getSingleton (eleTy.getContext (),
5661
+ charTy.getFKind ());
5662
+ if (auto seqTy = resTy.dyn_cast <fir::SequenceType>()) {
5663
+ assert (eleTy == seqTy.getEleTy ());
5664
+ resTy = fir::SequenceType::get (seqTy.getShape (), newEleTy);
5665
+ }
5666
+ eleTy = newEleTy;
5667
+ } else {
5668
+ TODO (loc, " dynamic sized type" );
5669
+ }
5670
+ }
5671
+ auto eleRefTy = builder.getRefType (eleTy);
5672
+ auto resRefTy = builder.getRefType (resTy);
5641
5673
auto nullPtr = builder.createNullConstant (loc, resRefTy);
5642
- auto one = builder.createIntegerConstant (loc, idxTy, 1 );
5643
- auto offset = builder.create <fir::CoordinateOp>(loc, eleRefTy, nullPtr,
5644
- mlir::ValueRange{one});
5674
+ auto offset = builder.create <fir::CoordinateOp>(
5675
+ loc, eleRefTy, nullPtr, mlir::ValueRange{multiplier});
5645
5676
return builder.createConvert (loc, idxTy, offset);
5646
5677
}
5647
5678
@@ -5789,7 +5820,6 @@ class ArrayExprLowering {
5789
5820
mlir::ValueRange{off});
5790
5821
auto val = builder.createConvert (loc, eleTy, v);
5791
5822
builder.create <fir::StoreOp>(loc, val, buffi);
5792
-
5793
5823
builder.create <fir::StoreOp>(loc, plusOne, buffPos);
5794
5824
},
5795
5825
[&](const fir::CharBoxValue &v) {
@@ -5847,21 +5877,28 @@ class ArrayExprLowering {
5847
5877
mem = loop.getRegionIterArgs ()[0 ];
5848
5878
5849
5879
auto eleRefTy = builder.getRefType (eleTy);
5850
- auto eleSz = computeElementSize (eleTy, eleRefTy, builder.getRefType (resTy));
5851
5880
5852
5881
// Cleanups for temps in loop body. Any temps created in the loop body
5853
5882
// need to be freed before the end of the loop.
5854
5883
Fortran::lower::StatementContext loopCtx;
5884
+ llvm::Optional<mlir::Value> charLen;
5855
5885
for (const Fortran::evaluate::ArrayConstructorValue<A> &acv : x.values ()) {
5856
5886
auto [exv, copyNeeded] = std::visit (
5857
5887
[&](const auto &v) {
5858
5888
return genArrayCtorInitializer (v, resTy, mem, buffPos, buffSize,
5859
5889
loopCtx);
5860
5890
},
5861
5891
acv.u );
5892
+ auto eleSz = computeElementSize (exv, eleTy, resTy);
5862
5893
mem = copyNeeded ? copyNextArrayCtorSection (exv, buffPos, buffSize, mem,
5863
5894
eleSz, eleTy, eleRefTy, resTy)
5864
5895
: fir::getBase (exv);
5896
+ if (fir::isa_char (seqTy.getEleTy ()) && !charLen.hasValue ()) {
5897
+ charLen = builder.createTemporary (loc, builder.getI64Type ());
5898
+ auto castLen =
5899
+ builder.createConvert (loc, builder.getI64Type (), fir::getLen (exv));
5900
+ builder.create <fir::StoreOp>(loc, castLen, charLen.getValue ());
5901
+ }
5865
5902
}
5866
5903
loopCtx.finalize ();
5867
5904
@@ -5873,10 +5910,8 @@ class ArrayExprLowering {
5873
5910
builder.create <fir::LoadOp>(loc, buffPos).getResult ()};
5874
5911
5875
5912
// Convert to extended value.
5876
- if (auto charTy =
5877
- seqTy.getEleTy ().template dyn_cast <fir::CharacterType>()) {
5878
- auto len = builder.createIntegerConstant (loc, builder.getI64Type (),
5879
- charTy.getLen ());
5913
+ if (fir::isa_char (seqTy.getEleTy ())) {
5914
+ auto len = builder.create <fir::LoadOp>(loc, charLen.getValue ());
5880
5915
return {fir::CharArrayBoxValue{mem, len, extents}, /* needCopy=*/ false };
5881
5916
}
5882
5917
return {fir::ArrayBoxValue{mem, extents}, /* needCopy=*/ false };
@@ -5925,19 +5960,26 @@ class ArrayExprLowering {
5925
5960
}
5926
5961
// Compute size of element
5927
5962
auto eleRefTy = builder.getRefType (eleTy);
5928
- auto eleSz = computeElementSize (eleTy, eleRefTy, builder.getRefType (resTy));
5929
5963
5930
5964
// Populate the buffer with the elements, growing as necessary.
5965
+ llvm::Optional<mlir::Value> charLen;
5931
5966
for (const auto &expr : x) {
5932
5967
auto [exv, copyNeeded] = std::visit (
5933
5968
[&](const auto &e) {
5934
5969
return genArrayCtorInitializer (e, resTy, mem, buffPos, buffSize,
5935
5970
stmtCtx);
5936
5971
},
5937
5972
expr.u );
5973
+ auto eleSz = computeElementSize (exv, eleTy, resTy);
5938
5974
mem = copyNeeded ? copyNextArrayCtorSection (exv, buffPos, buffSize, mem,
5939
5975
eleSz, eleTy, eleRefTy, resTy)
5940
5976
: fir::getBase (exv);
5977
+ if (fir::isa_char (seqTy.getEleTy ()) && !charLen.hasValue ()) {
5978
+ charLen = builder.createTemporary (loc, builder.getI64Type ());
5979
+ auto castLen =
5980
+ builder.createConvert (loc, builder.getI64Type (), fir::getLen (exv));
5981
+ builder.create <fir::StoreOp>(loc, castLen, charLen.getValue ());
5982
+ }
5941
5983
}
5942
5984
mem = builder.createConvert (loc, fir::HeapType::get (resTy), mem);
5943
5985
llvm::SmallVector<mlir::Value> extents = {
@@ -5949,10 +5991,8 @@ class ArrayExprLowering {
5949
5991
[bldr, loc, mem]() { bldr->create <fir::FreeMemOp>(loc, mem); });
5950
5992
5951
5993
// Return the continuation.
5952
- if (auto charTy =
5953
- seqTy.getEleTy ().template dyn_cast <fir::CharacterType>()) {
5954
- auto len = builder.createIntegerConstant (loc, builder.getI64Type (),
5955
- charTy.getLen ());
5994
+ if (fir::isa_char (seqTy.getEleTy ())) {
5995
+ auto len = builder.create <fir::LoadOp>(loc, charLen.getValue ());
5956
5996
return genarr (fir::CharArrayBoxValue{mem, len, extents});
5957
5997
}
5958
5998
return genarr (fir::ArrayBoxValue{mem, extents});
0 commit comments