//===-- ConvertExpr.cpp ---------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
//
//===----------------------------------------------------------------------===//

#include "flang/Lower/ConvertExpr.h"
#include "flang/Common/unwrap.h"
#include "flang/Evaluate/fold.h"
#include "flang/Evaluate/real.h"
#include "flang/Evaluate/traverse.h"
#include "flang/Lower/Allocatable.h"
#include "flang/Lower/Bridge.h"
#include "flang/Lower/BuiltinModules.h"
#include "flang/Lower/CallInterface.h"
#include "flang/Lower/ComponentPath.h"
#include "flang/Lower/ConvertCall.h"
#include "flang/Lower/ConvertConstant.h"
#include "flang/Lower/ConvertProcedureDesignator.h"
#include "flang/Lower/ConvertType.h"
#include "flang/Lower/ConvertVariable.h"
#include "flang/Lower/CustomIntrinsicCall.h"
#include "flang/Lower/Mangler.h"
#include "flang/Lower/MultiImageFortran.h"
#include "flang/Lower/Runtime.h"
#include "flang/Lower/Support/Utils.h"
#include "flang/Optimizer/Builder/Character.h"
#include "flang/Optimizer/Builder/Complex.h"
#include "flang/Optimizer/Builder/Factory.h"
#include "flang/Optimizer/Builder/IntrinsicCall.h"
#include "flang/Optimizer/Builder/Runtime/Assign.h"
#include "flang/Optimizer/Builder/Runtime/Character.h"
#include "flang/Optimizer/Builder/Runtime/Derived.h"
#include "flang/Optimizer/Builder/Runtime/Inquiry.h"
#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
#include "flang/Optimizer/Builder/Runtime/Ragged.h"
#include "flang/Optimizer/Builder/Todo.h"
#include "flang/Optimizer/Dialect/FIRAttr.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
#include "flang/Optimizer/Support/FatalError.h"
#include "flang/Runtime/support.h"
#include "flang/Semantics/dump-expr.h"
#include "flang/Semantics/expression.h"
#include "flang/Semantics/symbol.h"
#include "flang/Semantics/tools.h"
#include "flang/Semantics/type.h"
#include "flang/Support/default-kinds.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <optional>

#define DEBUG_TYPE "flang-lower-expr"

using namespace Fortran::runtime;

//===----------------------------------------------------------------------===//
// The composition and structure of Fortran::evaluate::Expr is defined in
// the various header files in include/flang/Evaluate. You are referred
// there for more information on these data structures. Generally speaking,
// these data structures are a strongly typed family of abstract data types
// that, composed as trees, describe the syntax of Fortran expressions.
//
// This part of the bridge can traverse these tree structures and lower them
// to the correct FIR representation in SSA form.
//===----------------------------------------------------------------------===//

static llvm::cl::opt<bool> generateArrayCoordinate(
    "gen-array-coor",
    llvm::cl::desc("in lowering create ArrayCoorOp instead of CoordinateOp"),
    llvm::cl::init(false));

// The default attempts to balance a modest allocation size with expected user
// input to minimize bounds checks and reallocations during dynamic array
// construction. Some user codes may have very large array constructors for
// which the default can be increased.
static llvm::cl::opt<unsigned> clInitialBufferSize(
    "array-constructor-initial-buffer-size",
    llvm::cl::desc(
        "set the incremental array construction buffer size (default=32)"),
    llvm::cl::init(32u));

// Lower TRANSPOSE as an "elemental" function that swaps the array
// expression's iteration space, so that no runtime call is needed.
// This lowering may help get rid of unnecessary creation of temporary
// arrays. Note that the runtime TRANSPOSE implementation may be different
// from the "inline" FIR, e.g. it may diagnose out-of-memory conditions
// during the temporary allocation whereas the inline implementation
// relies on AllocMemOp that will silently return null in case
// there is not enough memory.
//
// If it is set to false, then TRANSPOSE will be lowered using
// a runtime call. If it is set to true, then the lowering is controlled
// by LoweringOptions::optimizeTranspose bit (see isTransposeOptEnabled
// function in this file).
static llvm::cl::opt<bool> optimizeTranspose(
    "opt-transpose",
    llvm::cl::desc("lower transpose without using a runtime call"),
    llvm::cl::init(true));

// When copy-in/copy-out is generated for a boxed object we may
// either produce loops to copy the data or call the Fortran runtime's
// Assign function. Since the data copy happens under a runtime check
// (for IsContiguous) the copy loops can hardly provide any value
// to optimizations, instead, the optimizer just wastes compilation
// time on these loops.
//
// This internal option will force the loops generation, when set
// to true. It is false by default.
//
// Note that for copy-in/copy-out of non-boxed objects (e.g. for passing
// arguments by value) we always generate loops. Since the memory for
// such objects is contiguous, it may be better to expose them
// to the optimizer.
static llvm::cl::opt<bool> inlineCopyInOutForBoxes(
    "inline-copyinout-for-boxes",
    llvm::cl::desc(
        "generate loops for copy-in/copy-out of objects with descriptors"),
    llvm::cl::init(false));

/// The various semantics of a program constituent (or a part thereof) as it may
/// appear in an expression.
///
/// Given the following Fortran declarations.
/// ```fortran
///   REAL :: v1, v2, v3
///   REAL, POINTER :: vp1
///   REAL :: a1(c), a2(c)
///   REAL ELEMENTAL FUNCTION f1(arg) ! array -> array
///   FUNCTION f2(arg)                ! array -> array
///   vp1 => v3       ! 1
///   v1 = v2 * vp1   ! 2
///   a1 = a1 + a2    ! 3
///   a1 = f1(a2)     ! 4
///   a1 = f2(a2)     ! 5
/// ```
///
/// In line 1, `vp1` is a BoxAddr to copy a box value into. The box value is
/// constructed from the DataAddr of `v3`.
/// In line 2, `v1` is a DataAddr to copy a value into. The value is constructed
/// from the DataValue of `v2` and `vp1`. DataValue is implicitly a double
/// dereference in the `vp1` case.
/// In line 3, `a1` and `a2` on the rhs are RefTransparent. The `a1` on the lhs
/// is CopyInCopyOut as `a1` is replaced elementally by the additions.
/// In line 4, `a2` can be RefTransparent, ByValueArg, RefOpaque, or BoxAddr if
/// `arg` is declared as C-like pass-by-value, VALUE, INTENT(?), or ALLOCATABLE/
/// POINTER, respectively. `a1` on the lhs is CopyInCopyOut.
///  In line 5, `a2` may be DataAddr or BoxAddr assuming f2 is transformational.
///  `a1` on the lhs is again CopyInCopyOut.
enum class ConstituentSemantics {
  // Scalar data reference semantics.
  //
  // For these let `v` be the location in memory of a variable with value `x`
  DataValue, // refers to the value `x`
  DataAddr,  // refers to the address `v`
  BoxValue,  // refers to a box value containing `v`
  BoxAddr,   // refers to the address of a box value containing `v`

  // Array data reference semantics.
  //
  // For these let `a` be the location in memory of a sequence of value `[xs]`.
  // Let `x_i` be the `i`-th value in the sequence `[xs]`.

  // Referentially transparent. Refers to the array's value, `[xs]`.
  RefTransparent,
  // Refers to an ephemeral address `tmp` containing value `x_i` (15.5.2.3.p7
  // note 2). (Passing a copy by reference to simulate pass-by-value.)
  ByValueArg,
  // Refers to the merge of array value `[xs]` with another array value `[ys]`.
  // This merged array value will be written into memory location `a`.
  CopyInCopyOut,
  // Similar to CopyInCopyOut but `a` may be a transient projection (rather than
  // a whole array).
  ProjectedCopyInCopyOut,
  // Similar to ProjectedCopyInCopyOut, except the merge value is not assigned
  // automatically by the framework. Instead, and address for `[xs]` is made
  // accessible so that custom assignments to `[xs]` can be implemented.
  CustomCopyInCopyOut,
  // Referentially opaque. Refers to the address of `x_i`.
  RefOpaque
};

/// Convert parser's INTEGER relational operators to MLIR.  TODO: using
/// unordered, but we may want to cons ordered in certain situation.
static mlir::arith::CmpIPredicate
translateSignedRelational(Fortran::common::RelationalOperator rop) {
  switch (rop) {
  case Fortran::common::RelationalOperator::LT:
    return mlir::arith::CmpIPredicate::slt;
  case Fortran::common::RelationalOperator::LE:
    return mlir::arith::CmpIPredicate::sle;
  case Fortran::common::RelationalOperator::EQ:
    return mlir::arith::CmpIPredicate::eq;
  case Fortran::common::RelationalOperator::NE:
    return mlir::arith::CmpIPredicate::ne;
  case Fortran::common::RelationalOperator::GT:
    return mlir::arith::CmpIPredicate::sgt;
  case Fortran::common::RelationalOperator::GE:
    return mlir::arith::CmpIPredicate::sge;
  }
  llvm_unreachable("unhandled INTEGER relational operator");
}

static mlir::arith::CmpIPredicate
translateUnsignedRelational(Fortran::common::RelationalOperator rop) {
  switch (rop) {
  case Fortran::common::RelationalOperator::LT:
    return mlir::arith::CmpIPredicate::ult;
  case Fortran::common::RelationalOperator::LE:
    return mlir::arith::CmpIPredicate::ule;
  case Fortran::common::RelationalOperator::EQ:
    return mlir::arith::CmpIPredicate::eq;
  case Fortran::common::RelationalOperator::NE:
    return mlir::arith::CmpIPredicate::ne;
  case Fortran::common::RelationalOperator::GT:
    return mlir::arith::CmpIPredicate::ugt;
  case Fortran::common::RelationalOperator::GE:
    return mlir::arith::CmpIPredicate::uge;
  }
  llvm_unreachable("unhandled UNSIGNED relational operator");
}

/// Convert parser's REAL relational operators to MLIR.
/// The choice of order (O prefix) vs unorder (U prefix) follows Fortran 2018
/// requirements in the IEEE context (table 17.1 of F2018). This choice is
/// also applied in other contexts because it is easier and in line with
/// other Fortran compilers.
/// FIXME: The signaling/quiet aspect of the table 17.1 requirement is not
/// fully enforced. FIR and LLVM `fcmp` instructions do not give any guarantee
/// whether the comparison will signal or not in case of quiet NaN argument.
static mlir::arith::CmpFPredicate
translateFloatRelational(Fortran::common::RelationalOperator rop) {
  switch (rop) {
  case Fortran::common::RelationalOperator::LT:
    return mlir::arith::CmpFPredicate::OLT;
  case Fortran::common::RelationalOperator::LE:
    return mlir::arith::CmpFPredicate::OLE;
  case Fortran::common::RelationalOperator::EQ:
    return mlir::arith::CmpFPredicate::OEQ;
  case Fortran::common::RelationalOperator::NE:
    return mlir::arith::CmpFPredicate::UNE;
  case Fortran::common::RelationalOperator::GT:
    return mlir::arith::CmpFPredicate::OGT;
  case Fortran::common::RelationalOperator::GE:
    return mlir::arith::CmpFPredicate::OGE;
  }
  llvm_unreachable("unhandled REAL relational operator");
}

static mlir::Value genActualIsPresentTest(fir::FirOpBuilder &builder,
                                          mlir::Location loc,
                                          fir::ExtendedValue actual) {
  if (const auto *ptrOrAlloc = actual.getBoxOf<fir::MutableBoxValue>())
    return fir::factory::genIsAllocatedOrAssociatedTest(builder, loc,
                                                        *ptrOrAlloc);
  // Optional case (not that optional allocatable/pointer cannot be absent
  // when passed to CMPLX as per 15.5.2.12 point 3 (7) and (8)). It is
  // therefore possible to catch them in the `then` case above.
  return fir::IsPresentOp::create(builder, loc, builder.getI1Type(),
                                  fir::getBase(actual));
}

/// Convert the array_load, `load`, to an extended value. If `path` is not
/// empty, then traverse through the components designated. The base value is
/// `newBase`. This does not accept an array_load with a slice operand.
static fir::ExtendedValue
arrayLoadExtValue(fir::FirOpBuilder &builder, mlir::Location loc,
                  fir::ArrayLoadOp load, llvm::ArrayRef<mlir::Value> path,
                  mlir::Value newBase, mlir::Value newLen = {}) {
  // Recover the extended value from the load.
  if (load.getSlice())
    fir::emitFatalError(loc, "array_load with slice is not allowed");
  mlir::Type arrTy = load.getType();
  if (!path.empty()) {
    mlir::Type ty = fir::applyPathToType(arrTy, path);
    if (!ty)
      fir::emitFatalError(loc, "path does not apply to type");
    if (!mlir::isa<fir::SequenceType>(ty)) {
      if (fir::isa_char(ty)) {
        mlir::Value len = newLen;
        if (!len)
          len = fir::factory::CharacterExprHelper{builder, loc}.getLength(
              load.getMemref());
        if (!len) {
          assert(load.getTypeparams().size() == 1 &&
                 "length must be in array_load");
          len = load.getTypeparams()[0];
        }
        return fir::CharBoxValue{newBase, len};
      }
      return newBase;
    }
    arrTy = mlir::cast<fir::SequenceType>(ty);
  }

  auto arrayToExtendedValue =
      [&](const llvm::SmallVector<mlir::Value> &extents,
          const llvm::SmallVector<mlir::Value> &origins) -> fir::ExtendedValue {
    mlir::Type eleTy = fir::unwrapSequenceType(arrTy);
    if (fir::isa_char(eleTy)) {
      mlir::Value len = newLen;
      if (!len)
        len = fir::factory::CharacterExprHelper{builder, loc}.getLength(
            load.getMemref());
      if (!len) {
        assert(load.getTypeparams().size() == 1 &&
               "length must be in array_load");
        len = load.getTypeparams()[0];
      }
      return fir::CharArrayBoxValue(newBase, len, extents, origins);
    }
    return fir::ArrayBoxValue(newBase, extents, origins);
  };
  // Use the shape op, if there is one.
  mlir::Value shapeVal = load.getShape();
  if (shapeVal) {
    if (!mlir::isa<fir::ShiftOp>(shapeVal.getDefiningOp())) {
      auto extents = fir::factory::getExtents(shapeVal);
      auto origins = fir::factory::getOrigins(shapeVal);
      return arrayToExtendedValue(extents, origins);
    }
    if (!fir::isa_box_type(load.getMemref().getType()))
      fir::emitFatalError(loc, "shift op is invalid in this context");
  }

  // If we're dealing with the array_load op (not a subobject) and the load does
  // not have any type parameters, then read the extents from the original box.
  // The origin may be either from the box or a shift operation. Create and
  // return the array extended value.
  if (path.empty() && load.getTypeparams().empty()) {
    auto oldBox = load.getMemref();
    fir::ExtendedValue exv = fir::factory::readBoxValue(builder, loc, oldBox);
    auto extents = fir::factory::getExtents(loc, builder, exv);
    auto origins = fir::factory::getNonDefaultLowerBounds(builder, loc, exv);
    if (shapeVal) {
      // shapeVal is a ShiftOp and load.memref() is a boxed value.
      newBase = fir::ReboxOp::create(builder, loc, oldBox.getType(), oldBox,
                                     shapeVal, /*slice=*/mlir::Value{});
      origins = fir::factory::getOrigins(shapeVal);
    }
    return fir::substBase(arrayToExtendedValue(extents, origins), newBase);
  }
  TODO(loc, "path to a POINTER, ALLOCATABLE, or other component that requires "
            "dereferencing; generating the type parameters is a hard "
            "requirement for correctness.");
}

/// Place \p exv in memory if it is not already a memory reference. If
/// \p forceValueType is provided, the value is first casted to the provided
/// type before being stored (this is mainly intended for logicals whose value
/// may be `i1` but needed to be stored as Fortran logicals).
static fir::ExtendedValue
placeScalarValueInMemory(fir::FirOpBuilder &builder, mlir::Location loc,
                         const fir::ExtendedValue &exv,
                         mlir::Type storageType) {
  mlir::Value valBase = fir::getBase(exv);
  if (fir::conformsWithPassByRef(valBase.getType()))
    return exv;

  assert(!fir::hasDynamicSize(storageType) &&
         "only expect statically sized scalars to be by value");

  // Since `a` is not itself a valid referent, determine its value and
  // create a temporary location at the beginning of the function for
  // referencing.
  mlir::Value val = builder.createConvert(loc, storageType, valBase);
  mlir::Value temp = builder.createTemporary(
      loc, storageType,
      llvm::ArrayRef<mlir::NamedAttribute>{fir::getAdaptToByRefAttr(builder)});
  fir::StoreOp::create(builder, loc, val, temp);
  return fir::substBase(exv, temp);
}

// Copy a copy of scalar \p exv in a new temporary.
static fir::ExtendedValue
createInMemoryScalarCopy(fir::FirOpBuilder &builder, mlir::Location loc,
                         const fir::ExtendedValue &exv) {
  assert(exv.rank() == 0 && "input to scalar memory copy must be a scalar");
  if (exv.getCharBox() != nullptr)
    return fir::factory::CharacterExprHelper{builder, loc}.createTempFrom(exv);
  if (fir::isDerivedWithLenParameters(exv))
    TODO(loc, "copy derived type with length parameters");
  mlir::Type type = fir::unwrapPassByRefType(fir::getBase(exv).getType());
  fir::ExtendedValue temp = builder.createTemporary(loc, type);
  fir::factory::genScalarAssignment(builder, loc, temp, exv);
  return temp;
}

// An expression with non-zero rank is an array expression.
template <typename A>
static bool isArray(const A &x) {
  return x.Rank() != 0;
}

/// Is this a variable wrapped in parentheses?
template <typename A>
static bool isParenthesizedVariable(const A &) {
  return false;
}
template <typename T>
static bool isParenthesizedVariable(const Fortran::evaluate::Expr<T> &expr) {
  using ExprVariant = decltype(Fortran::evaluate::Expr<T>::u);
  using Parentheses = Fortran::evaluate::Parentheses<T>;
  if constexpr (Fortran::common::HasMember<Parentheses, ExprVariant>) {
    if (const auto *parentheses = std::get_if<Parentheses>(&expr.u))
      return Fortran::evaluate::IsVariable(parentheses->left());
    return false;
  } else {
    return Fortran::common::visit(
        [&](const auto &x) { return isParenthesizedVariable(x); }, expr.u);
  }
}

/// Generate a load of a value from an address. Beware that this will lose
/// any dynamic type information for polymorphic entities (note that unlimited
/// polymorphic cannot be loaded and must not be provided here).
static fir::ExtendedValue genLoad(fir::FirOpBuilder &builder,
                                  mlir::Location loc,
                                  const fir::ExtendedValue &addr) {
  return addr.match(
      [](const fir::CharBoxValue &box) -> fir::ExtendedValue { return box; },
      [&](const fir::PolymorphicValue &p) -> fir::ExtendedValue {
        if (mlir::isa<fir::RecordType>(
                fir::unwrapRefType(fir::getBase(p).getType())))
          return p;
        mlir::Value load = fir::LoadOp::create(builder, loc, fir::getBase(p));
        return fir::PolymorphicValue(load, p.getSourceBox());
      },
      [&](const fir::UnboxedValue &v) -> fir::ExtendedValue {
        if (mlir::isa<fir::RecordType>(
                fir::unwrapRefType(fir::getBase(v).getType())))
          return v;
        return fir::LoadOp::create(builder, loc, fir::getBase(v));
      },
      [&](const fir::MutableBoxValue &box) -> fir::ExtendedValue {
        return genLoad(builder, loc,
                       fir::factory::genMutableBoxRead(builder, loc, box));
      },
      [&](const fir::BoxValue &box) -> fir::ExtendedValue {
        return genLoad(builder, loc,
                       fir::factory::readBoxValue(builder, loc, box));
      },
      [&](const auto &) -> fir::ExtendedValue {
        fir::emitFatalError(
            loc, "attempting to load whole array or procedure address");
      });
}

/// Create an optional dummy argument value from entity \p exv that may be
/// absent. This can only be called with numerical or logical scalar \p exv.
/// If \p exv is considered absent according to 15.5.2.12 point 1., the returned
/// value is zero (or false), otherwise it is the value of \p exv.
static fir::ExtendedValue genOptionalValue(fir::FirOpBuilder &builder,
                                           mlir::Location loc,
                                           const fir::ExtendedValue &exv,
                                           mlir::Value isPresent) {
  mlir::Type eleType = fir::getBaseTypeOf(exv);
  assert(exv.rank() == 0 && fir::isa_trivial(eleType) &&
         "must be a numerical or logical scalar");
  return builder
      .genIfOp(loc, {eleType}, isPresent,
               /*withElseRegion=*/true)
      .genThen([&]() {
        mlir::Value val = fir::getBase(genLoad(builder, loc, exv));
        fir::ResultOp::create(builder, loc, val);
      })
      .genElse([&]() {
        mlir::Value zero = fir::factory::createZeroValue(builder, loc, eleType);
        fir::ResultOp::create(builder, loc, zero);
      })
      .getResults()[0];
}

/// Create an optional dummy argument address from entity \p exv that may be
/// absent. If \p exv is considered absent according to 15.5.2.12 point 1., the
/// returned value is a null pointer, otherwise it is the address of \p exv.
static fir::ExtendedValue genOptionalAddr(fir::FirOpBuilder &builder,
                                          mlir::Location loc,
                                          const fir::ExtendedValue &exv,
                                          mlir::Value isPresent) {
  // If it is an exv pointer/allocatable, then it cannot be absent
  // because it is passed to a non-pointer/non-allocatable.
  if (const auto *box = exv.getBoxOf<fir::MutableBoxValue>())
    return fir::factory::genMutableBoxRead(builder, loc, *box);
  // If this is not a POINTER or ALLOCATABLE, then it is already an OPTIONAL
  // address and can be passed directly.
  return exv;
}

/// Create an optional dummy argument address from entity \p exv that may be
/// absent. If \p exv is considered absent according to 15.5.2.12 point 1., the
/// returned value is an absent fir.box, otherwise it is a fir.box describing \p
/// exv.
static fir::ExtendedValue genOptionalBox(fir::FirOpBuilder &builder,
                                         mlir::Location loc,
                                         const fir::ExtendedValue &exv,
                                         mlir::Value isPresent) {
  // Non allocatable/pointer optional box -> simply forward
  if (exv.getBoxOf<fir::BoxValue>())
    return exv;

  fir::ExtendedValue newExv = exv;
  // Optional allocatable/pointer -> Cannot be absent, but need to translate
  // unallocated/diassociated into absent fir.box.
  if (const auto *box = exv.getBoxOf<fir::MutableBoxValue>())
    newExv = fir::factory::genMutableBoxRead(builder, loc, *box);

  // createBox will not do create any invalid memory dereferences if exv is
  // absent. The created fir.box will not be usable, but the SelectOp below
  // ensures it won't be.
  mlir::Value box = builder.createBox(loc, newExv);
  mlir::Type boxType = box.getType();
  auto absent = fir::AbsentOp::create(builder, loc, boxType);
  auto boxOrAbsent = mlir::arith::SelectOp::create(builder, loc, boxType,
                                                   isPresent, box, absent);
  return fir::BoxValue(boxOrAbsent);
}

/// Is this a call to an elemental procedure with at least one array argument?
static bool
isElementalProcWithArrayArgs(const Fortran::evaluate::ProcedureRef &procRef) {
  if (procRef.IsElemental())
    for (const std::optional<Fortran::evaluate::ActualArgument> &arg :
         procRef.arguments())
      if (arg && arg->Rank() != 0)
        return true;
  return false;
}
template <typename T>
static bool isElementalProcWithArrayArgs(const Fortran::evaluate::Expr<T> &) {
  return false;
}
template <>
bool isElementalProcWithArrayArgs(const Fortran::lower::SomeExpr &x) {
  if (const auto *procRef = std::get_if<Fortran::evaluate::ProcedureRef>(&x.u))
    return isElementalProcWithArrayArgs(*procRef);
  return false;
}

/// \p argTy must be a tuple (pair) of boxproc and integral types. Convert the
/// \p funcAddr argument to a boxproc value, with the host-association as
/// required. Call the factory function to finish creating the tuple value.
static mlir::Value
createBoxProcCharTuple(Fortran::lower::AbstractConverter &converter,
                       mlir::Type argTy, mlir::Value funcAddr,
                       mlir::Value charLen) {
  auto boxTy = mlir::cast<fir::BoxProcType>(
      mlir::cast<mlir::TupleType>(argTy).getType(0));
  mlir::Location loc = converter.getCurrentLocation();
  auto &builder = converter.getFirOpBuilder();

  // While character procedure arguments are expected here, Fortran allows
  // actual arguments of other types to be passed instead.
  // To support this, we cast any reference to the expected type or extract
  // procedures from their boxes if needed.
  mlir::Type fromTy = funcAddr.getType();
  mlir::Type toTy = boxTy.getEleTy();
  if (fir::isa_ref_type(fromTy))
    funcAddr = builder.createConvert(loc, toTy, funcAddr);
  else if (mlir::isa<fir::BoxProcType>(fromTy))
    funcAddr = fir::BoxAddrOp::create(builder, loc, toTy, funcAddr);

  auto boxProc = [&]() -> mlir::Value {
    if (auto host = Fortran::lower::argumentHostAssocs(converter, funcAddr))
      return fir::EmboxProcOp::create(
          builder, loc, boxTy, llvm::ArrayRef<mlir::Value>{funcAddr, host});
    return fir::EmboxProcOp::create(builder, loc, boxTy, funcAddr);
  }();
  return fir::factory::createCharacterProcedureTuple(builder, loc, argTy,
                                                     boxProc, charLen);
}

/// Given an optional fir.box, returns an fir.box that is the original one if
/// it is present and it otherwise an unallocated box.
/// Absent fir.box are implemented as a null pointer descriptor. Generated
/// code may need to unconditionally read a fir.box that can be absent.
/// This helper allows creating a fir.box that can be read in all cases
/// outside of a fir.if (isPresent) region. However, the usages of the value
/// read from such box should still only be done in a fir.if(isPresent).
static fir::ExtendedValue
absentBoxToUnallocatedBox(fir::FirOpBuilder &builder, mlir::Location loc,
                          const fir::ExtendedValue &exv,
                          mlir::Value isPresent) {
  mlir::Value box = fir::getBase(exv);
  mlir::Type boxType = box.getType();
  assert(mlir::isa<fir::BoxType>(boxType) && "argument must be a fir.box");
  mlir::Value emptyBox =
      fir::factory::createUnallocatedBox(builder, loc, boxType, {});
  auto safeToReadBox =
      mlir::arith::SelectOp::create(builder, loc, isPresent, box, emptyBox);
  return fir::substBase(exv, safeToReadBox);
}

// Helper to get the ultimate first symbol. This works around the fact that
// symbol resolution in the front end doesn't always resolve a symbol to its
// ultimate symbol but may leave placeholder indirections for use and host
// associations.
template <typename A>
const Fortran::semantics::Symbol &getFirstSym(const A &obj) {
  const Fortran::semantics::Symbol &sym = obj.GetFirstSymbol();
  return sym.HasLocalLocality() ? sym : sym.GetUltimate();
}

// Helper to get the ultimate last symbol.
template <typename A>
const Fortran::semantics::Symbol &getLastSym(const A &obj) {
  const Fortran::semantics::Symbol &sym = obj.GetLastSymbol();
  return sym.HasLocalLocality() ? sym : sym.GetUltimate();
}

// Return true if TRANSPOSE should be lowered without a runtime call.
static bool
isTransposeOptEnabled(const Fortran::lower::AbstractConverter &converter) {
  return optimizeTranspose &&
         converter.getLoweringOptions().getOptimizeTranspose();
}

// A set of visitors to detect if the given expression
// is a TRANSPOSE call that should be lowered without using
// runtime TRANSPOSE implementation.
template <typename T>
static bool isOptimizableTranspose(const T &,
                                   const Fortran::lower::AbstractConverter &) {
  return false;
}

static bool
isOptimizableTranspose(const Fortran::evaluate::ProcedureRef &procRef,
                       const Fortran::lower::AbstractConverter &converter) {
  const Fortran::evaluate::SpecificIntrinsic *intrin =
      procRef.proc().GetSpecificIntrinsic();
  if (isTransposeOptEnabled(converter) && intrin &&
      intrin->name == "transpose") {
    const std::optional<Fortran::evaluate::ActualArgument> matrix =
        procRef.arguments().at(0);
    return !(matrix && matrix->GetType() && matrix->GetType()->IsPolymorphic());
  }
  return false;
}

template <typename T>
static bool
isOptimizableTranspose(const Fortran::evaluate::FunctionRef<T> &funcRef,
                       const Fortran::lower::AbstractConverter &converter) {
  return isOptimizableTranspose(
      static_cast<const Fortran::evaluate::ProcedureRef &>(funcRef), converter);
}

template <typename T>
static bool
isOptimizableTranspose(Fortran::evaluate::Expr<T> expr,
                       const Fortran::lower::AbstractConverter &converter) {
  // If optimizeTranspose is not enabled, return false right away.
  if (!isTransposeOptEnabled(converter))
    return false;

  return Fortran::common::visit(
      [&](const auto &e) { return isOptimizableTranspose(e, converter); },
      expr.u);
}

namespace {

/// Lowering of Fortran::evaluate::Expr<T> expressions
class ScalarExprLowering {
public:
  using ExtValue = fir::ExtendedValue;

  explicit ScalarExprLowering(mlir::Location loc,
                              Fortran::lower::AbstractConverter &converter,
                              Fortran::lower::SymMap &symMap,
                              Fortran::lower::StatementContext &stmtCtx,
                              bool inInitializer = false)
      : location{loc}, converter{converter},
        builder{converter.getFirOpBuilder()}, stmtCtx{stmtCtx}, symMap{symMap},
        inInitializer{inInitializer} {}

  ExtValue genExtAddr(const Fortran::lower::SomeExpr &expr) {
    return gen(expr);
  }

  /// Lower `expr` to be passed as a fir.box argument. Do not create a temp
  /// for the expr if it is a variable that can be described as a fir.box.
  ExtValue genBoxArg(const Fortran::lower::SomeExpr &expr) {
    bool saveUseBoxArg = useBoxArg;
    useBoxArg = true;
    ExtValue result = gen(expr);
    useBoxArg = saveUseBoxArg;
    return result;
  }

  ExtValue genExtValue(const Fortran::lower::SomeExpr &expr) {
    return genval(expr);
  }

  /// Lower an expression that is a pointer or an allocatable to a
  /// MutableBoxValue.
  fir::MutableBoxValue
  genMutableBoxValue(const Fortran::lower::SomeExpr &expr) {
    // Pointers and allocatables can only be:
    //    - a simple designator "x"
    //    - a component designator "a%b(i,j)%x"
    //    - a function reference "foo()"
    //    - 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 = Fortran::common::visit(
        [&](const auto &x) { return genMutableBoxValueImpl(x); }, expr.u);
    const fir::MutableBoxValue *mutableBox =
        exv.getBoxOf<fir::MutableBoxValue>();
    if (!mutableBox)
      fir::emitFatalError(getLoc(), "expr was not lowered to MutableBoxValue");
    return *mutableBox;
  }

  template <typename T>
  ExtValue genMutableBoxValueImpl(const T &) {
    // NULL() case should not be handled here.
    fir::emitFatalError(getLoc(), "NULL() must be lowered in its context");
  }

  /// A `NULL()` in a position where a mutable box is expected has the same
  /// semantics as an absent optional box value. Note: this code should
  /// be depreciated because the rank information is not known here. A
  /// scalar fir.box is created: it should not be cast to an array box type
  /// later, but there is no way to enforce that here.
  ExtValue genMutableBoxValueImpl(const Fortran::evaluate::NullPointer &) {
    mlir::Location loc = getLoc();
    mlir::Type noneTy = mlir::NoneType::get(builder.getContext());
    mlir::Type polyRefTy = fir::PointerType::get(noneTy);
    mlir::Type boxType = fir::BoxType::get(polyRefTy);
    mlir::Value tempBox =
        fir::factory::genNullBoxStorage(builder, loc, boxType);
    return fir::MutableBoxValue(tempBox,
                                /*lenParameters=*/mlir::ValueRange{},
                                /*mutableProperties=*/{});
  }

  template <typename T>
  ExtValue
  genMutableBoxValueImpl(const Fortran::evaluate::FunctionRef<T> &funRef) {
    return genRawProcedureRef(funRef, converter.genType(toEvExpr(funRef)));
  }

  template <typename T>
  ExtValue
  genMutableBoxValueImpl(const Fortran::evaluate::Designator<T> &designator) {
    return Fortran::common::visit(
        Fortran::common::visitors{
            [&](const Fortran::evaluate::SymbolRef &sym) -> ExtValue {
              return converter.getSymbolExtendedValue(*sym, &symMap);
            },
            [&](const Fortran::evaluate::Component &comp) -> ExtValue {
              return genComponent(comp);
            },
            [&](const auto &) -> ExtValue {
              fir::emitFatalError(getLoc(),
                                  "not an allocatable or pointer designator");
            }},
        designator.u);
  }

  template <typename T>
  ExtValue genMutableBoxValueImpl(const Fortran::evaluate::Expr<T> &expr) {
    return Fortran::common::visit(
        [&](const auto &x) { return genMutableBoxValueImpl(x); }, expr.u);
  }

  mlir::Location getLoc() { return location; }

  template <typename A>
  mlir::Value genunbox(const A &expr) {
    ExtValue e = genval(expr);
    if (const fir::UnboxedValue *r = e.getUnboxed())
      return *r;
    fir::emitFatalError(getLoc(), "unboxed expression expected");
  }

  /// Generate an integral constant of `value`
  template <int KIND>
  mlir::Value genIntegerConstant(mlir::MLIRContext *context,
                                 std::int64_t value) {
    mlir::Type type =
        converter.genType(Fortran::common::TypeCategory::Integer, KIND);
    return builder.createIntegerConstant(getLoc(), type, value);
  }

  /// Generate a logical/boolean constant of `value`
  mlir::Value genBoolConstant(bool value) {
    return builder.createBool(getLoc(), value);
  }

  mlir::Type getSomeKindInteger() { return builder.getIndexType(); }

  mlir::func::FuncOp getFunction(llvm::StringRef name,
                                 mlir::FunctionType funTy) {
    if (mlir::func::FuncOp func = builder.getNamedFunction(name))
      return func;
    return builder.createFunction(getLoc(), name, funTy);
  }

  template <typename OpTy>
  mlir::Value createCompareOp(mlir::arith::CmpIPredicate pred,
                              const ExtValue &left, const ExtValue &right,
                              std::optional<int> unsignedKind = std::nullopt) {
    if (const fir::UnboxedValue *lhs = left.getUnboxed()) {
      if (const fir::UnboxedValue *rhs = right.getUnboxed()) {
        auto loc = getLoc();
        if (unsignedKind) {
          mlir::Type signlessType = converter.genType(
              Fortran::common::TypeCategory::Integer, *unsignedKind);
          mlir::Value lhsSL = builder.createConvert(loc, signlessType, *lhs);
          mlir::Value rhsSL = builder.createConvert(loc, signlessType, *rhs);
          return OpTy::create(builder, loc, pred, lhsSL, rhsSL);
        }
        return OpTy::create(builder, loc, pred, *lhs, *rhs);
      }
    }
    fir::emitFatalError(getLoc(), "array compare should be handled in genarr");
  }
  template <typename OpTy, typename A>
  mlir::Value createCompareOp(const A &ex, mlir::arith::CmpIPredicate pred,
                              std::optional<int> unsignedKind = std::nullopt) {
    ExtValue left = genval(ex.left());
    return createCompareOp<OpTy>(pred, left, genval(ex.right()), unsignedKind);
  }

  template <typename OpTy>
  mlir::Value createFltCmpOp(mlir::arith::CmpFPredicate pred,
                             const ExtValue &left, const ExtValue &right) {
    if (const fir::UnboxedValue *lhs = left.getUnboxed())
      if (const fir::UnboxedValue *rhs = right.getUnboxed())
        return OpTy::create(builder, getLoc(), pred, *lhs, *rhs);
    fir::emitFatalError(getLoc(), "array compare should be handled in genarr");
  }
  template <typename OpTy, typename A>
  mlir::Value createFltCmpOp(const A &ex, mlir::arith::CmpFPredicate pred) {
    ExtValue left = genval(ex.left());
    return createFltCmpOp<OpTy>(pred, left, genval(ex.right()));
  }

  /// Create a call to the runtime to compare two CHARACTER values.
  /// Precondition: This assumes that the two values have `fir.boxchar` type.
  mlir::Value createCharCompare(mlir::arith::CmpIPredicate pred,
                                const ExtValue &left, const ExtValue &right) {
    return fir::runtime::genCharCompare(builder, getLoc(), pred, left, right);
  }

  template <typename A>
  mlir::Value createCharCompare(const A &ex, mlir::arith::CmpIPredicate pred) {
    ExtValue left = genval(ex.left());
    return createCharCompare(pred, left, genval(ex.right()));
  }

  /// Returns a reference to a symbol or its box/boxChar descriptor if it has
  /// one.
  ExtValue gen(Fortran::semantics::SymbolRef sym) {
    fir::ExtendedValue exv = converter.getSymbolExtendedValue(sym, &symMap);
    if (const auto *box = exv.getBoxOf<fir::MutableBoxValue>())
      return fir::factory::genMutableBoxRead(builder, getLoc(), *box);
    return exv;
  }

  ExtValue genLoad(const ExtValue &exv) {
    return ::genLoad(builder, getLoc(), exv);
  }

  ExtValue genval(Fortran::semantics::SymbolRef sym) {
    mlir::Location loc = getLoc();
    ExtValue var = gen(sym);
    if (const fir::UnboxedValue *s = var.getUnboxed()) {
      if (fir::isa_ref_type(s->getType())) {
        // A function with multiple entry points returning different types
        // tags all result variables with one of the largest types to allow
        // them to share the same storage.  A reference to a result variable
        // of one of the other types requires conversion to the actual type.
        fir::UnboxedValue addr = *s;
        if (Fortran::semantics::IsFunctionResult(sym)) {
          mlir::Type resultType = converter.genType(*sym);
          if (addr.getType() != resultType)
            addr = builder.createConvert(loc, builder.getRefType(resultType),
                                         addr);
        } else if (sym->test(Fortran::semantics::Symbol::Flag::CrayPointee)) {
          // get the corresponding Cray pointer
          Fortran::semantics::SymbolRef ptrSym{
              Fortran::semantics::GetCrayPointer(sym)};
          ExtValue ptr = gen(ptrSym);
          mlir::Value ptrVal = fir::getBase(ptr);
          mlir::Type ptrTy = converter.genType(*ptrSym);

          ExtValue pte = gen(sym);
          mlir::Value pteVal = fir::getBase(pte);

          mlir::Value cnvrt = Fortran::lower::addCrayPointerInst(
              loc, builder, ptrVal, ptrTy, pteVal.getType());
          addr = fir::LoadOp::create(builder, loc, cnvrt);
        }
        return genLoad(addr);
      }
    }
    return var;
  }

  ExtValue genval(const Fortran::evaluate::BOZLiteralConstant &) {
    TODO(getLoc(), "BOZ");
  }

  /// Return indirection to function designated in ProcedureDesignator.
  /// The type of the function indirection is not guaranteed to match the one
  /// of the ProcedureDesignator due to Fortran implicit typing rules.
  ExtValue genval(const Fortran::evaluate::ProcedureDesignator &proc) {
    return Fortran::lower::convertProcedureDesignator(getLoc(), converter, proc,
                                                      symMap, stmtCtx);
  }
  ExtValue genval(const Fortran::evaluate::NullPointer &) {
    return builder.createNullConstant(getLoc());
  }

  static bool
  isDerivedTypeWithLenParameters(const Fortran::semantics::Symbol &sym) {
    if (const Fortran::semantics::DeclTypeSpec *declTy = sym.GetType())
      if (const Fortran::semantics::DerivedTypeSpec *derived =
              declTy->AsDerived())
        return Fortran::semantics::CountLenParameters(*derived) > 0;
    return false;
  }

  /// A structure constructor is lowered two ways. In an initializer context,
  /// the entire structure must be constant, so the aggregate value is
  /// constructed inline. This allows it to be the body of a GlobalOp.
  /// Otherwise, the structure constructor is in an expression. In that case, a
  /// temporary object is constructed in the stack frame of the procedure.
  ExtValue genval(const Fortran::evaluate::StructureConstructor &ctor) {
    mlir::Location loc = getLoc();
    if (inInitializer)
      return Fortran::lower::genInlinedStructureCtorLit(converter, loc, ctor);
    mlir::Type ty = translateSomeExprToFIRType(converter, toEvExpr(ctor));
    auto recTy = mlir::cast<fir::RecordType>(ty);
    auto fieldTy = fir::FieldType::get(ty.getContext());
    mlir::Value res = builder.createTemporary(loc, recTy);
    mlir::Value box = builder.createBox(loc, fir::ExtendedValue{res});
    fir::runtime::genDerivedTypeInitialize(builder, loc, box);

    for (const auto &value : ctor.values()) {
      const Fortran::semantics::Symbol &sym = *value.first;
      const Fortran::lower::SomeExpr &expr = value.second.value();
      if (sym.test(Fortran::semantics::Symbol::Flag::ParentComp)) {
        ExtValue from = gen(expr);
        mlir::Type fromTy = fir::unwrapPassByRefType(
            fir::unwrapRefType(fir::getBase(from).getType()));
        mlir::Value resCast =
            builder.createConvert(loc, builder.getRefType(fromTy), res);
        fir::factory::genRecordAssignment(builder, loc, resCast, from);
        continue;
      }

      if (isDerivedTypeWithLenParameters(sym))
        TODO(loc, "component with length parameters in structure constructor");

      std::string name = converter.getRecordTypeFieldName(sym);
      // FIXME: type parameters must come from the derived-type-spec
      mlir::Value field =
          fir::FieldIndexOp::create(builder, loc, fieldTy, name, ty,
                                    /*typeParams=*/mlir::ValueRange{} /*TODO*/);
      mlir::Type coorTy = builder.getRefType(recTy.getType(name));
      auto coor = fir::CoordinateOp::create(builder, loc, coorTy,
                                            fir::getBase(res), field);
      ExtValue to = fir::factory::componentToExtendedValue(builder, loc, coor);
      to.match(
          [&](const fir::UnboxedValue &toPtr) {
            ExtValue value = genval(expr);
            fir::factory::genScalarAssignment(builder, loc, to, value);
          },
          [&](const fir::CharBoxValue &) {
            ExtValue value = genval(expr);
            fir::factory::genScalarAssignment(builder, loc, to, value);
          },
          [&](const fir::ArrayBoxValue &) {
            Fortran::lower::createSomeArrayAssignment(converter, to, expr,
                                                      symMap, stmtCtx);
          },
          [&](const fir::CharArrayBoxValue &) {
            Fortran::lower::createSomeArrayAssignment(converter, to, expr,
                                                      symMap, stmtCtx);
          },
          [&](const fir::BoxValue &toBox) {
            fir::emitFatalError(loc, "derived type components must not be "
                                     "represented by fir::BoxValue");
          },
          [&](const fir::PolymorphicValue &) {
            TODO(loc, "polymorphic component in derived type assignment");
          },
          [&](const fir::MutableBoxValue &toBox) {
            if (toBox.isPointer()) {
              Fortran::lower::associateMutableBox(
                  converter, loc, toBox, expr,
                  /*lbounds=*/mlir::ValueRange{}, stmtCtx);
              return;
            }
            // For allocatable components, a deep copy is needed.
            TODO(loc, "allocatable components in derived type assignment");
          },
          [&](const fir::ProcBoxValue &toBox) {
            TODO(loc, "procedure pointer component in derived type assignment");
          });
    }
    return res;
  }

  /// Lowering of an <i>ac-do-variable</i>, which is not a Symbol.
  ExtValue genval(const Fortran::evaluate::ImpliedDoIndex &var) {
    mlir::Value value = converter.impliedDoBinding(toStringRef(var.name));
    // The index value generated by the implied-do has Index type,
    // while computations based on it inside the loop body are using
    // the original data type. So we need to cast it appropriately.
    mlir::Type varTy = converter.genType(toEvExpr(var));
    return builder.createConvert(getLoc(), varTy, value);
  }

  ExtValue genval(const Fortran::evaluate::DescriptorInquiry &desc) {
    ExtValue exv = desc.base().IsSymbol() ? gen(getLastSym(desc.base()))
                                          : gen(desc.base().GetComponent());
    mlir::IndexType idxTy = builder.getIndexType();
    mlir::Location loc = getLoc();
    auto castResult = [&](mlir::Value v) {
      using ResTy = Fortran::evaluate::DescriptorInquiry::Result;
      return builder.createConvert(
          loc, converter.genType(ResTy::category, ResTy::kind), v);
    };
    switch (desc.field()) {
    case Fortran::evaluate::DescriptorInquiry::Field::Len:
      return castResult(fir::factory::readCharLen(builder, loc, exv));
    case Fortran::evaluate::DescriptorInquiry::Field::LowerBound:
      return castResult(fir::factory::readLowerBound(
          builder, loc, exv, desc.dimension(),
          builder.createIntegerConstant(loc, idxTy, 1)));
    case Fortran::evaluate::DescriptorInquiry::Field::Extent:
      return castResult(
          fir::factory::readExtent(builder, loc, exv, desc.dimension()));
    case Fortran::evaluate::DescriptorInquiry::Field::Rank:
      TODO(loc, "rank inquiry on assumed rank");
    case Fortran::evaluate::DescriptorInquiry::Field::Stride:
      // So far the front end does not generate this inquiry.
      TODO(loc, "stride inquiry");
    }
    llvm_unreachable("unknown descriptor inquiry");
  }

  ExtValue genval(const Fortran::evaluate::TypeParamInquiry &) {
    TODO(getLoc(), "type parameter inquiry");
  }

  mlir::Value extractComplexPart(mlir::Value cplx, bool isImagPart) {
    return fir::factory::Complex{builder, getLoc()}.extractComplexPart(
        cplx, isImagPart);
  }

  template <int KIND>
  ExtValue genval(const Fortran::evaluate::ComplexComponent<KIND> &part) {
    return extractComplexPart(genunbox(part.left()), part.isImaginaryPart);
  }

  template <int KIND>
  ExtValue genval(const Fortran::evaluate::Negate<Fortran::evaluate::Type<
                      Fortran::common::TypeCategory::Integer, KIND>> &op) {
    mlir::Value input = genunbox(op.left());
    // Like LLVM, integer negation is the binary op "0 - value"
    mlir::Value zero = genIntegerConstant<KIND>(builder.getContext(), 0);
    return mlir::arith::SubIOp::create(builder, getLoc(), zero, input);
  }
  template <int KIND>
  ExtValue genval(const Fortran::evaluate::Negate<Fortran::evaluate::Type<
                      Fortran::common::TypeCategory::Unsigned, KIND>> &op) {
    auto loc = getLoc();
    mlir::Type signlessType =
        converter.genType(Fortran::common::TypeCategory::Integer, KIND);
    mlir::Value input = genunbox(op.left());
    mlir::Value signless = builder.createConvert(loc, signlessType, input);
    mlir::Value zero = genIntegerConstant<KIND>(builder.getContext(), 0);
    mlir::Value neg = mlir::arith::SubIOp::create(builder, loc, zero, signless);
    return builder.createConvert(loc, input.getType(), neg);
  }
  template <int KIND>
  ExtValue genval(const Fortran::evaluate::Negate<Fortran::evaluate::Type<
                      Fortran::common::TypeCategory::Real, KIND>> &op) {
    return mlir::arith::NegFOp::create(builder, getLoc(), genunbox(op.left()));
  }
  template <int KIND>
  ExtValue genval(const Fortran::evaluate::Negate<Fortran::evaluate::Type<
                      Fortran::common::TypeCategory::Complex, KIND>> &op) {
    return fir::NegcOp::create(builder, getLoc(), genunbox(op.left()));
  }

  template <typename OpTy>
  mlir::Value createBinaryOp(const ExtValue &left, const ExtValue &right) {
    assert(fir::isUnboxedValue(left) && fir::isUnboxedValue(right));
    mlir::Value lhs = fir::getBase(left);
    mlir::Value rhs = fir::getBase(right);
    assert(lhs.getType() == rhs.getType() && "types must be the same");
    return builder.createUnsigned<OpTy>(getLoc(), lhs.getType(), lhs, rhs);
  }

  template <typename OpTy, typename A>
  mlir::Value createBinaryOp(const A &ex) {
    ExtValue left = genval(ex.left());
    return createBinaryOp<OpTy>(left, genval(ex.right()));
  }

#undef GENBIN
#define GENBIN(GenBinEvOp, GenBinTyCat, GenBinFirOp)                           \
  template <int KIND>                                                          \
  ExtValue genval(const Fortran::evaluate::GenBinEvOp<Fortran::evaluate::Type< \
                      Fortran::common::TypeCategory::GenBinTyCat, KIND>> &x) { \
    return createBinaryOp<GenBinFirOp>(x);                                     \
  }

  GENBIN(Add, Integer, mlir::arith::AddIOp)
  GENBIN(Add, Unsigned, mlir::arith::AddIOp)
  GENBIN(Add, Real, mlir::arith::AddFOp)
  GENBIN(Add, Complex, fir::AddcOp)
  GENBIN(Subtract, Integer, mlir::arith::SubIOp)
  GENBIN(Subtract, Unsigned, mlir::arith::SubIOp)
  GENBIN(Subtract, Real, mlir::arith::SubFOp)
  GENBIN(Subtract, Complex, fir::SubcOp)
  GENBIN(Multiply, Integer, mlir::arith::MulIOp)
  GENBIN(Multiply, Unsigned, mlir::arith::MulIOp)
  GENBIN(Multiply, Real, mlir::arith::MulFOp)
  GENBIN(Multiply, Complex, fir::MulcOp)
  GENBIN(Divide, Integer, mlir::arith::DivSIOp)
  GENBIN(Divide, Unsigned, mlir::arith::DivUIOp)
  GENBIN(Divide, Real, mlir::arith::DivFOp)

  template <int KIND>
  ExtValue genval(const Fortran::evaluate::Divide<Fortran::evaluate::Type<
                      Fortran::common::TypeCategory::Complex, KIND>> &op) {
    mlir::Type ty =
        converter.genType(Fortran::common::TypeCategory::Complex, KIND);
    mlir::Value lhs = genunbox(op.left());
    mlir::Value rhs = genunbox(op.right());
    return fir::genDivC(builder, getLoc(), ty, lhs, rhs);
  }

  template <Fortran::common::TypeCategory TC, int KIND>
  ExtValue genval(
      const Fortran::evaluate::Power<Fortran::evaluate::Type<TC, KIND>> &op) {
    mlir::Type ty = converter.genType(TC, KIND);
    mlir::Value lhs = genunbox(op.left());
    mlir::Value rhs = genunbox(op.right());
    return fir::genPow(builder, getLoc(), ty, lhs, rhs);
  }

  template <Fortran::common::TypeCategory TC, int KIND>
  ExtValue genval(
      const Fortran::evaluate::RealToIntPower<Fortran::evaluate::Type<TC, KIND>>
          &op) {
    mlir::Type ty = converter.genType(TC, KIND);
    mlir::Value lhs = genunbox(op.left());
    mlir::Value rhs = genunbox(op.right());
    return fir::genPow(builder, getLoc(), ty, lhs, rhs);
  }

  template <int KIND>
  ExtValue genval(const Fortran::evaluate::ComplexConstructor<KIND> &op) {
    mlir::Value realPartValue = genunbox(op.left());
    return fir::factory::Complex{builder, getLoc()}.createComplex(
        realPartValue, genunbox(op.right()));
  }

  template <int KIND>
  ExtValue genval(const Fortran::evaluate::Concat<KIND> &op) {
    ExtValue lhs = genval(op.left());
    ExtValue rhs = genval(op.right());
    const fir::CharBoxValue *lhsChar = lhs.getCharBox();
    const fir::CharBoxValue *rhsChar = rhs.getCharBox();
    if (lhsChar && rhsChar)
      return fir::factory::CharacterExprHelper{builder, getLoc()}
          .createConcatenate(*lhsChar, *rhsChar);
    TODO(getLoc(), "character array concatenate");
  }

  /// MIN and MAX operations
  template <Fortran::common::TypeCategory TC, int KIND>
  ExtValue
  genval(const Fortran::evaluate::Extremum<Fortran::evaluate::Type<TC, KIND>>
             &op) {
    mlir::Value lhs = genunbox(op.left());
    mlir::Value rhs = genunbox(op.right());
    switch (op.ordering) {
    case Fortran::evaluate::Ordering::Greater:
      return fir::genMax(builder, getLoc(),
                         llvm::ArrayRef<mlir::Value>{lhs, rhs});
    case Fortran::evaluate::Ordering::Less:
      return fir::genMin(builder, getLoc(),
                         llvm::ArrayRef<mlir::Value>{lhs, rhs});
    case Fortran::evaluate::Ordering::Equal:
      llvm_unreachable("Equal is not a valid ordering in this context");
    }
    llvm_unreachable("unknown ordering");
  }

  // Change the dynamic length information without actually changing the
  // underlying character storage.
  fir::ExtendedValue
  replaceScalarCharacterLength(const fir::ExtendedValue &scalarChar,
                               mlir::Value newLenValue) {
    mlir::Location loc = getLoc();
    const fir::CharBoxValue *charBox = scalarChar.getCharBox();
    if (!charBox)
      fir::emitFatalError(loc, "expected scalar character");
    mlir::Value charAddr = charBox->getAddr();
    auto charType = mlir::cast<fir::CharacterType>(
        fir::unwrapPassByRefType(charAddr.getType()));
    if (charType.hasConstantLen()) {
      // Erase previous constant length from the base type.
      fir::CharacterType::LenType newLen = fir::CharacterType::unknownLen();
      mlir::Type newCharTy = fir::CharacterType::get(
          builder.getContext(), charType.getFKind(), newLen);
      mlir::Type newType = fir::ReferenceType::get(newCharTy);
      charAddr = builder.createConvert(loc, newType, charAddr);
      return fir::CharBoxValue{charAddr, newLenValue};
    }
    return fir::CharBoxValue{charAddr, newLenValue};
  }

  template <int KIND>
  ExtValue genval(const Fortran::evaluate::SetLength<KIND> &x) {
    mlir::Value newLenValue = genunbox(x.right());
    fir::ExtendedValue lhs = gen(x.left());
    fir::factory::CharacterExprHelper charHelper(builder, getLoc());
    fir::CharBoxValue temp = charHelper.createCharacterTemp(
        charHelper.getCharacterType(fir::getBase(lhs).getType()), newLenValue);
    charHelper.createAssign(temp, lhs);
    return fir::ExtendedValue{temp};
  }

  template <int KIND>
  ExtValue genval(const Fortran::evaluate::Relational<Fortran::evaluate::Type<
                      Fortran::common::TypeCategory::Integer, KIND>> &op) {
    return createCompareOp<mlir::arith::CmpIOp>(
        op, translateSignedRelational(op.opr));
  }
  template <int KIND>
  ExtValue genval(const Fortran::evaluate::Relational<Fortran::evaluate::Type<
                      Fortran::common::TypeCategory::Unsigned, KIND>> &op) {
    return createCompareOp<mlir::arith::CmpIOp>(
        op, translateUnsignedRelational(op.opr), KIND);
  }
  template <int KIND>
  ExtValue genval(const Fortran::evaluate::Relational<Fortran::evaluate::Type<
                      Fortran::common::TypeCategory::Real, KIND>> &op) {
    return createFltCmpOp<mlir::arith::CmpFOp>(
        op, translateFloatRelational(op.opr));
  }
  template <int KIND>
  ExtValue genval(const Fortran::evaluate::Relational<Fortran::evaluate::Type<
                      Fortran::common::TypeCategory::Complex, KIND>> &op) {
    return createFltCmpOp<fir::CmpcOp>(op, translateFloatRelational(op.opr));
  }
  template <int KIND>
  ExtValue genval(const Fortran::evaluate::Relational<Fortran::evaluate::Type<
                      Fortran::common::TypeCategory::Character, KIND>> &op) {
    return createCharCompare(op, translateSignedRelational(op.opr));
  }

  ExtValue
  genval(const Fortran::evaluate::Relational<Fortran::evaluate::SomeType> &op) {
    return Fortran::common::visit([&](const auto &x) { return genval(x); },
                                  op.u);
  }

  template <Fortran::common::TypeCategory TC1, int KIND,
            Fortran::common::TypeCategory TC2>
  ExtValue
  genval(const Fortran::evaluate::Convert<Fortran::evaluate::Type<TC1, KIND>,
                                          TC2> &convert) {
    mlir::Type ty = converter.genType(TC1, KIND);
    auto fromExpr = genval(convert.left());
    auto loc = getLoc();
    return fromExpr.match(
        [&](const fir::CharBoxValue &boxchar) -> ExtValue {
          if constexpr (TC1 == Fortran::common::TypeCategory::Character &&
                        TC2 == TC1) {
            return fir::factory::convertCharacterKind(builder, loc, boxchar,
                                                      KIND);
          } else {
            fir::emitFatalError(
                loc, "unsupported evaluate::Convert between CHARACTER type "
                     "category and non-CHARACTER category");
          }
        },
        [&](const fir::UnboxedValue &value) -> ExtValue {
          return builder.convertWithSemantics(loc, ty, value);
        },
        [&](auto &) -> ExtValue {
          fir::emitFatalError(loc, "unsupported evaluate::Convert");
        });
  }

  template <typename A>
  ExtValue genval(const Fortran::evaluate::Parentheses<A> &op) {
    ExtValue input = genval(op.left());
    mlir::Value base = fir::getBase(input);
    mlir::Value newBase =
        fir::NoReassocOp::create(builder, getLoc(), base.getType(), base);
    return fir::substBase(input, newBase);
  }

  template <int KIND>
  ExtValue genval(const Fortran::evaluate::Not<KIND> &op) {
    mlir::Value logical = genunbox(op.left());
    mlir::Value one = genBoolConstant(true);
    mlir::Value val =
        builder.createConvert(getLoc(), builder.getI1Type(), logical);
    return mlir::arith::XOrIOp::create(builder, getLoc(), val, one);
  }

  template <int KIND>
  ExtValue genval(const Fortran::evaluate::LogicalOperation<KIND> &op) {
    mlir::IntegerType i1Type = builder.getI1Type();
    mlir::Value slhs = genunbox(op.left());
    mlir::Value srhs = genunbox(op.right());
    mlir::Value lhs = builder.createConvert(getLoc(), i1Type, slhs);
    mlir::Value rhs = builder.createConvert(getLoc(), i1Type, srhs);
    switch (op.logicalOperator) {
    case Fortran::evaluate::LogicalOperator::And:
      return createBinaryOp<mlir::arith::AndIOp>(lhs, rhs);
    case Fortran::evaluate::LogicalOperator::Or:
      return createBinaryOp<mlir::arith::OrIOp>(lhs, rhs);
    case Fortran::evaluate::LogicalOperator::Eqv:
      return createCompareOp<mlir::arith::CmpIOp>(
          mlir::arith::CmpIPredicate::eq, lhs, rhs);
    case Fortran::evaluate::LogicalOperator::Neqv:
      return createCompareOp<mlir::arith::CmpIOp>(
          mlir::arith::CmpIPredicate::ne, lhs, rhs);
    case Fortran::evaluate::LogicalOperator::Not:
      // lib/evaluate expression for .NOT. is Fortran::evaluate::Not<KIND>.
      llvm_unreachable(".NOT. is not a binary operator");
    }
    llvm_unreachable("unhandled logical operation");
  }

  template <Fortran::common::TypeCategory TC, int KIND>
  ExtValue
  genval(const Fortran::evaluate::Constant<Fortran::evaluate::Type<TC, KIND>>
             &con) {
    return Fortran::lower::convertConstant(
        converter, getLoc(), con,
        /*outlineBigConstantsInReadOnlyMemory=*/!inInitializer);
  }

  fir::ExtendedValue genval(
      const Fortran::evaluate::Constant<Fortran::evaluate::SomeDerived> &con) {
    if (auto ctor = con.GetScalarValue())
      return genval(*ctor);
    return Fortran::lower::convertConstant(
        converter, getLoc(), con,
        /*outlineBigConstantsInReadOnlyMemory=*/false);
  }

  template <typename A>
  ExtValue genval(const Fortran::evaluate::ArrayConstructor<A> &) {
    fir::emitFatalError(getLoc(), "array constructor: should not reach here");
  }

  ExtValue gen(const Fortran::evaluate::ComplexPart &x) {
    mlir::Location loc = getLoc();
    auto idxTy = builder.getI32Type();
    ExtValue exv = gen(x.complex());
    mlir::Value base = fir::getBase(exv);
    fir::factory::Complex helper{builder, loc};
    mlir::Type eleTy =
        helper.getComplexPartType(fir::dyn_cast_ptrEleTy(base.getType()));
    mlir::Value offset = builder.createIntegerConstant(
        loc, idxTy,
        x.part() == Fortran::evaluate::ComplexPart::Part::RE ? 0 : 1);
    mlir::Value result =
        fir::CoordinateOp::create(builder, loc, builder.getRefType(eleTy), base,
                                  mlir::ValueRange{offset});
    return {result};
  }
  ExtValue genval(const Fortran::evaluate::ComplexPart &x) {
    return genLoad(gen(x));
  }

  /// Reference to a substring.
  ExtValue gen(const Fortran::evaluate::Substring &s) {
    // Get base string
    auto baseString = Fortran::common::visit(
        Fortran::common::visitors{
            [&](const Fortran::evaluate::DataRef &x) { return gen(x); },
            [&](const Fortran::evaluate::StaticDataObject::Pointer &p)
                -> ExtValue {
              if (std::optional<std::string> str = p->AsString())
                return fir::factory::createStringLiteral(builder, getLoc(),
                                                         *str);
              // TODO: convert StaticDataObject to Constant<T> and use normal
              // constant path. Beware that StaticDataObject data() takes into
              // account build machine endianness.
              TODO(getLoc(),
                   "StaticDataObject::Pointer substring with kind > 1");
            },
        },
        s.parent());
    llvm::SmallVector<mlir::Value> bounds;
    mlir::Value lower = genunbox(s.lower());
    bounds.push_back(lower);
    if (Fortran::evaluate::MaybeExtentExpr upperBound = s.upper()) {
      mlir::Value upper = genunbox(*upperBound);
      bounds.push_back(upper);
    }
    fir::factory::CharacterExprHelper charHelper{builder, getLoc()};
    return baseString.match(
        [&](const fir::CharBoxValue &x) -> ExtValue {
          return charHelper.createSubstring(x, bounds);
        },
        [&](const fir::CharArrayBoxValue &) -> ExtValue {
          fir::emitFatalError(
              getLoc(),
              "array substring should be handled in array expression");
        },
        [&](const auto &) -> ExtValue {
          fir::emitFatalError(getLoc(), "substring base is not a CharBox");
        });
  }

  /// The value of a substring.
  ExtValue genval(const Fortran::evaluate::Substring &ss) {
    // FIXME: why is the value of a substring being lowered the same as the
    // address of a substring?
    return gen(ss);
  }

  ExtValue genval(const Fortran::evaluate::Subscript &subs) {
    if (auto *s = std::get_if<Fortran::evaluate::IndirectSubscriptIntegerExpr>(
            &subs.u)) {
      if (s->value().Rank() > 0)
        fir::emitFatalError(getLoc(), "vector subscript is not scalar");
      return {genval(s->value())};
    }
    fir::emitFatalError(getLoc(), "subscript triple notation is not scalar");
  }
  ExtValue genSubscript(const Fortran::evaluate::Subscript &subs) {
    return genval(subs);
  }

  ExtValue gen(const Fortran::evaluate::DataRef &dref) {
    return Fortran::common::visit([&](const auto &x) { return gen(x); },
                                  dref.u);
  }
  ExtValue genval(const Fortran::evaluate::DataRef &dref) {
    return Fortran::common::visit([&](const auto &x) { return genval(x); },
                                  dref.u);
  }

  // Helper function to turn the Component structure into a list of nested
  // components, ordered from largest/leftmost to smallest/rightmost:
  //  - where only the smallest/rightmost item may be allocatable or a pointer
  //    (nested allocatable/pointer components require nested coordinate_of ops)
  //  - that does not contain any parent components
  //    (the front end places parent components directly in the object)
  // Return the object used as the base coordinate for the component chain.
  static Fortran::evaluate::DataRef const *
  reverseComponents(const Fortran::evaluate::Component &cmpt,
                    std::list<const Fortran::evaluate::Component *> &list) {
    if (!getLastSym(cmpt).test(Fortran::semantics::Symbol::Flag::ParentComp))
      list.push_front(&cmpt);
    return Fortran::common::visit(
        Fortran::common::visitors{
            [&](const Fortran::evaluate::Component &x) {
              if (Fortran::semantics::IsAllocatableOrPointer(getLastSym(x)))
                return &cmpt.base();
              return reverseComponents(x, list);
            },
            [&](auto &) { return &cmpt.base(); },
        },
        cmpt.base().u);
  }

  // Return the coordinate of the component reference
  ExtValue genComponent(const Fortran::evaluate::Component &cmpt) {
    std::list<const Fortran::evaluate::Component *> list;
    const Fortran::evaluate::DataRef *base = reverseComponents(cmpt, list);
    llvm::SmallVector<mlir::Value> coorArgs;
    ExtValue obj = gen(*base);
    mlir::Type ty = fir::dyn_cast_ptrOrBoxEleTy(fir::getBase(obj).getType());
    mlir::Location loc = getLoc();
    auto fldTy = fir::FieldType::get(&converter.getMLIRContext());
    // FIXME: need to thread the LEN type parameters here.
    for (const Fortran::evaluate::Component *field : list) {
      auto recTy = mlir::cast<fir::RecordType>(ty);
      const Fortran::semantics::Symbol &sym = getLastSym(*field);
      std::string name = converter.getRecordTypeFieldName(sym);
      coorArgs.push_back(fir::FieldIndexOp::create(
          builder, loc, fldTy, name, recTy, fir::getTypeParams(obj)));
      ty = recTy.getType(name);
    }
    // If parent component is referred then it has no coordinate argument.
    if (coorArgs.size() == 0)
      return obj;
    ty = builder.getRefType(ty);
    return fir::factory::componentToExtendedValue(
        builder, loc,
        fir::CoordinateOp::create(builder, loc, ty, fir::getBase(obj),
                                  coorArgs));
  }

  ExtValue gen(const Fortran::evaluate::Component &cmpt) {
    // Components may be pointer or allocatable. In the gen() path, the mutable
    // aspect is lost to simplify handling on the client side. To retain the
    // mutable aspect, genMutableBoxValue should be used.
    return genComponent(cmpt).match(
        [&](const fir::MutableBoxValue &mutableBox) {
          return fir::factory::genMutableBoxRead(builder, getLoc(), mutableBox);
        },
        [](auto &box) -> ExtValue { return box; });
  }

  ExtValue genval(const Fortran::evaluate::Component &cmpt) {
    return genLoad(gen(cmpt));
  }

  // Determine the result type after removing `dims` dimensions from the array
  // type `arrTy`
  mlir::Type genSubType(mlir::Type arrTy, unsigned dims) {
    mlir::Type unwrapTy = fir::dyn_cast_ptrOrBoxEleTy(arrTy);
    assert(unwrapTy && "must be a pointer or box type");
    auto seqTy = mlir::cast<fir::SequenceType>(unwrapTy);
    llvm::ArrayRef<int64_t> shape = seqTy.getShape();
    assert(shape.size() > 0 && "removing columns for sequence sans shape");
    assert(dims <= shape.size() && "removing more columns than exist");
    fir::SequenceType::Shape newBnds;
    // follow Fortran semantics and remove columns (from right)
    std::size_t e = shape.size() - dims;
    for (decltype(e) i = 0; i < e; ++i)
      newBnds.push_back(shape[i]);
    if (!newBnds.empty())
      return fir::SequenceType::get(newBnds, seqTy.getEleTy());
    return seqTy.getEleTy();
  }

  // Generate the code for a Bound value.
  ExtValue genval(const Fortran::semantics::Bound &bound) {
    if (bound.isExplicit()) {
      Fortran::semantics::MaybeSubscriptIntExpr sub = bound.GetExplicit();
      if (sub.has_value())
        return genval(*sub);
      return genIntegerConstant<8>(builder.getContext(), 1);
    }
    TODO(getLoc(), "non explicit semantics::Bound implementation");
  }

  static bool isSlice(const Fortran::evaluate::ArrayRef &aref) {
    for (const Fortran::evaluate::Subscript &sub : aref.subscript())
      if (std::holds_alternative<Fortran::evaluate::Triplet>(sub.u))
        return true;
    return false;
  }

  /// Lower an ArrayRef to a fir.coordinate_of given its lowered base.
  ExtValue genCoordinateOp(const ExtValue &array,
                           const Fortran::evaluate::ArrayRef &aref) {
    mlir::Location loc = getLoc();
    // References to array of rank > 1 with non constant shape that are not
    // fir.box must be collapsed into an offset computation in lowering already.
    // The same is needed with dynamic length character arrays of all ranks.
    mlir::Type baseType =
        fir::dyn_cast_ptrOrBoxEleTy(fir::getBase(array).getType());
    if ((array.rank() > 1 && fir::hasDynamicSize(baseType)) ||
        fir::characterWithDynamicLen(fir::unwrapSequenceType(baseType)))
      if (!array.getBoxOf<fir::BoxValue>())
        return genOffsetAndCoordinateOp(array, aref);
    // Generate a fir.coordinate_of with zero based array indexes.
    llvm::SmallVector<mlir::Value> args;
    for (const auto &subsc : llvm::enumerate(aref.subscript())) {
      ExtValue subVal = genSubscript(subsc.value());
      assert(fir::isUnboxedValue(subVal) && "subscript must be simple scalar");
      mlir::Value val = fir::getBase(subVal);
      mlir::Type ty = val.getType();
      mlir::Value lb = getLBound(array, subsc.index(), ty);
      args.push_back(mlir::arith::SubIOp::create(builder, loc, ty, val, lb));
    }
    mlir::Value base = fir::getBase(array);

    auto baseSym = getFirstSym(aref);
    if (baseSym.test(Fortran::semantics::Symbol::Flag::CrayPointee)) {
      // get the corresponding Cray pointer
      Fortran::semantics::SymbolRef ptrSym{
          Fortran::semantics::GetCrayPointer(baseSym)};
      fir::ExtendedValue ptr = gen(ptrSym);
      mlir::Value ptrVal = fir::getBase(ptr);
      mlir::Type ptrTy = ptrVal.getType();

      mlir::Value cnvrt = Fortran::lower::addCrayPointerInst(
          loc, builder, ptrVal, ptrTy, base.getType());
      base = fir::LoadOp::create(builder, loc, cnvrt);
    }

    mlir::Type eleTy = fir::dyn_cast_ptrOrBoxEleTy(base.getType());
    if (auto classTy = mlir::dyn_cast<fir::ClassType>(eleTy))
      eleTy = classTy.getEleTy();
    auto seqTy = mlir::cast<fir::SequenceType>(eleTy);
    assert(args.size() == seqTy.getDimension());
    mlir::Type ty = builder.getRefType(seqTy.getEleTy());
    auto addr = fir::CoordinateOp::create(builder, loc, ty, base, args);
    return fir::factory::arrayElementToExtendedValue(builder, loc, array, addr);
  }

  /// Lower an ArrayRef to a fir.coordinate_of using an element offset instead
  /// of array indexes.
  /// This generates offset computation from the indexes and length parameters,
  /// and use the offset to access the element with a fir.coordinate_of. This
  /// must only be used if it is not possible to generate a normal
  /// fir.coordinate_of using array indexes (i.e. when the shape information is
  /// unavailable in the IR).
  ExtValue genOffsetAndCoordinateOp(const ExtValue &array,
                                    const Fortran::evaluate::ArrayRef &aref) {
    mlir::Location loc = getLoc();
    mlir::Value addr = fir::getBase(array);
    mlir::Type arrTy = fir::dyn_cast_ptrEleTy(addr.getType());
    auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
    mlir::Type seqTy = builder.getRefType(builder.getVarLenSeqTy(eleTy));
    mlir::Type refTy = builder.getRefType(eleTy);
    mlir::Value base = builder.createConvert(loc, seqTy, addr);
    mlir::IndexType idxTy = builder.getIndexType();
    mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
    mlir::Value zero = builder.createIntegerConstant(loc, idxTy, 0);
    auto getLB = [&](const auto &arr, unsigned dim) -> mlir::Value {
      return arr.getLBounds().empty() ? one : arr.getLBounds()[dim];
    };
    auto genFullDim = [&](const auto &arr, mlir::Value delta) -> mlir::Value {
      mlir::Value total = zero;
      assert(arr.getExtents().size() == aref.subscript().size());
      delta = builder.createConvert(loc, idxTy, delta);
      unsigned dim = 0;
      for (auto [ext, sub] : llvm::zip(arr.getExtents(), aref.subscript())) {
        ExtValue subVal = genSubscript(sub);
        assert(fir::isUnboxedValue(subVal));
        mlir::Value val =
            builder.createConvert(loc, idxTy, fir::getBase(subVal));
        mlir::Value lb = builder.createConvert(loc, idxTy, getLB(arr, dim));
        mlir::Value diff = mlir::arith::SubIOp::create(builder, loc, val, lb);
        mlir::Value prod =
            mlir::arith::MulIOp::create(builder, loc, delta, diff);
        total = mlir::arith::AddIOp::create(builder, loc, prod, total);
        if (ext)
          delta = mlir::arith::MulIOp::create(builder, loc, delta, ext);
        ++dim;
      }
      mlir::Type origRefTy = refTy;
      if (fir::factory::CharacterExprHelper::isCharacterScalar(refTy)) {
        fir::CharacterType chTy =
            fir::factory::CharacterExprHelper::getCharacterType(refTy);
        if (fir::characterWithDynamicLen(chTy)) {
          mlir::MLIRContext *ctx = builder.getContext();
          fir::KindTy kind =
              fir::factory::CharacterExprHelper::getCharacterKind(chTy);
          fir::CharacterType singleTy =
              fir::CharacterType::getSingleton(ctx, kind);
          refTy = builder.getRefType(singleTy);
          mlir::Type seqRefTy =
              builder.getRefType(builder.getVarLenSeqTy(singleTy));
          base = builder.createConvert(loc, seqRefTy, base);
        }
      }
      auto coor = fir::CoordinateOp::create(builder, loc, refTy, base,
                                            llvm::ArrayRef<mlir::Value>{total});
      // Convert to expected, original type after address arithmetic.
      return builder.createConvert(loc, origRefTy, coor);
    };
    return array.match(
        [&](const fir::ArrayBoxValue &arr) -> ExtValue {
          // FIXME: this check can be removed when slicing is implemented
          if (isSlice(aref))
            fir::emitFatalError(
                getLoc(),
                "slice should be handled in array expression context");
          return genFullDim(arr, one);
        },
        [&](const fir::CharArrayBoxValue &arr) -> ExtValue {
          mlir::Value delta = arr.getLen();
          // If the length is known in the type, fir.coordinate_of will
          // already take the length into account.
          if (fir::factory::CharacterExprHelper::hasConstantLengthInType(arr))
            delta = one;
          return fir::CharBoxValue(genFullDim(arr, delta), arr.getLen());
        },
        [&](const fir::BoxValue &arr) -> ExtValue {
          // CoordinateOp for BoxValue is not generated here. The dimensions
          // must be kept in the fir.coordinate_op so that potential fir.box
          // strides can be applied by codegen.
          fir::emitFatalError(
              loc, "internal: BoxValue in dim-collapsed fir.coordinate_of");
        },
        [&](const auto &) -> ExtValue {
          fir::emitFatalError(loc, "internal: array processing failed");
        });
  }

  /// Lower an ArrayRef to a fir.array_coor.
  ExtValue genArrayCoorOp(const ExtValue &exv,
                          const Fortran::evaluate::ArrayRef &aref) {
    mlir::Location loc = getLoc();
    mlir::Value addr = fir::getBase(exv);
    mlir::Type arrTy = fir::dyn_cast_ptrOrBoxEleTy(addr.getType());
    mlir::Type eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
    mlir::Type refTy = builder.getRefType(eleTy);
    mlir::IndexType idxTy = builder.getIndexType();
    llvm::SmallVector<mlir::Value> arrayCoorArgs;
    // The ArrayRef is expected to be scalar here, arrays are handled in array
    // expression lowering. So no vector subscript or triplet is expected here.
    for (const auto &sub : aref.subscript()) {
      ExtValue subVal = genSubscript(sub);
      assert(fir::isUnboxedValue(subVal));
      arrayCoorArgs.push_back(
          builder.createConvert(loc, idxTy, fir::getBase(subVal)));
    }
    mlir::Value shape = builder.createShape(loc, exv);
    mlir::Value elementAddr = fir::ArrayCoorOp::create(
        builder, loc, refTy, addr, shape, /*slice=*/mlir::Value{},
        arrayCoorArgs, fir::getTypeParams(exv));
    return fir::factory::arrayElementToExtendedValue(builder, loc, exv,
                                                     elementAddr);
  }

  /// Return the coordinate of the array reference.
  ExtValue gen(const Fortran::evaluate::ArrayRef &aref) {
    ExtValue base = aref.base().IsSymbol() ? gen(getFirstSym(aref.base()))
                                           : gen(aref.base().GetComponent());
    // Check for command-line override to use array_coor op.
    if (generateArrayCoordinate)
      return genArrayCoorOp(base, aref);
    // Otherwise, use coordinate_of op.
    return genCoordinateOp(base, aref);
  }

  /// Return lower bounds of \p box in dimension \p dim. The returned value
  /// has type \ty.
  mlir::Value getLBound(const ExtValue &box, unsigned dim, mlir::Type ty) {
    assert(box.rank() > 0 && "must be an array");
    mlir::Location loc = getLoc();
    mlir::Value one = builder.createIntegerConstant(loc, ty, 1);
    mlir::Value lb = fir::factory::readLowerBound(builder, loc, box, dim, one);
    return builder.createConvert(loc, ty, lb);
  }

  ExtValue genval(const Fortran::evaluate::ArrayRef &aref) {
    return genLoad(gen(aref));
  }

  ExtValue gen(const Fortran::evaluate::CoarrayRef &coref) {
    return Fortran::lower::CoarrayExprHelper{converter, getLoc(), symMap}
        .genAddr(coref);
  }

  ExtValue genval(const Fortran::evaluate::CoarrayRef &coref) {
    return Fortran::lower::CoarrayExprHelper{converter, getLoc(), symMap}
        .genValue(coref);
  }

  template <typename A>
  ExtValue gen(const Fortran::evaluate::Designator<A> &des) {
    return Fortran::common::visit([&](const auto &x) { return gen(x); }, des.u);
  }
  template <typename A>
  ExtValue genval(const Fortran::evaluate::Designator<A> &des) {
    return Fortran::common::visit([&](const auto &x) { return genval(x); },
                                  des.u);
  }

  mlir::Type genType(const Fortran::evaluate::DynamicType &dt) {
    if (dt.category() != Fortran::common::TypeCategory::Derived)
      return converter.genType(dt.category(), dt.kind());
    if (dt.IsUnlimitedPolymorphic())
      return mlir::NoneType::get(&converter.getMLIRContext());
    return converter.genType(dt.GetDerivedTypeSpec());
  }

  /// Lower a function reference
  template <typename A>
  ExtValue genFunctionRef(const Fortran::evaluate::FunctionRef<A> &funcRef) {
    if (!funcRef.GetType().has_value())
      fir::emitFatalError(getLoc(), "a function must have a type");
    mlir::Type resTy = genType(*funcRef.GetType());
    return genProcedureRef(funcRef, {resTy});
  }

  /// Lower function call `funcRef` and return a reference to the resultant
  /// value. This is required for lowering expressions such as `f1(f2(v))`.
  template <typename A>
  ExtValue gen(const Fortran::evaluate::FunctionRef<A> &funcRef) {
    ExtValue retVal = genFunctionRef(funcRef);
    mlir::Type resultType = converter.genType(toEvExpr(funcRef));
    return placeScalarValueInMemory(builder, getLoc(), retVal, resultType);
  }

  /// Helper to lower intrinsic arguments for inquiry intrinsic.
  ExtValue
  lowerIntrinsicArgumentAsInquired(const Fortran::lower::SomeExpr &expr) {
    if (Fortran::evaluate::IsAllocatableOrPointerObject(expr))
      return genMutableBoxValue(expr);
    /// Do not create temps for array sections whose properties only need to be
    /// inquired: create a descriptor that will be inquired.
    if (Fortran::evaluate::IsVariable(expr) && isArray(expr) &&
        !Fortran::evaluate::UnwrapWholeSymbolOrComponentDataRef(expr))
      return lowerIntrinsicArgumentAsBox(expr);
    return gen(expr);
  }

  /// Helper to lower intrinsic arguments to a fir::BoxValue.
  /// It preserves all the non default lower bounds/non deferred length
  /// parameter information.
  ExtValue lowerIntrinsicArgumentAsBox(const Fortran::lower::SomeExpr &expr) {
    mlir::Location loc = getLoc();
    ExtValue exv = genBoxArg(expr);
    auto exvTy = fir::getBase(exv).getType();
    if (mlir::isa<mlir::FunctionType>(exvTy)) {
      auto boxProcTy =
          builder.getBoxProcType(mlir::cast<mlir::FunctionType>(exvTy));
      return fir::EmboxProcOp::create(builder, loc, boxProcTy,
                                      fir::getBase(exv));
    }
    mlir::Value box = builder.createBox(loc, exv, exv.isPolymorphic());
    if (Fortran::lower::isParentComponent(expr)) {
      fir::ExtendedValue newExv =
          Fortran::lower::updateBoxForParentComponent(converter, box, expr);
      box = fir::getBase(newExv);
    }
    return fir::BoxValue(
        box, fir::factory::getNonDefaultLowerBounds(builder, loc, exv),
        fir::factory::getNonDeferredLenParams(exv));
  }

  /// Generate a call to a Fortran intrinsic or intrinsic module procedure.
  ExtValue genIntrinsicRef(
      const Fortran::evaluate::ProcedureRef &procRef,
      std::optional<mlir::Type> resultType,
      std::optional<const Fortran::evaluate::SpecificIntrinsic> intrinsic =
          std::nullopt) {
    llvm::SmallVector<ExtValue> operands;

    std::string name =
        intrinsic ? intrinsic->name
                  : procRef.proc().GetSymbol()->GetUltimate().name().ToString();
    mlir::Location loc = getLoc();
    if (intrinsic && Fortran::lower::intrinsicRequiresCustomOptionalHandling(
                         procRef, *intrinsic, converter)) {
      using ExvAndPresence = std::pair<ExtValue, std::optional<mlir::Value>>;
      llvm::SmallVector<ExvAndPresence, 4> operands;
      auto prepareOptionalArg = [&](const Fortran::lower::SomeExpr &expr) {
        ExtValue optionalArg = lowerIntrinsicArgumentAsInquired(expr);
        mlir::Value isPresent =
            genActualIsPresentTest(builder, loc, optionalArg);
        operands.emplace_back(optionalArg, isPresent);
      };
      auto prepareOtherArg = [&](const Fortran::lower::SomeExpr &expr,
                                 fir::LowerIntrinsicArgAs lowerAs) {
        switch (lowerAs) {
        case fir::LowerIntrinsicArgAs::Value:
          operands.emplace_back(genval(expr), std::nullopt);
          return;
        case fir::LowerIntrinsicArgAs::Addr:
          operands.emplace_back(gen(expr), std::nullopt);
          return;
        case fir::LowerIntrinsicArgAs::Box:
          operands.emplace_back(lowerIntrinsicArgumentAsBox(expr),
                                std::nullopt);
          return;
        case fir::LowerIntrinsicArgAs::Inquired:
          operands.emplace_back(lowerIntrinsicArgumentAsInquired(expr),
                                std::nullopt);
          return;
        }
      };
      Fortran::lower::prepareCustomIntrinsicArgument(
          procRef, *intrinsic, resultType, prepareOptionalArg, prepareOtherArg,
          converter);

      auto getArgument = [&](std::size_t i, bool loadArg) -> ExtValue {
        if (loadArg && fir::conformsWithPassByRef(
                           fir::getBase(operands[i].first).getType()))
          return genLoad(operands[i].first);
        return operands[i].first;
      };
      auto isPresent = [&](std::size_t i) -> std::optional<mlir::Value> {
        return operands[i].second;
      };
      return Fortran::lower::lowerCustomIntrinsic(
          builder, loc, name, resultType, isPresent, getArgument,
          operands.size(), stmtCtx);
    }

    const fir::IntrinsicArgumentLoweringRules *argLowering =
        fir::getIntrinsicArgumentLowering(name);
    for (const auto &arg : llvm::enumerate(procRef.arguments())) {
      auto *expr =
          Fortran::evaluate::UnwrapExpr<Fortran::lower::SomeExpr>(arg.value());

      if (!expr && arg.value() && arg.value()->GetAssumedTypeDummy()) {
        // Assumed type optional.
        const Fortran::evaluate::Symbol *assumedTypeSym =
            arg.value()->GetAssumedTypeDummy();
        auto symBox = symMap.lookupSymbol(*assumedTypeSym);
        ExtValue exv =
            converter.getSymbolExtendedValue(*assumedTypeSym, &symMap);
        if (argLowering) {
          fir::ArgLoweringRule argRules =
              fir::lowerIntrinsicArgumentAs(*argLowering, arg.index());
          // Note: usages of TYPE(*) is limited by C710 but C_LOC and
          // IS_CONTIGUOUS may require an assumed size TYPE(*) to be passed to
          // the intrinsic library utility as a fir.box.
          if (argRules.lowerAs == fir::LowerIntrinsicArgAs::Box &&
              !mlir::isa<fir::BaseBoxType>(fir::getBase(exv).getType())) {
            operands.emplace_back(
                fir::factory::createBoxValue(builder, loc, exv));
            continue;
          }
        }
        operands.emplace_back(std::move(exv));
        continue;
      }
      if (!expr) {
        // Absent optional.
        operands.emplace_back(fir::getAbsentIntrinsicArgument());
        continue;
      }
      if (!argLowering) {
        // No argument lowering instruction, lower by value.
        operands.emplace_back(genval(*expr));
        continue;
      }
      // Ad-hoc argument lowering handling.
      fir::ArgLoweringRule argRules =
          fir::lowerIntrinsicArgumentAs(*argLowering, arg.index());
      if (argRules.handleDynamicOptional &&
          Fortran::evaluate::MayBePassedAsAbsentOptional(*expr)) {
        ExtValue optional = lowerIntrinsicArgumentAsInquired(*expr);
        mlir::Value isPresent = genActualIsPresentTest(builder, loc, optional);
        switch (argRules.lowerAs) {
        case fir::LowerIntrinsicArgAs::Value:
          operands.emplace_back(
              genOptionalValue(builder, loc, optional, isPresent));
          continue;
        case fir::LowerIntrinsicArgAs::Addr:
          operands.emplace_back(
              genOptionalAddr(builder, loc, optional, isPresent));
          continue;
        case fir::LowerIntrinsicArgAs::Box:
          operands.emplace_back(
              genOptionalBox(builder, loc, optional, isPresent));
          continue;
        case fir::LowerIntrinsicArgAs::Inquired:
          operands.emplace_back(optional);
          continue;
        }
        llvm_unreachable("bad switch");
      }
      switch (argRules.lowerAs) {
      case fir::LowerIntrinsicArgAs::Value:
        operands.emplace_back(genval(*expr));
        continue;
      case fir::LowerIntrinsicArgAs::Addr:
        operands.emplace_back(gen(*expr));
        continue;
      case fir::LowerIntrinsicArgAs::Box:
        operands.emplace_back(lowerIntrinsicArgumentAsBox(*expr));
        continue;
      case fir::LowerIntrinsicArgAs::Inquired:
        operands.emplace_back(lowerIntrinsicArgumentAsInquired(*expr));
        continue;
      }
      llvm_unreachable("bad switch");
    }
    // Let the intrinsic library lower the intrinsic procedure call
    return Fortran::lower::genIntrinsicCall(builder, getLoc(), name, resultType,
                                            operands, stmtCtx, &converter);
  }

  /// helper to detect statement functions
  static bool
  isStatementFunctionCall(const Fortran::evaluate::ProcedureRef &procRef) {
    if (const Fortran::semantics::Symbol *symbol = procRef.proc().GetSymbol())
      if (const auto *details =
              symbol->detailsIf<Fortran::semantics::SubprogramDetails>())
        return details->stmtFunction().has_value();
    return false;
  }

  /// Generate Statement function calls
  ExtValue genStmtFunctionRef(const Fortran::evaluate::ProcedureRef &procRef) {
    const Fortran::semantics::Symbol *symbol = procRef.proc().GetSymbol();
    assert(symbol && "expected symbol in ProcedureRef of statement functions");
    const auto &details = symbol->get<Fortran::semantics::SubprogramDetails>();

    // Statement functions have their own scope, we just need to associate
    // the dummy symbols to argument expressions. They are no
    // optional/alternate return arguments. Statement functions cannot be
    // recursive (directly or indirectly) so it is safe to add dummy symbols to
    // the local map here.
    symMap.pushScope();
    for (auto [arg, bind] :
         llvm::zip(details.dummyArgs(), procRef.arguments())) {
      assert(arg && "alternate return in statement function");
      assert(bind && "optional argument in statement function");
      const auto *expr = bind->UnwrapExpr();
      // TODO: assumed type in statement function, that surprisingly seems
      // allowed, probably because nobody thought of restricting this usage.
      // gfortran/ifort compiles this.
      assert(expr && "assumed type used as statement function argument");
      // As per Fortran 2018 C1580, statement function arguments can only be
      // scalars, so just pass the box with the address. The only care is to
      // to use the dummy character explicit length if any instead of the
      // actual argument length (that can be bigger).
      if (const Fortran::semantics::DeclTypeSpec *type = arg->GetType())
        if (type->category() == Fortran::semantics::DeclTypeSpec::Character)
          if (const Fortran::semantics::MaybeIntExpr &lenExpr =
                  type->characterTypeSpec().length().GetExplicit()) {
            mlir::Value len = fir::getBase(genval(*lenExpr));
            // F2018 7.4.4.2 point 5.
            len = fir::factory::genMaxWithZero(builder, getLoc(), len);
            symMap.addSymbol(*arg,
                             replaceScalarCharacterLength(gen(*expr), len));
            continue;
          }
      symMap.addSymbol(*arg, gen(*expr));
    }

    // Explicitly map statement function host associated symbols to their
    // parent scope lowered symbol box.
    for (const Fortran::semantics::SymbolRef &sym :
         Fortran::evaluate::CollectSymbols(*details.stmtFunction()))
      if (const auto *details =
              sym->detailsIf<Fortran::semantics::HostAssocDetails>())
        if (!symMap.lookupSymbol(*sym))
          symMap.addSymbol(*sym, gen(details->symbol()));

    ExtValue result = genval(details.stmtFunction().value());
    LLVM_DEBUG(llvm::dbgs() << "stmt-function: " << result << '\n');
    symMap.popScope();
    return result;
  }

  /// Create a contiguous temporary array with the same shape,
  /// length parameters and type as mold. It is up to the caller to deallocate
  /// the temporary.
  ExtValue genArrayTempFromMold(const ExtValue &mold,
                                llvm::StringRef tempName) {
    mlir::Type type = fir::dyn_cast_ptrOrBoxEleTy(fir::getBase(mold).getType());
    assert(type && "expected descriptor or memory type");
    mlir::Location loc = getLoc();
    llvm::SmallVector<mlir::Value> extents =
        fir::factory::getExtents(loc, builder, mold);
    llvm::SmallVector<mlir::Value> allocMemTypeParams =
        fir::getTypeParams(mold);
    mlir::Value charLen;
    mlir::Type elementType = fir::unwrapSequenceType(type);
    if (auto charType = mlir::dyn_cast<fir::CharacterType>(elementType)) {
      charLen = allocMemTypeParams.empty()
                    ? fir::factory::readCharLen(builder, loc, mold)
                    : allocMemTypeParams[0];
      if (charType.hasDynamicLen() && allocMemTypeParams.empty())
        allocMemTypeParams.push_back(charLen);
    } else if (fir::hasDynamicSize(elementType)) {
      TODO(loc, "creating temporary for derived type with length parameters");
    }

    mlir::Value temp = fir::AllocMemOp::create(builder, loc, type, tempName,
                                               allocMemTypeParams, extents);
    if (mlir::isa<fir::CharacterType>(fir::unwrapSequenceType(type)))
      return fir::CharArrayBoxValue{temp, charLen, extents};
    return fir::ArrayBoxValue{temp, extents};
  }

  /// Copy \p source array into \p dest array. Both arrays must be
  /// conforming, but neither array must be contiguous.
  void genArrayCopy(ExtValue dest, ExtValue source) {
    return createSomeArrayAssignment(converter, dest, source, symMap, stmtCtx);
  }

  /// Lower a non-elemental procedure reference and read allocatable and pointer
  /// results into normal values.
  ExtValue genProcedureRef(const Fortran::evaluate::ProcedureRef &procRef,
                           std::optional<mlir::Type> resultType) {
    ExtValue res = genRawProcedureRef(procRef, resultType);
    // In most contexts, pointers and allocatable do not appear as allocatable
    // or pointer variable on the caller side (see 8.5.3 note 1 for
    // allocatables). The few context where this can happen must call
    // genRawProcedureRef directly.
    if (const auto *box = res.getBoxOf<fir::MutableBoxValue>())
      return fir::factory::genMutableBoxRead(builder, getLoc(), *box);
    return res;
  }

  /// Like genExtAddr, but ensure the address returned is a temporary even if \p
  /// expr is variable inside parentheses.
  ExtValue genTempExtAddr(const Fortran::lower::SomeExpr &expr) {
    // In general, genExtAddr might not create a temp for variable inside
    // parentheses to avoid creating array temporary in sub-expressions. It only
    // ensures the sub-expression is not re-associated with other parts of the
    // expression. In the call semantics, there is a difference between expr and
    // variable (see R1524). For expressions, a variable storage must not be
    // argument associated since it could be modified inside the call, or the
    // variable could also be modified by other means during the call.
    if (!isParenthesizedVariable(expr))
      return genExtAddr(expr);
    if (expr.Rank() > 0)
      return asArray(expr);
    mlir::Location loc = getLoc();
    return genExtValue(expr).match(
        [&](const fir::CharBoxValue &boxChar) -> ExtValue {
          return fir::factory::CharacterExprHelper{builder, loc}.createTempFrom(
              boxChar);
        },
        [&](const fir::UnboxedValue &v) -> ExtValue {
          mlir::Type type = v.getType();
          mlir::Value value = v;
          if (fir::isa_ref_type(type))
            value = fir::LoadOp::create(builder, loc, value);
          mlir::Value temp = builder.createTemporary(loc, value.getType());
          fir::StoreOp::create(builder, loc, value, temp);
          return temp;
        },
        [&](const fir::BoxValue &x) -> ExtValue {
          // Derived type scalar that may be polymorphic.
          if (fir::isPolymorphicType(fir::getBase(x).getType()))
            TODO(loc, "polymorphic array temporary");
          assert(!x.hasRank() && x.isDerived());
          if (x.isDerivedWithLenParameters())
            fir::emitFatalError(
                loc, "making temps for derived type with length parameters");
          // TODO: polymorphic aspects should be kept but for now the temp
          // created always has the declared type.
          mlir::Value var =
              fir::getBase(fir::factory::readBoxValue(builder, loc, x));
          auto value = fir::LoadOp::create(builder, loc, var);
          mlir::Value temp = builder.createTemporary(loc, value.getType());
          fir::StoreOp::create(builder, loc, value, temp);
          return temp;
        },
        [&](const fir::PolymorphicValue &p) -> ExtValue {
          TODO(loc, "creating polymorphic temporary");
        },
        [&](const auto &) -> ExtValue {
          fir::emitFatalError(loc, "expr is not a scalar value");
        });
  }

  /// Helper structure to track potential copy-in of non contiguous variable
  /// argument into a contiguous temp. It is used to deallocate the temp that
  /// may have been created as well as to the copy-out from the temp to the
  /// variable after the call.
  struct CopyOutPair {
    ExtValue var;
    ExtValue temp;
    // Flag to indicate if the argument may have been modified by the
    // callee, in which case it must be copied-out to the variable.
    bool argMayBeModifiedByCall;
    // Optional boolean value that, if present and false, prevents
    // the copy-out and temp deallocation.
    std::optional<mlir::Value> restrictCopyAndFreeAtRuntime;
  };
  using CopyOutPairs = llvm::SmallVector<CopyOutPair, 4>;

  /// Helper to read any fir::BoxValue into other fir::ExtendedValue categories
  /// not based on fir.box.
  /// This will lose any non contiguous stride information and dynamic type and
  /// should only be called if \p exv is known to be contiguous or if its base
  /// address will be replaced by a contiguous one. If \p exv is not a
  /// fir::BoxValue, this is a no-op.
  ExtValue readIfBoxValue(const ExtValue &exv) {
    if (const auto *box = exv.getBoxOf<fir::BoxValue>())
      return fir::factory::readBoxValue(builder, getLoc(), *box);
    return exv;
  }

  /// Generate a contiguous temp to pass \p actualArg as argument \p arg. The
  /// creation of the temp and copy-in can be made conditional at runtime by
  /// providing a runtime boolean flag \p restrictCopyAtRuntime (in which case
  /// the temp and copy will only be made if the value is true at runtime).
  ExtValue genCopyIn(const ExtValue &actualArg,
                     const Fortran::lower::CallerInterface::PassedEntity &arg,
                     CopyOutPairs &copyOutPairs,
                     std::optional<mlir::Value> restrictCopyAtRuntime,
                     bool byValue) {
    const bool doCopyOut = !byValue && arg.mayBeModifiedByCall();
    llvm::StringRef tempName = byValue ? ".copy" : ".copyinout";
    mlir::Location loc = getLoc();
    bool isActualArgBox = fir::isa_box_type(fir::getBase(actualArg).getType());
    mlir::Value isContiguousResult;
    mlir::Type addrType = fir::HeapType::get(
        fir::unwrapPassByRefType(fir::getBase(actualArg).getType()));

    if (isActualArgBox) {
      // Check at runtime if the argument is contiguous so no copy is needed.
      isContiguousResult =
          fir::runtime::genIsContiguous(builder, loc, fir::getBase(actualArg));
    }

    auto doCopyIn = [&]() -> ExtValue {
      ExtValue temp = genArrayTempFromMold(actualArg, tempName);
      if (!arg.mayBeReadByCall() &&
          // INTENT(OUT) dummy argument finalization, automatically
          // done when the procedure is invoked, may imply reading
          // the argument value in the finalization routine.
          // So we need to make a copy, if finalization may occur.
          // TODO: do we have to avoid the copying for an actual
          // argument of type that does not require finalization?
          !arg.mayRequireIntentoutFinalization() &&
          // ALLOCATABLE dummy argument may require finalization.
          // If it has to be automatically deallocated at the end
          // of the procedure invocation (9.7.3.2 p. 2),
          // then the finalization may happen if the actual argument
          // is allocated (7.5.6.3 p. 2).
          !arg.hasAllocatableAttribute()) {
        // We have to initialize the temp if it may have components
        // that need initialization. If there are no components
        // requiring initialization, then the call is a no-op.
        if (mlir::isa<fir::RecordType>(getElementTypeOf(temp))) {
          mlir::Value tempBox = fir::getBase(builder.createBox(loc, temp));
          fir::runtime::genDerivedTypeInitialize(builder, loc, tempBox);
        }
        return temp;
      }
      if (!isActualArgBox || inlineCopyInOutForBoxes) {
        genArrayCopy(temp, actualArg);
        return temp;
      }

      // Generate AssignTemporary() call to copy data from the actualArg
      // to a temporary. AssignTemporary() will initialize the temporary,
      // if needed, before doing the assignment, which is required
      // since the temporary's components (if any) are uninitialized
      // at this point.
      mlir::Value destBox = fir::getBase(builder.createBox(loc, temp));
      mlir::Value boxRef = builder.createTemporary(loc, destBox.getType());
      fir::StoreOp::create(builder, loc, destBox, boxRef);
      fir::runtime::genAssignTemporary(builder, loc, boxRef,
                                       fir::getBase(actualArg));
      return temp;
    };

    auto noCopy = [&]() {
      mlir::Value box = fir::getBase(actualArg);
      mlir::Value boxAddr = fir::BoxAddrOp::create(builder, loc, addrType, box);
      fir::ResultOp::create(builder, loc, boxAddr);
    };

    auto combinedCondition = [&]() {
      if (isActualArgBox) {
        mlir::Value zero =
            builder.createIntegerConstant(loc, builder.getI1Type(), 0);
        mlir::Value notContiguous = mlir::arith::CmpIOp::create(
            builder, loc, mlir::arith::CmpIPredicate::eq, isContiguousResult,
            zero);
        if (!restrictCopyAtRuntime) {
          restrictCopyAtRuntime = notContiguous;
        } else {
          mlir::Value cond = mlir::arith::AndIOp::create(
              builder, loc, *restrictCopyAtRuntime, notContiguous);
          restrictCopyAtRuntime = cond;
        }
      }
    };

    if (!restrictCopyAtRuntime) {
      if (isActualArgBox) {
        // isContiguousResult = genIsContiguousCall();
        mlir::Value addr =
            builder
                .genIfOp(loc, {addrType}, isContiguousResult,
                         /*withElseRegion=*/true)
                .genThen([&]() { noCopy(); })
                .genElse([&] {
                  ExtValue temp = doCopyIn();
                  fir::ResultOp::create(builder, loc, fir::getBase(temp));
                })
                .getResults()[0];
        fir::ExtendedValue temp =
            fir::substBase(readIfBoxValue(actualArg), addr);
        combinedCondition();
        copyOutPairs.emplace_back(
            CopyOutPair{actualArg, temp, doCopyOut, restrictCopyAtRuntime});
        return temp;
      }

      ExtValue temp = doCopyIn();
      copyOutPairs.emplace_back(CopyOutPair{actualArg, temp, doCopyOut, {}});
      return temp;
    }

    // Otherwise, need to be careful to only copy-in if allowed at runtime.
    mlir::Value addr =
        builder
            .genIfOp(loc, {addrType}, *restrictCopyAtRuntime,
                     /*withElseRegion=*/true)
            .genThen([&]() {
              if (isActualArgBox) {
                // isContiguousResult = genIsContiguousCall();
                // Avoid copyin if the argument is contiguous at runtime.
                mlir::Value addr1 =
                    builder
                        .genIfOp(loc, {addrType}, isContiguousResult,
                                 /*withElseRegion=*/true)
                        .genThen([&]() { noCopy(); })
                        .genElse([&]() {
                          ExtValue temp = doCopyIn();
                          fir::ResultOp::create(builder, loc,
                                                fir::getBase(temp));
                        })
                        .getResults()[0];
                fir::ResultOp::create(builder, loc, addr1);
              } else {
                ExtValue temp = doCopyIn();
                fir::ResultOp::create(builder, loc, fir::getBase(temp));
              }
            })
            .genElse([&]() {
              mlir::Value nullPtr = builder.createNullConstant(loc, addrType);
              fir::ResultOp::create(builder, loc, nullPtr);
            })
            .getResults()[0];
    // Associate the temp address with actualArg lengths and extents if a
    // temporary is generated. Otherwise the same address is associated.
    fir::ExtendedValue temp = fir::substBase(readIfBoxValue(actualArg), addr);
    combinedCondition();
    copyOutPairs.emplace_back(
        CopyOutPair{actualArg, temp, doCopyOut, restrictCopyAtRuntime});
    return temp;
  }

  /// Generate copy-out if needed and free the temporary for an argument that
  /// has been copied-in into a contiguous temp.
  void genCopyOut(const CopyOutPair &copyOutPair) {
    mlir::Location loc = getLoc();
    bool isActualArgBox =
        fir::isa_box_type(fir::getBase(copyOutPair.var).getType());
    auto doCopyOut = [&]() {
      if (!isActualArgBox || inlineCopyInOutForBoxes) {
        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.
        fir::FreeMemOp::create(builder, loc, fir::getBase(copyOutPair.temp));
        return;
      }
      // Generate CopyOutAssign() call to copy data from the temporary
      // to the actualArg. Note that in case the actual argument
      // is ALLOCATABLE/POINTER the CopyOutAssign() implementation
      // should not engage its reallocation, because the temporary
      // is rank, shape and type compatible with it.
      // 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::Type allocBoxTy =
          mlir::cast<fir::BaseBoxType>(srcBox.getType())
              .getBoxTypeWithNewAttr(fir::BaseBoxType::Attribute::Allocatable);
      srcBox = fir::ReboxOp::create(builder, loc, allocBoxTy, srcBox,
                                    /*shift=*/mlir::Value{},
                                    /*slice=*/mlir::Value{});
      mlir::Value srcBoxRef = builder.createTemporary(loc, srcBox.getType());
      fir::StoreOp::create(builder, 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());
        fir::StoreOp::create(builder, loc, destBox, destBoxRef);
      } else {
        destBoxRef = fir::ZeroOp::create(builder, loc, srcBoxRef.getType());
      }
      fir::runtime::genCopyOutAssign(builder, loc, destBoxRef, srcBoxRef);
    };

    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
  /// ExtendedValue where all the properties (base address, shape and length
  /// parameters) can be safely read (set to zero if not present). It also
  /// returns a boolean mlir::Value telling if the variable is present at
  /// runtime.
  /// This is useful to later be able to do conditional copy-in/copy-out
  /// or to retrieve the base address without having to deal with the case
  /// where the actual may be an absent fir.box.
  std::pair<ExtValue, mlir::Value>
  prepareActualThatMayBeAbsent(const Fortran::lower::SomeExpr &expr) {
    mlir::Location loc = getLoc();
    if (Fortran::evaluate::IsAllocatableOrPointerObject(expr)) {
      // Fortran 2018 15.5.2.12 point 1: If unallocated/disassociated,
      // it is as if the argument was absent. The main care here is to
      // not do a copy-in/copy-out because the temp address, even though
      // pointing to a null size storage, would not be a nullptr and
      // therefore the argument would not be considered absent on the
      // callee side. Note: if wholeSymbol is optional, it cannot be
      // absent as per 15.5.2.12 point 7. and 8. We rely on this to
      // un-conditionally read the allocatable/pointer descriptor here.
      fir::MutableBoxValue mutableBox = genMutableBoxValue(expr);
      mlir::Value isPresent = fir::factory::genIsAllocatedOrAssociatedTest(
          builder, loc, mutableBox);
      fir::ExtendedValue actualArg =
          fir::factory::genMutableBoxRead(builder, loc, mutableBox);
      return {actualArg, isPresent};
    }
    // Absent descriptor cannot be read. To avoid any issue in
    // copy-in/copy-out, and when retrieving the address/length
    // create an descriptor pointing to a null address here if the
    // fir.box is absent.
    ExtValue actualArg = gen(expr);
    mlir::Value actualArgBase = fir::getBase(actualArg);
    mlir::Value isPresent = fir::IsPresentOp::create(
        builder, loc, builder.getI1Type(), actualArgBase);
    if (!mlir::isa<fir::BoxType>(actualArgBase.getType()))
      return {actualArg, isPresent};
    ExtValue safeToReadBox =
        absentBoxToUnallocatedBox(builder, loc, actualArg, isPresent);
    return {safeToReadBox, isPresent};
  }

  /// Create a temp on the stack for scalar actual arguments that may be absent
  /// at runtime, but must be passed via a temp if they are presents.
  fir::ExtendedValue
  createScalarTempForArgThatMayBeAbsent(ExtValue actualArg,
                                        mlir::Value isPresent) {
    mlir::Location loc = getLoc();
    mlir::Type type = fir::unwrapRefType(fir::getBase(actualArg).getType());
    if (fir::isDerivedWithLenParameters(actualArg))
      TODO(loc, "parametrized derived type optional scalar argument copy-in");
    if (const fir::CharBoxValue *charBox = actualArg.getCharBox()) {
      mlir::Value len = charBox->getLen();
      mlir::Value zero = builder.createIntegerConstant(loc, len.getType(), 0);
      len = mlir::arith::SelectOp::create(builder, loc, isPresent, len, zero);
      mlir::Value temp =
          builder.createTemporary(loc, type, /*name=*/{},
                                  /*shape=*/{}, mlir::ValueRange{len},
                                  llvm::ArrayRef<mlir::NamedAttribute>{
                                      fir::getAdaptToByRefAttr(builder)});
      return fir::CharBoxValue{temp, len};
    }
    assert((fir::isa_trivial(type) || mlir::isa<fir::RecordType>(type)) &&
           "must be simple scalar");
    return builder.createTemporary(loc, type,
                                   llvm::ArrayRef<mlir::NamedAttribute>{
                                       fir::getAdaptToByRefAttr(builder)});
  }

  template <typename A>
  bool isCharacterType(const A &exp) {
    if (auto type = exp.GetType())
      return type->category() == Fortran::common::TypeCategory::Character;
    return false;
  }

  /// Lower an actual argument that must be passed via an address.
  /// This generates of the copy-in/copy-out if the actual is not contiguous, or
  /// the creation of the temp if the actual is a variable and \p byValue is
  /// true. It handles the cases where the actual may be absent, and all of the
  /// copying has to be conditional at runtime.
  /// If the actual argument may be dynamically absent, return an additional
  /// boolean mlir::Value that if true means that the actual argument is
  /// present.
  std::pair<ExtValue, std::optional<mlir::Value>>
  prepareActualToBaseAddressLike(
      const Fortran::lower::SomeExpr &expr,
      const Fortran::lower::CallerInterface::PassedEntity &arg,
      CopyOutPairs &copyOutPairs, bool byValue) {
    mlir::Location loc = getLoc();
    const bool isArray = expr.Rank() > 0;
    const bool actualArgIsVariable = Fortran::evaluate::IsVariable(expr);
    // It must be possible to modify VALUE arguments on the callee side, even
    // if the actual argument is a literal or named constant. Hence, the
    // address of static storage must not be passed in that case, and a copy
    // must be made even if this is not a variable.
    // Note: isArray should be used here, but genBoxArg already creates copies
    // for it, so do not duplicate the copy until genBoxArg behavior is changed.
    const bool isStaticConstantByValue =
        byValue && Fortran::evaluate::IsActuallyConstant(expr) &&
        (isCharacterType(expr));
    const bool variableNeedsCopy =
        actualArgIsVariable &&
        (byValue || (isArray && !Fortran::evaluate::IsSimplyContiguous(
                                    expr, converter.getFoldingContext())));
    const bool needsCopy = isStaticConstantByValue || variableNeedsCopy;
    auto [argAddr, isPresent] =
        [&]() -> std::pair<ExtValue, std::optional<mlir::Value>> {
      if (!actualArgIsVariable && !needsCopy)
        // Actual argument is not a variable. Make sure a variable address is
        // not passed.
        return {genTempExtAddr(expr), std::nullopt};
      ExtValue baseAddr;
      if (arg.isOptional() &&
          Fortran::evaluate::MayBePassedAsAbsentOptional(expr)) {
        auto [actualArgBind, isPresent] = prepareActualThatMayBeAbsent(expr);
        const ExtValue &actualArg = actualArgBind;
        if (!needsCopy)
          return {actualArg, isPresent};

        if (isArray)
          return {genCopyIn(actualArg, arg, copyOutPairs, isPresent, byValue),
                  isPresent};
        // Scalars, create a temp, and use it conditionally at runtime if
        // the argument is present.
        ExtValue temp =
            createScalarTempForArgThatMayBeAbsent(actualArg, isPresent);
        mlir::Type tempAddrTy = fir::getBase(temp).getType();
        mlir::Value selectAddr =
            builder
                .genIfOp(loc, {tempAddrTy}, isPresent,
                         /*withElseRegion=*/true)
                .genThen([&]() {
                  fir::factory::genScalarAssignment(builder, loc, temp,
                                                    actualArg);
                  fir::ResultOp::create(builder, loc, fir::getBase(temp));
                })
                .genElse([&]() {
                  mlir::Value absent =
                      fir::AbsentOp::create(builder, loc, tempAddrTy);
                  fir::ResultOp::create(builder, loc, absent);
                })
                .getResults()[0];
        return {fir::substBase(temp, selectAddr), isPresent};
      }
      // Actual cannot be absent, the actual argument can safely be
      // copied-in/copied-out without any care if needed.
      if (isArray) {
        ExtValue box = genBoxArg(expr);
        if (needsCopy)
          return {genCopyIn(box, arg, copyOutPairs,
                            /*restrictCopyAtRuntime=*/std::nullopt, byValue),
                  std::nullopt};
        // Contiguous: just use the box we created above!
        // This gets "unboxed" below, if needed.
        return {box, std::nullopt};
      }
      // Actual argument is a non-optional, non-pointer, non-allocatable
      // scalar.
      ExtValue actualArg = genExtAddr(expr);
      if (needsCopy)
        return {createInMemoryScalarCopy(builder, loc, actualArg),
                std::nullopt};
      return {actualArg, std::nullopt};
    }();
    // Scalar and contiguous expressions may be lowered to a fir.box,
    // either to account for potential polymorphism, or because lowering
    // did not account for some contiguity hints.
    // Here, polymorphism does not matter (an entity of the declared type
    // is passed, not one of the dynamic type), and the expr is known to
    // be simply contiguous, so it is safe to unbox it and pass the
    // address without making a copy.
    return {readIfBoxValue(argAddr), isPresent};
  }

  /// Lower a non-elemental procedure reference.
  ExtValue genRawProcedureRef(const Fortran::evaluate::ProcedureRef &procRef,
                              std::optional<mlir::Type> resultType) {
    mlir::Location loc = getLoc();
    if (isElementalProcWithArrayArgs(procRef))
      fir::emitFatalError(loc, "trying to lower elemental procedure with array "
                               "arguments as normal procedure");

    if (const Fortran::evaluate::SpecificIntrinsic *intrinsic =
            procRef.proc().GetSpecificIntrinsic())
      return genIntrinsicRef(procRef, resultType, *intrinsic);

    if (Fortran::lower::isIntrinsicModuleProcRef(procRef) &&
        !Fortran::semantics::IsBindCProcedure(*procRef.proc().GetSymbol()))
      return genIntrinsicRef(procRef, resultType);

    if (isStatementFunctionCall(procRef))
      return genStmtFunctionRef(procRef);

    Fortran::lower::CallerInterface caller(procRef, converter);
    using PassBy = Fortran::lower::CallerInterface::PassEntityBy;

    llvm::SmallVector<fir::MutableBoxValue> mutableModifiedByCall;
    // List of <var, temp> where temp must be copied into var after the call.
    CopyOutPairs copyOutPairs;

    mlir::FunctionType callSiteType = caller.genFunctionType();

    // Lower the actual arguments and map the lowered values to the dummy
    // arguments.
    for (const Fortran::lower::CallInterface<
             Fortran::lower::CallerInterface>::PassedEntity &arg :
         caller.getPassedArguments()) {
      const auto *actual = arg.entity;
      mlir::Type argTy = callSiteType.getInput(arg.firArgument);
      if (!actual) {
        // Optional dummy argument for which there is no actual argument.
        caller.placeInput(arg, builder.genAbsentOp(loc, argTy));
        continue;
      }
      const auto *expr = actual->UnwrapExpr();
      if (!expr)
        TODO(loc, "assumed type actual argument");

      if (arg.passBy == PassBy::Value) {
        ExtValue argVal = genval(*expr);
        if (!fir::isUnboxedValue(argVal))
          fir::emitFatalError(
              loc, "internal error: passing non trivial value by value");
        caller.placeInput(arg, fir::getBase(argVal));
        continue;
      }

      if (arg.passBy == PassBy::MutableBox) {
        if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>(
                *expr)) {
          // If expr is NULL(), the mutableBox created must be a deallocated
          // pointer with the dummy argument characteristics (see table 16.5
          // in Fortran 2018 standard).
          // No length parameters are set for the created box because any non
          // deferred type parameters of the dummy will be evaluated on the
          // callee side, and it is illegal to use NULL without a MOLD if any
          // dummy length parameters are assumed.
          mlir::Type boxTy = fir::dyn_cast_ptrEleTy(argTy);
          assert(boxTy && mlir::isa<fir::BaseBoxType>(boxTy) &&
                 "must be a fir.box type");
          mlir::Value boxStorage = builder.createTemporary(loc, boxTy);
          mlir::Value nullBox = fir::factory::createUnallocatedBox(
              builder, loc, boxTy, /*nonDeferredParams=*/{});
          fir::StoreOp::create(builder, loc, nullBox, boxStorage);
          caller.placeInput(arg, boxStorage);
          continue;
        }
        if (fir::isPointerType(argTy) &&
            !Fortran::evaluate::IsObjectPointer(*expr)) {
          // Passing a non POINTER actual argument to a POINTER dummy argument.
          // Create a pointer of the dummy argument type and assign the actual
          // argument to it.
          mlir::Value irBox =
              builder.createTemporary(loc, fir::unwrapRefType(argTy));
          // Non deferred parameters will be evaluated on the callee side.
          fir::MutableBoxValue pointer(irBox,
                                       /*nonDeferredParams=*/mlir::ValueRange{},
                                       /*mutableProperties=*/{});
          Fortran::lower::associateMutableBox(converter, loc, pointer, *expr,
                                              /*lbounds=*/{}, stmtCtx);
          caller.placeInput(arg, irBox);
          continue;
        }
        // Passing a POINTER to a POINTER, or an ALLOCATABLE to an ALLOCATABLE.
        fir::MutableBoxValue mutableBox = genMutableBoxValue(*expr);
        if (fir::isAllocatableType(argTy) && arg.isIntentOut() &&
            Fortran::semantics::IsBindCProcedure(*procRef.proc().GetSymbol()))
          Fortran::lower::genDeallocateIfAllocated(converter, mutableBox, loc);
        mlir::Value irBox =
            fir::factory::getMutableIRBox(builder, loc, mutableBox);
        caller.placeInput(arg, irBox);
        if (arg.mayBeModifiedByCall())
          mutableModifiedByCall.emplace_back(std::move(mutableBox));
        continue;
      }
      if (arg.passBy == PassBy::BaseAddress || arg.passBy == PassBy::BoxChar ||
          arg.passBy == PassBy::BaseAddressValueAttribute ||
          arg.passBy == PassBy::CharBoxValueAttribute) {
        const bool byValue = arg.passBy == PassBy::BaseAddressValueAttribute ||
                             arg.passBy == PassBy::CharBoxValueAttribute;
        ExtValue argAddr =
            prepareActualToBaseAddressLike(*expr, arg, copyOutPairs, byValue)
                .first;
        if (arg.passBy == PassBy::BaseAddress ||
            arg.passBy == PassBy::BaseAddressValueAttribute) {
          caller.placeInput(arg, fir::getBase(argAddr));
        } else {
          assert(arg.passBy == PassBy::BoxChar ||
                 arg.passBy == PassBy::CharBoxValueAttribute);
          auto helper = fir::factory::CharacterExprHelper{builder, loc};
          auto boxChar = argAddr.match(
              [&](const fir::CharBoxValue &x) -> mlir::Value {
                // If a character procedure was passed instead, handle the
                // mismatch.
                auto funcTy =
                    mlir::dyn_cast<mlir::FunctionType>(x.getAddr().getType());
                if (funcTy && funcTy.getNumResults() == 1 &&
                    mlir::isa<fir::BoxCharType>(funcTy.getResult(0))) {
                  auto boxTy =
                      mlir::cast<fir::BoxCharType>(funcTy.getResult(0));
                  mlir::Value ref = builder.createConvertWithVolatileCast(
                      loc, builder.getRefType(boxTy.getEleTy()), x.getAddr());
                  auto len = fir::UndefOp::create(
                      builder, loc, builder.getCharacterLengthType());
                  return fir::EmboxCharOp::create(builder, loc, boxTy, ref,
                                                  len);
                }
                return helper.createEmbox(x);
              },
              [&](const fir::CharArrayBoxValue &x) {
                return helper.createEmbox(x);
              },
              [&](const auto &x) -> mlir::Value {
                // Fortran allows an actual argument of a completely different
                // type to be passed to a procedure expecting a CHARACTER in the
                // dummy argument position. When this happens, the data pointer
                // argument is simply assumed to point to CHARACTER data and the
                // LEN argument used is garbage. Simulate this behavior by
                // free-casting the base address to be a !fir.char reference and
                // setting the LEN argument to undefined. What could go wrong?
                auto dataPtr = fir::getBase(x);
                assert(!mlir::isa<fir::BoxType>(dataPtr.getType()));
                return builder.convertWithSemantics(
                    loc, argTy, dataPtr,
                    /*allowCharacterConversion=*/true);
              });
          caller.placeInput(arg, boxChar);
        }
      } else if (arg.passBy == PassBy::Box) {
        if (arg.mustBeMadeContiguous() &&
            !Fortran::evaluate::IsSimplyContiguous(
                *expr, converter.getFoldingContext())) {
          // If the expression is a PDT, or a polymorphic entity, or an assumed
          // rank, it cannot currently be safely handled by
          // prepareActualToBaseAddressLike that is intended to prepare
          // arguments that can be passed as simple base address.
          if (auto dynamicType = expr->GetType())
            if (dynamicType->IsPolymorphic())
              TODO(loc, "passing a polymorphic entity to an OPTIONAL "
                        "CONTIGUOUS argument");
          if (fir::isRecordWithTypeParameters(
                  fir::unwrapSequenceType(fir::unwrapPassByRefType(argTy))))
            TODO(loc, "passing to an OPTIONAL CONTIGUOUS derived type argument "
                      "with length parameters");
          if (Fortran::semantics::IsAssumedRank(*expr))
            TODO(loc, "passing an assumed rank entity to an OPTIONAL "
                      "CONTIGUOUS argument");
          // Assumed shape VALUE are currently TODO in the call interface
          // lowering.
          const bool byValue = false;
          auto [argAddr, isPresentValue] =
              prepareActualToBaseAddressLike(*expr, arg, copyOutPairs, byValue);
          mlir::Value box = builder.createBox(loc, argAddr);
          if (isPresentValue) {
            mlir::Value convertedBox = builder.createConvert(loc, argTy, box);
            auto absent = fir::AbsentOp::create(builder, loc, argTy);
            caller.placeInput(
                arg, mlir::arith::SelectOp::create(
                         builder, loc, *isPresentValue, convertedBox, absent));
          } else {
            caller.placeInput(arg, builder.createBox(loc, argAddr));
          }

        } else if (arg.isOptional() &&
                   Fortran::evaluate::IsAllocatableOrPointerObject(*expr)) {
          // Before lowering to an address, handle the allocatable/pointer
          // actual argument to optional fir.box dummy. It is legal to pass
          // unallocated/disassociated entity to an optional. In this case, an
          // absent fir.box must be created instead of a fir.box with a null
          // value (Fortran 2018 15.5.2.12 point 1).
          //
          // Note that passing an absent allocatable to a non-allocatable
          // optional dummy argument is illegal (15.5.2.12 point 3 (8)). So
          // nothing has to be done to generate an absent argument in this case,
          // and it is OK to unconditionally read the mutable box here.
          fir::MutableBoxValue mutableBox = genMutableBoxValue(*expr);
          mlir::Value isAllocated =
              fir::factory::genIsAllocatedOrAssociatedTest(builder, loc,
                                                           mutableBox);
          auto absent = fir::AbsentOp::create(builder, loc, argTy);
          /// For now, assume it is not OK to pass the allocatable/pointer
          /// descriptor to a non pointer/allocatable dummy. That is a strict
          /// interpretation of 18.3.6 point 4 that stipulates the descriptor
          /// has the dummy attributes in BIND(C) contexts.
          mlir::Value box = builder.createBox(
              loc, fir::factory::genMutableBoxRead(builder, loc, mutableBox));

          // NULL() passed as argument is passed as a !fir.box<none>. Since
          // select op requires the same type for its two argument, convert
          // !fir.box<none> to !fir.class<none> when the argument is
          // polymorphic.
          if (fir::isBoxNone(box.getType()) && fir::isPolymorphicType(argTy)) {
            box = builder.createConvert(
                loc,
                fir::ClassType::get(mlir::NoneType::get(builder.getContext())),
                box);
          } else if (mlir::isa<fir::BoxType>(box.getType()) &&
                     fir::isPolymorphicType(argTy)) {
            box = fir::ReboxOp::create(builder, loc, argTy, box, mlir::Value{},
                                       /*slice=*/mlir::Value{});
          }

          // Need the box types to be exactly similar for the selectOp.
          mlir::Value convertedBox = builder.createConvert(loc, argTy, box);
          caller.placeInput(
              arg, mlir::arith::SelectOp::create(builder, loc, isAllocated,
                                                 convertedBox, absent));
        } else {
          auto dynamicType = expr->GetType();
          mlir::Value box;

          // Special case when an intrinsic scalar variable is passed to a
          // function expecting an optional unlimited polymorphic dummy
          // argument.
          // The presence test needs to be performed before emboxing otherwise
          // the program will crash.
          if (dynamicType->category() !=
                  Fortran::common::TypeCategory::Derived &&
              expr->Rank() == 0 && fir::isUnlimitedPolymorphicType(argTy) &&
              arg.isOptional()) {
            ExtValue opt = lowerIntrinsicArgumentAsInquired(*expr);
            mlir::Value isPresent = genActualIsPresentTest(builder, loc, opt);
            box =
                builder
                    .genIfOp(loc, {argTy}, isPresent, /*withElseRegion=*/true)
                    .genThen([&]() {
                      auto boxed = builder.createBox(
                          loc, genBoxArg(*expr), fir::isPolymorphicType(argTy));
                      fir::ResultOp::create(builder, loc, boxed);
                    })
                    .genElse([&]() {
                      auto absent = fir::AbsentOp::create(builder, loc, argTy)
                                        .getResult();
                      fir::ResultOp::create(builder, loc, absent);
                    })
                    .getResults()[0];
          } else {
            // Make sure a variable address is only passed if the expression is
            // actually a variable.
            box = Fortran::evaluate::IsVariable(*expr)
                      ? builder.createBox(loc, genBoxArg(*expr),
                                          fir::isPolymorphicType(argTy),
                                          fir::isAssumedType(argTy))
                      : builder.createBox(getLoc(), genTempExtAddr(*expr),
                                          fir::isPolymorphicType(argTy),
                                          fir::isAssumedType(argTy));
            if (mlir::isa<fir::BoxType>(box.getType()) &&
                fir::isPolymorphicType(argTy) && !fir::isAssumedType(argTy)) {
              mlir::Type actualTy = argTy;
              if (Fortran::lower::isParentComponent(*expr))
                actualTy = fir::BoxType::get(converter.genType(*expr));
              // Rebox can only be performed on a present argument.
              if (arg.isOptional()) {
                mlir::Value isPresent =
                    genActualIsPresentTest(builder, loc, box);
                box = builder
                          .genIfOp(loc, {actualTy}, isPresent,
                                   /*withElseRegion=*/true)
                          .genThen([&]() {
                            auto rebox =
                                fir::ReboxOp::create(builder, loc, actualTy,
                                                     box, mlir::Value{},
                                                     /*slice=*/mlir::Value{})
                                    .getResult();
                            fir::ResultOp::create(builder, loc, rebox);
                          })
                          .genElse([&]() {
                            auto absent =
                                fir::AbsentOp::create(builder, loc, actualTy)
                                    .getResult();
                            fir::ResultOp::create(builder, loc, absent);
                          })
                          .getResults()[0];
              } else {
                box = fir::ReboxOp::create(builder, loc, actualTy, box,
                                           mlir::Value{},
                                           /*slice=*/mlir::Value{});
              }
            } else if (Fortran::lower::isParentComponent(*expr)) {
              fir::ExtendedValue newExv =
                  Fortran::lower::updateBoxForParentComponent(converter, box,
                                                              *expr);
              box = fir::getBase(newExv);
            }
          }
          caller.placeInput(arg, box);
        }
      } else if (arg.passBy == PassBy::AddressAndLength) {
        ExtValue argRef = genExtAddr(*expr);
        caller.placeAddressAndLengthInput(arg, fir::getBase(argRef),
                                          fir::getLen(argRef));
      } else if (arg.passBy == PassBy::CharProcTuple) {
        ExtValue argRef = genExtAddr(*expr);
        mlir::Value tuple = createBoxProcCharTuple(
            converter, argTy, fir::getBase(argRef), fir::getLen(argRef));
        caller.placeInput(arg, tuple);
      } else {
        TODO(loc, "pass by value in non elemental function call");
      }
    }

    auto loweredResult =
        Fortran::lower::genCallOpAndResult(loc, converter, symMap, stmtCtx,
                                           caller, callSiteType, resultType)
            .first;
    auto &result = std::get<ExtValue>(loweredResult);

    // Sync pointers and allocatables that may have been modified during the
    // call.
    for (const auto &mutableBox : mutableModifiedByCall)
      fir::factory::syncMutableBoxFromIRBox(builder, loc, mutableBox);
    // Handle case where result was passed as argument

    // Copy-out temps that were created for non contiguous variable arguments if
    // needed.
    for (const auto &copyOutPair : copyOutPairs)
      genCopyOut(copyOutPair);

    return result;
  }

  template <typename A>
  ExtValue genval(const Fortran::evaluate::FunctionRef<A> &funcRef) {
    ExtValue result = genFunctionRef(funcRef);
    if (result.rank() == 0 && fir::isa_ref_type(fir::getBase(result).getType()))
      return genLoad(result);
    return result;
  }

  ExtValue genval(const Fortran::evaluate::ProcedureRef &procRef) {
    std::optional<mlir::Type> resTy;
    if (procRef.hasAlternateReturns())
      resTy = builder.getIndexType();
    return genProcedureRef(procRef, resTy);
  }

  template <typename A>
  bool isScalar(const A &x) {
    return x.Rank() == 0;
  }

  /// Helper to detect Transformational function reference.
  template <typename T>
  bool isTransformationalRef(const T &) {
    return false;
  }
  template <typename T>
  bool isTransformationalRef(const Fortran::evaluate::FunctionRef<T> &funcRef) {
    return !funcRef.IsElemental() && funcRef.Rank();
  }
  template <typename T>
  bool isTransformationalRef(Fortran::evaluate::Expr<T> expr) {
    return Fortran::common::visit(
        [&](const auto &e) { return isTransformationalRef(e); }, expr.u);
  }

  template <typename A>
  ExtValue asArray(const A &x) {
    return Fortran::lower::createSomeArrayTempValue(converter, toEvExpr(x),
                                                    symMap, stmtCtx);
  }

  /// Lower an array value as an argument. This argument can be passed as a box
  /// value, so it may be possible to avoid making a temporary.
  template <typename A>
  ExtValue asArrayArg(const Fortran::evaluate::Expr<A> &x) {
    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 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) {
    // Designator is being passed as an argument to a procedure. Lower the
    // expression to a boxed value.
    auto someExpr = toEvExpr(x);
    return Fortran::lower::createBoxValue(getLoc(), converter, someExpr, symMap,
                                          stmtCtx);
  }
  template <typename A, typename B>
  ExtValue asArrayArg(const A &, const B &x) {
    // If the expression to pass as an argument is not a designator, then create
    // an array temp.
    return asArray(x);
  }

  template <typename A>
  mlir::Value getIfOverridenExpr(const Fortran::evaluate::Expr<A> &x) {
    if (const Fortran::lower::ExprToValueMap *map =
            converter.getExprOverrides()) {
      Fortran::lower::SomeExpr someExpr = toEvExpr(x);
      if (auto match = map->find(&someExpr); match != map->end())
        return match->second;
    }
    return mlir::Value{};
  }

  template <typename A>
  ExtValue gen(const Fortran::evaluate::Expr<A> &x) {
    if (mlir::Value val = getIfOverridenExpr(x))
      return val;
    // Whole array symbols or components, and results of transformational
    // functions already have a storage and the scalar expression lowering path
    // is used to not create a new temporary storage.
    if (isScalar(x) ||
        Fortran::evaluate::UnwrapWholeSymbolOrComponentDataRef(x) ||
        (isTransformationalRef(x) && !isOptimizableTranspose(x, converter)))
      return Fortran::common::visit([&](const auto &e) { return genref(e); },
                                    x.u);
    if (useBoxArg)
      return asArrayArg(x);
    return asArray(x);
  }
  template <typename A>
  ExtValue genval(const Fortran::evaluate::Expr<A> &x) {
    if (mlir::Value val = getIfOverridenExpr(x))
      return val;
    if (isScalar(x) || Fortran::evaluate::UnwrapWholeSymbolDataRef(x) ||
        inInitializer)
      return Fortran::common::visit([&](const auto &e) { return genval(e); },
                                    x.u);
    return asArray(x);
  }

  template <int KIND>
  ExtValue genval(const Fortran::evaluate::Expr<Fortran::evaluate::Type<
                      Fortran::common::TypeCategory::Logical, KIND>> &exp) {
    if (mlir::Value val = getIfOverridenExpr(exp))
      return val;
    return Fortran::common::visit([&](const auto &e) { return genval(e); },
                                  exp.u);
  }

  using RefSet =
      std::tuple<Fortran::evaluate::ComplexPart, Fortran::evaluate::Substring,
                 Fortran::evaluate::DataRef, Fortran::evaluate::Component,
                 Fortran::evaluate::ArrayRef, Fortran::evaluate::CoarrayRef,
                 Fortran::semantics::SymbolRef>;
  template <typename A>
  static constexpr bool inRefSet = Fortran::common::HasMember<A, RefSet>;

  template <typename A, typename = std::enable_if_t<inRefSet<A>>>
  ExtValue genref(const A &a) {
    return gen(a);
  }
  template <typename A>
  ExtValue genref(const A &a) {
    if (inInitializer) {
      // Initialization expressions can never allocate memory.
      return genval(a);
    }
    mlir::Type storageType = converter.genType(toEvExpr(a));
    return placeScalarValueInMemory(builder, getLoc(), genval(a), storageType);
  }

  template <typename A, template <typename> typename T,
            typename B = std::decay_t<T<A>>,
            std::enable_if_t<
                std::is_same_v<B, Fortran::evaluate::Expr<A>> ||
                    std::is_same_v<B, Fortran::evaluate::Designator<A>> ||
                    std::is_same_v<B, Fortran::evaluate::FunctionRef<A>>,
                bool> = true>
  ExtValue genref(const T<A> &x) {
    return gen(x);
  }

private:
  mlir::Location location;
  Fortran::lower::AbstractConverter &converter;
  fir::FirOpBuilder &builder;
  Fortran::lower::StatementContext &stmtCtx;
  Fortran::lower::SymMap &symMap;
  bool inInitializer = false;
  bool useBoxArg = false; // expression lowered as argument
};
} // namespace

#define CONCAT(x, y) CONCAT2(x, y)
#define CONCAT2(x, y) x##y

// Helper for changing the semantics in a given context. Preserves the current
// semantics which is resumed when the "push" goes out of scope.
#define PushSemantics(PushVal)                                                 \
  [[maybe_unused]] auto CONCAT(pushSemanticsLocalVariable, __LINE__) =         \
      Fortran::common::ScopedSet(semant, PushVal);

static bool isAdjustedArrayElementType(mlir::Type t) {
  return fir::isa_char(t) || fir::isa_derived(t) ||
         mlir::isa<fir::SequenceType>(t);
}
static bool elementTypeWasAdjusted(mlir::Type t) {
  if (auto ty = mlir::dyn_cast<fir::ReferenceType>(t))
    return isAdjustedArrayElementType(ty.getEleTy());
  return false;
}
static mlir::Type adjustedArrayElementType(mlir::Type t) {
  return isAdjustedArrayElementType(t) ? fir::ReferenceType::get(t) : t;
}

/// Helper to generate calls to scalar user defined assignment procedures.
static void genScalarUserDefinedAssignmentCall(fir::FirOpBuilder &builder,
                                               mlir::Location loc,
                                               mlir::func::FuncOp func,
                                               const fir::ExtendedValue &lhs,
                                               const fir::ExtendedValue &rhs) {
  auto prepareUserDefinedArg =
      [](fir::FirOpBuilder &builder, mlir::Location loc,
         const fir::ExtendedValue &value, mlir::Type argType) -> mlir::Value {
    if (mlir::isa<fir::BoxCharType>(argType)) {
      const fir::CharBoxValue *charBox = value.getCharBox();
      assert(charBox && "argument type mismatch in elemental user assignment");
      return fir::factory::CharacterExprHelper{builder, loc}.createEmbox(
          *charBox);
    }
    if (mlir::isa<fir::BaseBoxType>(argType)) {
      mlir::Value box =
          builder.createBox(loc, value, mlir::isa<fir::ClassType>(argType));
      return builder.createConvert(loc, argType, box);
    }
    // Simple pass by address.
    mlir::Type argBaseType = fir::unwrapRefType(argType);
    assert(!fir::hasDynamicSize(argBaseType));
    mlir::Value from = fir::getBase(value);
    if (argBaseType != fir::unwrapRefType(from.getType())) {
      // With logicals, it is possible that from is i1 here.
      if (fir::isa_ref_type(from.getType()))
        from = fir::LoadOp::create(builder, loc, from);
      from = builder.createConvert(loc, argBaseType, from);
    }
    if (!fir::isa_ref_type(from.getType())) {
      mlir::Value temp = builder.createTemporary(loc, argBaseType);
      fir::StoreOp::create(builder, loc, from, temp);
      from = temp;
    }
    return builder.createConvert(loc, argType, from);
  };
  assert(func.getNumArguments() == 2);
  mlir::Type lhsType = func.getFunctionType().getInput(0);
  mlir::Type rhsType = func.getFunctionType().getInput(1);
  mlir::Value lhsArg = prepareUserDefinedArg(builder, loc, lhs, lhsType);
  mlir::Value rhsArg = prepareUserDefinedArg(builder, loc, rhs, rhsType);
  fir::CallOp::create(builder, loc, func, mlir::ValueRange{lhsArg, rhsArg});
}

/// Convert the result of a fir.array_modify to an ExtendedValue given the
/// related fir.array_load.
static fir::ExtendedValue arrayModifyToExv(fir::FirOpBuilder &builder,
                                           mlir::Location loc,
                                           fir::ArrayLoadOp load,
                                           mlir::Value elementAddr) {
  mlir::Type eleTy = fir::unwrapPassByRefType(elementAddr.getType());
  if (fir::isa_char(eleTy)) {
    auto len = fir::factory::CharacterExprHelper{builder, loc}.getLength(
        load.getMemref());
    if (!len) {
      assert(load.getTypeparams().size() == 1 &&
             "length must be in array_load");
      len = load.getTypeparams()[0];
    }
    return fir::CharBoxValue{elementAddr, len};
  }
  return elementAddr;
}

//===----------------------------------------------------------------------===//
//
// Lowering of scalar expressions in an explicit iteration space context.
//
//===----------------------------------------------------------------------===//

// Shared code for creating a copy of a derived type element. This function is
// called from a continuation.
inline static fir::ArrayAmendOp
createDerivedArrayAmend(mlir::Location loc, fir::ArrayLoadOp destLoad,
                        fir::FirOpBuilder &builder, fir::ArrayAccessOp destAcc,
                        const fir::ExtendedValue &elementExv, mlir::Type eleTy,
                        mlir::Value innerArg) {
  if (destLoad.getTypeparams().empty()) {
    fir::factory::genRecordAssignment(builder, loc, destAcc, elementExv);
  } else {
    auto boxTy = fir::BoxType::get(eleTy);
    auto toBox = fir::EmboxOp::create(builder, loc, boxTy, destAcc.getResult(),
                                      mlir::Value{}, mlir::Value{},
                                      destLoad.getTypeparams());
    auto fromBox = fir::EmboxOp::create(
        builder, loc, boxTy, fir::getBase(elementExv), mlir::Value{},
        mlir::Value{}, destLoad.getTypeparams());
    fir::factory::genRecordAssignment(builder, loc, fir::BoxValue(toBox),
                                      fir::BoxValue(fromBox));
  }
  return fir::ArrayAmendOp::create(builder, loc, innerArg.getType(), innerArg,
                                   destAcc);
}

inline static fir::ArrayAmendOp
createCharArrayAmend(mlir::Location loc, fir::FirOpBuilder &builder,
                     fir::ArrayAccessOp dstOp, mlir::Value &dstLen,
                     const fir::ExtendedValue &srcExv, mlir::Value innerArg,
                     llvm::ArrayRef<mlir::Value> bounds) {
  fir::CharBoxValue dstChar(dstOp, dstLen);
  fir::factory::CharacterExprHelper helper{builder, loc};
  if (!bounds.empty()) {
    dstChar = helper.createSubstring(dstChar, bounds);
    fir::factory::genCharacterCopy(fir::getBase(srcExv), fir::getLen(srcExv),
                                   dstChar.getAddr(), dstChar.getLen(), builder,
                                   loc);
    // Update the LEN to the substring's LEN.
    dstLen = dstChar.getLen();
  }
  // For a CHARACTER, we generate the element assignment loops inline.
  helper.createAssign(fir::ExtendedValue{dstChar}, srcExv);
  // Mark this array element as amended.
  mlir::Type ty = innerArg.getType();
  auto amend = fir::ArrayAmendOp::create(builder, loc, ty, innerArg, dstOp);
  return amend;
}

/// Build an ExtendedValue from a fir.array<?x...?xT> without actually setting
/// the actual extents and lengths. This is only to allow their propagation as
/// ExtendedValue without triggering verifier failures when propagating
/// character/arrays as unboxed values. Only the base of the resulting
/// ExtendedValue should be used, it is undefined to use the length or extents
/// of the extended value returned,
inline static fir::ExtendedValue
convertToArrayBoxValue(mlir::Location loc, fir::FirOpBuilder &builder,
                       mlir::Value val, mlir::Value len) {
  mlir::Type ty = fir::unwrapRefType(val.getType());
  mlir::IndexType idxTy = builder.getIndexType();
  auto seqTy = mlir::cast<fir::SequenceType>(ty);
  auto undef = fir::UndefOp::create(builder, loc, idxTy);
  llvm::SmallVector<mlir::Value> extents(seqTy.getDimension(), undef);
  if (fir::isa_char(seqTy.getEleTy()))
    return fir::CharArrayBoxValue(val, len ? len : undef, extents);
  return fir::ArrayBoxValue(val, extents);
}

//===----------------------------------------------------------------------===//
//
// Lowering of array expressions.
//
//===----------------------------------------------------------------------===//

namespace {
class ArrayExprLowering {
  using ExtValue = fir::ExtendedValue;

  /// Structure to keep track of lowered array operands in the
  /// array expression. Useful to later deduce the shape of the
  /// array expression.
  struct ArrayOperand {
    /// Array base (can be a fir.box).
    mlir::Value memref;
    /// ShapeOp, ShapeShiftOp or ShiftOp
    mlir::Value shape;
    /// SliceOp
    mlir::Value slice;
    /// Can this operand be absent ?
    bool mayBeAbsent = false;
  };

  using ImplicitSubscripts = Fortran::lower::details::ImplicitSubscripts;
  using PathComponent = Fortran::lower::PathComponent;

  /// Active iteration space.
  using IterationSpace = Fortran::lower::IterationSpace;
  using IterSpace = const Fortran::lower::IterationSpace &;

  /// Current continuation. Function that will generate IR for a single
  /// iteration of the pending iterative loop structure.
  using CC = Fortran::lower::GenerateElementalArrayFunc;

  /// Projection continuation. Function that will project one iteration space
  /// into another.
  using PC = std::function<IterationSpace(IterSpace)>;
  using ArrayBaseTy =
      std::variant<std::monostate, const Fortran::evaluate::ArrayRef *,
                   const Fortran::evaluate::DataRef *>;
  using ComponentPath = Fortran::lower::ComponentPath;

public:
  //===--------------------------------------------------------------------===//
  // Regular array assignment
  //===--------------------------------------------------------------------===//

  /// Entry point for array assignments. Both the left-hand and right-hand sides
  /// can either be ExtendedValue or evaluate::Expr.
  template <typename TL, typename TR>
  static void lowerArrayAssignment(Fortran::lower::AbstractConverter &converter,
                                   Fortran::lower::SymMap &symMap,
                                   Fortran::lower::StatementContext &stmtCtx,
                                   const TL &lhs, const TR &rhs) {
    ArrayExprLowering ael(converter, stmtCtx, symMap,
                          ConstituentSemantics::CopyInCopyOut);
    ael.lowerArrayAssignment(lhs, rhs);
  }

  template <typename TL, typename TR>
  void lowerArrayAssignment(const TL &lhs, const TR &rhs) {
    mlir::Location loc = getLoc();
    /// Here the target subspace is not necessarily contiguous. The ArrayUpdate
    /// continuation is implicitly returned in `ccStoreToDest` and the ArrayLoad
    /// in `destination`.
    PushSemantics(ConstituentSemantics::ProjectedCopyInCopyOut);
    ccStoreToDest = genarr(lhs);
    determineShapeOfDest(lhs);
    semant = ConstituentSemantics::RefTransparent;
    ExtValue exv = lowerArrayExpression(rhs);
    if (explicitSpaceIsActive()) {
      explicitSpace->finalizeContext();
      fir::ResultOp::create(builder, loc, fir::getBase(exv));
    } else {
      fir::ArrayMergeStoreOp::create(
          builder, loc, destination, fir::getBase(exv), destination.getMemref(),
          destination.getSlice(), destination.getTypeparams());
    }
  }

  //===--------------------------------------------------------------------===//
  // WHERE array assignment, FORALL assignment, and FORALL+WHERE array
  // assignment
  //===--------------------------------------------------------------------===//

  /// Entry point for array assignment when the iteration space is explicitly
  /// defined (Fortran's FORALL) with or without masks, and/or the implied
  /// iteration space involves masks (Fortran's WHERE). Both contexts (explicit
  /// space and implicit space with masks) may be present.
  static void lowerAnyMaskedArrayAssignment(
      Fortran::lower::AbstractConverter &converter,
      Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
      const Fortran::lower::SomeExpr &lhs, const Fortran::lower::SomeExpr &rhs,
      Fortran::lower::ExplicitIterSpace &explicitSpace,
      Fortran::lower::ImplicitIterSpace &implicitSpace) {
    if (explicitSpace.isActive() && lhs.Rank() == 0) {
      // Scalar assignment expression in a FORALL context.
      ArrayExprLowering ael(converter, stmtCtx, symMap,
                            ConstituentSemantics::RefTransparent,
                            &explicitSpace, &implicitSpace);
      ael.lowerScalarAssignment(lhs, rhs);
      return;
    }
    // Array assignment expression in a FORALL and/or WHERE context.
    ArrayExprLowering ael(converter, stmtCtx, symMap,
                          ConstituentSemantics::CopyInCopyOut, &explicitSpace,
                          &implicitSpace);
    ael.lowerArrayAssignment(lhs, rhs);
  }

  //===--------------------------------------------------------------------===//
  // Array assignment to array of pointer box values.
  //===--------------------------------------------------------------------===//

  /// Entry point for assignment to pointer in an array of pointers.
  static void lowerArrayOfPointerAssignment(
      Fortran::lower::AbstractConverter &converter,
      Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
      const Fortran::lower::SomeExpr &lhs, const Fortran::lower::SomeExpr &rhs,
      Fortran::lower::ExplicitIterSpace &explicitSpace,
      Fortran::lower::ImplicitIterSpace &implicitSpace,
      const llvm::SmallVector<mlir::Value> &lbounds,
      std::optional<llvm::SmallVector<mlir::Value>> ubounds) {
    ArrayExprLowering ael(converter, stmtCtx, symMap,
                          ConstituentSemantics::CopyInCopyOut, &explicitSpace,
                          &implicitSpace);
    ael.lowerArrayOfPointerAssignment(lhs, rhs, lbounds, ubounds);
  }

  /// Scalar pointer assignment in an explicit iteration space.
  ///
  /// Pointers may be bound to targets in a FORALL context. This is a scalar
  /// assignment in the sense there is never an implied iteration space, even if
  /// the pointer is to a target with non-zero rank. Since the pointer
  /// assignment must appear in a FORALL construct, correctness may require that
  /// the array of pointers follow copy-in/copy-out semantics. The pointer
  /// assignment may include a bounds-spec (lower bounds), a bounds-remapping
  /// (lower and upper bounds), or neither.
  void lowerArrayOfPointerAssignment(
      const Fortran::lower::SomeExpr &lhs, const Fortran::lower::SomeExpr &rhs,
      const llvm::SmallVector<mlir::Value> &lbounds,
      std::optional<llvm::SmallVector<mlir::Value>> ubounds) {
    setPointerAssignmentBounds(lbounds, ubounds);
    if (rhs.Rank() == 0 ||
        (Fortran::evaluate::UnwrapWholeSymbolOrComponentDataRef(rhs) &&
         Fortran::evaluate::IsAllocatableOrPointerObject(rhs))) {
      lowerScalarAssignment(lhs, rhs);
      return;
    }
    TODO(getLoc(),
         "auto boxing of a ranked expression on RHS for pointer assignment");
  }

  //===--------------------------------------------------------------------===//
  // Array assignment to allocatable array
  //===--------------------------------------------------------------------===//

  /// Entry point for assignment to allocatable array.
  static void lowerAllocatableArrayAssignment(
      Fortran::lower::AbstractConverter &converter,
      Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
      const Fortran::lower::SomeExpr &lhs, const Fortran::lower::SomeExpr &rhs,
      Fortran::lower::ExplicitIterSpace &explicitSpace,
      Fortran::lower::ImplicitIterSpace &implicitSpace) {
    ArrayExprLowering ael(converter, stmtCtx, symMap,
                          ConstituentSemantics::CopyInCopyOut, &explicitSpace,
                          &implicitSpace);
    ael.lowerAllocatableArrayAssignment(lhs, rhs);
  }

  /// Lower an assignment to allocatable array, where the LHS array
  /// is represented with \p lhs extended value produced in different
  /// branches created in genReallocIfNeeded(). The RHS lowering
  /// is provided via \p rhsCC continuation.
  void lowerAllocatableArrayAssignment(ExtValue lhs, CC rhsCC) {
    mlir::Location loc = getLoc();
    // Check if the initial destShape is null, which means
    // it has not been computed from rhs (e.g. rhs is scalar).
    bool destShapeIsEmpty = destShape.empty();
    // Create ArrayLoad for the mutable box and save it into `destination`.
    PushSemantics(ConstituentSemantics::ProjectedCopyInCopyOut);
    ccStoreToDest = genarr(lhs);
    // destShape is either non-null on entry to this function,
    // or has been just set by lhs lowering.
    assert(!destShape.empty() && "destShape must have been set.");
    // Finish lowering the loop nest.
    assert(destination && "destination must have been set");
    ExtValue exv = lowerArrayExpression(rhsCC, destination.getType());
    if (!explicitSpaceIsActive())
      fir::ArrayMergeStoreOp::create(
          builder, loc, destination, fir::getBase(exv), destination.getMemref(),
          destination.getSlice(), destination.getTypeparams());
    // destShape may originally be null, if rhs did not define a shape.
    // In this case the destShape is computed from lhs, and we may have
    // multiple different lhs values for different branches created
    // in genReallocIfNeeded(). We cannot reuse destShape computed
    // in different branches, so we have to reset it,
    // so that it is recomputed for the next branch FIR generation.
    if (destShapeIsEmpty)
      destShape.clear();
  }

  /// Assignment to allocatable array.
  ///
  /// The semantics are reverse that of a "regular" array assignment. The rhs
  /// defines the iteration space of the computation and the lhs is
  /// resized/reallocated to fit if necessary.
  void lowerAllocatableArrayAssignment(const Fortran::lower::SomeExpr &lhs,
                                       const Fortran::lower::SomeExpr &rhs) {
    // With assignment to allocatable, we want to lower the rhs first and use
    // its shape to determine if we need to reallocate, etc.
    mlir::Location loc = getLoc();
    // FIXME: If the lhs is in an explicit iteration space, the assignment may
    // be to an array of allocatable arrays rather than a single allocatable
    // array.
    if (explicitSpaceIsActive() && lhs.Rank() > 0)
      TODO(loc, "assignment to whole allocatable array inside FORALL");

    fir::MutableBoxValue mutableBox =
        Fortran::lower::createMutableBox(loc, converter, lhs, symMap);
    if (rhs.Rank() > 0)
      determineShapeOfDest(rhs);
    auto rhsCC = [&]() {
      PushSemantics(ConstituentSemantics::RefTransparent);
      return genarr(rhs);
    }();

    llvm::SmallVector<mlir::Value> lengthParams;
    // Currently no safe way to gather length from rhs (at least for
    // character, it cannot be taken from array_loads since it may be
    // changed by concatenations).
    if ((mutableBox.isCharacter() && !mutableBox.hasNonDeferredLenParams()) ||
        mutableBox.isDerivedWithLenParameters())
      TODO(loc, "gather rhs LEN parameters in assignment to allocatable");

    // The allocatable must take lower bounds from the expr if it is
    // reallocated and the right hand side is not a scalar.
    const bool takeLboundsIfRealloc = rhs.Rank() > 0;
    llvm::SmallVector<mlir::Value> lbounds;
    // When the reallocated LHS takes its lower bounds from the RHS,
    // they will be non default only if the RHS is a whole array
    // variable. Otherwise, lbounds is left empty and default lower bounds
    // will be used.
    if (takeLboundsIfRealloc &&
        Fortran::evaluate::UnwrapWholeSymbolOrComponentDataRef(rhs)) {
      assert(arrayOperands.size() == 1 &&
             "lbounds can only come from one array");
      auto lbs = fir::factory::getOrigins(arrayOperands[0].shape);
      lbounds.append(lbs.begin(), lbs.end());
    }
    auto assignToStorage = [&](fir::ExtendedValue newLhs) {
      // The lambda will be called repeatedly by genReallocIfNeeded().
      lowerAllocatableArrayAssignment(newLhs, rhsCC);
    };
    fir::factory::MutableBoxReallocation realloc =
        fir::factory::genReallocIfNeeded(builder, loc, mutableBox, destShape,
                                         lengthParams, assignToStorage);
    if (explicitSpaceIsActive()) {
      explicitSpace->finalizeContext();
      fir::ResultOp::create(builder, loc, fir::getBase(realloc.newValue));
    }
    fir::factory::finalizeRealloc(builder, loc, mutableBox, lbounds,
                                  takeLboundsIfRealloc, realloc);
  }

  /// Entry point for when an array expression appears in a context where the
  /// result must be boxed. (BoxValue semantics.)
  static ExtValue
  lowerBoxedArrayExpression(Fortran::lower::AbstractConverter &converter,
                            Fortran::lower::SymMap &symMap,
                            Fortran::lower::StatementContext &stmtCtx,
                            const Fortran::lower::SomeExpr &expr) {
    ArrayExprLowering ael{converter, stmtCtx, symMap,
                          ConstituentSemantics::BoxValue};
    return ael.lowerBoxedArrayExpr(expr);
  }

  ExtValue lowerBoxedArrayExpr(const Fortran::lower::SomeExpr &exp) {
    PushSemantics(ConstituentSemantics::BoxValue);
    return Fortran::common::visit(
        [&](const auto &e) {
          auto f = genarr(e);
          ExtValue exv = f(IterationSpace{});
          if (mlir::isa<fir::BaseBoxType>(fir::getBase(exv).getType()))
            return exv;
          fir::emitFatalError(getLoc(), "array must be emboxed");
        },
        exp.u);
  }

  /// Entry point into lowering an expression with rank. This entry point is for
  /// lowering a rhs expression, for example. (RefTransparent semantics.)
  static ExtValue
  lowerNewArrayExpression(Fortran::lower::AbstractConverter &converter,
                          Fortran::lower::SymMap &symMap,
                          Fortran::lower::StatementContext &stmtCtx,
                          const Fortran::lower::SomeExpr &expr) {
    ArrayExprLowering ael{converter, stmtCtx, symMap};
    ael.determineShapeOfDest(expr);
    ExtValue loopRes = ael.lowerArrayExpression(expr);
    fir::ArrayLoadOp dest = ael.destination;
    mlir::Value tempRes = dest.getMemref();
    fir::FirOpBuilder &builder = converter.getFirOpBuilder();
    mlir::Location loc = converter.getCurrentLocation();
    fir::ArrayMergeStoreOp::create(builder, loc, dest, fir::getBase(loopRes),
                                   tempRes, dest.getSlice(),
                                   dest.getTypeparams());

    auto arrTy = mlir::cast<fir::SequenceType>(
        fir::dyn_cast_ptrEleTy(tempRes.getType()));
    if (auto charTy = mlir::dyn_cast<fir::CharacterType>(arrTy.getEleTy())) {
      if (fir::characterWithDynamicLen(charTy))
        TODO(loc, "CHARACTER does not have constant LEN");
      mlir::Value len = builder.createIntegerConstant(
          loc, builder.getCharacterLengthType(), charTy.getLen());
      return fir::CharArrayBoxValue(tempRes, len, dest.getExtents());
    }
    return fir::ArrayBoxValue(tempRes, dest.getExtents());
  }

  static void lowerLazyArrayExpression(
      Fortran::lower::AbstractConverter &converter,
      Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
      const Fortran::lower::SomeExpr &expr, mlir::Value raggedHeader) {
    ArrayExprLowering ael(converter, stmtCtx, symMap);
    ael.lowerLazyArrayExpression(expr, raggedHeader);
  }

  /// Lower the expression \p expr into a buffer that is created on demand. The
  /// variable containing the pointer to the buffer is \p var and the variable
  /// containing the shape of the buffer is \p shapeBuffer.
  void lowerLazyArrayExpression(const Fortran::lower::SomeExpr &expr,
                                mlir::Value header) {
    mlir::Location loc = getLoc();
    mlir::TupleType hdrTy = fir::factory::getRaggedArrayHeaderType(builder);
    mlir::IntegerType i32Ty = builder.getIntegerType(32);

    // Once the loop extents have been computed, which may require being inside
    // some explicit loops, lazily allocate the expression on the heap. The
    // following continuation creates the buffer as needed.
    ccPrelude = [=](llvm::ArrayRef<mlir::Value> shape) {
      mlir::IntegerType i64Ty = builder.getIntegerType(64);
      mlir::Value byteSize = builder.createIntegerConstant(loc, i64Ty, 1);
      fir::runtime::genRaggedArrayAllocate(
          loc, builder, header, /*asHeaders=*/false, byteSize, shape);
    };

    // Create a dummy array_load before the loop. We're storing to a lazy
    // temporary, so there will be no conflict and no copy-in. TODO: skip this
    // as there isn't any necessity for it.
    ccLoadDest = [=](llvm::ArrayRef<mlir::Value> shape) -> fir::ArrayLoadOp {
      mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1);
      auto var = fir::CoordinateOp::create(
          builder, loc, builder.getRefType(hdrTy.getType(1)), header, one);
      auto load = fir::LoadOp::create(builder, loc, var);
      mlir::Type eleTy =
          fir::unwrapSequenceType(fir::unwrapRefType(load.getType()));
      auto seqTy = fir::SequenceType::get(eleTy, shape.size());
      mlir::Value castTo =
          builder.createConvert(loc, fir::HeapType::get(seqTy), load);
      mlir::Value shapeOp = builder.genShape(loc, shape);
      return fir::ArrayLoadOp::create(builder, loc, seqTy, castTo, shapeOp,
                                      /*slice=*/mlir::Value{},
                                      mlir::ValueRange{});
    };
    // Custom lowering of the element store to deal with the extra indirection
    // to the lazy allocated buffer.
    ccStoreToDest = [=](IterSpace iters) {
      mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1);
      auto var = fir::CoordinateOp::create(
          builder, loc, builder.getRefType(hdrTy.getType(1)), header, one);
      auto load = fir::LoadOp::create(builder, loc, var);
      mlir::Type eleTy =
          fir::unwrapSequenceType(fir::unwrapRefType(load.getType()));
      auto seqTy = fir::SequenceType::get(eleTy, iters.iterVec().size());
      auto toTy = fir::HeapType::get(seqTy);
      mlir::Value castTo = builder.createConvert(loc, toTy, load);
      mlir::Value shape = builder.genShape(loc, genIterationShape());
      llvm::SmallVector<mlir::Value> indices = fir::factory::originateIndices(
          loc, builder, castTo.getType(), shape, iters.iterVec());
      auto eleAddr = fir::ArrayCoorOp::create(
          builder, loc, builder.getRefType(eleTy), castTo, shape,
          /*slice=*/mlir::Value{}, indices, destination.getTypeparams());
      mlir::Value eleVal =
          builder.createConvert(loc, eleTy, iters.getElement());
      fir::StoreOp::create(builder, loc, eleVal, eleAddr);
      return iters.innerArgument();
    };

    // Lower the array expression now. Clean-up any temps that may have
    // been generated when lowering `expr` right after the lowered value
    // was stored to the ragged array temporary. The local temps will not
    // be needed afterwards.
    stmtCtx.pushScope();
    [[maybe_unused]] ExtValue loopRes = lowerArrayExpression(expr);
    stmtCtx.finalizeAndPop();
    assert(fir::getBase(loopRes));
  }

  static void
  lowerElementalUserAssignment(Fortran::lower::AbstractConverter &converter,
                               Fortran::lower::SymMap &symMap,
                               Fortran::lower::StatementContext &stmtCtx,
                               Fortran::lower::ExplicitIterSpace &explicitSpace,
                               Fortran::lower::ImplicitIterSpace &implicitSpace,
                               const Fortran::evaluate::ProcedureRef &procRef) {
    ArrayExprLowering ael(converter, stmtCtx, symMap,
                          ConstituentSemantics::CustomCopyInCopyOut,
                          &explicitSpace, &implicitSpace);
    assert(procRef.arguments().size() == 2);
    const auto *lhs = procRef.arguments()[0].value().UnwrapExpr();
    const auto *rhs = procRef.arguments()[1].value().UnwrapExpr();
    assert(lhs && rhs &&
           "user defined assignment arguments must be expressions");
    mlir::func::FuncOp func =
        Fortran::lower::CallerInterface(procRef, converter).getFuncOp();
    ael.lowerElementalUserAssignment(func, *lhs, *rhs);
  }

  void lowerElementalUserAssignment(mlir::func::FuncOp userAssignment,
                                    const Fortran::lower::SomeExpr &lhs,
                                    const Fortran::lower::SomeExpr &rhs) {
    mlir::Location loc = getLoc();
    PushSemantics(ConstituentSemantics::CustomCopyInCopyOut);
    auto genArrayModify = genarr(lhs);
    ccStoreToDest = [=](IterSpace iters) -> ExtValue {
      auto modifiedArray = genArrayModify(iters);
      auto arrayModify = mlir::dyn_cast_or_null<fir::ArrayModifyOp>(
          fir::getBase(modifiedArray).getDefiningOp());
      assert(arrayModify && "must be created by ArrayModifyOp");
      fir::ExtendedValue lhs =
          arrayModifyToExv(builder, loc, destination, arrayModify.getResult(0));
      genScalarUserDefinedAssignmentCall(builder, loc, userAssignment, lhs,
                                         iters.elementExv());
      return modifiedArray;
    };
    determineShapeOfDest(lhs);
    semant = ConstituentSemantics::RefTransparent;
    auto exv = lowerArrayExpression(rhs);
    if (explicitSpaceIsActive()) {
      explicitSpace->finalizeContext();
      fir::ResultOp::create(builder, loc, fir::getBase(exv));
    } else {
      fir::ArrayMergeStoreOp::create(
          builder, loc, destination, fir::getBase(exv), destination.getMemref(),
          destination.getSlice(), destination.getTypeparams());
    }
  }

  /// Lower an elemental subroutine call with at least one array argument.
  /// An elemental subroutine is an exception and does not have copy-in/copy-out
  /// semantics. See 15.8.3.
  /// Do NOT use this for user defined assignments.
  static void
  lowerElementalSubroutine(Fortran::lower::AbstractConverter &converter,
                           Fortran::lower::SymMap &symMap,
                           Fortran::lower::StatementContext &stmtCtx,
                           const Fortran::lower::SomeExpr &call) {
    ArrayExprLowering ael(converter, stmtCtx, symMap,
                          ConstituentSemantics::RefTransparent);
    ael.lowerElementalSubroutine(call);
  }

  static const std::optional<Fortran::evaluate::ActualArgument>
  extractPassedArgFromProcRef(const Fortran::evaluate::ProcedureRef &procRef,
                              Fortran::lower::AbstractConverter &converter) {
    // First look for passed object in actual arguments.
    for (const std::optional<Fortran::evaluate::ActualArgument> &arg :
         procRef.arguments())
      if (arg && arg->isPassedObject())
        return arg;

    // If passed object is not found by here, it means the call was fully
    // resolved to the correct procedure. Look for the pass object in the
    // dummy arguments. Pick the first polymorphic one.
    Fortran::lower::CallerInterface caller(procRef, converter);
    unsigned idx = 0;
    for (const auto &arg : caller.characterize().dummyArguments) {
      if (const auto *dummy =
              std::get_if<Fortran::evaluate::characteristics::DummyDataObject>(
                  &arg.u))
        if (dummy->type.type().IsPolymorphic())
          return procRef.arguments()[idx];
      ++idx;
    }
    return std::nullopt;
  }

  // TODO: See the comment in genarr(const Fortran::lower::Parentheses<T>&).
  // This is skipping generation of copy-in/copy-out code for analysis that is
  // required when arguments are in parentheses.
  void lowerElementalSubroutine(const Fortran::lower::SomeExpr &call) {
    if (const auto *procRef =
            std::get_if<Fortran::evaluate::ProcedureRef>(&call.u))
      setLoweredProcRef(procRef);
    auto f = genarr(call);
    llvm::SmallVector<mlir::Value> shape = genIterationShape();
    auto [iterSpace, insPt] = genImplicitLoops(shape, /*innerArg=*/{});
    f(iterSpace);
    finalizeElementCtx();
    builder.restoreInsertionPoint(insPt);
  }

  ExtValue lowerScalarAssignment(const Fortran::lower::SomeExpr &lhs,
                                 const Fortran::lower::SomeExpr &rhs) {
    PushSemantics(ConstituentSemantics::RefTransparent);
    // 1) Lower the rhs expression with array_fetch op(s).
    IterationSpace iters;
    iters.setElement(genarr(rhs)(iters));
    // 2) Lower the lhs expression to an array_update.
    semant = ConstituentSemantics::ProjectedCopyInCopyOut;
    auto lexv = genarr(lhs)(iters);
    // 3) Finalize the inner context.
    explicitSpace->finalizeContext();
    // 4) Thread the array value updated forward. Note: the lhs might be
    // ill-formed (performing scalar assignment in an array context),
    // in which case there is no array to thread.
    auto loc = getLoc();
    auto createResult = [&](auto op) {
      mlir::Value oldInnerArg = op.getSequence();
      std::size_t offset = explicitSpace->argPosition(oldInnerArg);
      explicitSpace->setInnerArg(offset, fir::getBase(lexv));
      finalizeElementCtx();
      fir::ResultOp::create(builder, loc, fir::getBase(lexv));
    };
    if (mlir::Operation *defOp = fir::getBase(lexv).getDefiningOp()) {
      llvm::TypeSwitch<mlir::Operation *>(defOp)
          .Case([&](fir::ArrayUpdateOp op) { createResult(op); })
          .Case([&](fir::ArrayAmendOp op) { createResult(op); })
          .Case([&](fir::ArrayModifyOp op) { createResult(op); })
          .Default([&](mlir::Operation *) { finalizeElementCtx(); });
    } else {
      // `lhs` isn't from a `fir.array_load`, so there is no array modifications
      // to thread through the iteration space.
      finalizeElementCtx();
    }
    return lexv;
  }

  static ExtValue lowerScalarUserAssignment(
      Fortran::lower::AbstractConverter &converter,
      Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
      Fortran::lower::ExplicitIterSpace &explicitIterSpace,
      mlir::func::FuncOp userAssignmentFunction,
      const Fortran::lower::SomeExpr &lhs,
      const Fortran::lower::SomeExpr &rhs) {
    Fortran::lower::ImplicitIterSpace implicit;
    ArrayExprLowering ael(converter, stmtCtx, symMap,
                          ConstituentSemantics::RefTransparent,
                          &explicitIterSpace, &implicit);
    return ael.lowerScalarUserAssignment(userAssignmentFunction, lhs, rhs);
  }

  ExtValue lowerScalarUserAssignment(mlir::func::FuncOp userAssignment,
                                     const Fortran::lower::SomeExpr &lhs,
                                     const Fortran::lower::SomeExpr &rhs) {
    mlir::Location loc = getLoc();
    if (rhs.Rank() > 0)
      TODO(loc, "user-defined elemental assignment from expression with rank");
    // 1) Lower the rhs expression with array_fetch op(s).
    IterationSpace iters;
    iters.setElement(genarr(rhs)(iters));
    fir::ExtendedValue elementalExv = iters.elementExv();
    // 2) Lower the lhs expression to an array_modify.
    semant = ConstituentSemantics::CustomCopyInCopyOut;
    auto lexv = genarr(lhs)(iters);
    bool isIllFormedLHS = false;
    // 3) Insert the call
    if (auto modifyOp = mlir::dyn_cast<fir::ArrayModifyOp>(
            fir::getBase(lexv).getDefiningOp())) {
      mlir::Value oldInnerArg = modifyOp.getSequence();
      std::size_t offset = explicitSpace->argPosition(oldInnerArg);
      explicitSpace->setInnerArg(offset, fir::getBase(lexv));
      auto lhsLoad = explicitSpace->getLhsLoad(0);
      assert(lhsLoad.has_value());
      fir::ExtendedValue exv =
          arrayModifyToExv(builder, loc, *lhsLoad, modifyOp.getResult(0));
      genScalarUserDefinedAssignmentCall(builder, loc, userAssignment, exv,
                                         elementalExv);
    } else {
      // LHS is ill formed, it is a scalar with no references to FORALL
      // subscripts, so there is actually no array assignment here. The user
      // code is probably bad, but still insert user assignment call since it
      // was not rejected by semantics (a warning was emitted).
      isIllFormedLHS = true;
      genScalarUserDefinedAssignmentCall(builder, getLoc(), userAssignment,
                                         lexv, elementalExv);
    }
    // 4) Finalize the inner context.
    explicitSpace->finalizeContext();
    // 5). Thread the array value updated forward.
    if (!isIllFormedLHS) {
      finalizeElementCtx();
      fir::ResultOp::create(builder, getLoc(), fir::getBase(lexv));
    }
    return lexv;
  }

private:
  void determineShapeOfDest(const fir::ExtendedValue &lhs) {
    destShape = fir::factory::getExtents(getLoc(), builder, lhs);
  }

  void determineShapeOfDest(const Fortran::lower::SomeExpr &lhs) {
    if (!destShape.empty())
      return;
    if (explicitSpaceIsActive() && determineShapeWithSlice(lhs))
      return;
    mlir::Type idxTy = builder.getIndexType();
    mlir::Location loc = getLoc();
    if (std::optional<Fortran::evaluate::ConstantSubscripts> constantShape =
            Fortran::evaluate::GetConstantExtents(converter.getFoldingContext(),
                                                  lhs))
      for (Fortran::common::ConstantSubscript extent : *constantShape)
        destShape.push_back(builder.createIntegerConstant(loc, idxTy, extent));
  }

  bool genShapeFromDataRef(const Fortran::semantics::Symbol &x) {
    return false;
  }
  bool genShapeFromDataRef(const Fortran::evaluate::CoarrayRef &) {
    TODO(getLoc(), "coarray: reference to a coarray in an expression");
    return false;
  }
  bool genShapeFromDataRef(const Fortran::evaluate::Component &x) {
    return x.base().Rank() > 0 ? genShapeFromDataRef(x.base()) : false;
  }
  bool genShapeFromDataRef(const Fortran::evaluate::ArrayRef &x) {
    if (x.Rank() == 0)
      return false;
    if (x.base().Rank() > 0)
      if (genShapeFromDataRef(x.base()))
        return true;
    // x has rank and x.base did not produce a shape.
    ExtValue exv = x.base().IsSymbol() ? asScalarRef(getFirstSym(x.base()))
                                       : asScalarRef(x.base().GetComponent());
    mlir::Location loc = getLoc();
    mlir::IndexType idxTy = builder.getIndexType();
    llvm::SmallVector<mlir::Value> definedShape =
        fir::factory::getExtents(loc, builder, exv);
    mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
    for (auto ss : llvm::enumerate(x.subscript())) {
      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;
  }
  bool genShapeFromDataRef(const Fortran::evaluate::NamedEntity &x) {
    if (x.IsSymbol())
      return genShapeFromDataRef(getFirstSym(x));
    return genShapeFromDataRef(x.GetComponent());
  }
  bool genShapeFromDataRef(const Fortran::evaluate::DataRef &x) {
    return Fortran::common::visit(
        [&](const auto &v) { return genShapeFromDataRef(v); }, x.u);
  }

  /// When in an explicit space, the ranked component must be evaluated to
  /// determine the actual number of iterations when slicing triples are
  /// present. Lower these expressions here.
  bool determineShapeWithSlice(const Fortran::lower::SomeExpr &lhs) {
    LLVM_DEBUG(Fortran::semantics::DumpEvaluateExpr::Dump(
        llvm::dbgs() << "determine shape of:\n", lhs));
    // FIXME: We may not want to use ExtractDataRef here since it doesn't deal
    // with substrings, etc.
    std::optional<Fortran::evaluate::DataRef> dref =
        Fortran::evaluate::ExtractDataRef(lhs);
    return dref.has_value() ? genShapeFromDataRef(*dref) : false;
  }

  /// CHARACTER and derived type elements are treated as memory references. The
  /// numeric types are treated as values.
  static mlir::Type adjustedArraySubtype(mlir::Type ty,
                                         mlir::ValueRange indices) {
    mlir::Type pathTy = fir::applyPathToType(ty, indices);
    assert(pathTy && "indices failed to apply to type");
    return adjustedArrayElementType(pathTy);
  }

  /// Lower rhs of an array expression.
  ExtValue lowerArrayExpression(const Fortran::lower::SomeExpr &exp) {
    mlir::Type resTy = converter.genType(exp);

    if (fir::isPolymorphicType(resTy) &&
        Fortran::evaluate::HasVectorSubscript(exp))
      TODO(getLoc(),
           "polymorphic array expression lowering with vector subscript");

    return Fortran::common::visit(
        [&](const auto &e) { return lowerArrayExpression(genarr(e), resTy); },
        exp.u);
  }
  ExtValue lowerArrayExpression(const ExtValue &exv) {
    assert(!explicitSpace);
    mlir::Type resTy = fir::unwrapPassByRefType(fir::getBase(exv).getType());
    return lowerArrayExpression(genarr(exv), resTy);
  }

  void populateBounds(llvm::SmallVectorImpl<mlir::Value> &bounds,
                      const Fortran::evaluate::Substring *substring) {
    if (!substring)
      return;
    bounds.push_back(fir::getBase(asScalar(substring->lower())));
    if (auto upper = substring->upper())
      bounds.push_back(fir::getBase(asScalar(*upper)));
  }

  /// Convert the original value, \p origVal, to type \p eleTy. When in a
  /// pointer assignment context, generate an appropriate `fir.rebox` for
  /// dealing with any bounds parameters on the pointer assignment.
  mlir::Value convertElementForUpdate(mlir::Location loc, mlir::Type eleTy,
                                      mlir::Value origVal) {
    if (auto origEleTy = fir::dyn_cast_ptrEleTy(origVal.getType()))
      if (mlir::isa<fir::BaseBoxType>(origEleTy)) {
        // If origVal is a box variable, load it so it is in the value domain.
        origVal = fir::LoadOp::create(builder, loc, origVal);
      }
    if (mlir::isa<fir::BoxType>(origVal.getType()) &&
        !mlir::isa<fir::BoxType>(eleTy)) {
      if (isPointerAssignment())
        TODO(loc, "lhs of pointer assignment returned unexpected value");
      TODO(loc, "invalid box conversion in elemental computation");
    }
    if (isPointerAssignment() && mlir::isa<fir::BoxType>(eleTy) &&
        !mlir::isa<fir::BoxType>(origVal.getType())) {
      // This is a pointer assignment and the rhs is a raw reference to a TARGET
      // in memory. Embox the reference so it can be stored to the boxed
      // POINTER variable.
      assert(fir::isa_ref_type(origVal.getType()));
      if (auto eleTy = fir::dyn_cast_ptrEleTy(origVal.getType());
          fir::hasDynamicSize(eleTy))
        TODO(loc, "TARGET of pointer assignment with runtime size/shape");
      auto memrefTy = fir::boxMemRefType(mlir::cast<fir::BoxType>(eleTy));
      auto castTo = builder.createConvert(loc, memrefTy, origVal);
      origVal = fir::EmboxOp::create(builder, loc, eleTy, castTo);
    }
    mlir::Value val = builder.convertWithSemantics(loc, eleTy, origVal);
    if (isBoundsSpec()) {
      assert(lbounds.has_value());
      auto lbs = *lbounds;
      if (lbs.size() > 0) {
        // Rebox the value with user-specified shift.
        auto shiftTy = fir::ShiftType::get(eleTy.getContext(), lbs.size());
        mlir::Value shiftOp = fir::ShiftOp::create(builder, loc, shiftTy, lbs);
        val = fir::ReboxOp::create(builder, loc, eleTy, val, shiftOp,
                                   mlir::Value{});
      }
    } else if (isBoundsRemap()) {
      assert(lbounds.has_value());
      auto lbs = *lbounds;
      if (lbs.size() > 0) {
        // Rebox the value with user-specified shift and shape.
        assert(ubounds.has_value());
        auto shapeShiftArgs = flatZip(lbs, *ubounds);
        auto shapeTy = fir::ShapeShiftType::get(eleTy.getContext(), lbs.size());
        mlir::Value shapeShift =
            fir::ShapeShiftOp::create(builder, loc, shapeTy, shapeShiftArgs);
        val = fir::ReboxOp::create(builder, loc, eleTy, val, shapeShift,
                                   mlir::Value{});
      }
    }
    return val;
  }

  /// Default store to destination implementation.
  /// This implements the default case, which is to assign the value in
  /// `iters.element` into the destination array, `iters.innerArgument`. Handles
  /// by value and by reference assignment.
  CC defaultStoreToDestination(const Fortran::evaluate::Substring *substring) {
    return [=](IterSpace iterSpace) -> ExtValue {
      mlir::Location loc = getLoc();
      mlir::Value innerArg = iterSpace.innerArgument();
      fir::ExtendedValue exv = iterSpace.elementExv();
      mlir::Type arrTy = innerArg.getType();
      mlir::Type eleTy = fir::applyPathToType(arrTy, iterSpace.iterVec());
      if (isAdjustedArrayElementType(eleTy)) {
        // The elemental update is in the memref domain. Under this semantics,
        // we must always copy the computed new element from its location in
        // memory into the destination array.
        mlir::Type resRefTy = builder.getRefType(eleTy);
        // Get a reference to the array element to be amended.
        auto arrayOp = fir::ArrayAccessOp::create(
            builder, loc, resRefTy, innerArg, iterSpace.iterVec(),
            fir::factory::getTypeParams(loc, builder, destination));
        if (auto charTy = mlir::dyn_cast<fir::CharacterType>(eleTy)) {
          llvm::SmallVector<mlir::Value> substringBounds;
          populateBounds(substringBounds, substring);
          mlir::Value dstLen = fir::factory::genLenOfCharacter(
              builder, loc, destination, iterSpace.iterVec(), substringBounds);
          fir::ArrayAmendOp amend = createCharArrayAmend(
              loc, builder, arrayOp, dstLen, exv, innerArg, substringBounds);
          return abstractArrayExtValue(amend, dstLen);
        }
        if (fir::isa_derived(eleTy)) {
          fir::ArrayAmendOp amend = createDerivedArrayAmend(
              loc, destination, builder, arrayOp, exv, eleTy, innerArg);
          return abstractArrayExtValue(amend /*FIXME: typeparams?*/);
        }
        assert(mlir::isa<fir::SequenceType>(eleTy) && "must be an array");
        TODO(loc, "array (as element) assignment");
      }
      // By value semantics. The element is being assigned by value.
      auto ele = convertElementForUpdate(loc, eleTy, fir::getBase(exv));
      auto update = fir::ArrayUpdateOp::create(builder, loc, arrTy, innerArg,
                                               ele, iterSpace.iterVec(),
                                               destination.getTypeparams());
      return abstractArrayExtValue(update);
    };
  }

  /// For an elemental array expression.
  ///   1. Lower the scalars and array loads.
  ///   2. Create the iteration space.
  ///   3. Create the element-by-element computation in the loop.
  ///   4. Return the resulting array value.
  /// If no destination was set in the array context, a temporary of
  /// \p resultTy will be created to hold the evaluated expression.
  /// Otherwise, \p resultTy is ignored and the expression is evaluated
  /// in the destination. \p f is a continuation built from an
  /// evaluate::Expr or an ExtendedValue.
  ExtValue lowerArrayExpression(CC f, mlir::Type resultTy) {
    mlir::Location loc = getLoc();
    auto [iterSpace, insPt] = genIterSpace(resultTy);
    auto exv = f(iterSpace);
    iterSpace.setElement(std::move(exv));
    auto lambda = ccStoreToDest
                      ? *ccStoreToDest
                      : defaultStoreToDestination(/*substring=*/nullptr);
    mlir::Value updVal = fir::getBase(lambda(iterSpace));
    finalizeElementCtx();
    fir::ResultOp::create(builder, loc, updVal);
    builder.restoreInsertionPoint(insPt);
    return abstractArrayExtValue(iterSpace.outerResult());
  }

  /// Compute the shape of a slice.
  llvm::SmallVector<mlir::Value> computeSliceShape(mlir::Value slice) {
    llvm::SmallVector<mlir::Value> slicedShape;
    auto slOp = mlir::cast<fir::SliceOp>(slice.getDefiningOp());
    mlir::Operation::operand_range triples = slOp.getTriples();
    mlir::IndexType idxTy = builder.getIndexType();
    mlir::Location loc = getLoc();
    for (unsigned i = 0, end = triples.size(); i < end; i += 3) {
      if (!mlir::isa_and_nonnull<fir::UndefOp>(
              triples[i + 1].getDefiningOp())) {
        // (..., lb:ub:step, ...) case:  extent = max((ub-lb+step)/step, 0)
        // See Fortran 2018 9.5.3.3.2 section for more details.
        mlir::Value res = builder.genExtentFromTriplet(
            loc, triples[i], triples[i + 1], triples[i + 2], idxTy);
        slicedShape.emplace_back(res);
      } else {
        // do nothing. `..., i, ...` case, so dimension is dropped.
      }
    }
    return slicedShape;
  }

  /// Get the shape from an ArrayOperand. The shape of the array is adjusted if
  /// the array was sliced.
  llvm::SmallVector<mlir::Value> getShape(ArrayOperand array) {
    if (array.slice)
      return computeSliceShape(array.slice);
    if (mlir::isa<fir::BaseBoxType>(array.memref.getType()))
      return fir::factory::readExtents(builder, getLoc(),
                                       fir::BoxValue{array.memref});
    return fir::factory::getExtents(array.shape);
  }

  /// Get the shape from an ArrayLoad.
  llvm::SmallVector<mlir::Value> getShape(fir::ArrayLoadOp arrayLoad) {
    return getShape(ArrayOperand{arrayLoad.getMemref(), arrayLoad.getShape(),
                                 arrayLoad.getSlice()});
  }

  /// Returns the first array operand that may not be absent. If all
  /// array operands may be absent, return the first one.
  const ArrayOperand &getInducingShapeArrayOperand() const {
    assert(!arrayOperands.empty());
    for (const ArrayOperand &op : arrayOperands)
      if (!op.mayBeAbsent)
        return op;
    // If all arrays operand appears in optional position, then none of them
    // is allowed to be absent as per 15.5.2.12 point 3. (6). Just pick the
    // first operands.
    // TODO: There is an opportunity to add a runtime check here that
    // this array is present as required.
    return arrayOperands[0];
  }

  /// Generate the shape of the iteration space over the array expression. The
  /// iteration space may be implicit, explicit, or both. If it is implied it is
  /// based on the destination and operand array loads, or an optional
  /// Fortran::evaluate::Shape from the front end. If the shape is explicit,
  /// this returns any implicit shape component, if it exists.
  llvm::SmallVector<mlir::Value> genIterationShape() {
    // Use the precomputed destination shape.
    if (!destShape.empty())
      return destShape;
    // Otherwise, use the destination's shape.
    if (destination)
      return getShape(destination);
    // Otherwise, use the first ArrayLoad operand shape.
    if (!arrayOperands.empty())
      return getShape(getInducingShapeArrayOperand());
    // Otherwise, in elemental context, try to find the passed object and
    // retrieve the iteration shape from it.
    if (loweredProcRef && loweredProcRef->IsElemental()) {
      const std::optional<Fortran::evaluate::ActualArgument> passArg =
          extractPassedArgFromProcRef(*loweredProcRef, converter);
      if (passArg) {
        ExtValue exv = asScalarRef(*passArg->UnwrapExpr());
        fir::FirOpBuilder *builder = &converter.getFirOpBuilder();
        auto extents = fir::factory::getExtents(getLoc(), *builder, exv);
        if (extents.size() == 0)
          TODO(getLoc(), "getting shape from polymorphic array in elemental "
                         "procedure reference");
        return extents;
      }
    }
    fir::emitFatalError(getLoc(),
                        "failed to compute the array expression shape");
  }

  bool explicitSpaceIsActive() const {
    return explicitSpace && explicitSpace->isActive();
  }

  bool implicitSpaceHasMasks() const {
    return implicitSpace && !implicitSpace->empty();
  }

  CC genMaskAccess(mlir::Value tmp, mlir::Value shape) {
    mlir::Location loc = getLoc();
    return [=, builder = &converter.getFirOpBuilder()](IterSpace iters) {
      mlir::Type arrTy = fir::dyn_cast_ptrOrBoxEleTy(tmp.getType());
      auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
      mlir::Type eleRefTy = builder->getRefType(eleTy);
      mlir::IntegerType i1Ty = builder->getI1Type();
      // Adjust indices for any shift of the origin of the array.
      llvm::SmallVector<mlir::Value> indices = fir::factory::originateIndices(
          loc, *builder, tmp.getType(), shape, iters.iterVec());
      auto addr = fir::ArrayCoorOp::create(*builder, loc, eleRefTy, tmp, shape,
                                           /*slice=*/mlir::Value{}, indices,
                                           /*typeParams=*/mlir::ValueRange{});
      auto load = fir::LoadOp::create(*builder, loc, addr);
      return builder->createConvert(loc, i1Ty, load);
    };
  }

  /// Construct the incremental instantiations of the ragged array structure.
  /// Rebind the lazy buffer variable, etc. as we go.
  template <bool withAllocation = false>
  mlir::Value prepareRaggedArrays(Fortran::lower::FrontEndExpr expr) {
    assert(explicitSpaceIsActive());
    mlir::Location loc = getLoc();
    mlir::TupleType raggedTy = fir::factory::getRaggedArrayHeaderType(builder);
    llvm::SmallVector<llvm::SmallVector<fir::DoLoopOp>> loopStack =
        explicitSpace->getLoopStack();
    const std::size_t depth = loopStack.size();
    mlir::IntegerType i64Ty = builder.getIntegerType(64);
    [[maybe_unused]] mlir::Value byteSize =
        builder.createIntegerConstant(loc, i64Ty, 1);
    mlir::Value header = implicitSpace->lookupMaskHeader(expr);
    for (std::remove_const_t<decltype(depth)> i = 0; i < depth; ++i) {
      auto insPt = builder.saveInsertionPoint();
      if (i < depth - 1)
        builder.setInsertionPoint(loopStack[i + 1][0]);

      // Compute and gather the extents.
      llvm::SmallVector<mlir::Value> extents;
      for (auto doLoop : loopStack[i])
        extents.push_back(builder.genExtentFromTriplet(
            loc, doLoop.getLowerBound(), doLoop.getUpperBound(),
            doLoop.getStep(), i64Ty));
      if constexpr (withAllocation) {
        fir::runtime::genRaggedArrayAllocate(
            loc, builder, header, /*asHeader=*/true, byteSize, extents);
      }

      // Compute the dynamic position into the header.
      llvm::SmallVector<mlir::Value> offsets;
      for (auto doLoop : loopStack[i]) {
        auto m = mlir::arith::SubIOp::create(
            builder, loc, doLoop.getInductionVar(), doLoop.getLowerBound());
        auto n =
            mlir::arith::DivSIOp::create(builder, loc, m, doLoop.getStep());
        mlir::Value one = builder.createIntegerConstant(loc, n.getType(), 1);
        offsets.push_back(mlir::arith::AddIOp::create(builder, loc, n, one));
      }
      mlir::IntegerType i32Ty = builder.getIntegerType(32);
      mlir::Value uno = builder.createIntegerConstant(loc, i32Ty, 1);
      mlir::Type coorTy = builder.getRefType(raggedTy.getType(1));
      auto hdOff = fir::CoordinateOp::create(builder, loc, coorTy, header, uno);
      auto toTy = fir::SequenceType::get(raggedTy, offsets.size());
      mlir::Type toRefTy = builder.getRefType(toTy);
      auto ldHdr = fir::LoadOp::create(builder, loc, hdOff);
      mlir::Value hdArr = builder.createConvert(loc, toRefTy, ldHdr);
      auto shapeOp = builder.genShape(loc, extents);
      header = fir::ArrayCoorOp::create(
          builder, loc, builder.getRefType(raggedTy), hdArr, shapeOp,
          /*slice=*/mlir::Value{}, offsets,
          /*typeparams=*/mlir::ValueRange{});
      auto hdrVar =
          fir::CoordinateOp::create(builder, loc, coorTy, header, uno);
      auto inVar = fir::LoadOp::create(builder, loc, hdrVar);
      mlir::Value two = builder.createIntegerConstant(loc, i32Ty, 2);
      mlir::Type coorTy2 = builder.getRefType(raggedTy.getType(2));
      auto hdrSh =
          fir::CoordinateOp::create(builder, loc, coorTy2, header, two);
      auto shapePtr = fir::LoadOp::create(builder, loc, hdrSh);
      // Replace the binding.
      implicitSpace->rebind(expr, genMaskAccess(inVar, shapePtr));
      if (i < depth - 1)
        builder.restoreInsertionPoint(insPt);
    }
    return header;
  }

  /// Lower mask expressions with implied iteration spaces from the variants of
  /// WHERE syntax. Since it is legal for mask expressions to have side-effects
  /// and modify values that will be used for the lhs, rhs, or both of
  /// subsequent assignments, the mask must be evaluated before the assignment
  /// is processed.
  /// Mask expressions are array expressions too.
  void genMasks() {
    // Lower the mask expressions, if any.
    if (implicitSpaceHasMasks()) {
      mlir::Location loc = getLoc();
      // Mask expressions are array expressions too.
      for (const auto *e : implicitSpace->getExprs())
        if (e && !implicitSpace->isLowered(e)) {
          if (mlir::Value var = implicitSpace->lookupMaskVariable(e)) {
            // Allocate the mask buffer lazily.
            assert(explicitSpaceIsActive());
            mlir::Value header =
                prepareRaggedArrays</*withAllocations=*/true>(e);
            Fortran::lower::createLazyArrayTempValue(converter, *e, header,
                                                     symMap, stmtCtx);
            // Close the explicit loops.
            fir::ResultOp::create(builder, loc, explicitSpace->getInnerArgs());
            builder.setInsertionPointAfter(explicitSpace->getOuterLoop());
            // Open a new copy of the explicit loop nest.
            explicitSpace->genLoopNest();
            continue;
          }
          fir::ExtendedValue tmp = Fortran::lower::createSomeArrayTempValue(
              converter, *e, symMap, stmtCtx);
          mlir::Value shape = builder.createShape(loc, tmp);
          implicitSpace->bind(e, genMaskAccess(fir::getBase(tmp), shape));
        }

      // Set buffer from the header.
      for (const auto *e : implicitSpace->getExprs()) {
        if (!e)
          continue;
        if (implicitSpace->lookupMaskVariable(e)) {
          // Index into the ragged buffer to retrieve cached results.
          const int rank = e->Rank();
          assert(destShape.empty() ||
                 static_cast<std::size_t>(rank) == destShape.size());
          mlir::Value header = prepareRaggedArrays(e);
          mlir::TupleType raggedTy =
              fir::factory::getRaggedArrayHeaderType(builder);
          mlir::IntegerType i32Ty = builder.getIntegerType(32);
          mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1);
          auto coor1 = fir::CoordinateOp::create(
              builder, loc, builder.getRefType(raggedTy.getType(1)), header,
              one);
          auto db = fir::LoadOp::create(builder, loc, coor1);
          mlir::Type eleTy =
              fir::unwrapSequenceType(fir::unwrapRefType(db.getType()));
          mlir::Type buffTy =
              builder.getRefType(fir::SequenceType::get(eleTy, rank));
          // Address of ragged buffer data.
          mlir::Value buff = builder.createConvert(loc, buffTy, db);

          mlir::Value two = builder.createIntegerConstant(loc, i32Ty, 2);
          auto coor2 = fir::CoordinateOp::create(
              builder, loc, builder.getRefType(raggedTy.getType(2)), header,
              two);
          auto shBuff = fir::LoadOp::create(builder, loc, coor2);
          mlir::IntegerType i64Ty = builder.getIntegerType(64);
          mlir::IndexType idxTy = builder.getIndexType();
          llvm::SmallVector<mlir::Value> extents;
          for (std::remove_const_t<decltype(rank)> i = 0; i < rank; ++i) {
            mlir::Value off = builder.createIntegerConstant(loc, i32Ty, i);
            auto coor = fir::CoordinateOp::create(
                builder, loc, builder.getRefType(i64Ty), shBuff, off);
            auto ldExt = fir::LoadOp::create(builder, loc, coor);
            extents.push_back(builder.createConvert(loc, idxTy, ldExt));
          }
          if (destShape.empty())
            destShape = extents;
          // Construct shape of buffer.
          mlir::Value shapeOp = builder.genShape(loc, extents);

          // Replace binding with the local result.
          implicitSpace->rebind(e, genMaskAccess(buff, shapeOp));
        }
      }
    }
  }

  // FIXME: should take multiple inner arguments.
  std::pair<IterationSpace, mlir::OpBuilder::InsertPoint>
  genImplicitLoops(mlir::ValueRange shape, mlir::Value innerArg) {
    mlir::Location loc = getLoc();
    mlir::IndexType idxTy = builder.getIndexType();
    mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
    mlir::Value zero = builder.createIntegerConstant(loc, idxTy, 0);
    llvm::SmallVector<mlir::Value> loopUppers;

    // Convert any implied shape to closed interval form. The fir.do_loop will
    // run from 0 to `extent - 1` inclusive.
    for (auto extent : shape)
      loopUppers.push_back(
          mlir::arith::SubIOp::create(builder, loc, extent, one));

    // Iteration space is created with outermost columns, innermost rows
    llvm::SmallVector<fir::DoLoopOp> loops;

    const std::size_t loopDepth = loopUppers.size();
    llvm::SmallVector<mlir::Value> ivars;

    for (auto i : llvm::enumerate(llvm::reverse(loopUppers))) {
      if (i.index() > 0) {
        assert(!loops.empty());
        builder.setInsertionPointToStart(loops.back().getBody());
      }
      fir::DoLoopOp loop;
      if (innerArg) {
        loop = fir::DoLoopOp::create(
            builder, loc, zero, i.value(), one, isUnordered(),
            /*finalCount=*/false, mlir::ValueRange{innerArg});
        innerArg = loop.getRegionIterArgs().front();
        if (explicitSpaceIsActive())
          explicitSpace->setInnerArg(0, innerArg);
      } else {
        loop = fir::DoLoopOp::create(builder, loc, zero, i.value(), one,
                                     isUnordered(),
                                     /*finalCount=*/false);
      }
      ivars.push_back(loop.getInductionVar());
      loops.push_back(loop);
    }

    if (innerArg)
      for (std::remove_const_t<decltype(loopDepth)> i = 0; i + 1 < loopDepth;
           ++i) {
        builder.setInsertionPointToEnd(loops[i].getBody());
        fir::ResultOp::create(builder, loc, loops[i + 1].getResult(0));
      }

    // Move insertion point to the start of the innermost loop in the nest.
    builder.setInsertionPointToStart(loops.back().getBody());
    // Set `afterLoopNest` to just after the entire loop nest.
    auto currPt = builder.saveInsertionPoint();
    builder.setInsertionPointAfter(loops[0]);
    auto afterLoopNest = builder.saveInsertionPoint();
    builder.restoreInsertionPoint(currPt);

    // Put the implicit loop variables in row to column order to match FIR's
    // Ops. (The loops were constructed from outermost column to innermost
    // row.)
    mlir::Value outerRes;
    if (loops[0].getNumResults() != 0)
      outerRes = loops[0].getResult(0);
    return {IterationSpace(innerArg, outerRes, llvm::reverse(ivars)),
            afterLoopNest};
  }

  /// Build the iteration space into which the array expression will be lowered.
  /// The resultType is used to create a temporary, if needed.
  std::pair<IterationSpace, mlir::OpBuilder::InsertPoint>
  genIterSpace(mlir::Type resultType) {
    mlir::Location loc = getLoc();
    llvm::SmallVector<mlir::Value> shape = genIterationShape();
    if (!destination) {
      // Allocate storage for the result if it is not already provided.
      destination = createAndLoadSomeArrayTemp(resultType, shape);
    }

    // Generate the lazy mask allocation, if one was given.
    if (ccPrelude)
      (*ccPrelude)(shape);

    // Now handle the implicit loops.
    mlir::Value inner = explicitSpaceIsActive()
                            ? explicitSpace->getInnerArgs().front()
                            : destination.getResult();
    auto [iters, afterLoopNest] = genImplicitLoops(shape, inner);
    mlir::Value innerArg = iters.innerArgument();

    // Generate the mask conditional structure, if there are masks. Unlike the
    // explicit masks, which are interleaved, these mask expression appear in
    // the innermost loop.
    if (implicitSpaceHasMasks()) {
      // Recover the cached condition from the mask buffer.
      auto genCond = [&](Fortran::lower::FrontEndExpr e, IterSpace iters) {
        return implicitSpace->getBoundClosure(e)(iters);
      };

      // Handle the negated conditions in topological order of the WHERE
      // clauses. See 10.2.3.2p4 as to why this control structure is produced.
      for (llvm::SmallVector<Fortran::lower::FrontEndExpr> maskExprs :
           implicitSpace->getMasks()) {
        const std::size_t size = maskExprs.size() - 1;
        auto genFalseBlock = [&](const auto *e, auto &&cond) {
          auto ifOp = fir::IfOp::create(builder, loc,
                                        mlir::TypeRange{innerArg.getType()},
                                        fir::getBase(cond),
                                        /*withElseRegion=*/true);
          fir::ResultOp::create(builder, loc, ifOp.getResult(0));
          builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
          fir::ResultOp::create(builder, loc, innerArg);
          builder.setInsertionPointToStart(&ifOp.getElseRegion().front());
        };
        auto genTrueBlock = [&](const auto *e, auto &&cond) {
          auto ifOp = fir::IfOp::create(builder, loc,
                                        mlir::TypeRange{innerArg.getType()},
                                        fir::getBase(cond),
                                        /*withElseRegion=*/true);
          fir::ResultOp::create(builder, loc, ifOp.getResult(0));
          builder.setInsertionPointToStart(&ifOp.getElseRegion().front());
          fir::ResultOp::create(builder, loc, innerArg);
          builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
        };
        for (std::remove_const_t<decltype(size)> i = 0; i < size; ++i)
          if (const auto *e = maskExprs[i])
            genFalseBlock(e, genCond(e, iters));

        // The last condition is either non-negated or unconditionally negated.
        if (const auto *e = maskExprs[size])
          genTrueBlock(e, genCond(e, iters));
      }
    }

    // We're ready to lower the body (an assignment statement) for this context
    // of loop nests at this point.
    return {iters, afterLoopNest};
  }

  fir::ArrayLoadOp
  createAndLoadSomeArrayTemp(mlir::Type type,
                             llvm::ArrayRef<mlir::Value> shape) {
    mlir::Location loc = getLoc();
    if (fir::isPolymorphicType(type))
      TODO(loc, "polymorphic array temporary");
    if (ccLoadDest)
      return (*ccLoadDest)(shape);
    auto seqTy = mlir::dyn_cast<fir::SequenceType>(type);
    assert(seqTy && "must be an array");
    // TODO: Need to thread the LEN parameters here. For character, they may
    // differ from the operands length (e.g concatenation). So the array loads
    // type parameters are not enough.
    if (auto charTy = mlir::dyn_cast<fir::CharacterType>(seqTy.getEleTy()))
      if (charTy.hasDynamicLen())
        TODO(loc, "character array expression temp with dynamic length");
    if (auto recTy = mlir::dyn_cast<fir::RecordType>(seqTy.getEleTy()))
      if (recTy.getNumLenParams() > 0)
        TODO(loc, "derived type array expression temp with LEN parameters");
    if (mlir::Type eleTy = fir::unwrapSequenceType(type);
        fir::isRecordWithAllocatableMember(eleTy))
      TODO(loc, "creating an array temp where the element type has "
                "allocatable members");
    mlir::Value temp =
        !seqTy.hasDynamicExtents()
            ? fir::AllocMemOp::create(builder, loc, type)
            : fir::AllocMemOp::create(builder, loc, type, ".array.expr",
                                      mlir::ValueRange{}, shape);
    fir::FirOpBuilder *bldr = &converter.getFirOpBuilder();
    stmtCtx.attachCleanup(
        [bldr, loc, temp]() { fir::FreeMemOp::create(*bldr, loc, temp); });
    mlir::Value shapeOp = genShapeOp(shape);
    return fir::ArrayLoadOp::create(builder, loc, seqTy, temp, shapeOp,
                                    /*slice=*/mlir::Value{},
                                    mlir::ValueRange{});
  }

  static fir::ShapeOp genShapeOp(mlir::Location loc, fir::FirOpBuilder &builder,
                                 llvm::ArrayRef<mlir::Value> shape) {
    mlir::IndexType idxTy = builder.getIndexType();
    llvm::SmallVector<mlir::Value> idxShape;
    for (auto s : shape)
      idxShape.push_back(builder.createConvert(loc, idxTy, s));
    return fir::ShapeOp::create(builder, loc, idxShape);
  }

  fir::ShapeOp genShapeOp(llvm::ArrayRef<mlir::Value> shape) {
    return genShapeOp(getLoc(), builder, shape);
  }

  //===--------------------------------------------------------------------===//
  // Expression traversal and lowering.
  //===--------------------------------------------------------------------===//

  /// Lower the expression, \p x, in a scalar context.
  template <typename A>
  ExtValue asScalar(const A &x) {
    return ScalarExprLowering{getLoc(), converter, symMap, stmtCtx}.genval(x);
  }

  /// Lower the expression, \p x, in a scalar context. If this is an explicit
  /// space, the expression may be scalar and refer to an array. We want to
  /// raise the array access to array operations in FIR to analyze potential
  /// conflicts even when the result is a scalar element.
  template <typename A>
  ExtValue asScalarArray(const A &x) {
    return explicitSpaceIsActive() && !isPointerAssignment()
               ? genarr(x)(IterationSpace{})
               : asScalar(x);
  }

  /// Lower the expression in a scalar context to a memory reference.
  template <typename A>
  ExtValue asScalarRef(const A &x) {
    return ScalarExprLowering{getLoc(), converter, symMap, stmtCtx}.gen(x);
  }

  /// Lower an expression without dereferencing any indirection that may be
  /// a nullptr (because this is an absent optional or unallocated/disassociated
  /// descriptor). The returned expression cannot be addressed directly, it is
  /// meant to inquire about its status before addressing the related entity.
  template <typename A>
  ExtValue asInquired(const A &x) {
    return ScalarExprLowering{getLoc(), converter, symMap, stmtCtx}
        .lowerIntrinsicArgumentAsInquired(x);
  }

  /// Some temporaries are allocated on an element-by-element basis during the
  /// array expression evaluation. Collect the cleanups here so the resources
  /// can be freed before the next loop iteration, avoiding memory leaks. etc.
  Fortran::lower::StatementContext &getElementCtx() {
    if (!elementCtx) {
      stmtCtx.pushScope();
      elementCtx = true;
    }
    return stmtCtx;
  }

  /// If there were temporaries created for this element evaluation, finalize
  /// and deallocate the resources now. This should be done just prior to the
  /// fir::ResultOp at the end of the innermost loop.
  void finalizeElementCtx() {
    if (elementCtx) {
      stmtCtx.finalizeAndPop();
      elementCtx = false;
    }
  }

  /// Lower an elemental function array argument. This ensures array
  /// sub-expressions that are not variables and must be passed by address
  /// are lowered by value and placed in memory.
  template <typename A>
  CC genElementalArgument(const A &x) {
    // Ensure the returned element is in memory if this is what was requested.
    if ((semant == ConstituentSemantics::RefOpaque ||
         semant == ConstituentSemantics::DataAddr ||
         semant == ConstituentSemantics::ByValueArg)) {
      if (!Fortran::evaluate::IsVariable(x)) {
        PushSemantics(ConstituentSemantics::DataValue);
        CC cc = genarr(x);
        mlir::Location loc = getLoc();
        if (isParenthesizedVariable(x)) {
          // Parenthesised variables are lowered to a reference to the variable
          // storage. When passing it as an argument, a copy must be passed.
          return [=](IterSpace iters) -> ExtValue {
            return createInMemoryScalarCopy(builder, loc, cc(iters));
          };
        }
        mlir::Type storageType =
            fir::unwrapSequenceType(converter.genType(toEvExpr(x)));
        return [=](IterSpace iters) -> ExtValue {
          return placeScalarValueInMemory(builder, loc, cc(iters), storageType);
        };
      } else if (isArray(x)) {
        // An array reference is needed, but the indices used in its path must
        // still be retrieved by value.
        assert(!nextPathSemant && "Next path semantics already set!");
        nextPathSemant = ConstituentSemantics::RefTransparent;
        CC cc = genarr(x);
        assert(!nextPathSemant && "Next path semantics wasn't used!");
        return cc;
      }
    }
    return genarr(x);
  }

  // A reference to a Fortran elemental intrinsic or intrinsic module procedure.
  CC genElementalIntrinsicProcRef(
      const Fortran::evaluate::ProcedureRef &procRef,
      std::optional<mlir::Type> retTy,
      std::optional<const Fortran::evaluate::SpecificIntrinsic> intrinsic =
          std::nullopt) {

    llvm::SmallVector<CC> operands;
    std::string name =
        intrinsic ? intrinsic->name
                  : procRef.proc().GetSymbol()->GetUltimate().name().ToString();
    const fir::IntrinsicArgumentLoweringRules *argLowering =
        fir::getIntrinsicArgumentLowering(name);
    mlir::Location loc = getLoc();
    if (intrinsic && Fortran::lower::intrinsicRequiresCustomOptionalHandling(
                         procRef, *intrinsic, converter)) {
      using CcPairT = std::pair<CC, std::optional<mlir::Value>>;
      llvm::SmallVector<CcPairT> operands;
      auto prepareOptionalArg = [&](const Fortran::lower::SomeExpr &expr) {
        if (expr.Rank() == 0) {
          ExtValue optionalArg = this->asInquired(expr);
          mlir::Value isPresent =
              genActualIsPresentTest(builder, loc, optionalArg);
          operands.emplace_back(
              [=](IterSpace iters) -> ExtValue {
                return genLoad(builder, loc, optionalArg);
              },
              isPresent);
        } else {
          auto [cc, isPresent, _] = this->genOptionalArrayFetch(expr);
          operands.emplace_back(cc, isPresent);
        }
      };
      auto prepareOtherArg = [&](const Fortran::lower::SomeExpr &expr,
                                 fir::LowerIntrinsicArgAs lowerAs) {
        assert(lowerAs == fir::LowerIntrinsicArgAs::Value &&
               "expect value arguments for elemental intrinsic");
        PushSemantics(ConstituentSemantics::RefTransparent);
        operands.emplace_back(genElementalArgument(expr), std::nullopt);
      };
      Fortran::lower::prepareCustomIntrinsicArgument(
          procRef, *intrinsic, retTy, prepareOptionalArg, prepareOtherArg,
          converter);

      fir::FirOpBuilder *bldr = &converter.getFirOpBuilder();
      return [=](IterSpace iters) -> ExtValue {
        auto getArgument = [&](std::size_t i, bool) -> ExtValue {
          return operands[i].first(iters);
        };
        auto isPresent = [&](std::size_t i) -> std::optional<mlir::Value> {
          return operands[i].second;
        };
        return Fortran::lower::lowerCustomIntrinsic(
            *bldr, loc, name, retTy, isPresent, getArgument, operands.size(),
            getElementCtx());
      };
    }
    /// Otherwise, pre-lower arguments and use intrinsic lowering utility.
    for (const auto &arg : llvm::enumerate(procRef.arguments())) {
      const auto *expr =
          Fortran::evaluate::UnwrapExpr<Fortran::lower::SomeExpr>(arg.value());
      if (!expr) {
        // Absent optional.
        operands.emplace_back([=](IterSpace) { return mlir::Value{}; });
      } else if (!argLowering) {
        // No argument lowering instruction, lower by value.
        PushSemantics(ConstituentSemantics::RefTransparent);
        operands.emplace_back(genElementalArgument(*expr));
      } else {
        // Ad-hoc argument lowering handling.
        fir::ArgLoweringRule argRules =
            fir::lowerIntrinsicArgumentAs(*argLowering, arg.index());
        if (argRules.handleDynamicOptional &&
            Fortran::evaluate::MayBePassedAsAbsentOptional(*expr)) {
          // Currently, there is not elemental intrinsic that requires lowering
          // a potentially absent argument to something else than a value (apart
          // from character MAX/MIN that are handled elsewhere.)
          if (argRules.lowerAs != fir::LowerIntrinsicArgAs::Value)
            TODO(loc, "non trivial optional elemental intrinsic array "
                      "argument");
          PushSemantics(ConstituentSemantics::RefTransparent);
          operands.emplace_back(genarrForwardOptionalArgumentToCall(*expr));
          continue;
        }
        switch (argRules.lowerAs) {
        case fir::LowerIntrinsicArgAs::Value: {
          PushSemantics(ConstituentSemantics::RefTransparent);
          operands.emplace_back(genElementalArgument(*expr));
        } break;
        case fir::LowerIntrinsicArgAs::Addr: {
          // Note: assume does not have Fortran VALUE attribute semantics.
          PushSemantics(ConstituentSemantics::RefOpaque);
          operands.emplace_back(genElementalArgument(*expr));
        } break;
        case fir::LowerIntrinsicArgAs::Box: {
          PushSemantics(ConstituentSemantics::RefOpaque);
          auto lambda = genElementalArgument(*expr);
          operands.emplace_back([=](IterSpace iters) {
            return builder.createBox(loc, lambda(iters));
          });
        } break;
        case fir::LowerIntrinsicArgAs::Inquired:
          TODO(loc, "intrinsic function with inquired argument");
          break;
        }
      }
    }

    // Let the intrinsic library lower the intrinsic procedure call
    return [=](IterSpace iters) {
      llvm::SmallVector<ExtValue> args;
      for (const auto &cc : operands)
        args.push_back(cc(iters));
      return Fortran::lower::genIntrinsicCall(builder, loc, name, retTy, args,
                                              getElementCtx());
    };
  }

  /// Lower a procedure reference to a user-defined elemental procedure.
  CC genElementalUserDefinedProcRef(
      const Fortran::evaluate::ProcedureRef &procRef,
      std::optional<mlir::Type> retTy) {
    using PassBy = Fortran::lower::CallerInterface::PassEntityBy;

    // 10.1.4 p5. Impure elemental procedures must be called in element order.
    if (const Fortran::semantics::Symbol *procSym = procRef.proc().GetSymbol())
      if (!Fortran::semantics::IsPureProcedure(*procSym))
        setUnordered(false);

    Fortran::lower::CallerInterface caller(procRef, converter);
    llvm::SmallVector<CC> operands;
    operands.reserve(caller.getPassedArguments().size());
    mlir::Location loc = getLoc();
    mlir::FunctionType callSiteType = caller.genFunctionType();
    for (const Fortran::lower::CallInterface<
             Fortran::lower::CallerInterface>::PassedEntity &arg :
         caller.getPassedArguments()) {
      // 15.8.3 p1. Elemental procedure with intent(out)/intent(inout)
      // arguments must be called in element order.
      if (arg.mayBeModifiedByCall())
        setUnordered(false);
      const auto *actual = arg.entity;
      mlir::Type argTy = callSiteType.getInput(arg.firArgument);
      if (!actual) {
        // Optional dummy argument for which there is no actual argument.
        auto absent = fir::AbsentOp::create(builder, loc, argTy);
        operands.emplace_back([=](IterSpace) { return absent; });
        continue;
      }
      const auto *expr = actual->UnwrapExpr();
      if (!expr)
        TODO(loc, "assumed type actual argument");

      LLVM_DEBUG(expr->AsFortran(llvm::dbgs()
                                 << "argument: " << arg.firArgument << " = [")
                 << "]\n");
      if (arg.isOptional() &&
          Fortran::evaluate::MayBePassedAsAbsentOptional(*expr))
        TODO(loc,
             "passing dynamically optional argument to elemental procedures");
      switch (arg.passBy) {
      case PassBy::Value: {
        // True pass-by-value semantics.
        PushSemantics(ConstituentSemantics::RefTransparent);
        operands.emplace_back(genElementalArgument(*expr));
      } break;
      case PassBy::BaseAddressValueAttribute: {
        // VALUE attribute or pass-by-reference to a copy semantics. (byval*)
        if (isArray(*expr)) {
          PushSemantics(ConstituentSemantics::ByValueArg);
          operands.emplace_back(genElementalArgument(*expr));
        } else {
          // Store scalar value in a temp to fulfill VALUE attribute.
          mlir::Value val = fir::getBase(asScalar(*expr));
          mlir::Value temp =
              builder.createTemporary(loc, val.getType(),
                                      llvm::ArrayRef<mlir::NamedAttribute>{
                                          fir::getAdaptToByRefAttr(builder)});
          fir::StoreOp::create(builder, loc, val, temp);
          operands.emplace_back(
              [=](IterSpace iters) -> ExtValue { return temp; });
        }
      } break;
      case PassBy::BaseAddress: {
        if (isArray(*expr)) {
          PushSemantics(ConstituentSemantics::RefOpaque);
          operands.emplace_back(genElementalArgument(*expr));
        } else {
          ExtValue exv = asScalarRef(*expr);
          operands.emplace_back([=](IterSpace iters) { return exv; });
        }
      } break;
      case PassBy::CharBoxValueAttribute: {
        if (isArray(*expr)) {
          PushSemantics(ConstituentSemantics::DataValue);
          auto lambda = genElementalArgument(*expr);
          operands.emplace_back([=](IterSpace iters) {
            return fir::factory::CharacterExprHelper{builder, loc}
                .createTempFrom(lambda(iters));
          });
        } else {
          fir::factory::CharacterExprHelper helper(builder, loc);
          fir::CharBoxValue argVal = helper.createTempFrom(asScalarRef(*expr));
          operands.emplace_back(
              [=](IterSpace iters) -> ExtValue { return argVal; });
        }
      } break;
      case PassBy::BoxChar: {
        PushSemantics(ConstituentSemantics::RefOpaque);
        operands.emplace_back(genElementalArgument(*expr));
      } break;
      case PassBy::AddressAndLength:
        // PassBy::AddressAndLength is only used for character results. Results
        // are not handled here.
        fir::emitFatalError(
            loc, "unexpected PassBy::AddressAndLength in elemental call");
        break;
      case PassBy::CharProcTuple: {
        ExtValue argRef = asScalarRef(*expr);
        mlir::Value tuple = createBoxProcCharTuple(
            converter, argTy, fir::getBase(argRef), fir::getLen(argRef));
        operands.emplace_back(
            [=](IterSpace iters) -> ExtValue { return tuple; });
      } break;
      case PassBy::Box:
      case PassBy::MutableBox:
        // Handle polymorphic passed object.
        if (fir::isPolymorphicType(argTy)) {
          if (isArray(*expr)) {
            ExtValue exv = asScalarRef(*expr);
            mlir::Value sourceBox;
            if (fir::isPolymorphicType(fir::getBase(exv).getType()))
              sourceBox = fir::getBase(exv);
            mlir::Type baseTy =
                fir::dyn_cast_ptrOrBoxEleTy(fir::getBase(exv).getType());
            mlir::Type innerTy = fir::unwrapSequenceType(baseTy);
            operands.emplace_back([=](IterSpace iters) -> ExtValue {
              mlir::Value coord = fir::CoordinateOp::create(
                  builder, loc, fir::ReferenceType::get(innerTy),
                  fir::getBase(exv), iters.iterVec());
              mlir::Value empty;
              mlir::ValueRange emptyRange;
              return fir::EmboxOp::create(builder, loc,
                                          fir::ClassType::get(innerTy), coord,
                                          empty, empty, emptyRange, sourceBox);
            });
          } else {
            ExtValue exv = asScalarRef(*expr);
            if (mlir::isa<fir::BaseBoxType>(fir::getBase(exv).getType())) {
              operands.emplace_back(
                  [=](IterSpace iters) -> ExtValue { return exv; });
            } else {
              mlir::Type baseTy =
                  fir::dyn_cast_ptrOrBoxEleTy(fir::getBase(exv).getType());
              operands.emplace_back([=](IterSpace iters) -> ExtValue {
                mlir::Value empty;
                mlir::ValueRange emptyRange;
                return fir::EmboxOp::create(
                    builder, loc, fir::ClassType::get(baseTy),
                    fir::getBase(exv), empty, empty, emptyRange);
              });
            }
          }
          break;
        }
        // See C15100 and C15101
        fir::emitFatalError(loc, "cannot be POINTER, ALLOCATABLE");
      case PassBy::BoxProcRef:
        // Procedure pointer: no action here.
        break;
      }
    }

    if (caller.getIfIndirectCall())
      fir::emitFatalError(loc, "cannot be indirect call");

    // The lambda is mutable so that `caller` copy can be modified inside it.
    return [=,
            caller = std::move(caller)](IterSpace iters) mutable -> ExtValue {
      for (const auto &[cc, argIface] :
           llvm::zip(operands, caller.getPassedArguments())) {
        auto exv = cc(iters);
        auto arg = exv.match(
            [&](const fir::CharBoxValue &cb) -> mlir::Value {
              return fir::factory::CharacterExprHelper{builder, loc}
                  .createEmbox(cb);
            },
            [&](const auto &) { return fir::getBase(exv); });
        caller.placeInput(argIface, arg);
      }
      Fortran::lower::LoweredResult res =
          Fortran::lower::genCallOpAndResult(loc, converter, symMap,
                                             getElementCtx(), caller,
                                             callSiteType, retTy)
              .first;
      return std::get<ExtValue>(res);
    };
  }

  /// Lower TRANSPOSE call without using runtime TRANSPOSE.
  /// Return continuation for generating the TRANSPOSE result.
  /// The continuation just swaps the iteration space before
  /// invoking continuation for the argument.
  CC genTransposeProcRef(const Fortran::evaluate::ProcedureRef &procRef) {
    assert(procRef.arguments().size() == 1 &&
           "TRANSPOSE must have one argument.");
    const auto *argExpr = procRef.arguments()[0].value().UnwrapExpr();
    assert(argExpr);

    llvm::SmallVector<mlir::Value> savedDestShape = destShape;
    assert((destShape.empty() || destShape.size() == 2) &&
           "TRANSPOSE destination must have rank 2.");

    if (!savedDestShape.empty())
      std::swap(destShape[0], destShape[1]);

    PushSemantics(ConstituentSemantics::RefTransparent);
    llvm::SmallVector<CC> operands{genElementalArgument(*argExpr)};

    if (!savedDestShape.empty()) {
      // If destShape was set before transpose lowering, then
      // restore it. Otherwise, ...
      destShape = savedDestShape;
    } else if (!destShape.empty()) {
      // ... if destShape has been set from the argument lowering,
      // then reverse it.
      assert(destShape.size() == 2 &&
             "TRANSPOSE destination must have rank 2.");
      std::swap(destShape[0], destShape[1]);
    }

    return [=](IterSpace iters) {
      assert(iters.iterVec().size() == 2 &&
             "TRANSPOSE expects 2D iterations space.");
      IterationSpace newIters(iters, {iters.iterValue(1), iters.iterValue(0)});
      return operands.front()(newIters);
    };
  }

  /// Generate a procedure reference. This code is shared for both functions and
  /// subroutines, the difference being reflected by `retTy`.
  CC genProcRef(const Fortran::evaluate::ProcedureRef &procRef,
                std::optional<mlir::Type> retTy) {
    mlir::Location loc = getLoc();
    setLoweredProcRef(&procRef);

    if (isOptimizableTranspose(procRef, converter))
      return genTransposeProcRef(procRef);

    if (procRef.IsElemental()) {
      if (const Fortran::evaluate::SpecificIntrinsic *intrin =
              procRef.proc().GetSpecificIntrinsic()) {
        // All elemental intrinsic functions are pure and cannot modify their
        // arguments. The only elemental subroutine, MVBITS has an Intent(inout)
        // argument. So for this last one, loops must be in element order
        // according to 15.8.3 p1.
        if (!retTy)
          setUnordered(false);

        // Elemental intrinsic call.
        // The intrinsic procedure is called once per element of the array.
        return genElementalIntrinsicProcRef(procRef, retTy, *intrin);
      }
      if (Fortran::lower::isIntrinsicModuleProcRef(procRef))
        return genElementalIntrinsicProcRef(procRef, retTy);
      if (ScalarExprLowering::isStatementFunctionCall(procRef))
        fir::emitFatalError(loc, "statement function cannot be elemental");

      // Elemental call.
      // The procedure is called once per element of the array argument(s).
      return genElementalUserDefinedProcRef(procRef, retTy);
    }

    // Transformational call.
    // The procedure is called once and produces a value of rank > 0.
    if (const Fortran::evaluate::SpecificIntrinsic *intrinsic =
            procRef.proc().GetSpecificIntrinsic()) {
      if (explicitSpaceIsActive() && procRef.Rank() == 0) {
        // Elide any implicit loop iters.
        return [=, &procRef](IterSpace) {
          return ScalarExprLowering{loc, converter, symMap, stmtCtx}
              .genIntrinsicRef(procRef, retTy, *intrinsic);
        };
      }
      return genarr(
          ScalarExprLowering{loc, converter, symMap, stmtCtx}.genIntrinsicRef(
              procRef, retTy, *intrinsic));
    }

    const bool isPtrAssn = isPointerAssignment();
    if (explicitSpaceIsActive() && procRef.Rank() == 0) {
      // Elide any implicit loop iters.
      return [=, &procRef](IterSpace) {
        ScalarExprLowering sel(loc, converter, symMap, stmtCtx);
        return isPtrAssn ? sel.genRawProcedureRef(procRef, retTy)
                         : sel.genProcedureRef(procRef, retTy);
      };
    }
    // In the default case, the call can be hoisted out of the loop nest. Apply
    // the iterations to the result, which may be an array value.
    ScalarExprLowering sel(loc, converter, symMap, stmtCtx);
    auto exv = isPtrAssn ? sel.genRawProcedureRef(procRef, retTy)
                         : sel.genProcedureRef(procRef, retTy);
    return genarr(exv);
  }

  CC genarr(const Fortran::evaluate::ProcedureDesignator &) {
    TODO(getLoc(), "procedure designator");
  }
  CC genarr(const Fortran::evaluate::ProcedureRef &x) {
    if (x.hasAlternateReturns())
      fir::emitFatalError(getLoc(),
                          "array procedure reference with alt-return");
    return genProcRef(x, std::nullopt);
  }
  template <typename A>
  CC genScalarAndForwardValue(const A &x) {
    ExtValue result = asScalar(x);
    return [=](IterSpace) { return result; };
  }
  template <typename A, typename = std::enable_if_t<Fortran::common::HasMember<
                            A, Fortran::evaluate::TypelessExpression>>>
  CC genarr(const A &x) {
    return genScalarAndForwardValue(x);
  }

  template <typename A>
  CC genarr(const Fortran::evaluate::Expr<A> &x) {
    LLVM_DEBUG(Fortran::semantics::DumpEvaluateExpr::Dump(llvm::dbgs(), x));
    if (isArray(x) || (explicitSpaceIsActive() && isLeftHandSide()) ||
        isElementalProcWithArrayArgs(x))
      return Fortran::common::visit([&](const auto &e) { return genarr(e); },
                                    x.u);
    if (explicitSpaceIsActive()) {
      assert(!isArray(x) && !isLeftHandSide());
      auto cc =
          Fortran::common::visit([&](const auto &e) { return genarr(e); }, x.u);
      auto result = cc(IterationSpace{});
      return [=](IterSpace) { return result; };
    }
    return genScalarAndForwardValue(x);
  }

  // Converting a value of memory bound type requires creating a temp and
  // copying the value.
  static ExtValue convertAdjustedType(fir::FirOpBuilder &builder,
                                      mlir::Location loc, mlir::Type toType,
                                      const ExtValue &exv) {
    return exv.match(
        [&](const fir::CharBoxValue &cb) -> ExtValue {
          mlir::Value len = cb.getLen();
          auto mem = fir::AllocaOp::create(builder, loc, toType,
                                           mlir::ValueRange{len});
          fir::CharBoxValue result(mem, len);
          fir::factory::CharacterExprHelper{builder, loc}.createAssign(
              ExtValue{result}, exv);
          return result;
        },
        [&](const auto &) -> ExtValue {
          fir::emitFatalError(loc, "convert on adjusted extended value");
        });
  }
  template <Fortran::common::TypeCategory TC1, int KIND,
            Fortran::common::TypeCategory TC2>
  CC genarr(const Fortran::evaluate::Convert<Fortran::evaluate::Type<TC1, KIND>,
                                             TC2> &x) {
    mlir::Location loc = getLoc();
    auto lambda = genarr(x.left());
    mlir::Type ty = converter.genType(TC1, KIND);
    return [=](IterSpace iters) -> ExtValue {
      auto exv = lambda(iters);
      mlir::Value val = fir::getBase(exv);
      auto valTy = val.getType();
      if (elementTypeWasAdjusted(valTy) &&
          !(fir::isa_ref_type(valTy) && fir::isa_integer(ty)))
        return convertAdjustedType(builder, loc, ty, exv);
      return builder.createConvert(loc, ty, val);
    };
  }

  template <int KIND>
  CC genarr(const Fortran::evaluate::ComplexComponent<KIND> &x) {
    mlir::Location loc = getLoc();
    auto lambda = genarr(x.left());
    bool isImagPart = x.isImaginaryPart;
    return [=](IterSpace iters) -> ExtValue {
      mlir::Value lhs = fir::getBase(lambda(iters));
      return fir::factory::Complex{builder, loc}.extractComplexPart(lhs,
                                                                    isImagPart);
    };
  }

  template <typename T>
  CC genarr(const Fortran::evaluate::Parentheses<T> &x) {
    mlir::Location loc = getLoc();
    if (isReferentiallyOpaque()) {
      // Context is a call argument in, for example, an elemental procedure
      // call. TODO: all array arguments should use array_load, array_access,
      // array_amend, and INTENT(OUT), INTENT(INOUT) arguments should have
      // array_merge_store ops.
      TODO(loc, "parentheses on argument in elemental call");
    }
    auto f = genarr(x.left());
    return [=](IterSpace iters) -> ExtValue {
      auto val = f(iters);
      mlir::Value base = fir::getBase(val);
      auto newBase =
          fir::NoReassocOp::create(builder, loc, base.getType(), base);
      return fir::substBase(val, newBase);
    };
  }
  template <Fortran::common::TypeCategory CAT, int KIND>
  CC genarrIntNeg(
      const Fortran::evaluate::Expr<Fortran::evaluate::Type<CAT, KIND>> &left) {
    mlir::Location loc = getLoc();
    auto f = genarr(left);
    return [=](IterSpace iters) -> ExtValue {
      mlir::Value val = fir::getBase(f(iters));
      mlir::Type ty =
          converter.genType(Fortran::common::TypeCategory::Integer, KIND);
      mlir::Value zero = builder.createIntegerConstant(loc, ty, 0);
      if constexpr (CAT == Fortran::common::TypeCategory::Unsigned) {
        mlir::Value signless = builder.createConvert(loc, ty, val);
        mlir::Value neg =
            mlir::arith::SubIOp::create(builder, loc, zero, signless);
        return builder.createConvert(loc, val.getType(), neg);
      }
      return mlir::arith::SubIOp::create(builder, loc, zero, val);
    };
  }
  template <int KIND>
  CC genarr(const Fortran::evaluate::Negate<Fortran::evaluate::Type<
                Fortran::common::TypeCategory::Integer, KIND>> &x) {
    return genarrIntNeg(x.left());
  }
  template <int KIND>
  CC genarr(const Fortran::evaluate::Negate<Fortran::evaluate::Type<
                Fortran::common::TypeCategory::Unsigned, KIND>> &x) {
    return genarrIntNeg(x.left());
  }
  template <int KIND>
  CC genarr(const Fortran::evaluate::Negate<Fortran::evaluate::Type<
                Fortran::common::TypeCategory::Real, KIND>> &x) {
    mlir::Location loc = getLoc();
    auto f = genarr(x.left());
    return [=](IterSpace iters) -> ExtValue {
      return mlir::arith::NegFOp::create(builder, loc, fir::getBase(f(iters)));
    };
  }
  template <int KIND>
  CC genarr(const Fortran::evaluate::Negate<Fortran::evaluate::Type<
                Fortran::common::TypeCategory::Complex, KIND>> &x) {
    mlir::Location loc = getLoc();
    auto f = genarr(x.left());
    return [=](IterSpace iters) -> ExtValue {
      return fir::NegcOp::create(builder, loc, fir::getBase(f(iters)));
    };
  }

  //===--------------------------------------------------------------------===//
  // Binary elemental ops
  //===--------------------------------------------------------------------===//

  template <typename OP, typename A>
  CC createBinaryOp(const A &evEx) {
    mlir::Location loc = getLoc();
    auto lambda = genarr(evEx.left());
    auto rf = genarr(evEx.right());
    return [=](IterSpace iters) -> ExtValue {
      mlir::Value left = fir::getBase(lambda(iters));
      mlir::Value right = fir::getBase(rf(iters));
      assert(left.getType() == right.getType() && "types must be the same");
      return builder.createUnsigned<OP>(loc, left.getType(), left, right);
    };
  }

#undef GENBIN
#define GENBIN(GenBinEvOp, GenBinTyCat, GenBinFirOp)                           \
  template <int KIND>                                                          \
  CC genarr(const Fortran::evaluate::GenBinEvOp<Fortran::evaluate::Type<       \
                Fortran::common::TypeCategory::GenBinTyCat, KIND>> &x) {       \
    return createBinaryOp<GenBinFirOp>(x);                                     \
  }

  GENBIN(Add, Integer, mlir::arith::AddIOp)
  GENBIN(Add, Unsigned, mlir::arith::AddIOp)
  GENBIN(Add, Real, mlir::arith::AddFOp)
  GENBIN(Add, Complex, fir::AddcOp)
  GENBIN(Subtract, Integer, mlir::arith::SubIOp)
  GENBIN(Subtract, Unsigned, mlir::arith::SubIOp)
  GENBIN(Subtract, Real, mlir::arith::SubFOp)
  GENBIN(Subtract, Complex, fir::SubcOp)
  GENBIN(Multiply, Integer, mlir::arith::MulIOp)
  GENBIN(Multiply, Unsigned, mlir::arith::MulIOp)
  GENBIN(Multiply, Real, mlir::arith::MulFOp)
  GENBIN(Multiply, Complex, fir::MulcOp)
  GENBIN(Divide, Integer, mlir::arith::DivSIOp)
  GENBIN(Divide, Unsigned, mlir::arith::DivUIOp)
  GENBIN(Divide, Real, mlir::arith::DivFOp)

  template <int KIND>
  CC genarr(const Fortran::evaluate::Divide<Fortran::evaluate::Type<
                Fortran::common::TypeCategory::Complex, KIND>> &x) {
    mlir::Location loc = getLoc();
    mlir::Type ty =
        converter.genType(Fortran::common::TypeCategory::Complex, KIND);
    auto lf = genarr(x.left());
    auto rf = genarr(x.right());
    return [=](IterSpace iters) -> ExtValue {
      mlir::Value lhs = fir::getBase(lf(iters));
      mlir::Value rhs = fir::getBase(rf(iters));
      return fir::genDivC(builder, loc, ty, lhs, rhs);
    };
  }

  template <Fortran::common::TypeCategory TC, int KIND>
  CC genarr(
      const Fortran::evaluate::Power<Fortran::evaluate::Type<TC, KIND>> &x) {
    mlir::Location loc = getLoc();
    mlir::Type ty = converter.genType(TC, KIND);
    auto lf = genarr(x.left());
    auto rf = genarr(x.right());
    return [=](IterSpace iters) -> ExtValue {
      mlir::Value lhs = fir::getBase(lf(iters));
      mlir::Value rhs = fir::getBase(rf(iters));
      return fir::genPow(builder, loc, ty, lhs, rhs);
    };
  }
  template <Fortran::common::TypeCategory TC, int KIND>
  CC genarr(
      const Fortran::evaluate::Extremum<Fortran::evaluate::Type<TC, KIND>> &x) {
    mlir::Location loc = getLoc();
    auto lf = genarr(x.left());
    auto rf = genarr(x.right());
    switch (x.ordering) {
    case Fortran::evaluate::Ordering::Greater:
      return [=](IterSpace iters) -> ExtValue {
        mlir::Value lhs = fir::getBase(lf(iters));
        mlir::Value rhs = fir::getBase(rf(iters));
        return fir::genMax(builder, loc, llvm::ArrayRef<mlir::Value>{lhs, rhs});
      };
    case Fortran::evaluate::Ordering::Less:
      return [=](IterSpace iters) -> ExtValue {
        mlir::Value lhs = fir::getBase(lf(iters));
        mlir::Value rhs = fir::getBase(rf(iters));
        return fir::genMin(builder, loc, llvm::ArrayRef<mlir::Value>{lhs, rhs});
      };
    case Fortran::evaluate::Ordering::Equal:
      llvm_unreachable("Equal is not a valid ordering in this context");
    }
    llvm_unreachable("unknown ordering");
  }
  template <Fortran::common::TypeCategory TC, int KIND>
  CC genarr(
      const Fortran::evaluate::RealToIntPower<Fortran::evaluate::Type<TC, KIND>>
          &x) {
    mlir::Location loc = getLoc();
    auto ty = converter.genType(TC, KIND);
    auto lf = genarr(x.left());
    auto rf = genarr(x.right());
    return [=](IterSpace iters) {
      mlir::Value lhs = fir::getBase(lf(iters));
      mlir::Value rhs = fir::getBase(rf(iters));
      return fir::genPow(builder, loc, ty, lhs, rhs);
    };
  }
  template <int KIND>
  CC genarr(const Fortran::evaluate::ComplexConstructor<KIND> &x) {
    mlir::Location loc = getLoc();
    auto lf = genarr(x.left());
    auto rf = genarr(x.right());
    return [=](IterSpace iters) -> ExtValue {
      mlir::Value lhs = fir::getBase(lf(iters));
      mlir::Value rhs = fir::getBase(rf(iters));
      return fir::factory::Complex{builder, loc}.createComplex(lhs, rhs);
    };
  }

  /// Fortran's concatenation operator `//`.
  template <int KIND>
  CC genarr(const Fortran::evaluate::Concat<KIND> &x) {
    mlir::Location loc = getLoc();
    auto lf = genarr(x.left());
    auto rf = genarr(x.right());
    return [=](IterSpace iters) -> ExtValue {
      auto lhs = lf(iters);
      auto rhs = rf(iters);
      const fir::CharBoxValue *lchr = lhs.getCharBox();
      const fir::CharBoxValue *rchr = rhs.getCharBox();
      if (lchr && rchr) {
        return fir::factory::CharacterExprHelper{builder, loc}
            .createConcatenate(*lchr, *rchr);
      }
      TODO(loc, "concat on unexpected extended values");
      return mlir::Value{};
    };
  }

  template <int KIND>
  CC genarr(const Fortran::evaluate::SetLength<KIND> &x) {
    auto lf = genarr(x.left());
    mlir::Value rhs = fir::getBase(asScalar(x.right()));
    fir::CharBoxValue temp =
        fir::factory::CharacterExprHelper(builder, getLoc())
            .createCharacterTemp(
                fir::CharacterType::getUnknownLen(builder.getContext(), KIND),
                rhs);
    return [=](IterSpace iters) -> ExtValue {
      fir::factory::CharacterExprHelper(builder, getLoc())
          .createAssign(temp, lf(iters));
      return temp;
    };
  }

  template <typename T>
  CC genarr(const Fortran::evaluate::Constant<T> &x) {
    if (x.Rank() == 0)
      return genScalarAndForwardValue(x);
    return genarr(Fortran::lower::convertConstant(
        converter, getLoc(), x,
        /*outlineBigConstantsInReadOnlyMemory=*/true));
  }

  //===--------------------------------------------------------------------===//
  // A vector subscript expression may be wrapped with a cast to INTEGER*8.
  // Get rid of it here so the vector can be loaded. Add it back when
  // generating the elemental evaluation (inside the loop nest).

  static Fortran::lower::SomeExpr
  ignoreEvConvert(const Fortran::evaluate::Expr<Fortran::evaluate::Type<
                      Fortran::common::TypeCategory::Integer, 8>> &x) {
    return Fortran::common::visit(
        [&](const auto &v) { return ignoreEvConvert(v); }, x.u);
  }
  template <Fortran::common::TypeCategory FROM>
  static Fortran::lower::SomeExpr ignoreEvConvert(
      const Fortran::evaluate::Convert<
          Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer, 8>,
          FROM> &x) {
    return toEvExpr(x.left());
  }
  template <typename A>
  static Fortran::lower::SomeExpr ignoreEvConvert(const A &x) {
    return toEvExpr(x);
  }

  //===--------------------------------------------------------------------===//
  // Get the `Se::Symbol*` for the subscript expression, `x`. This symbol can
  // be used to determine the lbound, ubound of the vector.

  template <typename A>
  static const Fortran::semantics::Symbol *
  extractSubscriptSymbol(const Fortran::evaluate::Expr<A> &x) {
    return Fortran::common::visit(
        [&](const auto &v) { return extractSubscriptSymbol(v); }, x.u);
  }
  template <typename A>
  static const Fortran::semantics::Symbol *
  extractSubscriptSymbol(const Fortran::evaluate::Designator<A> &x) {
    return Fortran::evaluate::UnwrapWholeSymbolDataRef(x);
  }
  template <typename A>
  static const Fortran::semantics::Symbol *extractSubscriptSymbol(const A &x) {
    return nullptr;
  }

  //===--------------------------------------------------------------------===//

  /// Get the declared lower bound value of the array `x` in dimension `dim`.
  /// The argument `one` must be an ssa-value for the constant 1.
  mlir::Value getLBound(const ExtValue &x, unsigned dim, mlir::Value one) {
    return fir::factory::readLowerBound(builder, getLoc(), x, dim, one);
  }

  /// Get the declared upper bound value of the array `x` in dimension `dim`.
  /// The argument `one` must be an ssa-value for the constant 1.
  mlir::Value getUBound(const ExtValue &x, unsigned dim, mlir::Value one) {
    mlir::Location loc = getLoc();
    mlir::Value lb = getLBound(x, dim, one);
    mlir::Value extent = fir::factory::readExtent(builder, loc, x, dim);
    auto add = mlir::arith::AddIOp::create(builder, loc, lb, extent);
    return mlir::arith::SubIOp::create(builder, loc, add, one);
  }

  /// Return the extent of the boxed array `x` in dimesion `dim`.
  mlir::Value getExtent(const ExtValue &x, unsigned dim) {
    return fir::factory::readExtent(builder, getLoc(), x, dim);
  }

  template <typename A>
  ExtValue genArrayBase(const A &base) {
    ScalarExprLowering sel{getLoc(), converter, symMap, stmtCtx};
    return base.IsSymbol() ? sel.gen(getFirstSym(base))
                           : sel.gen(base.GetComponent());
  }

  template <typename A>
  bool hasEvArrayRef(const A &x) {
    struct HasEvArrayRefHelper
        : public Fortran::evaluate::AnyTraverse<HasEvArrayRefHelper> {
      HasEvArrayRefHelper()
          : Fortran::evaluate::AnyTraverse<HasEvArrayRefHelper>(*this) {}
      using Fortran::evaluate::AnyTraverse<HasEvArrayRefHelper>::operator();
      bool operator()(const Fortran::evaluate::ArrayRef &) const {
        return true;
      }
    } helper;
    return helper(x);
  }

  CC genVectorSubscriptArrayFetch(const Fortran::lower::SomeExpr &expr,
                                  std::size_t dim) {
    PushSemantics(ConstituentSemantics::RefTransparent);
    auto saved = Fortran::common::ScopedSet(explicitSpace, nullptr);
    llvm::SmallVector<mlir::Value> savedDestShape = destShape;
    destShape.clear();
    auto result = genarr(expr);
    if (destShape.empty())
      TODO(getLoc(), "expected vector to have an extent");
    assert(destShape.size() == 1 && "vector has rank > 1");
    if (destShape[0] != savedDestShape[dim]) {
      // Not the same, so choose the smaller value.
      mlir::Location loc = getLoc();
      auto cmp = mlir::arith::CmpIOp::create(builder, loc,
                                             mlir::arith::CmpIPredicate::sgt,
                                             destShape[0], savedDestShape[dim]);
      auto sel = mlir::arith::SelectOp::create(
          builder, loc, cmp, savedDestShape[dim], destShape[0]);
      savedDestShape[dim] = sel;
      destShape = savedDestShape;
    }
    return result;
  }

  /// Generate an access by vector subscript using the index in the iteration
  /// vector at `dim`.
  mlir::Value genAccessByVector(mlir::Location loc, CC genArrFetch,
                                IterSpace iters, std::size_t dim) {
    IterationSpace vecIters(iters,
                            llvm::ArrayRef<mlir::Value>{iters.iterValue(dim)});
    fir::ExtendedValue fetch = genArrFetch(vecIters);
    mlir::IndexType idxTy = builder.getIndexType();
    return builder.createConvert(loc, idxTy, fir::getBase(fetch));
  }

  /// When we have an array reference, the expressions specified in each
  /// dimension may be slice operations (e.g. `i:j:k`), vectors, or simple
  /// (loop-invarianet) scalar expressions. This returns the base entity, the
  /// resulting type, and a continuation to adjust the default iteration space.
  void genSliceIndices(ComponentPath &cmptData, const ExtValue &arrayExv,
                       const Fortran::evaluate::ArrayRef &x, bool atBase) {
    mlir::Location loc = getLoc();
    mlir::IndexType idxTy = builder.getIndexType();
    mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
    llvm::SmallVector<mlir::Value> &trips = cmptData.trips;
    LLVM_DEBUG(llvm::dbgs() << "array: " << arrayExv << '\n');
    auto &pc = cmptData.pc;
    const bool useTripsForSlice = !explicitSpaceIsActive();
    const bool createDestShape = destShape.empty();
    bool useSlice = false;
    std::size_t shapeIndex = 0;
    for (auto sub : llvm::enumerate(x.subscript())) {
      const std::size_t subsIndex = sub.index();
      Fortran::common::visit(
          Fortran::common::visitors{
              [&](const Fortran::evaluate::Triplet &t) {
                mlir::Value lowerBound;
                if (auto optLo = t.lower())
                  lowerBound = fir::getBase(asScalarArray(*optLo));
                else
                  lowerBound = getLBound(arrayExv, subsIndex, one);
                lowerBound = builder.createConvert(loc, idxTy, lowerBound);
                mlir::Value stride = fir::getBase(asScalarArray(t.stride()));
                stride = builder.createConvert(loc, idxTy, stride);
                if (useTripsForSlice || createDestShape) {
                  // Generate a slice operation for the triplet. The first and
                  // second position of the triplet may be omitted, and the
                  // declared lbound and/or ubound expression values,
                  // respectively, should be used instead.
                  trips.push_back(lowerBound);
                  mlir::Value upperBound;
                  if (auto optUp = t.upper())
                    upperBound = fir::getBase(asScalarArray(*optUp));
                  else
                    upperBound = getUBound(arrayExv, subsIndex, one);
                  upperBound = builder.createConvert(loc, idxTy, upperBound);
                  trips.push_back(upperBound);
                  trips.push_back(stride);
                  if (createDestShape) {
                    auto extent = builder.genExtentFromTriplet(
                        loc, lowerBound, upperBound, stride, idxTy);
                    destShape.push_back(extent);
                  }
                  useSlice = true;
                }
                if (!useTripsForSlice) {
                  auto currentPC = pc;
                  pc = [=](IterSpace iters) {
                    IterationSpace newIters = currentPC(iters);
                    mlir::Value impliedIter = newIters.iterValue(subsIndex);
                    // FIXME: must use the lower bound of this component.
                    auto arrLowerBound =
                        atBase ? getLBound(arrayExv, subsIndex, one) : one;
                    auto initial = mlir::arith::SubIOp::create(
                        builder, loc, lowerBound, arrLowerBound);
                    auto prod = mlir::arith::MulIOp::create(
                        builder, loc, impliedIter, stride);
                    auto result = mlir::arith::AddIOp::create(builder, loc,
                                                              initial, prod);
                    newIters.setIndexValue(subsIndex, result);
                    return newIters;
                  };
                }
                shapeIndex++;
              },
              [&](const Fortran::evaluate::IndirectSubscriptIntegerExpr &ie) {
                const auto &e = ie.value(); // dereference
                if (isArray(e)) {
                  // This is a vector subscript. Use the index values as read
                  // from a vector to determine the temporary array value.
                  // Note: 9.5.3.3.3(3) specifies undefined behavior for
                  // multiple updates to any specific array element through a
                  // vector subscript with replicated values.
                  assert(!isBoxValue() &&
                         "fir.box cannot be created with vector subscripts");
                  // TODO: Avoid creating a new evaluate::Expr here
                  auto arrExpr = ignoreEvConvert(e);
                  if (createDestShape) {
                    destShape.push_back(fir::factory::getExtentAtDimension(
                        loc, builder, arrayExv, subsIndex));
                  }
                  auto genArrFetch =
                      genVectorSubscriptArrayFetch(arrExpr, shapeIndex);
                  auto currentPC = pc;
                  pc = [=](IterSpace iters) {
                    IterationSpace newIters = currentPC(iters);
                    auto val = genAccessByVector(loc, genArrFetch, newIters,
                                                 subsIndex);
                    // Value read from vector subscript array and normalized
                    // using the base array's lower bound value.
                    mlir::Value lb = fir::factory::readLowerBound(
                        builder, loc, arrayExv, subsIndex, one);
                    auto origin = mlir::arith::SubIOp::create(builder, loc,
                                                              idxTy, val, lb);
                    newIters.setIndexValue(subsIndex, origin);
                    return newIters;
                  };
                  if (useTripsForSlice) {
                    [[maybe_unused]] auto vectorSubscriptShape =
                        getShape(arrayOperands.back());
                    auto undef = fir::UndefOp::create(builder, loc, idxTy);
                    trips.push_back(undef);
                    trips.push_back(undef);
                    trips.push_back(undef);
                  }
                  shapeIndex++;
                } else {
                  // This is a regular scalar subscript.
                  if (useTripsForSlice) {
                    // A regular scalar index, which does not yield an array
                    // section. Use a degenerate slice operation
                    // `(e:undef:undef)` in this dimension as a placeholder.
                    // This does not necessarily change the rank of the original
                    // array, so the iteration space must also be extended to
                    // include this expression in this dimension to adjust to
                    // the array's declared rank.
                    mlir::Value v = fir::getBase(asScalarArray(e));
                    trips.push_back(v);
                    auto undef = fir::UndefOp::create(builder, loc, idxTy);
                    trips.push_back(undef);
                    trips.push_back(undef);
                    auto currentPC = pc;
                    // Cast `e` to index type.
                    mlir::Value iv = builder.createConvert(loc, idxTy, v);
                    // Normalize `e` by subtracting the declared lbound.
                    mlir::Value lb = fir::factory::readLowerBound(
                        builder, loc, arrayExv, subsIndex, one);
                    mlir::Value ivAdj = mlir::arith::SubIOp::create(
                        builder, loc, idxTy, iv, lb);
                    // Add lbound adjusted value of `e` to the iteration vector
                    // (except when creating a box because the iteration vector
                    // is empty).
                    if (!isBoxValue())
                      pc = [=](IterSpace iters) {
                        IterationSpace newIters = currentPC(iters);
                        newIters.insertIndexValue(subsIndex, ivAdj);
                        return newIters;
                      };
                  } else {
                    auto currentPC = pc;
                    mlir::Value newValue = fir::getBase(asScalarArray(e));
                    mlir::Value result =
                        builder.createConvert(loc, idxTy, newValue);
                    mlir::Value lb = fir::factory::readLowerBound(
                        builder, loc, arrayExv, subsIndex, one);
                    result = mlir::arith::SubIOp::create(builder, loc, idxTy,
                                                         result, lb);
                    pc = [=](IterSpace iters) {
                      IterationSpace newIters = currentPC(iters);
                      newIters.insertIndexValue(subsIndex, result);
                      return newIters;
                    };
                  }
                }
              }},
          sub.value().u);
    }
    if (!useSlice)
      trips.clear();
  }

  static mlir::Type unwrapBoxEleTy(mlir::Type ty) {
    if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(ty))
      return fir::unwrapRefType(boxTy.getEleTy());
    return ty;
  }

  llvm::SmallVector<mlir::Value> getShape(mlir::Type ty) {
    llvm::SmallVector<mlir::Value> result;
    ty = unwrapBoxEleTy(ty);
    mlir::Location loc = getLoc();
    mlir::IndexType idxTy = builder.getIndexType();
    auto seqType = mlir::cast<fir::SequenceType>(ty);
    for (auto extent : seqType.getShape()) {
      auto v = extent == fir::SequenceType::getUnknownExtent()
                   ? fir::UndefOp::create(builder, loc, idxTy).getResult()
                   : builder.createIntegerConstant(loc, idxTy, extent);
      result.push_back(v);
    }
    return result;
  }

  CC genarr(const Fortran::semantics::SymbolRef &sym,
            ComponentPath &components) {
    return genarr(sym.get(), components);
  }

  ExtValue abstractArrayExtValue(mlir::Value val, mlir::Value len = {}) {
    return convertToArrayBoxValue(getLoc(), builder, val, len);
  }

  CC genarr(const ExtValue &extMemref) {
    ComponentPath dummy(/*isImplicit=*/true);
    return genarr(extMemref, dummy);
  }

  // If the slice values are given then use them. Otherwise, generate triples
  // that cover the entire shape specified by \p shapeVal.
  inline llvm::SmallVector<mlir::Value>
  padSlice(llvm::ArrayRef<mlir::Value> triples, mlir::Value shapeVal) {
    llvm::SmallVector<mlir::Value> result;
    mlir::Location loc = getLoc();
    if (triples.size()) {
      result.assign(triples.begin(), triples.end());
    } else {
      auto one = builder.createIntegerConstant(loc, builder.getIndexType(), 1);
      if (!shapeVal) {
        TODO(loc, "shape must be recovered from box");
      } else if (auto shapeOp = mlir::dyn_cast_or_null<fir::ShapeOp>(
                     shapeVal.getDefiningOp())) {
        for (auto ext : shapeOp.getExtents()) {
          result.push_back(one);
          result.push_back(ext);
          result.push_back(one);
        }
      } else if (auto shapeShift = mlir::dyn_cast_or_null<fir::ShapeShiftOp>(
                     shapeVal.getDefiningOp())) {
        for (auto [lb, ext] :
             llvm::zip(shapeShift.getOrigins(), shapeShift.getExtents())) {
          result.push_back(lb);
          result.push_back(ext);
          result.push_back(one);
        }
      } else {
        TODO(loc, "shape must be recovered from box");
      }
    }
    return result;
  }

  /// Base case of generating an array reference,
  CC genarr(const ExtValue &extMemref, ComponentPath &components,
            mlir::Value CrayPtr = nullptr) {
    mlir::Location loc = getLoc();
    mlir::Value memref = fir::getBase(extMemref);
    mlir::Type arrTy = fir::dyn_cast_ptrOrBoxEleTy(memref.getType());
    assert(mlir::isa<fir::SequenceType>(arrTy) &&
           "memory ref must be an array");
    mlir::Value shape = builder.createShape(loc, extMemref);
    mlir::Value slice;
    if (components.isSlice()) {
      if (isBoxValue() && components.substring) {
        // Append the substring operator to emboxing Op as it will become an
        // interior adjustment (add offset, adjust LEN) to the CHARACTER value
        // being referenced in the descriptor.
        llvm::SmallVector<mlir::Value> substringBounds;
        populateBounds(substringBounds, components.substring);
        // Convert to (offset, size)
        mlir::Type iTy = substringBounds[0].getType();
        if (substringBounds.size() != 2) {
          fir::CharacterType charTy =
              fir::factory::CharacterExprHelper::getCharType(arrTy);
          if (charTy.hasConstantLen()) {
            mlir::IndexType idxTy = builder.getIndexType();
            fir::CharacterType::LenType charLen = charTy.getLen();
            mlir::Value lenValue =
                builder.createIntegerConstant(loc, idxTy, charLen);
            substringBounds.push_back(lenValue);
          } else {
            llvm::SmallVector<mlir::Value> typeparams =
                fir::getTypeParams(extMemref);
            substringBounds.push_back(typeparams.back());
          }
        }
        // Convert the lower bound to 0-based substring.
        mlir::Value one =
            builder.createIntegerConstant(loc, substringBounds[0].getType(), 1);
        substringBounds[0] =
            mlir::arith::SubIOp::create(builder, loc, substringBounds[0], one);
        // Convert the upper bound to a length.
        mlir::Value cast = builder.createConvert(loc, iTy, substringBounds[1]);
        mlir::Value zero = builder.createIntegerConstant(loc, iTy, 0);
        auto size =
            mlir::arith::SubIOp::create(builder, loc, cast, substringBounds[0]);
        auto cmp = mlir::arith::CmpIOp::create(
            builder, loc, mlir::arith::CmpIPredicate::sgt, size, zero);
        // size = MAX(upper - (lower - 1), 0)
        substringBounds[1] =
            mlir::arith::SelectOp::create(builder, loc, cmp, size, zero);
        slice = fir::SliceOp::create(
            builder, loc, padSlice(components.trips, shape),
            components.suffixComponents, substringBounds);
      } else {
        slice = builder.createSlice(loc, extMemref, components.trips,
                                    components.suffixComponents);
      }
      if (components.hasComponents()) {
        auto seqTy = mlir::cast<fir::SequenceType>(arrTy);
        mlir::Type eleTy =
            fir::applyPathToType(seqTy.getEleTy(), components.suffixComponents);
        if (!eleTy)
          fir::emitFatalError(loc, "slicing path is ill-formed");
        // create the type of the projected array.
        arrTy = fir::SequenceType::get(seqTy.getShape(), eleTy);
        LLVM_DEBUG(llvm::dbgs()
                   << "type of array projection from component slicing: "
                   << eleTy << ", " << arrTy << '\n');
      }
    }
    arrayOperands.push_back(ArrayOperand{memref, shape, slice});
    if (destShape.empty())
      destShape = getShape(arrayOperands.back());
    if (isBoxValue()) {
      // Semantics are a reference to a boxed array.
      // This case just requires that an embox operation be created to box the
      // value. The value of the box is forwarded in the continuation.
      mlir::Type reduceTy = reduceRank(arrTy, slice);
      mlir::Type boxTy = fir::BoxType::get(reduceTy);
      if (mlir::isa<fir::ClassType>(memref.getType()) &&
          !components.hasComponents())
        boxTy = fir::ClassType::get(reduceTy);
      if (components.substring) {
        // Adjust char length to substring size.
        fir::CharacterType charTy =
            fir::factory::CharacterExprHelper::getCharType(reduceTy);
        auto seqTy = mlir::cast<fir::SequenceType>(reduceTy);
        // TODO: Use a constant for fir.char LEN if we can compute it.
        boxTy = fir::BoxType::get(
            fir::SequenceType::get(fir::CharacterType::getUnknownLen(
                                       builder.getContext(), charTy.getFKind()),
                                   seqTy.getDimension()));
      }
      llvm::SmallVector<mlir::Value> lbounds;
      llvm::SmallVector<mlir::Value> nonDeferredLenParams;
      if (!slice) {
        lbounds =
            fir::factory::getNonDefaultLowerBounds(builder, loc, extMemref);
        nonDeferredLenParams = fir::factory::getNonDeferredLenParams(extMemref);
      }
      mlir::Value embox =
          mlir::isa<fir::BaseBoxType>(memref.getType())
              ? fir::ReboxOp::create(builder, loc, boxTy, memref, shape, slice)
                    .getResult()
              : fir::EmboxOp::create(builder, loc, boxTy, memref, shape, slice,
                                     fir::getTypeParams(extMemref))
                    .getResult();
      return [=](IterSpace) -> ExtValue {
        return fir::BoxValue(embox, lbounds, nonDeferredLenParams);
      };
    }
    auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
    if (isReferentiallyOpaque()) {
      // Semantics are an opaque reference to an array.
      // This case forwards a continuation that will generate the address
      // arithmetic to the array element. This does not have copy-in/copy-out
      // semantics. No attempt to copy the array value will be made during the
      // interpretation of the Fortran statement.
      mlir::Type refEleTy = builder.getRefType(eleTy);
      return [=](IterSpace iters) -> ExtValue {
        // ArrayCoorOp does not expect zero based indices.
        llvm::SmallVector<mlir::Value> indices = fir::factory::originateIndices(
            loc, builder, memref.getType(), shape, iters.iterVec());
        mlir::Value coor = fir::ArrayCoorOp::create(
            builder, loc, refEleTy, memref, shape, slice, indices,
            fir::getTypeParams(extMemref));
        if (auto charTy = mlir::dyn_cast<fir::CharacterType>(eleTy)) {
          llvm::SmallVector<mlir::Value> substringBounds;
          populateBounds(substringBounds, components.substring);
          if (!substringBounds.empty()) {
            mlir::Value dstLen = fir::factory::genLenOfCharacter(
                builder, loc, mlir::cast<fir::SequenceType>(arrTy), memref,
                fir::getTypeParams(extMemref), iters.iterVec(),
                substringBounds);
            fir::CharBoxValue dstChar(coor, dstLen);
            return fir::factory::CharacterExprHelper{builder, loc}
                .createSubstring(dstChar, substringBounds);
          }
        }
        return fir::factory::arraySectionElementToExtendedValue(
            builder, loc, extMemref, coor, slice);
      };
    }
    auto arrLoad =
        fir::ArrayLoadOp::create(builder, loc, arrTy, memref, shape, slice,
                                 fir::getTypeParams(extMemref));

    if (CrayPtr) {
      mlir::Type ptrTy = CrayPtr.getType();
      mlir::Value cnvrt = Fortran::lower::addCrayPointerInst(
          loc, builder, CrayPtr, ptrTy, memref.getType());
      auto addr = fir::LoadOp::create(builder, loc, cnvrt);
      arrLoad = fir::ArrayLoadOp::create(builder, loc, arrTy, addr, shape,
                                         slice, fir::getTypeParams(extMemref));
    }

    mlir::Value arrLd = arrLoad.getResult();
    if (isProjectedCopyInCopyOut()) {
      // Semantics are projected copy-in copy-out.
      // The backing store of the destination of an array expression may be
      // partially modified. These updates are recorded in FIR by forwarding a
      // continuation that generates an `array_update` Op. The destination is
      // always loaded at the beginning of the statement and merged at the
      // end.
      destination = arrLoad;
      auto lambda = ccStoreToDest
                        ? *ccStoreToDest
                        : defaultStoreToDestination(components.substring);
      return [=](IterSpace iters) -> ExtValue { return lambda(iters); };
    }
    if (isCustomCopyInCopyOut()) {
      // Create an array_modify to get the LHS element address and indicate
      // the assignment, the actual assignment must be implemented in
      // ccStoreToDest.
      destination = arrLoad;
      return [=](IterSpace iters) -> ExtValue {
        mlir::Value innerArg = iters.innerArgument();
        mlir::Type resTy = innerArg.getType();
        mlir::Type eleTy = fir::applyPathToType(resTy, iters.iterVec());
        mlir::Type refEleTy =
            fir::isa_ref_type(eleTy) ? eleTy : builder.getRefType(eleTy);
        auto arrModify = fir::ArrayModifyOp::create(
            builder, loc, mlir::TypeRange{refEleTy, resTy}, innerArg,
            iters.iterVec(), destination.getTypeparams());
        return abstractArrayExtValue(arrModify.getResult(1));
      };
    }
    if (isCopyInCopyOut()) {
      // Semantics are copy-in copy-out.
      // The continuation simply forwards the result of the `array_load` Op,
      // which is the value of the array as it was when loaded. All data
      // references with rank > 0 in an array expression typically have
      // copy-in copy-out semantics.
      return [=](IterSpace) -> ExtValue { return arrLd; };
    }
    llvm::SmallVector<mlir::Value> arrLdTypeParams =
        fir::factory::getTypeParams(loc, builder, arrLoad);
    if (isValueAttribute()) {
      // Semantics are value attribute.
      // Here the continuation will `array_fetch` a value from an array and
      // then store that value in a temporary. One can thus imitate pass by
      // value even when the call is pass by reference.
      return [=](IterSpace iters) -> ExtValue {
        mlir::Value base;
        mlir::Type eleTy = fir::applyPathToType(arrTy, iters.iterVec());
        if (isAdjustedArrayElementType(eleTy)) {
          mlir::Type eleRefTy = builder.getRefType(eleTy);
          base = fir::ArrayAccessOp::create(builder, loc, eleRefTy, arrLd,
                                            iters.iterVec(), arrLdTypeParams);
        } else {
          base = fir::ArrayFetchOp::create(builder, loc, eleTy, arrLd,
                                           iters.iterVec(), arrLdTypeParams);
        }
        mlir::Value temp =
            builder.createTemporary(loc, base.getType(),
                                    llvm::ArrayRef<mlir::NamedAttribute>{
                                        fir::getAdaptToByRefAttr(builder)});
        fir::StoreOp::create(builder, loc, base, temp);
        return fir::factory::arraySectionElementToExtendedValue(
            builder, loc, extMemref, temp, slice);
      };
    }
    // In the default case, the array reference forwards an `array_fetch` or
    // `array_access` Op in the continuation.
    return [=](IterSpace iters) -> ExtValue {
      mlir::Type eleTy = fir::applyPathToType(arrTy, iters.iterVec());
      if (isAdjustedArrayElementType(eleTy)) {
        mlir::Type eleRefTy = builder.getRefType(eleTy);
        mlir::Value arrayOp = fir::ArrayAccessOp::create(
            builder, loc, eleRefTy, arrLd, iters.iterVec(), arrLdTypeParams);
        if (auto charTy = mlir::dyn_cast<fir::CharacterType>(eleTy)) {
          llvm::SmallVector<mlir::Value> substringBounds;
          populateBounds(substringBounds, components.substring);
          if (!substringBounds.empty()) {
            mlir::Value dstLen = fir::factory::genLenOfCharacter(
                builder, loc, arrLoad, iters.iterVec(), substringBounds);
            fir::CharBoxValue dstChar(arrayOp, dstLen);
            return fir::factory::CharacterExprHelper{builder, loc}
                .createSubstring(dstChar, substringBounds);
          }
        }
        return fir::factory::arraySectionElementToExtendedValue(
            builder, loc, extMemref, arrayOp, slice);
      }
      auto arrFetch = fir::ArrayFetchOp::create(
          builder, loc, eleTy, arrLd, iters.iterVec(), arrLdTypeParams);
      return fir::factory::arraySectionElementToExtendedValue(
          builder, loc, extMemref, arrFetch, slice);
    };
  }

  std::tuple<CC, mlir::Value, mlir::Type>
  genOptionalArrayFetch(const Fortran::lower::SomeExpr &expr) {
    assert(expr.Rank() > 0 && "expr must be an array");
    mlir::Location loc = getLoc();
    ExtValue optionalArg = asInquired(expr);
    mlir::Value isPresent = genActualIsPresentTest(builder, loc, optionalArg);
    // Generate an array load and access to an array that may be an absent
    // optional or an unallocated optional.
    mlir::Value base = getBase(optionalArg);
    const bool hasOptionalAttr =
        fir::valueHasFirAttribute(base, fir::getOptionalAttrName());
    mlir::Type baseType = fir::unwrapRefType(base.getType());
    const bool isBox = mlir::isa<fir::BoxType>(baseType);
    const bool isAllocOrPtr =
        Fortran::evaluate::IsAllocatableOrPointerObject(expr);
    mlir::Type arrType = fir::unwrapPassByRefType(baseType);
    mlir::Type eleType = fir::unwrapSequenceType(arrType);
    ExtValue exv = optionalArg;
    if (hasOptionalAttr && isBox && !isAllocOrPtr) {
      // Elemental argument cannot be allocatable or pointers (C15100).
      // Hence, per 15.5.2.12 3 (8) and (9), the provided Allocatable and
      // Pointer optional arrays cannot be absent. The only kind of entities
      // that can get here are optional assumed shape and polymorphic entities.
      exv = absentBoxToUnallocatedBox(builder, loc, exv, isPresent);
    }
    // All the properties can be read from any fir.box but the read values may
    // be undefined and should only be used inside a fir.if (canBeRead) region.
    if (const auto *mutableBox = exv.getBoxOf<fir::MutableBoxValue>())
      exv = fir::factory::genMutableBoxRead(builder, loc, *mutableBox);

    mlir::Value memref = fir::getBase(exv);
    mlir::Value shape = builder.createShape(loc, exv);
    mlir::Value noSlice;
    auto arrLoad = fir::ArrayLoadOp::create(
        builder, loc, arrType, memref, shape, noSlice, fir::getTypeParams(exv));
    mlir::Operation::operand_range arrLdTypeParams = arrLoad.getTypeparams();
    mlir::Value arrLd = arrLoad.getResult();
    // Mark the load to tell later passes it is unsafe to use this array_load
    // shape unconditionally.
    arrLoad->setAttr(fir::getOptionalAttrName(), builder.getUnitAttr());

    // Place the array as optional on the arrayOperands stack so that its
    // shape will only be used as a fallback to induce the implicit loop nest
    // (that is if there is no non optional array arguments).
    arrayOperands.push_back(
        ArrayOperand{memref, shape, noSlice, /*mayBeAbsent=*/true});

    // By value semantics.
    auto cc = [=](IterSpace iters) -> ExtValue {
      auto arrFetch = fir::ArrayFetchOp::create(
          builder, loc, eleType, arrLd, iters.iterVec(), arrLdTypeParams);
      return fir::factory::arraySectionElementToExtendedValue(
          builder, loc, exv, arrFetch, noSlice);
    };
    return {cc, isPresent, eleType};
  }

  /// Generate a continuation to pass \p expr to an OPTIONAL argument of an
  /// elemental procedure. This is meant to handle the cases where \p expr might
  /// be dynamically absent (i.e. when it is a POINTER, an ALLOCATABLE or an
  /// OPTIONAL variable). If p\ expr is guaranteed to be present genarr() can
  /// directly be called instead.
  CC genarrForwardOptionalArgumentToCall(const Fortran::lower::SomeExpr &expr) {
    mlir::Location loc = getLoc();
    // Only by-value numerical and logical so far.
    if (semant != ConstituentSemantics::RefTransparent)
      TODO(loc, "optional arguments in user defined elemental procedures");

    // Handle scalar argument case (the if-then-else is generated outside of the
    // implicit loop nest).
    if (expr.Rank() == 0) {
      ExtValue optionalArg = asInquired(expr);
      mlir::Value isPresent = genActualIsPresentTest(builder, loc, optionalArg);
      mlir::Value elementValue =
          fir::getBase(genOptionalValue(builder, loc, optionalArg, isPresent));
      return [=](IterSpace iters) -> ExtValue { return elementValue; };
    }

    CC cc;
    mlir::Value isPresent;
    mlir::Type eleType;
    std::tie(cc, isPresent, eleType) = genOptionalArrayFetch(expr);
    return [=](IterSpace iters) -> ExtValue {
      mlir::Value elementValue =
          builder
              .genIfOp(loc, {eleType}, isPresent,
                       /*withElseRegion=*/true)
              .genThen([&]() {
                fir::ResultOp::create(builder, loc, fir::getBase(cc(iters)));
              })
              .genElse([&]() {
                mlir::Value zero =
                    fir::factory::createZeroValue(builder, loc, eleType);
                fir::ResultOp::create(builder, loc, zero);
              })
              .getResults()[0];
      return elementValue;
    };
  }

  /// Reduce the rank of a array to be boxed based on the slice's operands.
  static mlir::Type reduceRank(mlir::Type arrTy, mlir::Value slice) {
    if (slice) {
      auto slOp = mlir::dyn_cast<fir::SliceOp>(slice.getDefiningOp());
      assert(slOp && "expected slice op");
      auto seqTy = mlir::dyn_cast<fir::SequenceType>(arrTy);
      assert(seqTy && "expected array type");
      mlir::Operation::operand_range triples = slOp.getTriples();
      fir::SequenceType::Shape shape;
      // reduce the rank for each invariant dimension
      for (unsigned i = 1, end = triples.size(); i < end; i += 3) {
        if (auto extent = fir::factory::getExtentFromTriplet(
                triples[i - 1], triples[i], triples[i + 1]))
          shape.push_back(*extent);
        else if (!mlir::isa_and_nonnull<fir::UndefOp>(
                     triples[i].getDefiningOp()))
          shape.push_back(fir::SequenceType::getUnknownExtent());
      }
      return fir::SequenceType::get(shape, seqTy.getEleTy());
    }
    // not sliced, so no change in rank
    return arrTy;
  }

  /// Example: <code>array%RE</code>
  CC genarr(const Fortran::evaluate::ComplexPart &x,
            ComponentPath &components) {
    components.reversePath.push_back(&x);
    return genarr(x.complex(), components);
  }

  template <typename A>
  CC genSlicePath(const A &x, ComponentPath &components) {
    return genarr(x, components);
  }

  CC genarr(const Fortran::evaluate::StaticDataObject::Pointer &,
            ComponentPath &components) {
    TODO(getLoc(), "substring of static object inside FORALL");
  }

  /// Substrings (see 9.4.1)
  CC genarr(const Fortran::evaluate::Substring &x, ComponentPath &components) {
    components.substring = &x;
    return Fortran::common::visit(
        [&](const auto &v) { return genarr(v, components); }, x.parent());
  }

  template <typename T>
  CC genarr(const Fortran::evaluate::FunctionRef<T> &funRef) {
    // Note that it's possible that the function being called returns either an
    // array or a scalar.  In the first case, use the element type of the array.
    return genProcRef(
        funRef, fir::unwrapSequenceType(converter.genType(toEvExpr(funRef))));
  }

  //===--------------------------------------------------------------------===//
  // Array construction
  //===--------------------------------------------------------------------===//

  /// Target agnostic computation of the size of an element in the array.
  /// Returns the size in bytes with type `index` or a null Value if the element
  /// size is not constant.
  mlir::Value computeElementSize(const ExtValue &exv, mlir::Type eleTy,
                                 mlir::Type resTy) {
    mlir::Location loc = getLoc();
    mlir::IndexType idxTy = builder.getIndexType();
    mlir::Value multiplier = builder.createIntegerConstant(loc, idxTy, 1);
    if (fir::hasDynamicSize(eleTy)) {
      if (auto charTy = mlir::dyn_cast<fir::CharacterType>(eleTy)) {
        // Array of char with dynamic LEN parameter. Downcast to an array
        // of singleton char, and scale by the len type parameter from
        // `exv`.
        exv.match(
            [&](const fir::CharBoxValue &cb) { multiplier = cb.getLen(); },
            [&](const fir::CharArrayBoxValue &cb) { multiplier = cb.getLen(); },
            [&](const fir::BoxValue &box) {
              multiplier = fir::factory::CharacterExprHelper(builder, loc)
                               .readLengthFromBox(box.getAddr());
            },
            [&](const fir::MutableBoxValue &box) {
              multiplier = fir::factory::CharacterExprHelper(builder, loc)
                               .readLengthFromBox(box.getAddr());
            },
            [&](const auto &) {
              fir::emitFatalError(loc,
                                  "array constructor element has unknown size");
            });
        fir::CharacterType newEleTy = fir::CharacterType::getSingleton(
            eleTy.getContext(), charTy.getFKind());
        if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(resTy)) {
          assert(eleTy == seqTy.getEleTy());
          resTy = fir::SequenceType::get(seqTy.getShape(), newEleTy);
        }
        eleTy = newEleTy;
      } else {
        TODO(loc, "dynamic sized type");
      }
    }
    mlir::Type eleRefTy = builder.getRefType(eleTy);
    mlir::Type resRefTy = builder.getRefType(resTy);
    mlir::Value nullPtr = builder.createNullConstant(loc, resRefTy);
    auto offset = fir::CoordinateOp::create(builder, loc, eleRefTy, nullPtr,
                                            mlir::ValueRange{multiplier});
    return builder.createConvert(loc, idxTy, offset);
  }

  /// Get the function signature of the LLVM memcpy intrinsic.
  mlir::FunctionType memcpyType() {
    auto ptrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
    llvm::SmallVector<mlir::Type> args = {ptrTy, ptrTy, builder.getI64Type()};
    return mlir::FunctionType::get(builder.getContext(), args, {});
  }

  /// Create a call to the LLVM memcpy intrinsic.
  void createCallMemcpy(llvm::ArrayRef<mlir::Value> args, bool isVolatile) {
    mlir::Location loc = getLoc();
    mlir::LLVM::MemcpyOp::create(builder, loc, args[0], args[1], args[2],
                                 isVolatile);
  }

  // Construct code to check for a buffer overrun and realloc the buffer when
  // space is depleted. This is done between each item in the ac-value-list.
  mlir::Value growBuffer(mlir::Value mem, mlir::Value needed,
                         mlir::Value bufferSize, mlir::Value buffSize,
                         mlir::Value eleSz) {
    mlir::Location loc = getLoc();
    mlir::func::FuncOp reallocFunc = fir::factory::getRealloc(builder);
    auto cond = mlir::arith::CmpIOp::create(
        builder, loc, mlir::arith::CmpIPredicate::sle, bufferSize, needed);
    auto ifOp = fir::IfOp::create(builder, loc, mem.getType(), cond,
                                  /*withElseRegion=*/true);
    auto insPt = builder.saveInsertionPoint();
    builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
    // Not enough space, resize the buffer.
    mlir::IndexType idxTy = builder.getIndexType();
    mlir::Value two = builder.createIntegerConstant(loc, idxTy, 2);
    auto newSz = mlir::arith::MulIOp::create(builder, loc, needed, two);
    fir::StoreOp::create(builder, loc, newSz, buffSize);
    mlir::Value byteSz =
        mlir::arith::MulIOp::create(builder, loc, newSz, eleSz);
    mlir::SymbolRefAttr funcSymAttr =
        builder.getSymbolRefAttr(reallocFunc.getName());
    mlir::FunctionType funcTy = reallocFunc.getFunctionType();
    auto newMem = fir::CallOp::create(
        builder, loc, funcSymAttr, funcTy.getResults(),
        llvm::ArrayRef<mlir::Value>{
            builder.createConvert(loc, funcTy.getInputs()[0], mem),
            builder.createConvert(loc, funcTy.getInputs()[1], byteSz)});
    mlir::Value castNewMem =
        builder.createConvert(loc, mem.getType(), newMem.getResult(0));
    fir::ResultOp::create(builder, loc, castNewMem);
    builder.setInsertionPointToStart(&ifOp.getElseRegion().front());
    // Otherwise, just forward the buffer.
    fir::ResultOp::create(builder, loc, mem);
    builder.restoreInsertionPoint(insPt);
    return ifOp.getResult(0);
  }

  /// Copy the next value (or vector of values) into the array being
  /// constructed.
  mlir::Value copyNextArrayCtorSection(const ExtValue &exv, mlir::Value buffPos,
                                       mlir::Value buffSize, mlir::Value mem,
                                       mlir::Value eleSz, mlir::Type eleTy,
                                       mlir::Type eleRefTy, mlir::Type resTy) {
    mlir::Location loc = getLoc();
    auto off = fir::LoadOp::create(builder, loc, buffPos);
    auto limit = fir::LoadOp::create(builder, loc, buffSize);
    mlir::IndexType idxTy = builder.getIndexType();
    mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);

    if (fir::isRecordWithAllocatableMember(eleTy))
      TODO(loc, "deep copy on allocatable members");

    if (!eleSz) {
      // Compute the element size at runtime.
      assert(fir::hasDynamicSize(eleTy));
      if (auto charTy = mlir::dyn_cast<fir::CharacterType>(eleTy)) {
        auto charBytes =
            builder.getKindMap().getCharacterBitsize(charTy.getFKind()) / 8;
        mlir::Value bytes =
            builder.createIntegerConstant(loc, idxTy, charBytes);
        mlir::Value length = fir::getLen(exv);
        if (!length)
          fir::emitFatalError(loc, "result is not boxed character");
        eleSz = mlir::arith::MulIOp::create(builder, loc, bytes, length);
      } else {
        TODO(loc, "PDT size");
        // Will call the PDT's size function with the type parameters.
      }
    }

    // Compute the coordinate using `fir.coordinate_of`, or, if the type has
    // dynamic size, generating the pointer arithmetic.
    auto computeCoordinate = [&](mlir::Value buff, mlir::Value off) {
      mlir::Type refTy = eleRefTy;
      if (fir::hasDynamicSize(eleTy)) {
        if (auto charTy = mlir::dyn_cast<fir::CharacterType>(eleTy)) {
          // Scale a simple pointer using dynamic length and offset values.
          auto chTy = fir::CharacterType::getSingleton(charTy.getContext(),
                                                       charTy.getFKind());
          refTy = builder.getRefType(chTy);
          mlir::Type toTy = builder.getRefType(builder.getVarLenSeqTy(chTy));
          buff = builder.createConvert(loc, toTy, buff);
          off = mlir::arith::MulIOp::create(builder, loc, off, eleSz);
        } else {
          TODO(loc, "PDT offset");
        }
      }
      auto coor = fir::CoordinateOp::create(builder, loc, refTy, buff,
                                            mlir::ValueRange{off});
      return builder.createConvert(loc, eleRefTy, coor);
    };

    // Lambda to lower an abstract array box value.
    auto doAbstractArray = [&](const auto &v) {
      // Compute the array size.
      mlir::Value arrSz = one;
      for (auto ext : v.getExtents())
        arrSz = mlir::arith::MulIOp::create(builder, loc, arrSz, ext);

      // Grow the buffer as needed.
      auto endOff = mlir::arith::AddIOp::create(builder, loc, off, arrSz);
      mem = growBuffer(mem, endOff, limit, buffSize, eleSz);

      // Copy the elements to the buffer.
      mlir::Value byteSz =
          mlir::arith::MulIOp::create(builder, loc, arrSz, eleSz);
      auto buff = builder.createConvert(loc, fir::HeapType::get(resTy), mem);
      mlir::Value buffi = computeCoordinate(buff, off);
      llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
          builder, loc, memcpyType(), buffi, v.getAddr(), byteSz);
      const bool isVolatile = fir::isa_volatile_type(v.getAddr().getType());
      createCallMemcpy(args, isVolatile);

      // Save the incremented buffer position.
      fir::StoreOp::create(builder, loc, endOff, buffPos);
    };

    // Copy a trivial scalar value into the buffer.
    auto doTrivialScalar = [&](const ExtValue &v, mlir::Value len = {}) {
      // Increment the buffer position.
      auto plusOne = mlir::arith::AddIOp::create(builder, loc, off, one);

      // Grow the buffer as needed.
      mem = growBuffer(mem, plusOne, limit, buffSize, eleSz);

      // Store the element in the buffer.
      mlir::Value buff =
          builder.createConvert(loc, fir::HeapType::get(resTy), mem);
      auto buffi = fir::CoordinateOp::create(builder, loc, eleRefTy, buff,
                                             mlir::ValueRange{off});
      fir::factory::genScalarAssignment(
          builder, loc,
          [&]() -> ExtValue {
            if (len)
              return fir::CharBoxValue(buffi, len);
            return buffi;
          }(),
          v);
      fir::StoreOp::create(builder, loc, plusOne, buffPos);
    };

    // Copy the value.
    exv.match(
        [&](mlir::Value) { doTrivialScalar(exv); },
        [&](const fir::CharBoxValue &v) {
          auto buffer = v.getBuffer();
          if (fir::isa_char(buffer.getType())) {
            doTrivialScalar(exv, eleSz);
          } else {
            // Increment the buffer position.
            auto plusOne = mlir::arith::AddIOp::create(builder, loc, off, one);

            // Grow the buffer as needed.
            mem = growBuffer(mem, plusOne, limit, buffSize, eleSz);

            // Store the element in the buffer.
            mlir::Value buff =
                builder.createConvert(loc, fir::HeapType::get(resTy), mem);
            mlir::Value buffi = computeCoordinate(buff, off);
            llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
                builder, loc, memcpyType(), buffi, v.getAddr(), eleSz);
            const bool isVolatile =
                fir::isa_volatile_type(v.getAddr().getType());
            createCallMemcpy(args, isVolatile);

            fir::StoreOp::create(builder, loc, plusOne, buffPos);
          }
        },
        [&](const fir::ArrayBoxValue &v) { doAbstractArray(v); },
        [&](const fir::CharArrayBoxValue &v) { doAbstractArray(v); },
        [&](const auto &) {
          TODO(loc, "unhandled array constructor expression");
        });
    return mem;
  }

  // Lower the expr cases in an ac-value-list.
  template <typename A>
  std::pair<ExtValue, bool>
  genArrayCtorInitializer(const Fortran::evaluate::Expr<A> &x, mlir::Type,
                          mlir::Value, mlir::Value, mlir::Value,
                          Fortran::lower::StatementContext &stmtCtx) {
    if (isArray(x))
      return {lowerNewArrayExpression(converter, symMap, stmtCtx, toEvExpr(x)),
              /*needCopy=*/true};
    return {asScalar(x), /*needCopy=*/true};
  }

  // Lower an ac-implied-do in an ac-value-list.
  template <typename A>
  std::pair<ExtValue, bool>
  genArrayCtorInitializer(const Fortran::evaluate::ImpliedDo<A> &x,
                          mlir::Type resTy, mlir::Value mem,
                          mlir::Value buffPos, mlir::Value buffSize,
                          Fortran::lower::StatementContext &) {
    mlir::Location loc = getLoc();
    mlir::IndexType idxTy = builder.getIndexType();
    mlir::Value lo =
        builder.createConvert(loc, idxTy, fir::getBase(asScalar(x.lower())));
    mlir::Value up =
        builder.createConvert(loc, idxTy, fir::getBase(asScalar(x.upper())));
    mlir::Value step =
        builder.createConvert(loc, idxTy, fir::getBase(asScalar(x.stride())));
    auto seqTy = mlir::cast<fir::SequenceType>(resTy);
    mlir::Type eleTy = fir::unwrapSequenceType(seqTy);
    auto loop =
        fir::DoLoopOp::create(builder, loc, lo, up, step, /*unordered=*/false,
                              /*finalCount=*/false, mem);
    // create a new binding for x.name(), to ac-do-variable, to the iteration
    // value.
    symMap.pushImpliedDoBinding(toStringRef(x.name()), loop.getInductionVar());
    auto insPt = builder.saveInsertionPoint();
    builder.setInsertionPointToStart(loop.getBody());
    // Thread mem inside the loop via loop argument.
    mem = loop.getRegionIterArgs()[0];

    mlir::Type eleRefTy = builder.getRefType(eleTy);

    // Any temps created in the loop body must be freed inside the loop body.
    stmtCtx.pushScope();
    std::optional<mlir::Value> charLen;
    for (const Fortran::evaluate::ArrayConstructorValue<A> &acv : x.values()) {
      auto [exv, copyNeeded] = Fortran::common::visit(
          [&](const auto &v) {
            return genArrayCtorInitializer(v, resTy, mem, buffPos, buffSize,
                                           stmtCtx);
          },
          acv.u);
      mlir::Value eleSz = computeElementSize(exv, eleTy, resTy);
      mem = copyNeeded ? copyNextArrayCtorSection(exv, buffPos, buffSize, mem,
                                                  eleSz, eleTy, eleRefTy, resTy)
                       : fir::getBase(exv);
      if (fir::isa_char(seqTy.getEleTy()) && !charLen) {
        charLen = builder.createTemporary(loc, builder.getI64Type());
        mlir::Value castLen =
            builder.createConvert(loc, builder.getI64Type(), fir::getLen(exv));
        assert(charLen.has_value());
        fir::StoreOp::create(builder, loc, castLen, *charLen);
      }
    }
    stmtCtx.finalizeAndPop();

    fir::ResultOp::create(builder, loc, mem);
    builder.restoreInsertionPoint(insPt);
    mem = loop.getResult(0);
    symMap.popImpliedDoBinding();
    llvm::SmallVector<mlir::Value> extents = {
        fir::LoadOp::create(builder, loc, buffPos).getResult()};

    // Convert to extended value.
    if (fir::isa_char(seqTy.getEleTy())) {
      assert(charLen.has_value());
      auto len = fir::LoadOp::create(builder, loc, *charLen);
      return {fir::CharArrayBoxValue{mem, len, extents}, /*needCopy=*/false};
    }
    return {fir::ArrayBoxValue{mem, extents}, /*needCopy=*/false};
  }

  // To simplify the handling and interaction between the various cases, array
  // constructors are always lowered to the incremental construction code
  // pattern, even if the extent of the array value is constant. After the
  // MemToReg pass and constant folding, the optimizer should be able to
  // determine that all the buffer overrun tests are false when the
  // incremental construction wasn't actually required.
  template <typename A>
  CC genarr(const Fortran::evaluate::ArrayConstructor<A> &x) {
    mlir::Location loc = getLoc();
    auto evExpr = toEvExpr(x);
    mlir::Type resTy = translateSomeExprToFIRType(converter, evExpr);
    mlir::IndexType idxTy = builder.getIndexType();
    auto seqTy = mlir::cast<fir::SequenceType>(resTy);
    mlir::Type eleTy = fir::unwrapSequenceType(resTy);
    mlir::Value buffSize = builder.createTemporary(loc, idxTy, ".buff.size");
    mlir::Value zero = builder.createIntegerConstant(loc, idxTy, 0);
    mlir::Value buffPos = builder.createTemporary(loc, idxTy, ".buff.pos");
    fir::StoreOp::create(builder, loc, zero, buffPos);
    // Allocate space for the array to be constructed.
    mlir::Value mem;
    if (fir::hasDynamicSize(resTy)) {
      if (fir::hasDynamicSize(eleTy)) {
        // The size of each element may depend on a general expression. Defer
        // creating the buffer until after the expression is evaluated.
        mem = builder.createNullConstant(loc, builder.getRefType(eleTy));
        fir::StoreOp::create(builder, loc, zero, buffSize);
      } else {
        mlir::Value initBuffSz =
            builder.createIntegerConstant(loc, idxTy, clInitialBufferSize);
        mem = fir::AllocMemOp::create(
            builder, loc, eleTy, /*typeparams=*/mlir::ValueRange{}, initBuffSz);
        fir::StoreOp::create(builder, loc, initBuffSz, buffSize);
      }
    } else {
      mem = fir::AllocMemOp::create(builder, loc, resTy);
      int64_t buffSz = 1;
      for (auto extent : seqTy.getShape())
        buffSz *= extent;
      mlir::Value initBuffSz =
          builder.createIntegerConstant(loc, idxTy, buffSz);
      fir::StoreOp::create(builder, loc, initBuffSz, buffSize);
    }
    // Compute size of element
    mlir::Type eleRefTy = builder.getRefType(eleTy);

    // Populate the buffer with the elements, growing as necessary.
    std::optional<mlir::Value> charLen;
    for (const auto &expr : x) {
      auto [exv, copyNeeded] = Fortran::common::visit(
          [&](const auto &e) {
            return genArrayCtorInitializer(e, resTy, mem, buffPos, buffSize,
                                           stmtCtx);
          },
          expr.u);
      mlir::Value eleSz = computeElementSize(exv, eleTy, resTy);
      mem = copyNeeded ? copyNextArrayCtorSection(exv, buffPos, buffSize, mem,
                                                  eleSz, eleTy, eleRefTy, resTy)
                       : fir::getBase(exv);
      if (fir::isa_char(seqTy.getEleTy()) && !charLen) {
        charLen = builder.createTemporary(loc, builder.getI64Type());
        mlir::Value castLen =
            builder.createConvert(loc, builder.getI64Type(), fir::getLen(exv));
        fir::StoreOp::create(builder, loc, castLen, *charLen);
      }
    }
    mem = builder.createConvert(loc, fir::HeapType::get(resTy), mem);
    llvm::SmallVector<mlir::Value> extents = {
        fir::LoadOp::create(builder, loc, buffPos)};

    // Cleanup the temporary.
    fir::FirOpBuilder *bldr = &converter.getFirOpBuilder();
    stmtCtx.attachCleanup(
        [bldr, loc, mem]() { fir::FreeMemOp::create(*bldr, loc, mem); });

    // Return the continuation.
    if (fir::isa_char(seqTy.getEleTy())) {
      if (charLen) {
        auto len = fir::LoadOp::create(builder, loc, *charLen);
        return genarr(fir::CharArrayBoxValue{mem, len, extents});
      }
      return genarr(fir::CharArrayBoxValue{mem, zero, extents});
    }
    return genarr(fir::ArrayBoxValue{mem, extents});
  }

  CC genarr(const Fortran::evaluate::ImpliedDoIndex &) {
    fir::emitFatalError(getLoc(), "implied do index cannot have rank > 0");
  }
  CC genarr(const Fortran::evaluate::TypeParamInquiry &x) {
    TODO(getLoc(), "array expr type parameter inquiry");
    return [](IterSpace iters) -> ExtValue { return mlir::Value{}; };
  }
  CC genarr(const Fortran::evaluate::DescriptorInquiry &x) {
    TODO(getLoc(), "array expr descriptor inquiry");
    return [](IterSpace iters) -> ExtValue { return mlir::Value{}; };
  }
  CC genarr(const Fortran::evaluate::StructureConstructor &x) {
    TODO(getLoc(), "structure constructor");
    return [](IterSpace iters) -> ExtValue { return mlir::Value{}; };
  }

  //===--------------------------------------------------------------------===//
  // LOCICAL operators (.NOT., .AND., .EQV., etc.)
  //===--------------------------------------------------------------------===//

  template <int KIND>
  CC genarr(const Fortran::evaluate::Not<KIND> &x) {
    mlir::Location loc = getLoc();
    mlir::IntegerType i1Ty = builder.getI1Type();
    auto lambda = genarr(x.left());
    mlir::Value truth = builder.createBool(loc, true);
    return [=](IterSpace iters) -> ExtValue {
      mlir::Value logical = fir::getBase(lambda(iters));
      mlir::Value val = builder.createConvert(loc, i1Ty, logical);
      return mlir::arith::XOrIOp::create(builder, loc, val, truth);
    };
  }
  template <typename OP, typename A>
  CC createBinaryBoolOp(const A &x) {
    mlir::Location loc = getLoc();
    mlir::IntegerType i1Ty = builder.getI1Type();
    auto lf = genarr(x.left());
    auto rf = genarr(x.right());
    return [=](IterSpace iters) -> ExtValue {
      mlir::Value left = fir::getBase(lf(iters));
      mlir::Value right = fir::getBase(rf(iters));
      mlir::Value lhs = builder.createConvert(loc, i1Ty, left);
      mlir::Value rhs = builder.createConvert(loc, i1Ty, right);
      return OP::create(builder, loc, lhs, rhs);
    };
  }
  template <typename OP, typename A>
  CC createCompareBoolOp(mlir::arith::CmpIPredicate pred, const A &x) {
    mlir::Location loc = getLoc();
    mlir::IntegerType i1Ty = builder.getI1Type();
    auto lf = genarr(x.left());
    auto rf = genarr(x.right());
    return [=](IterSpace iters) -> ExtValue {
      mlir::Value left = fir::getBase(lf(iters));
      mlir::Value right = fir::getBase(rf(iters));
      mlir::Value lhs = builder.createConvert(loc, i1Ty, left);
      mlir::Value rhs = builder.createConvert(loc, i1Ty, right);
      return OP::create(builder, loc, pred, lhs, rhs);
    };
  }
  template <int KIND>
  CC genarr(const Fortran::evaluate::LogicalOperation<KIND> &x) {
    switch (x.logicalOperator) {
    case Fortran::evaluate::LogicalOperator::And:
      return createBinaryBoolOp<mlir::arith::AndIOp>(x);
    case Fortran::evaluate::LogicalOperator::Or:
      return createBinaryBoolOp<mlir::arith::OrIOp>(x);
    case Fortran::evaluate::LogicalOperator::Eqv:
      return createCompareBoolOp<mlir::arith::CmpIOp>(
          mlir::arith::CmpIPredicate::eq, x);
    case Fortran::evaluate::LogicalOperator::Neqv:
      return createCompareBoolOp<mlir::arith::CmpIOp>(
          mlir::arith::CmpIPredicate::ne, x);
    case Fortran::evaluate::LogicalOperator::Not:
      llvm_unreachable(".NOT. handled elsewhere");
    }
    llvm_unreachable("unhandled case");
  }

  //===--------------------------------------------------------------------===//
  // Relational operators (<, <=, ==, etc.)
  //===--------------------------------------------------------------------===//

  template <typename OP, typename PRED, typename A>
  CC createCompareOp(PRED pred, const A &x,
                     std::optional<int> unsignedKind = std::nullopt) {
    mlir::Location loc = getLoc();
    auto lf = genarr(x.left());
    auto rf = genarr(x.right());
    return [=](IterSpace iters) -> ExtValue {
      mlir::Value lhs = fir::getBase(lf(iters));
      mlir::Value rhs = fir::getBase(rf(iters));
      if (unsignedKind) {
        mlir::Type signlessType = converter.genType(
            Fortran::common::TypeCategory::Integer, *unsignedKind);
        mlir::Value lhsSL = builder.createConvert(loc, signlessType, lhs);
        mlir::Value rhsSL = builder.createConvert(loc, signlessType, rhs);
        return OP::create(builder, loc, pred, lhsSL, rhsSL);
      }
      return OP::create(builder, loc, pred, lhs, rhs);
    };
  }
  template <typename A>
  CC createCompareCharOp(mlir::arith::CmpIPredicate pred, const A &x) {
    mlir::Location loc = getLoc();
    auto lf = genarr(x.left());
    auto rf = genarr(x.right());
    return [=](IterSpace iters) -> ExtValue {
      auto lhs = lf(iters);
      auto rhs = rf(iters);
      return fir::runtime::genCharCompare(builder, loc, pred, lhs, rhs);
    };
  }
  template <int KIND>
  CC genarr(const Fortran::evaluate::Relational<Fortran::evaluate::Type<
                Fortran::common::TypeCategory::Integer, KIND>> &x) {
    return createCompareOp<mlir::arith::CmpIOp>(
        translateSignedRelational(x.opr), x);
  }
  template <int KIND>
  CC genarr(const Fortran::evaluate::Relational<Fortran::evaluate::Type<
                Fortran::common::TypeCategory::Unsigned, KIND>> &x) {
    return createCompareOp<mlir::arith::CmpIOp>(
        translateUnsignedRelational(x.opr), x, KIND);
  }
  template <int KIND>
  CC genarr(const Fortran::evaluate::Relational<Fortran::evaluate::Type<
                Fortran::common::TypeCategory::Character, KIND>> &x) {
    return createCompareCharOp(translateSignedRelational(x.opr), x);
  }
  template <int KIND>
  CC genarr(const Fortran::evaluate::Relational<Fortran::evaluate::Type<
                Fortran::common::TypeCategory::Real, KIND>> &x) {
    return createCompareOp<mlir::arith::CmpFOp>(translateFloatRelational(x.opr),
                                                x);
  }
  template <int KIND>
  CC genarr(const Fortran::evaluate::Relational<Fortran::evaluate::Type<
                Fortran::common::TypeCategory::Complex, KIND>> &x) {
    return createCompareOp<fir::CmpcOp>(translateFloatRelational(x.opr), x);
  }
  CC genarr(
      const Fortran::evaluate::Relational<Fortran::evaluate::SomeType> &r) {
    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 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 Fortran::common::visit(
        Fortran::common::visitors{
            [](const ImplicitSubscripts &) { return false; },
            [](const auto *v) { return v->Rank() > 0; }},
        x);
  }

  void extendComponent(Fortran::lower::ComponentPath &component,
                       mlir::Type coorTy, mlir::ValueRange vals) {
    auto *bldr = &converter.getFirOpBuilder();
    llvm::SmallVector<mlir::Value> offsets(vals.begin(), vals.end());
    auto currentFunc = component.getExtendCoorRef();
    auto loc = getLoc();
    auto newCoorRef = [bldr, coorTy, offsets, currentFunc,
                       loc](mlir::Value val) -> mlir::Value {
      return fir::CoordinateOp::create(*bldr, loc, bldr->getRefType(coorTy),
                                       currentFunc(val), offsets);
    };
    component.extendCoorRef = newCoorRef;
  }

  //===-------------------------------------------------------------------===//
  // Array data references in an explicit iteration space.
  //
  // Use the base array that was loaded before the loop nest.
  //===-------------------------------------------------------------------===//

  /// Lower the path (`revPath`, in reverse) to be appended to an array_fetch or
  /// array_update op. \p ty is the initial type of the array
  /// (reference). Returns the type of the element after application of the
  /// path in \p components.
  ///
  /// TODO: This needs to deal with array's with initial bounds other than 1.
  /// TODO: Thread type parameters correctly.
  mlir::Type lowerPath(const ExtValue &arrayExv, ComponentPath &components) {
    mlir::Location loc = getLoc();
    mlir::Type ty = fir::getBase(arrayExv).getType();
    auto &revPath = components.reversePath;
    ty = fir::unwrapPassByRefType(ty);
    bool prefix = true;
    bool deref = false;
    auto addComponentList = [&](mlir::Type ty, mlir::ValueRange vals) {
      if (deref) {
        extendComponent(components, ty, vals);
      } else if (prefix) {
        for (auto v : vals)
          components.prefixComponents.push_back(v);
      } else {
        for (auto v : vals)
          components.suffixComponents.push_back(v);
      }
    };
    mlir::IndexType idxTy = builder.getIndexType();
    mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
    bool atBase = true;
    PushSemantics(isProjectedCopyInCopyOut()
                      ? ConstituentSemantics::RefTransparent
                      : nextPathSemantics());
    unsigned index = 0;
    for (const auto &v : llvm::reverse(revPath)) {
      Fortran::common::visit(
          Fortran::common::visitors{
              [&](const ImplicitSubscripts &) {
                prefix = false;
                ty = fir::unwrapSequenceType(ty);
              },
              [&](const Fortran::evaluate::ComplexPart *x) {
                assert(!prefix && "complex part must be at end");
                mlir::Value offset = builder.createIntegerConstant(
                    loc, builder.getI32Type(),
                    x->part() == Fortran::evaluate::ComplexPart::Part::RE ? 0
                                                                          : 1);
                components.suffixComponents.push_back(offset);
                ty = fir::applyPathToType(ty, mlir::ValueRange{offset});
              },
              [&](const Fortran::evaluate::ArrayRef *x) {
                if (Fortran::lower::isRankedArrayAccess(*x)) {
                  genSliceIndices(components, arrayExv, *x, atBase);
                  ty = fir::unwrapSeqOrBoxedSeqType(ty);
                } else {
                  // Array access where the expressions are scalar and cannot
                  // depend upon the implied iteration space.
                  unsigned ssIndex = 0u;
                  llvm::SmallVector<mlir::Value> componentsToAdd;
                  for (const auto &ss : x->subscript()) {
                    Fortran::common::visit(
                        Fortran::common::visitors{
                            [&](const Fortran::evaluate::
                                    IndirectSubscriptIntegerExpr &ie) {
                              const auto &e = ie.value();
                              if (isArray(e))
                                fir::emitFatalError(
                                    loc,
                                    "multiple components along single path "
                                    "generating array subexpressions");
                              // Lower scalar index expression, append it to
                              // subs.
                              mlir::Value subscriptVal =
                                  fir::getBase(asScalarArray(e));
                              // arrayExv is the base array. It needs to reflect
                              // the current array component instead.
                              // FIXME: must use lower bound of this component,
                              // not just the constant 1.
                              mlir::Value lb =
                                  atBase ? fir::factory::readLowerBound(
                                               builder, loc, arrayExv, ssIndex,
                                               one)
                                         : one;
                              mlir::Value val = builder.createConvert(
                                  loc, idxTy, subscriptVal);
                              mlir::Value ivAdj = mlir::arith::SubIOp::create(
                                  builder, loc, idxTy, val, lb);
                              componentsToAdd.push_back(
                                  builder.createConvert(loc, idxTy, ivAdj));
                            },
                            [&](const auto &) {
                              fir::emitFatalError(
                                  loc, "multiple components along single path "
                                       "generating array subexpressions");
                            }},
                        ss.u);
                    ssIndex++;
                  }
                  ty = fir::unwrapSeqOrBoxedSeqType(ty);
                  addComponentList(ty, componentsToAdd);
                }
              },
              [&](const Fortran::evaluate::Component *x) {
                auto fieldTy = fir::FieldType::get(builder.getContext());
                std::string name =
                    converter.getRecordTypeFieldName(getLastSym(*x));
                if (auto recTy = mlir::dyn_cast<fir::RecordType>(ty)) {
                  ty = recTy.getType(name);
                  auto fld = fir::FieldIndexOp::create(
                      builder, loc, fieldTy, name, recTy,
                      fir::getTypeParams(arrayExv));
                  addComponentList(ty, {fld});
                  if (index != revPath.size() - 1 || !isPointerAssignment()) {
                    // Need an intermediate  dereference if the boxed value
                    // appears in the middle of the component path or if it is
                    // on the right and this is not a pointer assignment.
                    if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(ty)) {
                      auto currentFunc = components.getExtendCoorRef();
                      auto loc = getLoc();
                      auto *bldr = &converter.getFirOpBuilder();
                      auto newCoorRef = [=](mlir::Value val) -> mlir::Value {
                        return fir::LoadOp::create(*bldr, loc,
                                                   currentFunc(val));
                      };
                      components.extendCoorRef = newCoorRef;
                      deref = true;
                    }
                  }
                } else if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(ty)) {
                  ty = fir::unwrapRefType(boxTy.getEleTy());
                  auto recTy = mlir::cast<fir::RecordType>(ty);
                  ty = recTy.getType(name);
                  auto fld = fir::FieldIndexOp::create(
                      builder, loc, fieldTy, name, recTy,
                      fir::getTypeParams(arrayExv));
                  extendComponent(components, ty, {fld});
                } else {
                  TODO(loc, "other component type");
                }
              }},
          v);
      atBase = false;
      ++index;
    }
    ty = fir::unwrapSequenceType(ty);
    components.applied = true;
    return ty;
  }

  llvm::SmallVector<mlir::Value> genSubstringBounds(ComponentPath &components) {
    llvm::SmallVector<mlir::Value> result;
    if (components.substring)
      populateBounds(result, components.substring);
    return result;
  }

  CC applyPathToArrayLoad(fir::ArrayLoadOp load, ComponentPath &components) {
    mlir::Location loc = getLoc();
    auto revPath = components.reversePath;
    fir::ExtendedValue arrayExv =
        arrayLoadExtValue(builder, loc, load, {}, load);
    mlir::Type eleTy = lowerPath(arrayExv, components);
    auto currentPC = components.pc;
    auto pc = [=, prefix = components.prefixComponents,
               suffix = components.suffixComponents](IterSpace iters) {
      // Add path prefix and suffix.
      return IterationSpace(currentPC(iters), prefix, suffix);
    };
    components.resetPC();
    llvm::SmallVector<mlir::Value> substringBounds =
        genSubstringBounds(components);
    if (isProjectedCopyInCopyOut()) {
      destination = load;
      auto lambda = [=, esp = this->explicitSpace](IterSpace iters) mutable {
        mlir::Value innerArg = esp->findArgumentOfLoad(load);
        if (isAdjustedArrayElementType(eleTy)) {
          mlir::Type eleRefTy = builder.getRefType(eleTy);
          auto arrayOp = fir::ArrayAccessOp::create(
              builder, loc, eleRefTy, innerArg, iters.iterVec(),
              fir::factory::getTypeParams(loc, builder, load));
          if (auto charTy = mlir::dyn_cast<fir::CharacterType>(eleTy)) {
            mlir::Value dstLen = fir::factory::genLenOfCharacter(
                builder, loc, load, iters.iterVec(), substringBounds);
            fir::ArrayAmendOp amend = createCharArrayAmend(
                loc, builder, arrayOp, dstLen, iters.elementExv(), innerArg,
                substringBounds);
            return arrayLoadExtValue(builder, loc, load, iters.iterVec(), amend,
                                     dstLen);
          }
          if (fir::isa_derived(eleTy)) {
            fir::ArrayAmendOp amend =
                createDerivedArrayAmend(loc, load, builder, arrayOp,
                                        iters.elementExv(), eleTy, innerArg);
            return arrayLoadExtValue(builder, loc, load, iters.iterVec(),
                                     amend);
          }
          assert(mlir::isa<fir::SequenceType>(eleTy));
          TODO(loc, "array (as element) assignment");
        }
        if (components.hasExtendCoorRef()) {
          auto eleBoxTy =
              fir::applyPathToType(innerArg.getType(), iters.iterVec());
          if (!eleBoxTy || !mlir::isa<fir::BoxType>(eleBoxTy))
            TODO(loc, "assignment in a FORALL involving a designator with a "
                      "POINTER or ALLOCATABLE component part-ref");
          auto arrayOp = fir::ArrayAccessOp::create(
              builder, loc, builder.getRefType(eleBoxTy), innerArg,
              iters.iterVec(), fir::factory::getTypeParams(loc, builder, load));
          mlir::Value addr = components.getExtendCoorRef()(arrayOp);
          components.resetExtendCoorRef();
          // When the lhs is a boxed value and the context is not a pointer
          // assignment, then insert the dereference of the box before any
          // conversion and store.
          if (!isPointerAssignment()) {
            if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(eleTy)) {
              eleTy = fir::boxMemRefType(boxTy);
              addr = fir::BoxAddrOp::create(builder, loc, eleTy, addr);
              eleTy = fir::unwrapRefType(eleTy);
            }
          }
          auto ele = convertElementForUpdate(loc, eleTy, iters.getElement());
          fir::StoreOp::create(builder, loc, ele, addr);
          auto amend = fir::ArrayAmendOp::create(
              builder, loc, innerArg.getType(), innerArg, arrayOp);
          return arrayLoadExtValue(builder, loc, load, iters.iterVec(), amend);
        }
        auto ele = convertElementForUpdate(loc, eleTy, iters.getElement());
        auto update = fir::ArrayUpdateOp::create(
            builder, loc, innerArg.getType(), innerArg, ele, iters.iterVec(),
            fir::factory::getTypeParams(loc, builder, load));
        return arrayLoadExtValue(builder, loc, load, iters.iterVec(), update);
      };
      return [=](IterSpace iters) mutable { return lambda(pc(iters)); };
    }
    if (isCustomCopyInCopyOut()) {
      // Create an array_modify to get the LHS element address and indicate
      // the assignment, and create the call to the user defined assignment.
      destination = load;
      auto lambda = [=](IterSpace iters) mutable {
        mlir::Value innerArg = explicitSpace->findArgumentOfLoad(load);
        mlir::Type refEleTy =
            fir::isa_ref_type(eleTy) ? eleTy : builder.getRefType(eleTy);
        auto arrModify = fir::ArrayModifyOp::create(
            builder, loc, mlir::TypeRange{refEleTy, innerArg.getType()},
            innerArg, iters.iterVec(), load.getTypeparams());
        return arrayLoadExtValue(builder, loc, load, iters.iterVec(),
                                 arrModify.getResult(1));
      };
      return [=](IterSpace iters) mutable { return lambda(pc(iters)); };
    }
    auto lambda = [=, semant = this->semant](IterSpace iters) mutable {
      if (semant == ConstituentSemantics::RefOpaque ||
          isAdjustedArrayElementType(eleTy)) {
        mlir::Type resTy = builder.getRefType(eleTy);
        // Use array element reference semantics.
        auto access = fir::ArrayAccessOp::create(
            builder, loc, resTy, load, iters.iterVec(),
            fir::factory::getTypeParams(loc, builder, load));
        mlir::Value newBase = access;
        if (fir::isa_char(eleTy)) {
          mlir::Value dstLen = fir::factory::genLenOfCharacter(
              builder, loc, load, iters.iterVec(), substringBounds);
          if (!substringBounds.empty()) {
            fir::CharBoxValue charDst{access, dstLen};
            fir::factory::CharacterExprHelper helper{builder, loc};
            charDst = helper.createSubstring(charDst, substringBounds);
            newBase = charDst.getAddr();
          }
          return arrayLoadExtValue(builder, loc, load, iters.iterVec(), newBase,
                                   dstLen);
        }
        return arrayLoadExtValue(builder, loc, load, iters.iterVec(), newBase);
      }
      if (components.hasExtendCoorRef()) {
        auto eleBoxTy = fir::applyPathToType(load.getType(), iters.iterVec());
        if (!eleBoxTy || !mlir::isa<fir::BoxType>(eleBoxTy))
          TODO(loc, "assignment in a FORALL involving a designator with a "
                    "POINTER or ALLOCATABLE component part-ref");
        auto access = fir::ArrayAccessOp::create(
            builder, loc, builder.getRefType(eleBoxTy), load, iters.iterVec(),
            fir::factory::getTypeParams(loc, builder, load));
        mlir::Value addr = components.getExtendCoorRef()(access);
        components.resetExtendCoorRef();
        return arrayLoadExtValue(builder, loc, load, iters.iterVec(), addr);
      }
      if (isPointerAssignment()) {
        auto eleTy = fir::applyPathToType(load.getType(), iters.iterVec());
        if (!mlir::isa<fir::BoxType>(eleTy)) {
          // Rhs is a regular expression that will need to be boxed before
          // assigning to the boxed variable.
          auto typeParams = fir::factory::getTypeParams(loc, builder, load);
          auto access = fir::ArrayAccessOp::create(
              builder, loc, builder.getRefType(eleTy), load, iters.iterVec(),
              typeParams);
          auto addr = components.getExtendCoorRef()(access);
          components.resetExtendCoorRef();
          auto ptrEleTy = fir::PointerType::get(eleTy);
          auto ptrAddr = builder.createConvert(loc, ptrEleTy, addr);
          auto boxTy = fir::BoxType::get(
              ptrEleTy, fir::isa_volatile_type(addr.getType()));
          // FIXME: The typeparams to the load may be different than those of
          // the subobject.
          if (components.hasExtendCoorRef())
            TODO(loc, "need to adjust typeparameter(s) to reflect the final "
                      "component");
          mlir::Value embox =
              fir::EmboxOp::create(builder, loc, boxTy, ptrAddr,
                                   /*shape=*/mlir::Value{},
                                   /*slice=*/mlir::Value{}, typeParams);
          return arrayLoadExtValue(builder, loc, load, iters.iterVec(), embox);
        }
      }
      auto fetch = fir::ArrayFetchOp::create(
          builder, loc, eleTy, load, iters.iterVec(), load.getTypeparams());
      return arrayLoadExtValue(builder, loc, load, iters.iterVec(), fetch);
    };
    return [=](IterSpace iters) mutable { return lambda(pc(iters)); };
  }

  template <typename A>
  CC genImplicitArrayAccess(const A &x, ComponentPath &components) {
    components.reversePath.push_back(ImplicitSubscripts{});
    ExtValue exv = asScalarRef(x);
    lowerPath(exv, components);
    auto lambda = genarr(exv, components);
    return [=](IterSpace iters) { return lambda(components.pc(iters)); };
  }
  CC genImplicitArrayAccess(const Fortran::evaluate::NamedEntity &x,
                            ComponentPath &components) {
    if (x.IsSymbol())
      return genImplicitArrayAccess(getFirstSym(x), components);
    return genImplicitArrayAccess(x.GetComponent(), components);
  }

  CC genImplicitArrayAccess(const Fortran::semantics::Symbol &x,
                            ComponentPath &components) {
    mlir::Value ptrVal = nullptr;
    if (x.test(Fortran::semantics::Symbol::Flag::CrayPointee)) {
      Fortran::semantics::SymbolRef ptrSym{
          Fortran::semantics::GetCrayPointer(x)};
      ExtValue ptr = converter.getSymbolExtendedValue(ptrSym);
      ptrVal = fir::getBase(ptr);
    }
    components.reversePath.push_back(ImplicitSubscripts{});
    ExtValue exv = asScalarRef(x);
    lowerPath(exv, components);
    auto lambda = genarr(exv, components, ptrVal);
    return [=](IterSpace iters) { return lambda(components.pc(iters)); };
  }

  template <typename A>
  CC genAsScalar(const A &x) {
    mlir::Location loc = getLoc();
    if (isProjectedCopyInCopyOut()) {
      return [=, &x, builder = &converter.getFirOpBuilder()](
                 IterSpace iters) -> ExtValue {
        ExtValue exv = asScalarRef(x);
        mlir::Value addr = fir::getBase(exv);
        mlir::Type eleTy = fir::unwrapRefType(addr.getType());
        if (isAdjustedArrayElementType(eleTy)) {
          if (fir::isa_char(eleTy)) {
            fir::factory::CharacterExprHelper{*builder, loc}.createAssign(
                exv, iters.elementExv());
          } else if (fir::isa_derived(eleTy)) {
            TODO(loc, "assignment of derived type");
          } else {
            fir::emitFatalError(loc, "array type not expected in scalar");
          }
        } else {
          auto eleVal = convertElementForUpdate(loc, eleTy, iters.getElement());
          fir::StoreOp::create(*builder, loc, eleVal, addr);
        }
        return exv;
      };
    }
    return [=, &x](IterSpace) { return asScalar(x); };
  }

  bool tailIsPointerInPointerAssignment(const Fortran::semantics::Symbol &x,
                                        ComponentPath &components) {
    return isPointerAssignment() && Fortran::semantics::IsPointer(x) &&
           !components.hasComponents();
  }
  bool tailIsPointerInPointerAssignment(const Fortran::evaluate::Component &x,
                                        ComponentPath &components) {
    return tailIsPointerInPointerAssignment(getLastSym(x), components);
  }

  CC genarr(const Fortran::semantics::Symbol &x, ComponentPath &components) {
    if (explicitSpaceIsActive()) {
      if (x.Rank() > 0 && !tailIsPointerInPointerAssignment(x, components))
        components.reversePath.push_back(ImplicitSubscripts{});
      if (fir::ArrayLoadOp load = explicitSpace->findBinding(&x))
        return applyPathToArrayLoad(load, components);
    } else {
      return genImplicitArrayAccess(x, components);
    }
    if (pathIsEmpty(components))
      return components.substring ? genAsScalar(*components.substring)
                                  : genAsScalar(x);
    mlir::Location loc = getLoc();
    return [=](IterSpace) -> ExtValue {
      fir::emitFatalError(loc, "reached symbol with path");
    };
  }

  /// Lower a component path with or without rank.
  /// Example: <code>array%baz%qux%waldo</code>
  CC genarr(const Fortran::evaluate::Component &x, ComponentPath &components) {
    if (explicitSpaceIsActive()) {
      if (x.base().Rank() == 0 && x.Rank() > 0 &&
          !tailIsPointerInPointerAssignment(x, components))
        components.reversePath.push_back(ImplicitSubscripts{});
      if (fir::ArrayLoadOp load = explicitSpace->findBinding(&x))
        return applyPathToArrayLoad(load, components);
    } else {
      if (x.base().Rank() == 0)
        return genImplicitArrayAccess(x, components);
    }
    bool atEnd = pathIsEmpty(components);
    if (!getLastSym(x).test(Fortran::semantics::Symbol::Flag::ParentComp))
      // Skip parent components; their components are placed directly in the
      // object.
      components.reversePath.push_back(&x);
    auto result = genarr(x.base(), components);
    if (components.applied)
      return result;
    if (atEnd)
      return genAsScalar(x);
    mlir::Location loc = getLoc();
    return [=](IterSpace) -> ExtValue {
      fir::emitFatalError(loc, "reached component with path");
    };
  }

  /// Array reference with subscripts. If this has rank > 0, this is a form
  /// of an array section (slice).
  ///
  /// There are two "slicing" primitives that may be applied on a dimension by
  /// dimension basis: (1) triple notation and (2) vector addressing. Since
  /// dimensions can be selectively sliced, some dimensions may contain
  /// regular scalar expressions and those dimensions do not participate in
  /// the array expression evaluation.
  CC genarr(const Fortran::evaluate::ArrayRef &x, ComponentPath &components) {
    if (explicitSpaceIsActive()) {
      if (Fortran::lower::isRankedArrayAccess(x))
        components.reversePath.push_back(ImplicitSubscripts{});
      if (fir::ArrayLoadOp load = explicitSpace->findBinding(&x)) {
        components.reversePath.push_back(&x);
        return applyPathToArrayLoad(load, components);
      }
    } else {
      if (Fortran::lower::isRankedArrayAccess(x)) {
        components.reversePath.push_back(&x);
        return genImplicitArrayAccess(x.base(), components);
      }
    }
    bool atEnd = pathIsEmpty(components);
    components.reversePath.push_back(&x);
    auto result = genarr(x.base(), components);
    if (components.applied)
      return result;
    mlir::Location loc = getLoc();
    if (atEnd) {
      if (x.Rank() == 0)
        return genAsScalar(x);
      fir::emitFatalError(loc, "expected scalar");
    }
    return [=](IterSpace) -> ExtValue {
      fir::emitFatalError(loc, "reached arrayref with path");
    };
  }

  CC genarr(const Fortran::evaluate::CoarrayRef &x, ComponentPath &components) {
    TODO(getLoc(), "coarray: reference to a coarray in an expression");
  }

  CC genarr(const Fortran::evaluate::NamedEntity &x,
            ComponentPath &components) {
    return x.IsSymbol() ? genarr(getFirstSym(x), components)
                        : genarr(x.GetComponent(), components);
  }

  CC genarr(const Fortran::evaluate::DataRef &x, ComponentPath &components) {
    return Fortran::common::visit(
        [&](const auto &v) { return genarr(v, components); }, x.u);
  }

  bool pathIsEmpty(const ComponentPath &components) {
    return components.reversePath.empty();
  }

  explicit ArrayExprLowering(Fortran::lower::AbstractConverter &converter,
                             Fortran::lower::StatementContext &stmtCtx,
                             Fortran::lower::SymMap &symMap)
      : converter{converter}, builder{converter.getFirOpBuilder()},
        stmtCtx{stmtCtx}, symMap{symMap} {}

  explicit ArrayExprLowering(Fortran::lower::AbstractConverter &converter,
                             Fortran::lower::StatementContext &stmtCtx,
                             Fortran::lower::SymMap &symMap,
                             ConstituentSemantics sem)
      : converter{converter}, builder{converter.getFirOpBuilder()},
        stmtCtx{stmtCtx}, symMap{symMap}, semant{sem} {}

  explicit ArrayExprLowering(Fortran::lower::AbstractConverter &converter,
                             Fortran::lower::StatementContext &stmtCtx,
                             Fortran::lower::SymMap &symMap,
                             ConstituentSemantics sem,
                             Fortran::lower::ExplicitIterSpace *expSpace,
                             Fortran::lower::ImplicitIterSpace *impSpace)
      : converter{converter}, builder{converter.getFirOpBuilder()},
        stmtCtx{stmtCtx}, symMap{symMap},
        explicitSpace((expSpace && expSpace->isActive()) ? expSpace : nullptr),
        implicitSpace((impSpace && !impSpace->empty()) ? impSpace : nullptr),
        semant{sem} {
    // Generate any mask expressions, as necessary. This is the compute step
    // that creates the effective masks. See 10.2.3.2 in particular.
    genMasks();
  }

  mlir::Location getLoc() { return converter.getCurrentLocation(); }

  /// Array appears in a lhs context such that it is assigned after the rhs is
  /// fully evaluated.
  inline bool isCopyInCopyOut() {
    return semant == ConstituentSemantics::CopyInCopyOut;
  }

  /// Array appears in a lhs (or temp) context such that a projected,
  /// discontiguous subspace of the array is assigned after the rhs is fully
  /// evaluated. That is, the rhs array value is merged into a section of the
  /// lhs array.
  inline bool isProjectedCopyInCopyOut() {
    return semant == ConstituentSemantics::ProjectedCopyInCopyOut;
  }

  // ???: Do we still need this?
  inline bool isCustomCopyInCopyOut() {
    return semant == ConstituentSemantics::CustomCopyInCopyOut;
  }

  /// Are we lowering in a left-hand side context?
  inline bool isLeftHandSide() {
    return isCopyInCopyOut() || isProjectedCopyInCopyOut() ||
           isCustomCopyInCopyOut();
  }

  /// Array appears in a context where it must be boxed.
  inline bool isBoxValue() { return semant == ConstituentSemantics::BoxValue; }

  /// Array appears in a context where differences in the memory reference can
  /// be observable in the computational results. For example, an array
  /// element is passed to an impure procedure.
  inline bool isReferentiallyOpaque() {
    return semant == ConstituentSemantics::RefOpaque;
  }

  /// Array appears in a context where it is passed as a VALUE argument.
  inline bool isValueAttribute() {
    return semant == ConstituentSemantics::ByValueArg;
  }

  /// Semantics to use when lowering the next array path.
  /// If no value was set, the path uses the same semantics as the array.
  inline ConstituentSemantics nextPathSemantics() {
    if (nextPathSemant) {
      ConstituentSemantics sema = nextPathSemant.value();
      nextPathSemant.reset();
      return sema;
    }

    return semant;
  }

  /// Can the loops over the expression be unordered?
  inline bool isUnordered() const { return unordered; }

  void setUnordered(bool b) { unordered = b; }

  inline bool isPointerAssignment() const { return lbounds.has_value(); }

  inline bool isBoundsSpec() const {
    return isPointerAssignment() && !ubounds.has_value();
  }

  inline bool isBoundsRemap() const {
    return isPointerAssignment() && ubounds.has_value();
  }

  void setPointerAssignmentBounds(
      const llvm::SmallVector<mlir::Value> &lbs,
      std::optional<llvm::SmallVector<mlir::Value>> ubs) {
    lbounds = lbs;
    ubounds = ubs;
  }

  void setLoweredProcRef(const Fortran::evaluate::ProcedureRef *procRef) {
    loweredProcRef = procRef;
  }

  Fortran::lower::AbstractConverter &converter;
  fir::FirOpBuilder &builder;
  Fortran::lower::StatementContext &stmtCtx;
  bool elementCtx = false;
  Fortran::lower::SymMap &symMap;
  /// The continuation to generate code to update the destination.
  std::optional<CC> ccStoreToDest;
  std::optional<std::function<void(llvm::ArrayRef<mlir::Value>)>> ccPrelude;
  std::optional<std::function<fir::ArrayLoadOp(llvm::ArrayRef<mlir::Value>)>>
      ccLoadDest;
  /// The destination is the loaded array into which the results will be
  /// merged.
  fir::ArrayLoadOp destination;
  /// The shape of the destination.
  llvm::SmallVector<mlir::Value> destShape;
  /// List of arrays in the expression that have been loaded.
  llvm::SmallVector<ArrayOperand> arrayOperands;
  /// If there is a user-defined iteration space, explicitShape will hold the
  /// information from the front end.
  Fortran::lower::ExplicitIterSpace *explicitSpace = nullptr;
  Fortran::lower::ImplicitIterSpace *implicitSpace = nullptr;
  ConstituentSemantics semant = ConstituentSemantics::RefTransparent;
  std::optional<ConstituentSemantics> nextPathSemant;
  /// `lbounds`, `ubounds` are used in POINTER value assignments, which may only
  /// occur in an explicit iteration space.
  std::optional<llvm::SmallVector<mlir::Value>> lbounds;
  std::optional<llvm::SmallVector<mlir::Value>> ubounds;
  // Can the array expression be evaluated in any order?
  // Will be set to false if any of the expression parts prevent this.
  bool unordered = true;
  // ProcedureRef currently being lowered. Used to retrieve the iteration shape
  // in elemental context with passed object.
  const Fortran::evaluate::ProcedureRef *loweredProcRef = nullptr;
};
} // namespace

fir::ExtendedValue Fortran::lower::createSomeExtendedExpression(
    mlir::Location loc, Fortran::lower::AbstractConverter &converter,
    const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &symMap,
    Fortran::lower::StatementContext &stmtCtx) {
  LLVM_DEBUG(expr.AsFortran(llvm::dbgs() << "expr: ") << '\n');
  return ScalarExprLowering{loc, converter, symMap, stmtCtx}.genval(expr);
}

fir::ExtendedValue Fortran::lower::createSomeInitializerExpression(
    mlir::Location loc, Fortran::lower::AbstractConverter &converter,
    const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &symMap,
    Fortran::lower::StatementContext &stmtCtx) {
  LLVM_DEBUG(expr.AsFortran(llvm::dbgs() << "expr: ") << '\n');
  return ScalarExprLowering{loc, converter, symMap, stmtCtx,
                            /*inInitializer=*/true}
      .genval(expr);
}

fir::ExtendedValue Fortran::lower::createSomeExtendedAddress(
    mlir::Location loc, Fortran::lower::AbstractConverter &converter,
    const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &symMap,
    Fortran::lower::StatementContext &stmtCtx) {
  LLVM_DEBUG(expr.AsFortran(llvm::dbgs() << "address: ") << '\n');
  return ScalarExprLowering(loc, converter, symMap, stmtCtx).gen(expr);
}

fir::ExtendedValue Fortran::lower::createInitializerAddress(
    mlir::Location loc, Fortran::lower::AbstractConverter &converter,
    const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &symMap,
    Fortran::lower::StatementContext &stmtCtx) {
  LLVM_DEBUG(expr.AsFortran(llvm::dbgs() << "address: ") << '\n');
  return ScalarExprLowering(loc, converter, symMap, stmtCtx,
                            /*inInitializer=*/true)
      .gen(expr);
}

void Fortran::lower::createSomeArrayAssignment(
    Fortran::lower::AbstractConverter &converter,
    const Fortran::lower::SomeExpr &lhs, const Fortran::lower::SomeExpr &rhs,
    Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx) {
  LLVM_DEBUG(lhs.AsFortran(llvm::dbgs() << "onto array: ") << '\n';
             rhs.AsFortran(llvm::dbgs() << "assign expression: ") << '\n';);
  ArrayExprLowering::lowerArrayAssignment(converter, symMap, stmtCtx, lhs, rhs);
}

void Fortran::lower::createSomeArrayAssignment(
    Fortran::lower::AbstractConverter &converter, const fir::ExtendedValue &lhs,
    const Fortran::lower::SomeExpr &rhs, Fortran::lower::SymMap &symMap,
    Fortran::lower::StatementContext &stmtCtx) {
  LLVM_DEBUG(llvm::dbgs() << "onto array: " << lhs << '\n';
             rhs.AsFortran(llvm::dbgs() << "assign expression: ") << '\n';);
  ArrayExprLowering::lowerArrayAssignment(converter, symMap, stmtCtx, lhs, rhs);
}
void Fortran::lower::createSomeArrayAssignment(
    Fortran::lower::AbstractConverter &converter, const fir::ExtendedValue &lhs,
    const fir::ExtendedValue &rhs, Fortran::lower::SymMap &symMap,
    Fortran::lower::StatementContext &stmtCtx) {
  LLVM_DEBUG(llvm::dbgs() << "onto array: " << lhs << '\n';
             llvm::dbgs() << "assign expression: " << rhs << '\n';);
  ArrayExprLowering::lowerArrayAssignment(converter, symMap, stmtCtx, lhs, rhs);
}

void Fortran::lower::createAnyMaskedArrayAssignment(
    Fortran::lower::AbstractConverter &converter,
    const Fortran::lower::SomeExpr &lhs, const Fortran::lower::SomeExpr &rhs,
    Fortran::lower::ExplicitIterSpace &explicitSpace,
    Fortran::lower::ImplicitIterSpace &implicitSpace,
    Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx) {
  LLVM_DEBUG(lhs.AsFortran(llvm::dbgs() << "onto array: ") << '\n';
             rhs.AsFortran(llvm::dbgs() << "assign expression: ")
             << " given the explicit iteration space:\n"
             << explicitSpace << "\n and implied mask conditions:\n"
             << implicitSpace << '\n';);
  ArrayExprLowering::lowerAnyMaskedArrayAssignment(
      converter, symMap, stmtCtx, lhs, rhs, explicitSpace, implicitSpace);
}

void Fortran::lower::createAllocatableArrayAssignment(
    Fortran::lower::AbstractConverter &converter,
    const Fortran::lower::SomeExpr &lhs, const Fortran::lower::SomeExpr &rhs,
    Fortran::lower::ExplicitIterSpace &explicitSpace,
    Fortran::lower::ImplicitIterSpace &implicitSpace,
    Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx) {
  LLVM_DEBUG(lhs.AsFortran(llvm::dbgs() << "defining array: ") << '\n';
             rhs.AsFortran(llvm::dbgs() << "assign expression: ")
             << " given the explicit iteration space:\n"
             << explicitSpace << "\n and implied mask conditions:\n"
             << implicitSpace << '\n';);
  ArrayExprLowering::lowerAllocatableArrayAssignment(
      converter, symMap, stmtCtx, lhs, rhs, explicitSpace, implicitSpace);
}

void Fortran::lower::createArrayOfPointerAssignment(
    Fortran::lower::AbstractConverter &converter,
    const Fortran::lower::SomeExpr &lhs, const Fortran::lower::SomeExpr &rhs,
    Fortran::lower::ExplicitIterSpace &explicitSpace,
    Fortran::lower::ImplicitIterSpace &implicitSpace,
    const llvm::SmallVector<mlir::Value> &lbounds,
    std::optional<llvm::SmallVector<mlir::Value>> ubounds,
    Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx) {
  LLVM_DEBUG(lhs.AsFortran(llvm::dbgs() << "defining pointer: ") << '\n';
             rhs.AsFortran(llvm::dbgs() << "assign expression: ")
             << " given the explicit iteration space:\n"
             << explicitSpace << "\n and implied mask conditions:\n"
             << implicitSpace << '\n';);
  assert(explicitSpace.isActive() && "must be in FORALL construct");
  ArrayExprLowering::lowerArrayOfPointerAssignment(
      converter, symMap, stmtCtx, lhs, rhs, explicitSpace, implicitSpace,
      lbounds, ubounds);
}

fir::ExtendedValue Fortran::lower::createSomeArrayTempValue(
    Fortran::lower::AbstractConverter &converter,
    const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &symMap,
    Fortran::lower::StatementContext &stmtCtx) {
  LLVM_DEBUG(expr.AsFortran(llvm::dbgs() << "array value: ") << '\n');
  return ArrayExprLowering::lowerNewArrayExpression(converter, symMap, stmtCtx,
                                                    expr);
}

void Fortran::lower::createLazyArrayTempValue(
    Fortran::lower::AbstractConverter &converter,
    const Fortran::lower::SomeExpr &expr, mlir::Value raggedHeader,
    Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx) {
  LLVM_DEBUG(expr.AsFortran(llvm::dbgs() << "array value: ") << '\n');
  ArrayExprLowering::lowerLazyArrayExpression(converter, symMap, stmtCtx, expr,
                                              raggedHeader);
}

fir::ExtendedValue
Fortran::lower::createSomeArrayBox(Fortran::lower::AbstractConverter &converter,
                                   const Fortran::lower::SomeExpr &expr,
                                   Fortran::lower::SymMap &symMap,
                                   Fortran::lower::StatementContext &stmtCtx) {
  LLVM_DEBUG(expr.AsFortran(llvm::dbgs() << "box designator: ") << '\n');
  return ArrayExprLowering::lowerBoxedArrayExpression(converter, symMap,
                                                      stmtCtx, expr);
}

fir::MutableBoxValue Fortran::lower::createMutableBox(
    mlir::Location loc, Fortran::lower::AbstractConverter &converter,
    const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &symMap) {
  // MutableBox lowering StatementContext does not need to be propagated
  // to the caller because the result value is a variable, not a temporary
  // expression. The StatementContext clean-up can occur before using the
  // resulting MutableBoxValue. Variables of all other types are handled in the
  // bridge.
  Fortran::lower::StatementContext dummyStmtCtx;
  return ScalarExprLowering{loc, converter, symMap, dummyStmtCtx}
      .genMutableBoxValue(expr);
}

bool Fortran::lower::isParentComponent(const Fortran::lower::SomeExpr &expr) {
  if (const Fortran::semantics::Symbol * symbol{GetLastSymbol(expr)}) {
    if (symbol->test(Fortran::semantics::Symbol::Flag::ParentComp))
      return true;
  }
  return false;
}

// Handling special case where the last component is referring to the
// parent component.
//
// TYPE t
//   integer :: a
// END TYPE
// TYPE, EXTENDS(t) :: t2
//   integer :: b
// END TYPE
// TYPE(t2) :: y(2)
// TYPE(t2) :: a
// y(:)%t  ! just need to update the box with a slice pointing to the first
//         ! component of `t`.
// a%t     ! simple conversion to TYPE(t).
fir::ExtendedValue Fortran::lower::updateBoxForParentComponent(
    Fortran::lower::AbstractConverter &converter, fir::ExtendedValue box,
    const Fortran::lower::SomeExpr &expr) {
  mlir::Location loc = converter.getCurrentLocation();
  auto &builder = converter.getFirOpBuilder();
  mlir::Value boxBase = fir::getBase(box);
  mlir::Operation *op = boxBase.getDefiningOp();
  mlir::Type actualTy = converter.genType(expr);

  if (op) {
    if (auto embox = mlir::dyn_cast<fir::EmboxOp>(op)) {
      auto newBox = fir::EmboxOp::create(
          builder, loc, fir::BoxType::get(actualTy), embox.getMemref(),
          embox.getShape(), embox.getSlice(), embox.getTypeparams());
      return fir::substBase(box, newBox);
    }
    if (auto rebox = mlir::dyn_cast<fir::ReboxOp>(op)) {
      auto newBox = fir::ReboxOp::create(
          builder, loc, fir::BoxType::get(actualTy), rebox.getBox(),
          rebox.getShape(), rebox.getSlice());
      return fir::substBase(box, newBox);
    }
  }

  mlir::Value empty;
  mlir::ValueRange emptyRange;
  return fir::ReboxOp::create(builder, loc, fir::BoxType::get(actualTy),
                              boxBase,
                              /*shape=*/empty,
                              /*slice=*/empty);
}

fir::ExtendedValue Fortran::lower::createBoxValue(
    mlir::Location loc, Fortran::lower::AbstractConverter &converter,
    const Fortran::lower::SomeExpr &expr, Fortran::lower::SymMap &symMap,
    Fortran::lower::StatementContext &stmtCtx) {
  if (expr.Rank() > 0 && Fortran::evaluate::IsVariable(expr) &&
      !Fortran::evaluate::HasVectorSubscript(expr)) {
    fir::ExtendedValue result =
        Fortran::lower::createSomeArrayBox(converter, expr, symMap, stmtCtx);
    if (isParentComponent(expr))
      result = updateBoxForParentComponent(converter, result, expr);
    return result;
  }
  fir::ExtendedValue addr = Fortran::lower::createSomeExtendedAddress(
      loc, converter, expr, symMap, stmtCtx);
  fir::ExtendedValue result = fir::BoxValue(
      converter.getFirOpBuilder().createBox(loc, addr, addr.isPolymorphic()));
  if (isParentComponent(expr))
    result = updateBoxForParentComponent(converter, result, expr);
  return result;
}

mlir::Value Fortran::lower::createSubroutineCall(
    AbstractConverter &converter, const evaluate::ProcedureRef &call,
    ExplicitIterSpace &explicitIterSpace, ImplicitIterSpace &implicitIterSpace,
    SymMap &symMap, StatementContext &stmtCtx, bool isUserDefAssignment) {
  mlir::Location loc = converter.getCurrentLocation();

  if (isUserDefAssignment) {
    assert(call.arguments().size() == 2);
    const auto *lhs = call.arguments()[0].value().UnwrapExpr();
    const auto *rhs = call.arguments()[1].value().UnwrapExpr();
    assert(lhs && rhs &&
           "user defined assignment arguments must be expressions");
    if (call.IsElemental() && lhs->Rank() > 0) {
      // Elemental user defined assignment has special requirements to deal with
      // LHS/RHS overlaps. See 10.2.1.5 p2.
      ArrayExprLowering::lowerElementalUserAssignment(
          converter, symMap, stmtCtx, explicitIterSpace, implicitIterSpace,
          call);
    } else if (explicitIterSpace.isActive() && lhs->Rank() == 0) {
      // Scalar defined assignment (elemental or not) in a FORALL context.
      mlir::func::FuncOp func =
          Fortran::lower::CallerInterface(call, converter).getFuncOp();
      ArrayExprLowering::lowerScalarUserAssignment(
          converter, symMap, stmtCtx, explicitIterSpace, func, *lhs, *rhs);
    } else if (explicitIterSpace.isActive()) {
      // TODO: need to array fetch/modify sub-arrays?
      TODO(loc, "non elemental user defined array assignment inside FORALL");
    } else {
      if (!implicitIterSpace.empty())
        fir::emitFatalError(
            loc,
            "C1032: user defined assignment inside WHERE must be elemental");
      // Non elemental user defined assignment outside of FORALL and WHERE.
      // FIXME: The non elemental user defined assignment case with array
      // arguments must be take into account potential overlap. So far the front
      // end does not add parentheses around the RHS argument in the call as it
      // should according to 15.4.3.4.3 p2.
      Fortran::lower::createSomeExtendedExpression(
          loc, converter, toEvExpr(call), symMap, stmtCtx);
    }
    return {};
  }

  assert(implicitIterSpace.empty() && !explicitIterSpace.isActive() &&
         "subroutine calls are not allowed inside WHERE and FORALL");

  if (isElementalProcWithArrayArgs(call)) {
    ArrayExprLowering::lowerElementalSubroutine(converter, symMap, stmtCtx,
                                                toEvExpr(call));
    return {};
  }
  // Simple subroutine call, with potential alternate return.
  auto res = Fortran::lower::createSomeExtendedExpression(
      loc, converter, toEvExpr(call), symMap, stmtCtx);
  return fir::getBase(res);
}

template <typename A>
fir::ArrayLoadOp genArrayLoad(mlir::Location loc,
                              Fortran::lower::AbstractConverter &converter,
                              fir::FirOpBuilder &builder, const A *x,
                              Fortran::lower::SymMap &symMap,
                              Fortran::lower::StatementContext &stmtCtx) {
  auto exv = ScalarExprLowering{loc, converter, symMap, stmtCtx}.gen(*x);
  mlir::Value addr = fir::getBase(exv);
  mlir::Value shapeOp = builder.createShape(loc, exv);
  mlir::Type arrTy = fir::dyn_cast_ptrOrBoxEleTy(addr.getType());
  return fir::ArrayLoadOp::create(builder, loc, arrTy, addr, shapeOp,
                                  /*slice=*/mlir::Value{},
                                  fir::getTypeParams(exv));
}
template <>
fir::ArrayLoadOp
genArrayLoad(mlir::Location loc, Fortran::lower::AbstractConverter &converter,
             fir::FirOpBuilder &builder, const Fortran::evaluate::ArrayRef *x,
             Fortran::lower::SymMap &symMap,
             Fortran::lower::StatementContext &stmtCtx) {
  if (x->base().IsSymbol())
    return genArrayLoad(loc, converter, builder, &getLastSym(x->base()), symMap,
                        stmtCtx);
  return genArrayLoad(loc, converter, builder, &x->base().GetComponent(),
                      symMap, stmtCtx);
}

void Fortran::lower::createArrayLoads(
    Fortran::lower::AbstractConverter &converter,
    Fortran::lower::ExplicitIterSpace &esp, Fortran::lower::SymMap &symMap) {
  std::size_t counter = esp.getCounter();
  fir::FirOpBuilder &builder = converter.getFirOpBuilder();
  mlir::Location loc = converter.getCurrentLocation();
  Fortran::lower::StatementContext &stmtCtx = esp.stmtContext();
  // Gen the fir.array_load ops.
  auto genLoad = [&](const auto *x) -> fir::ArrayLoadOp {
    return genArrayLoad(loc, converter, builder, x, symMap, stmtCtx);
  };
  if (esp.lhsBases[counter]) {
    auto &base = *esp.lhsBases[counter];
    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, Fortran::common::visit(genLoad, base));
}

void Fortran::lower::createArrayMergeStores(
    Fortran::lower::AbstractConverter &converter,
    Fortran::lower::ExplicitIterSpace &esp) {
  fir::FirOpBuilder &builder = converter.getFirOpBuilder();
  mlir::Location loc = converter.getCurrentLocation();
  builder.setInsertionPointAfter(esp.getOuterLoop());
  // Gen the fir.array_merge_store ops for all LHS arrays.
  for (auto i : llvm::enumerate(esp.getOuterLoop().getResults()))
    if (std::optional<fir::ArrayLoadOp> ldOpt = esp.getLhsLoad(i.index())) {
      fir::ArrayLoadOp load = *ldOpt;
      fir::ArrayMergeStoreOp::create(builder, loc, load, i.value(),
                                     load.getMemref(), load.getSlice(),
                                     load.getTypeparams());
    }
  if (esp.loopCleanup) {
    (*esp.loopCleanup)(builder);
    esp.loopCleanup = std::nullopt;
  }
  esp.initialArgs.clear();
  esp.innerArgs.clear();
  esp.outerLoop = std::nullopt;
  esp.resetBindings();
  esp.incrementCounter();
}

mlir::Value Fortran::lower::addCrayPointerInst(mlir::Location loc,
                                               fir::FirOpBuilder &builder,
                                               mlir::Value ptrVal,
                                               mlir::Type ptrTy,
                                               mlir::Type pteTy) {

  mlir::Value empty;
  mlir::ValueRange emptyRange;
  auto boxTy = fir::BoxType::get(ptrTy);
  auto box = fir::EmboxOp::create(builder, loc, boxTy, ptrVal, empty, empty,
                                  emptyRange);
  mlir::Value addrof = (mlir::isa<fir::ReferenceType>(ptrTy))
                           ? fir::BoxAddrOp::create(builder, loc, ptrTy, box)
                           : fir::BoxAddrOp::create(
                                 builder, loc, builder.getRefType(ptrTy), box);

  auto refPtrTy =
      builder.getRefType(fir::PointerType::get(fir::dyn_cast_ptrEleTy(pteTy)));
  return builder.createConvert(loc, refPtrTy, addrof);
}
