Skip to content

Commit 6eb7893

Browse files
authored
Merge pull request #1156 from schweitzpgi/ch-bug2
Fixes array constructor of array of CHARACTERs. Threads the LEN value
2 parents cd3d951 + 67f3b40 commit 6eb7893

File tree

2 files changed

+62
-20
lines changed

2 files changed

+62
-20
lines changed

flang/lib/Lower/ConvertExpr.cpp

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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});

flang/lib/Optimizer/CodeGen/CodeGen.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2155,7 +2155,8 @@ struct CoordinateOpConversion
21552155
}
21562156

21572157
if (fir::hasDynamicSize(fir::unwrapSequenceType(cpnTy)))
2158-
TODO(loc, "type has dynamic size");
2158+
return mlir::emitError(
2159+
loc, "fir.coordinate_of with a dynamic element size is unsupported");
21592160

21602161
if (hasKnownShape || columnIsDeferred) {
21612162
SmallVector<mlir::Value> offs;
@@ -2213,7 +2214,8 @@ struct CoordinateOpConversion
22132214
rewriter.replaceOp(coor, retval);
22142215
return success();
22152216
}
2216-
return mlir::emitError(loc, "fir.coordinate_of base must have box type");
2217+
return mlir::emitError(
2218+
loc, "fir.coordinate_of base operand has unsupported type");
22172219
}
22182220

22192221
unsigned getFieldNumber(fir::RecordType ty, mlir::Value op) const {

0 commit comments

Comments
 (0)