@@ -5632,16 +5632,47 @@ class ArrayExprLowering {
56325632 // / Target agnostic computation of the size of an element in the array.
56335633 // / Returns the size in bytes with type `index` or a null Value if the element
56345634 // / 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) {
56395637 auto loc = getLoc ();
56405638 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);
56415673 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});
56455676 return builder.createConvert (loc, idxTy, offset);
56465677 }
56475678
@@ -5789,7 +5820,6 @@ class ArrayExprLowering {
57895820 mlir::ValueRange{off});
57905821 auto val = builder.createConvert (loc, eleTy, v);
57915822 builder.create <fir::StoreOp>(loc, val, buffi);
5792-
57935823 builder.create <fir::StoreOp>(loc, plusOne, buffPos);
57945824 },
57955825 [&](const fir::CharBoxValue &v) {
@@ -5847,21 +5877,28 @@ class ArrayExprLowering {
58475877 mem = loop.getRegionIterArgs ()[0 ];
58485878
58495879 auto eleRefTy = builder.getRefType (eleTy);
5850- auto eleSz = computeElementSize (eleTy, eleRefTy, builder.getRefType (resTy));
58515880
58525881 // Cleanups for temps in loop body. Any temps created in the loop body
58535882 // need to be freed before the end of the loop.
58545883 Fortran::lower::StatementContext loopCtx;
5884+ llvm::Optional<mlir::Value> charLen;
58555885 for (const Fortran::evaluate::ArrayConstructorValue<A> &acv : x.values ()) {
58565886 auto [exv, copyNeeded] = std::visit (
58575887 [&](const auto &v) {
58585888 return genArrayCtorInitializer (v, resTy, mem, buffPos, buffSize,
58595889 loopCtx);
58605890 },
58615891 acv.u );
5892+ auto eleSz = computeElementSize (exv, eleTy, resTy);
58625893 mem = copyNeeded ? copyNextArrayCtorSection (exv, buffPos, buffSize, mem,
58635894 eleSz, eleTy, eleRefTy, resTy)
58645895 : 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+ }
58655902 }
58665903 loopCtx.finalize ();
58675904
@@ -5873,10 +5910,8 @@ class ArrayExprLowering {
58735910 builder.create <fir::LoadOp>(loc, buffPos).getResult ()};
58745911
58755912 // 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 ());
58805915 return {fir::CharArrayBoxValue{mem, len, extents}, /* needCopy=*/ false };
58815916 }
58825917 return {fir::ArrayBoxValue{mem, extents}, /* needCopy=*/ false };
@@ -5925,19 +5960,26 @@ class ArrayExprLowering {
59255960 }
59265961 // Compute size of element
59275962 auto eleRefTy = builder.getRefType (eleTy);
5928- auto eleSz = computeElementSize (eleTy, eleRefTy, builder.getRefType (resTy));
59295963
59305964 // Populate the buffer with the elements, growing as necessary.
5965+ llvm::Optional<mlir::Value> charLen;
59315966 for (const auto &expr : x) {
59325967 auto [exv, copyNeeded] = std::visit (
59335968 [&](const auto &e) {
59345969 return genArrayCtorInitializer (e, resTy, mem, buffPos, buffSize,
59355970 stmtCtx);
59365971 },
59375972 expr.u );
5973+ auto eleSz = computeElementSize (exv, eleTy, resTy);
59385974 mem = copyNeeded ? copyNextArrayCtorSection (exv, buffPos, buffSize, mem,
59395975 eleSz, eleTy, eleRefTy, resTy)
59405976 : 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+ }
59415983 }
59425984 mem = builder.createConvert (loc, fir::HeapType::get (resTy), mem);
59435985 llvm::SmallVector<mlir::Value> extents = {
@@ -5949,10 +5991,8 @@ class ArrayExprLowering {
59495991 [bldr, loc, mem]() { bldr->create <fir::FreeMemOp>(loc, mem); });
59505992
59515993 // 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 ());
59565996 return genarr (fir::CharArrayBoxValue{mem, len, extents});
59575997 }
59585998 return genarr (fir::ArrayBoxValue{mem, extents});
0 commit comments