summaryrefslogtreecommitdiff
path: root/flang/lib/Lower/ConvertExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'flang/lib/Lower/ConvertExpr.cpp')
-rw-r--r--flang/lib/Lower/ConvertExpr.cpp243
1 files changed, 128 insertions, 115 deletions
diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp
index 9567685aa3d2..44c3dc88edd3 100644
--- a/flang/lib/Lower/ConvertExpr.cpp
+++ b/flang/lib/Lower/ConvertExpr.cpp
@@ -398,8 +398,8 @@ static bool isParenthesizedVariable(const Fortran::evaluate::Expr<T> &expr) {
return Fortran::evaluate::IsVariable(parentheses->left());
return false;
} else {
- return std::visit([&](const auto &x) { return isParenthesizedVariable(x); },
- expr.u);
+ return Fortran::common::visit(
+ [&](const auto &x) { return isParenthesizedVariable(x); }, expr.u);
}
}
@@ -646,7 +646,7 @@ isOptimizableTranspose(Fortran::evaluate::Expr<T> expr,
if (!isTransposeOptEnabled(converter))
return false;
- return std::visit(
+ return Fortran::common::visit(
[&](const auto &e) { return isOptimizableTranspose(e, converter); },
expr.u);
}
@@ -696,7 +696,7 @@ public:
// - result of NULL() or NULL(MOLD) intrinsic.
// NULL() requires some context to be lowered, so it is not handled
// here and must be lowered according to the context where it appears.
- ExtValue exv = std::visit(
+ ExtValue exv = Fortran::common::visit(
[&](const auto &x) { return genMutableBoxValueImpl(x); }, expr.u);
const fir::MutableBoxValue *mutableBox =
exv.getBoxOf<fir::MutableBoxValue>();
@@ -737,7 +737,7 @@ public:
template <typename T>
ExtValue
genMutableBoxValueImpl(const Fortran::evaluate::Designator<T> &designator) {
- return std::visit(
+ return Fortran::common::visit(
Fortran::common::visitors{
[&](const Fortran::evaluate::SymbolRef &sym) -> ExtValue {
return converter.getSymbolExtendedValue(*sym, &symMap);
@@ -754,8 +754,8 @@ public:
template <typename T>
ExtValue genMutableBoxValueImpl(const Fortran::evaluate::Expr<T> &expr) {
- return std::visit([&](const auto &x) { return genMutableBoxValueImpl(x); },
- expr.u);
+ return Fortran::common::visit(
+ [&](const auto &x) { return genMutableBoxValueImpl(x); }, expr.u);
}
mlir::Location getLoc() { return location; }
@@ -1222,7 +1222,8 @@ public:
ExtValue
genval(const Fortran::evaluate::Relational<Fortran::evaluate::SomeType> &op) {
- return std::visit([&](const auto &x) { return genval(x); }, op.u);
+ return Fortran::common::visit([&](const auto &x) { return genval(x); },
+ op.u);
}
template <Fortran::common::TypeCategory TC1, int KIND,
@@ -1341,7 +1342,7 @@ public:
/// Reference to a substring.
ExtValue gen(const Fortran::evaluate::Substring &s) {
// Get base string
- auto baseString = std::visit(
+ auto baseString = Fortran::common::visit(
Fortran::common::visitors{
[&](const Fortran::evaluate::DataRef &x) { return gen(x); },
[&](const Fortran::evaluate::StaticDataObject::Pointer &p)
@@ -1400,10 +1401,12 @@ public:
}
ExtValue gen(const Fortran::evaluate::DataRef &dref) {
- return std::visit([&](const auto &x) { return gen(x); }, dref.u);
+ return Fortran::common::visit([&](const auto &x) { return gen(x); },
+ dref.u);
}
ExtValue genval(const Fortran::evaluate::DataRef &dref) {
- return std::visit([&](const auto &x) { return genval(x); }, dref.u);
+ return Fortran::common::visit([&](const auto &x) { return genval(x); },
+ dref.u);
}
// Helper function to turn the Component structure into a list of nested
@@ -1418,7 +1421,7 @@ public:
std::list<const Fortran::evaluate::Component *> &list) {
if (!getLastSym(cmpt).test(Fortran::semantics::Symbol::Flag::ParentComp))
list.push_front(&cmpt);
- return std::visit(
+ return Fortran::common::visit(
Fortran::common::visitors{
[&](const Fortran::evaluate::Component &x) {
if (Fortran::semantics::IsAllocatableOrPointer(getLastSym(x)))
@@ -1713,11 +1716,12 @@ public:
template <typename A>
ExtValue gen(const Fortran::evaluate::Designator<A> &des) {
- return std::visit([&](const auto &x) { return gen(x); }, des.u);
+ return Fortran::common::visit([&](const auto &x) { return gen(x); }, des.u);
}
template <typename A>
ExtValue genval(const Fortran::evaluate::Designator<A> &des) {
- return std::visit([&](const auto &x) { return genval(x); }, des.u);
+ return Fortran::common::visit([&](const auto &x) { return genval(x); },
+ des.u);
}
mlir::Type genType(const Fortran::evaluate::DynamicType &dt) {
@@ -2286,11 +2290,21 @@ public:
bool isActualArgBox =
fir::isa_box_type(fir::getBase(copyOutPair.var).getType());
auto doCopyOut = [&]() {
- if (!copyOutPair.argMayBeModifiedByCall) {
- return;
- }
if (!isActualArgBox || inlineCopyInOutForBoxes) {
- genArrayCopy(copyOutPair.var, copyOutPair.temp);
+ if (copyOutPair.argMayBeModifiedByCall)
+ genArrayCopy(copyOutPair.var, copyOutPair.temp);
+ if (mlir::isa<fir::RecordType>(
+ fir::getElementTypeOf(copyOutPair.temp))) {
+ // Destroy components of the temporary (if any).
+ // If there are no components requiring destruction, then the call
+ // is a no-op.
+ mlir::Value tempBox =
+ fir::getBase(builder.createBox(loc, copyOutPair.temp));
+ fir::runtime::genDerivedTypeDestroyWithoutFinalization(builder, loc,
+ tempBox);
+ }
+ // Deallocate the top-level entity of the temporary.
+ builder.create<fir::FreeMemOp>(loc, fir::getBase(copyOutPair.temp));
return;
}
// Generate CopyOutAssign() call to copy data from the temporary
@@ -2301,51 +2315,39 @@ public:
// Moreover, CopyOutAssign() guarantees that there will be no
// finalization for the LHS even if it is of a derived type
// with finalization.
+
+ // Create allocatable descriptor for the temp so that the runtime may
+ // deallocate it.
mlir::Value srcBox =
fir::getBase(builder.createBox(loc, copyOutPair.temp));
- mlir::Value destBox =
- fir::getBase(builder.createBox(loc, copyOutPair.var));
- mlir::Value destBoxRef = builder.createTemporary(loc, destBox.getType());
- builder.create<fir::StoreOp>(loc, destBox, destBoxRef);
- fir::runtime::genCopyOutAssign(builder, loc, destBoxRef, srcBox,
- /*skipToInit=*/true);
- };
- if (!copyOutPair.restrictCopyAndFreeAtRuntime) {
- doCopyOut();
-
- if (mlir::isa<fir::RecordType>(fir::getElementTypeOf(copyOutPair.temp))) {
- // Destroy components of the temporary (if any).
- // If there are no components requiring destruction, then the call
- // is a no-op.
- mlir::Value tempBox =
- fir::getBase(builder.createBox(loc, copyOutPair.temp));
- fir::runtime::genDerivedTypeDestroyWithoutFinalization(builder, loc,
- tempBox);
+ mlir::Type allocBoxTy =
+ mlir::cast<fir::BaseBoxType>(srcBox.getType())
+ .getBoxTypeWithNewAttr(fir::BaseBoxType::Attribute::Allocatable);
+ srcBox = builder.create<fir::ReboxOp>(loc, allocBoxTy, srcBox,
+ /*shift=*/mlir::Value{},
+ /*slice=*/mlir::Value{});
+ mlir::Value srcBoxRef = builder.createTemporary(loc, srcBox.getType());
+ builder.create<fir::StoreOp>(loc, srcBox, srcBoxRef);
+ // Create descriptor pointer to variable descriptor if copy out is needed,
+ // and nullptr otherwise.
+ mlir::Value destBoxRef;
+ if (copyOutPair.argMayBeModifiedByCall) {
+ mlir::Value destBox =
+ fir::getBase(builder.createBox(loc, copyOutPair.var));
+ destBoxRef = builder.createTemporary(loc, destBox.getType());
+ builder.create<fir::StoreOp>(loc, destBox, destBoxRef);
+ } else {
+ destBoxRef = builder.create<fir::ZeroOp>(loc, srcBoxRef.getType());
}
+ fir::runtime::genCopyOutAssign(builder, loc, destBoxRef, srcBoxRef);
+ };
- // Deallocate the top-level entity of the temporary.
- builder.create<fir::FreeMemOp>(loc, fir::getBase(copyOutPair.temp));
- return;
- }
-
- builder.genIfThen(loc, *copyOutPair.restrictCopyAndFreeAtRuntime)
- .genThen([&]() {
- doCopyOut();
- if (mlir::isa<fir::RecordType>(
- fir::getElementTypeOf(copyOutPair.temp))) {
- // Destroy components of the temporary (if any).
- // If there are no components requiring destruction, then the call
- // is a no-op.
- mlir::Value tempBox =
- fir::getBase(builder.createBox(loc, copyOutPair.temp));
- fir::runtime::genDerivedTypeDestroyWithoutFinalization(builder, loc,
- tempBox);
- }
-
- // Deallocate the top-level entity of the temporary.
- builder.create<fir::FreeMemOp>(loc, fir::getBase(copyOutPair.temp));
- })
- .end();
+ if (!copyOutPair.restrictCopyAndFreeAtRuntime)
+ doCopyOut();
+ else
+ builder.genIfThen(loc, *copyOutPair.restrictCopyAndFreeAtRuntime)
+ .genThen([&]() { doCopyOut(); })
+ .end();
}
/// Lower a designator to a variable that may be absent at runtime into an
@@ -2900,8 +2902,8 @@ public:
}
template <typename T>
bool isTransformationalRef(Fortran::evaluate::Expr<T> expr) {
- return std::visit([&](const auto &e) { return isTransformationalRef(e); },
- expr.u);
+ return Fortran::common::visit(
+ [&](const auto &e) { return isTransformationalRef(e); }, expr.u);
}
template <typename A>
@@ -2914,11 +2916,13 @@ public:
/// value, so it may be possible to avoid making a temporary.
template <typename A>
ExtValue asArrayArg(const Fortran::evaluate::Expr<A> &x) {
- return std::visit([&](const auto &e) { return asArrayArg(e, x); }, x.u);
+ return Fortran::common::visit(
+ [&](const auto &e) { return asArrayArg(e, x); }, x.u);
}
template <typename A, typename B>
ExtValue asArrayArg(const Fortran::evaluate::Expr<A> &x, const B &y) {
- return std::visit([&](const auto &e) { return asArrayArg(e, y); }, x.u);
+ return Fortran::common::visit(
+ [&](const auto &e) { return asArrayArg(e, y); }, x.u);
}
template <typename A, typename B>
ExtValue asArrayArg(const Fortran::evaluate::Designator<A> &, const B &x) {
@@ -2956,7 +2960,8 @@ public:
if (isScalar(x) ||
Fortran::evaluate::UnwrapWholeSymbolOrComponentDataRef(x) ||
(isTransformationalRef(x) && !isOptimizableTranspose(x, converter)))
- return std::visit([&](const auto &e) { return genref(e); }, x.u);
+ return Fortran::common::visit([&](const auto &e) { return genref(e); },
+ x.u);
if (useBoxArg)
return asArrayArg(x);
return asArray(x);
@@ -2967,7 +2972,8 @@ public:
return val;
if (isScalar(x) || Fortran::evaluate::UnwrapWholeSymbolDataRef(x) ||
inInitializer)
- return std::visit([&](const auto &e) { return genval(e); }, x.u);
+ return Fortran::common::visit([&](const auto &e) { return genval(e); },
+ x.u);
return asArray(x);
}
@@ -2976,7 +2982,8 @@ public:
Fortran::common::TypeCategory::Logical, KIND>> &exp) {
if (mlir::Value val = getIfOverridenExpr(exp))
return val;
- return std::visit([&](const auto &e) { return genval(e); }, exp.u);
+ return Fortran::common::visit([&](const auto &e) { return genval(e); },
+ exp.u);
}
using RefSet =
@@ -3462,7 +3469,7 @@ public:
ExtValue lowerBoxedArrayExpr(const Fortran::lower::SomeExpr &exp) {
PushSemantics(ConstituentSemantics::BoxValue);
- return std::visit(
+ return Fortran::common::visit(
[&](const auto &e) {
auto f = genarr(e);
ExtValue exv = f(IterationSpace{});
@@ -3824,28 +3831,29 @@ private:
fir::factory::getExtents(loc, builder, exv);
mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
for (auto ss : llvm::enumerate(x.subscript())) {
- std::visit(Fortran::common::visitors{
- [&](const Fortran::evaluate::Triplet &trip) {
- // For a subscript of triple notation, we compute the
- // range of this dimension of the iteration space.
- auto lo = [&]() {
- if (auto optLo = trip.lower())
- return fir::getBase(asScalar(*optLo));
- return getLBound(exv, ss.index(), one);
- }();
- auto hi = [&]() {
- if (auto optHi = trip.upper())
- return fir::getBase(asScalar(*optHi));
- return getUBound(exv, ss.index(), one);
- }();
- auto step = builder.createConvert(
- loc, idxTy, fir::getBase(asScalar(trip.stride())));
- auto extent = builder.genExtentFromTriplet(loc, lo, hi,
- step, idxTy);
- destShape.push_back(extent);
- },
- [&](auto) {}},
- ss.value().u);
+ Fortran::common::visit(
+ Fortran::common::visitors{
+ [&](const Fortran::evaluate::Triplet &trip) {
+ // For a subscript of triple notation, we compute the
+ // range of this dimension of the iteration space.
+ auto lo = [&]() {
+ if (auto optLo = trip.lower())
+ return fir::getBase(asScalar(*optLo));
+ return getLBound(exv, ss.index(), one);
+ }();
+ auto hi = [&]() {
+ if (auto optHi = trip.upper())
+ return fir::getBase(asScalar(*optHi));
+ return getUBound(exv, ss.index(), one);
+ }();
+ auto step = builder.createConvert(
+ loc, idxTy, fir::getBase(asScalar(trip.stride())));
+ auto extent =
+ builder.genExtentFromTriplet(loc, lo, hi, step, idxTy);
+ destShape.push_back(extent);
+ },
+ [&](auto) {}},
+ ss.value().u);
}
return true;
}
@@ -3855,8 +3863,8 @@ private:
return genShapeFromDataRef(x.GetComponent());
}
bool genShapeFromDataRef(const Fortran::evaluate::DataRef &x) {
- return std::visit([&](const auto &v) { return genShapeFromDataRef(v); },
- x.u);
+ return Fortran::common::visit(
+ [&](const auto &v) { return genShapeFromDataRef(v); }, x.u);
}
/// When in an explicit space, the ranked component must be evaluated to
@@ -3890,7 +3898,7 @@ private:
TODO(getLoc(),
"polymorphic array expression lowering with vector subscript");
- return std::visit(
+ return Fortran::common::visit(
[&](const auto &e) { return lowerArrayExpression(genarr(e), resTy); },
exp.u);
}
@@ -5012,10 +5020,12 @@ private:
LLVM_DEBUG(Fortran::lower::DumpEvaluateExpr::dump(llvm::dbgs(), x));
if (isArray(x) || (explicitSpaceIsActive() && isLeftHandSide()) ||
isElementalProcWithArrayArgs(x))
- return std::visit([&](const auto &e) { return genarr(e); }, x.u);
+ return Fortran::common::visit([&](const auto &e) { return genarr(e); },
+ x.u);
if (explicitSpaceIsActive()) {
assert(!isArray(x) && !isLeftHandSide());
- auto cc = std::visit([&](const auto &e) { return genarr(e); }, x.u);
+ auto cc =
+ Fortran::common::visit([&](const auto &e) { return genarr(e); }, x.u);
auto result = cc(IterationSpace{});
return [=](IterSpace) { return result; };
}
@@ -5289,7 +5299,8 @@ private:
static Fortran::lower::SomeExpr
ignoreEvConvert(const Fortran::evaluate::Expr<Fortran::evaluate::Type<
Fortran::common::TypeCategory::Integer, 8>> &x) {
- return std::visit([&](const auto &v) { return ignoreEvConvert(v); }, x.u);
+ return Fortran::common::visit(
+ [&](const auto &v) { return ignoreEvConvert(v); }, x.u);
}
template <Fortran::common::TypeCategory FROM>
static Fortran::lower::SomeExpr ignoreEvConvert(
@@ -5310,8 +5321,8 @@ private:
template <typename A>
static const Fortran::semantics::Symbol *
extractSubscriptSymbol(const Fortran::evaluate::Expr<A> &x) {
- return std::visit([&](const auto &v) { return extractSubscriptSymbol(v); },
- x.u);
+ return Fortran::common::visit(
+ [&](const auto &v) { return extractSubscriptSymbol(v); }, x.u);
}
template <typename A>
static const Fortran::semantics::Symbol *
@@ -5420,7 +5431,7 @@ private:
std::size_t shapeIndex = 0;
for (auto sub : llvm::enumerate(x.subscript())) {
const std::size_t subsIndex = sub.index();
- std::visit(
+ Fortran::common::visit(
Fortran::common::visitors{
[&](const Fortran::evaluate::Triplet &t) {
mlir::Value lowerBound;
@@ -6034,8 +6045,8 @@ private:
/// Substrings (see 9.4.1)
CC genarr(const Fortran::evaluate::Substring &x, ComponentPath &components) {
components.substring = &x;
- return std::visit([&](const auto &v) { return genarr(v, components); },
- x.parent());
+ return Fortran::common::visit(
+ [&](const auto &v) { return genarr(v, components); }, x.parent());
}
template <typename T>
@@ -6333,7 +6344,7 @@ private:
stmtCtx.pushScope();
std::optional<mlir::Value> charLen;
for (const Fortran::evaluate::ArrayConstructorValue<A> &acv : x.values()) {
- auto [exv, copyNeeded] = std::visit(
+ auto [exv, copyNeeded] = Fortran::common::visit(
[&](const auto &v) {
return genArrayCtorInitializer(v, resTy, mem, buffPos, buffSize,
stmtCtx);
@@ -6417,7 +6428,7 @@ private:
// Populate the buffer with the elements, growing as necessary.
std::optional<mlir::Value> charLen;
for (const auto &expr : x) {
- auto [exv, copyNeeded] = std::visit(
+ auto [exv, copyNeeded] = Fortran::common::visit(
[&](const auto &e) {
return genArrayCtorInitializer(e, resTy, mem, buffPos, buffSize,
stmtCtx);
@@ -6582,22 +6593,24 @@ private:
}
CC genarr(
const Fortran::evaluate::Relational<Fortran::evaluate::SomeType> &r) {
- return std::visit([&](const auto &x) { return genarr(x); }, r.u);
+ return Fortran::common::visit([&](const auto &x) { return genarr(x); },
+ r.u);
}
template <typename A>
CC genarr(const Fortran::evaluate::Designator<A> &des) {
ComponentPath components(des.Rank() > 0);
- return std::visit([&](const auto &x) { return genarr(x, components); },
- des.u);
+ return Fortran::common::visit(
+ [&](const auto &x) { return genarr(x, components); }, des.u);
}
/// Is the path component rank > 0?
static bool ranked(const PathComponent &x) {
- return std::visit(Fortran::common::visitors{
- [](const ImplicitSubscripts &) { return false; },
- [](const auto *v) { return v->Rank() > 0; }},
- x);
+ return Fortran::common::visit(
+ Fortran::common::visitors{
+ [](const ImplicitSubscripts &) { return false; },
+ [](const auto *v) { return v->Rank() > 0; }},
+ x);
}
void extendComponent(Fortran::lower::ComponentPath &component,
@@ -6653,7 +6666,7 @@ private:
: nextPathSemantics());
unsigned index = 0;
for (const auto &v : llvm::reverse(revPath)) {
- std::visit(
+ Fortran::common::visit(
Fortran::common::visitors{
[&](const ImplicitSubscripts &) {
prefix = false;
@@ -6678,7 +6691,7 @@ private:
unsigned ssIndex = 0u;
llvm::SmallVector<mlir::Value> componentsToAdd;
for (const auto &ss : x->subscript()) {
- std::visit(
+ Fortran::common::visit(
Fortran::common::visitors{
[&](const Fortran::evaluate::
IndirectSubscriptIntegerExpr &ie) {
@@ -7099,8 +7112,8 @@ private:
}
CC genarr(const Fortran::evaluate::DataRef &x, ComponentPath &components) {
- return std::visit([&](const auto &v) { return genarr(v, components); },
- x.u);
+ return Fortran::common::visit(
+ [&](const auto &v) { return genarr(v, components); }, x.u);
}
bool pathIsEmpty(const ComponentPath &components) {
@@ -7575,13 +7588,13 @@ void Fortran::lower::createArrayLoads(
};
if (esp.lhsBases[counter]) {
auto &base = *esp.lhsBases[counter];
- auto load = std::visit(genLoad, base);
+ auto load = Fortran::common::visit(genLoad, base);
esp.initialArgs.push_back(load);
esp.resetInnerArgs();
esp.bindLoad(base, load);
}
for (const auto &base : esp.rhsBases[counter])
- esp.bindLoad(base, std::visit(genLoad, base));
+ esp.bindLoad(base, Fortran::common::visit(genLoad, base));
}
void Fortran::lower::createArrayMergeStores(