//===- ConvertToFIR.cpp - Convert HLFIR to FIR ----------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// This file defines a pass to lower HLFIR to FIR
//===----------------------------------------------------------------------===//

#include "flang/Optimizer/Builder/Character.h"
#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Builder/HLFIRTools.h"
#include "flang/Optimizer/Builder/MutableBox.h"
#include "flang/Optimizer/Builder/Runtime/Assign.h"
#include "flang/Optimizer/Builder/Runtime/Derived.h"
#include "flang/Optimizer/Builder/Runtime/Inquiry.h"
#include "flang/Optimizer/Builder/Todo.h"
#include "flang/Optimizer/Dialect/CUF/Attributes/CUFAttr.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
#include "flang/Optimizer/HLFIR/Passes.h"
#include "mlir/Transforms/DialectConversion.h"
#include "llvm/ADT/SmallSet.h"

namespace hlfir {
#define GEN_PASS_DEF_CONVERTHLFIRTOFIR
#include "flang/Optimizer/HLFIR/Passes.h.inc"
} // namespace hlfir

using namespace mlir;

namespace {
/// May \p lhs alias with \p rhs?
/// TODO: implement HLFIR alias analysis.
class AssignOpConversion : public mlir::OpRewritePattern<hlfir::AssignOp> {
public:
  explicit AssignOpConversion(mlir::MLIRContext *ctx) : OpRewritePattern{ctx} {}

  llvm::LogicalResult
  matchAndRewrite(hlfir::AssignOp assignOp,
                  mlir::PatternRewriter &rewriter) const override {
    mlir::Location loc = assignOp->getLoc();
    hlfir::Entity lhs(assignOp.getLhs());
    hlfir::Entity rhs(assignOp.getRhs());
    auto module = assignOp->getParentOfType<mlir::ModuleOp>();
    fir::FirOpBuilder builder(rewriter, module);

    if (mlir::isa<hlfir::ExprType>(rhs.getType())) {
      mlir::emitError(loc, "hlfir must be bufferized with --bufferize-hlfir "
                           "pass before being converted to FIR");
      return mlir::failure();
    }
    auto [rhsExv, rhsCleanUp] =
        hlfir::translateToExtendedValue(loc, builder, rhs);
    auto [lhsExv, lhsCleanUp] =
        hlfir::translateToExtendedValue(loc, builder, lhs);
    assert(!lhsCleanUp && !rhsCleanUp &&
           "variable to fir::ExtendedValue must not require cleanup");

    auto emboxRHS = [&](fir::ExtendedValue &rhsExv) -> mlir::Value {
      // There may be overlap between lhs and rhs. The runtime is able to detect
      // and to make a copy of the rhs before modifying the lhs if needed.
      // The code below relies on this and does not do any compile time alias
      // analysis.
      const bool rhsIsValue = fir::isa_trivial(fir::getBase(rhsExv).getType());
      if (rhsIsValue) {
        // createBox can only be called for fir::ExtendedValue that are
        // already in memory. Place the integer/real/complex/logical scalar
        // in memory.
        // The RHS might be i1, which is not supported for emboxing.
        // If LHS is not polymorphic, we may cast the RHS to the LHS type
        // before emboxing. If LHS is polymorphic we have to figure out
        // the data type for RHS emboxing anyway.
        // It is probably a good idea to make sure that the data type
        // of the RHS is always a valid Fortran storage data type.
        // For the time being, just handle i1 explicitly here.
        mlir::Type rhsType = rhs.getFortranElementType();
        mlir::Value rhsVal = fir::getBase(rhsExv);
        if (rhsType == builder.getI1Type()) {
          rhsType = fir::LogicalType::get(builder.getContext(), 4);
          rhsVal = builder.createConvert(loc, rhsType, rhsVal);
        }
        mlir::Value temp = fir::AllocaOp::create(builder, loc, rhsType);
        fir::StoreOp::create(builder, loc, rhsVal, temp);
        rhsExv = temp;
      }
      return fir::getBase(builder.createBox(loc, rhsExv));
    };

    if (assignOp.isAllocatableAssignment()) {
      // For trivial scalar allocatable assignments that are not polymorphic,
      // not character, not temporary, and not CUDA Fortran, inline the
      // assignment instead of calling the runtime.
      if (!assignOp.mustKeepLhsLengthInAllocatableAssignment() &&
          !assignOp.isTemporaryLHS() && !lhs.isPolymorphic() &&
          !lhs.isArray() && fir::isa_trivial(lhs.getFortranElementType()) &&
          !cuf::getDataAttr(lhs.getDefiningOp())) {
        mlir::Value rhsVal = fir::getBase(rhsExv);
        mlir::Value boxRef = fir::getBase(lhsExv);
        mlir::Value box = fir::LoadOp::create(builder, loc, boxRef);
        mlir::Value addr = fir::BoxAddrOp::create(builder, loc, box);
        mlir::Value isAllocated = builder.genIsNotNullAddr(loc, addr);
        auto boxType = mlir::cast<fir::BoxType>(box.getType());
        auto heapType = mlir::cast<fir::HeapType>(boxType.getEleTy());
        mlir::Type elemType = heapType.getEleTy();
        builder.genIfThenElse(loc, isAllocated)
            .genThen(
                [&]() { fir::StoreOp::create(builder, loc, rhsVal, addr); })
            .genElse([&]() {
              mlir::Value newMem =
                  fir::AllocMemOp::create(builder, loc, elemType);
              fir::StoreOp::create(builder, loc, rhsVal, newMem);
              mlir::Value newBox =
                  fir::EmboxOp::create(builder, loc, boxType, newMem);
              fir::StoreOp::create(builder, loc, newBox, boxRef);
            })
            .end();
      } else {
        // Whole allocatable assignment: use the runtime to deal with the
        // reallocation.
        mlir::Value from = emboxRHS(rhsExv);
        mlir::Value to = fir::getBase(lhsExv);
        if (assignOp.mustKeepLhsLengthInAllocatableAssignment()) {
          // Indicate the runtime that it should not reallocate in case of
          // length mismatch, and that it should use the LHS
          // explicit/assumed length if allocating/reallocation the LHS.
          // Note that AssignExplicitLengthCharacter() must be used
          // when isTemporaryLHS() is true here: the LHS is known to be
          // character allocatable in this case, so finalization will not
          // happen (as implied by temporary_lhs attribute), and LHS
          // must keep its length (as implied by keep_lhs_length_if_realloc).
          fir::runtime::genAssignExplicitLengthCharacter(builder, loc, to,
                                                         from);
        } else if (assignOp.isTemporaryLHS()) {
          // Use AssignTemporary, when the LHS is a compiler generated
          // temporary. Note that it also works properly for polymorphic
          // LHS (i.e. the LHS will have the RHS dynamic type after the
          // assignment).
          fir::runtime::genAssignTemporary(builder, loc, to, from);
        } else if (lhs.isPolymorphic()) {
          // Indicate the runtime that the LHS must have the RHS dynamic
          // type after the assignment.
          fir::runtime::genAssignPolymorphic(builder, loc, to, from);
        } else {
          fir::runtime::genAssign(builder, loc, to, from);
        }
      }
    } else if (lhs.isArray() ||
               // Special case for element-by-element (or scalar) assignments
               // generated for creating polymorphic expressions.
               // The LHS of these assignments is a box describing just
               // a single element, not the whole allocatable temp.
               // They do not have 'realloc' attribute, because reallocation
               // must not happen. The only expected effect of such an
               // assignment is the copy of the contents, because the dynamic
               // types of the LHS and the RHS must match already. We use the
               // runtime in this case so that the polymorphic (including
               // unlimited) content is copied properly.
               (lhs.isPolymorphic() && assignOp.isTemporaryLHS())) {
      // Use the runtime for simplicity. An optimization pass will be added to
      // inline array assignment when profitable.
      mlir::Value from = emboxRHS(rhsExv);
      mlir::Value to = fir::getBase(builder.createBox(loc, lhsExv));
      // This is not a whole allocatable assignment: the runtime will not
      // reallocate and modify "toMutableBox" even if it is taking it by
      // reference.
      auto toMutableBox = builder.createTemporary(loc, to.getType());
      fir::StoreOp::create(builder, loc, to, toMutableBox);
      if (assignOp.isTemporaryLHS())
        fir::runtime::genAssignTemporary(builder, loc, toMutableBox, from);
      else
        fir::runtime::genAssign(builder, loc, toMutableBox, from);
    } else {
      // TODO: use the type specification to see if IsFinalizable is set,
      // or propagate IsFinalizable attribute from lowering.
      bool needFinalization =
          !assignOp.isTemporaryLHS() &&
          mlir::isa<fir::RecordType>(fir::getElementTypeOf(lhsExv));

      mlir::ArrayAttr accessGroups;
      if (auto attrs = assignOp.getOperation()->getAttrOfType<mlir::ArrayAttr>(
              fir::getAccessGroupsAttrName()))
        accessGroups = attrs;

      // genScalarAssignment() must take care of potential overlap
      // between LHS and RHS. Note that the overlap is possible
      // also for components of LHS/RHS, and the Assign() runtime
      // must take care of it.
      fir::factory::genScalarAssignment(
          builder, loc, lhsExv, rhsExv, needFinalization,
          assignOp.isTemporaryLHS(), accessGroups);
    }
    rewriter.eraseOp(assignOp);
    return mlir::success();
  }
};

class CopyInOpConversion : public mlir::OpRewritePattern<hlfir::CopyInOp> {
public:
  explicit CopyInOpConversion(mlir::MLIRContext *ctx) : OpRewritePattern{ctx} {}

  struct CopyInResult {
    mlir::Value addr;
    mlir::Value wasCopied;
  };

  static CopyInResult genNonOptionalCopyIn(mlir::Location loc,
                                           fir::FirOpBuilder &builder,
                                           hlfir::CopyInOp copyInOp) {
    mlir::Value inputVariable = copyInOp.getVar();
    mlir::Type resultAddrType = copyInOp.getCopiedIn().getType();
    mlir::Value isContiguous =
        fir::runtime::genIsContiguous(builder, loc, inputVariable);
    mlir::Value addr =
        builder
            .genIfOp(loc, {resultAddrType}, isContiguous,
                     /*withElseRegion=*/true)
            .genThen(
                [&]() { fir::ResultOp::create(builder, loc, inputVariable); })
            .genElse([&] {
              // Create temporary on the heap. Note that the runtime is used and
              // that is desired: 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.
              mlir::Value temp = copyInOp.getTempBox();
              fir::runtime::genCopyInAssign(builder, loc, temp, inputVariable);
              mlir::Value copy = fir::LoadOp::create(builder, loc, temp);
              // Get rid of allocatable flag in the fir.box.
              if (mlir::cast<fir::BaseBoxType>(resultAddrType).isAssumedRank())
                copy = fir::ReboxAssumedRankOp::create(
                    builder, loc, resultAddrType, copy,
                    fir::LowerBoundModifierAttribute::Preserve);
              else
                copy = fir::ReboxOp::create(builder, loc, resultAddrType, copy,
                                            /*shape=*/mlir::Value{},
                                            /*slice=*/mlir::Value{});
              fir::ResultOp::create(builder, loc, copy);
            })
            .getResults()[0];
    return {addr, builder.genNot(loc, isContiguous)};
  }

  static CopyInResult genOptionalCopyIn(mlir::Location loc,
                                        fir::FirOpBuilder &builder,
                                        hlfir::CopyInOp copyInOp) {
    mlir::Type resultAddrType = copyInOp.getCopiedIn().getType();
    mlir::Value isPresent = copyInOp.getVarIsPresent();
    auto res =
        builder
            .genIfOp(loc, {resultAddrType, builder.getI1Type()}, isPresent,
                     /*withElseRegion=*/true)
            .genThen([&]() {
              CopyInResult res = genNonOptionalCopyIn(loc, builder, copyInOp);
              fir::ResultOp::create(builder, loc,
                                    mlir::ValueRange{res.addr, res.wasCopied});
            })
            .genElse([&] {
              mlir::Value absent =
                  fir::AbsentOp::create(builder, loc, resultAddrType);
              fir::ResultOp::create(builder, loc,
                                    mlir::ValueRange{absent, isPresent});
            })
            .getResults();
    return {res[0], res[1]};
  }

  llvm::LogicalResult
  matchAndRewrite(hlfir::CopyInOp copyInOp,
                  mlir::PatternRewriter &rewriter) const override {
    mlir::Location loc = copyInOp.getLoc();
    fir::FirOpBuilder builder(rewriter, copyInOp.getOperation());
    CopyInResult result = copyInOp.getVarIsPresent()
                              ? genOptionalCopyIn(loc, builder, copyInOp)
                              : genNonOptionalCopyIn(loc, builder, copyInOp);
    rewriter.replaceOp(copyInOp, {result.addr, result.wasCopied});
    return mlir::success();
  }
};

class CopyOutOpConversion : public mlir::OpRewritePattern<hlfir::CopyOutOp> {
public:
  explicit CopyOutOpConversion(mlir::MLIRContext *ctx)
      : OpRewritePattern{ctx} {}

  llvm::LogicalResult
  matchAndRewrite(hlfir::CopyOutOp copyOutOp,
                  mlir::PatternRewriter &rewriter) const override {
    mlir::Location loc = copyOutOp.getLoc();
    fir::FirOpBuilder builder(rewriter, copyOutOp.getOperation());

    builder.genIfThen(loc, copyOutOp.getWasCopied())
        .genThen([&]() {
          mlir::Value temp = copyOutOp.getTemp();
          mlir::Value varMutableBox;
          // Generate CopyOutAssign runtime call.
          if (mlir::Value var = copyOutOp.getVar()) {
            // Set the variable descriptor pointer in order 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.
            varMutableBox = builder.createTemporary(loc, var.getType());
            fir::StoreOp::create(builder, loc, var, varMutableBox);
          } else {
            // Even when there is no need to copy back the data (e.g., the dummy
            // argument was intent(in), CopyOutAssign is called to
            // destroy/deallocate the temporary.
            varMutableBox = fir::ZeroOp::create(builder, loc, temp.getType());
          }
          fir::runtime::genCopyOutAssign(builder, loc, varMutableBox,
                                         copyOutOp.getTemp());
        })
        .end();
    rewriter.eraseOp(copyOutOp);
    return mlir::success();
  }
};

class DeclareOpConversion : public mlir::OpRewritePattern<hlfir::DeclareOp> {
public:
  explicit DeclareOpConversion(mlir::MLIRContext *ctx)
      : OpRewritePattern{ctx} {}

  llvm::LogicalResult
  matchAndRewrite(hlfir::DeclareOp declareOp,
                  mlir::PatternRewriter &rewriter) const override {
    mlir::Location loc = declareOp->getLoc();
    mlir::Value memref = declareOp.getMemref();
    fir::FortranVariableFlagsAttr fortranAttrs;
    cuf::DataAttributeAttr dataAttr;
    if (auto attrs = declareOp.getFortranAttrs())
      fortranAttrs =
          fir::FortranVariableFlagsAttr::get(rewriter.getContext(), *attrs);
    if (auto attr = declareOp.getDataAttr())
      dataAttr = cuf::DataAttributeAttr::get(rewriter.getContext(), *attr);
    auto firDeclareOp = fir::DeclareOp::create(
        rewriter, loc, memref.getType(), memref, declareOp.getShape(),
        declareOp.getTypeparams(), declareOp.getDummyScope(),
        /*storage=*/declareOp.getStorage(),
        /*storage_offset=*/declareOp.getStorageOffset(),
        declareOp.getUniqName(), fortranAttrs, dataAttr,
        declareOp.getDummyArgNoAttr());

    // Propagate other attributes from hlfir.declare to fir.declare.
    // OpenACC's acc.declare is one example. Right now, the propagation
    // is verbatim.
    llvm::SmallSet<llvm::StringRef, 8> elidedAttrs;
    for (const mlir::NamedAttribute &firAttr : firDeclareOp->getAttrs())
      elidedAttrs.insert(firAttr.getName());
    elidedAttrs.insert(declareOp.getSkipReboxAttrName());
    for (const mlir::NamedAttribute &attr : declareOp->getAttrs())
      if (!elidedAttrs.contains(attr.getName()))
        firDeclareOp->setAttr(attr.getName(), attr.getValue());

    auto firBase = firDeclareOp.getResult();
    mlir::Value hlfirBase;
    mlir::Type hlfirBaseType = declareOp.getBase().getType();
    if (mlir::isa<fir::BaseBoxType>(hlfirBaseType)) {
      fir::FirOpBuilder builder(rewriter, declareOp.getOperation());
      // Helper to generate the hlfir fir.box with the local lower bounds and
      // type parameters.
      auto genHlfirBox = [&]() -> mlir::Value {
        if (auto baseBoxType =
                mlir::dyn_cast<fir::BaseBoxType>(firBase.getType())) {
          if (declareOp.getSkipRebox())
            return firBase;
          // Rebox so that lower bounds and attributes are correct.
          if (baseBoxType.isAssumedRank())
            return fir::ReboxAssumedRankOp::create(
                builder, loc, hlfirBaseType, firBase,
                fir::LowerBoundModifierAttribute::SetToOnes);
          if (!fir::extractSequenceType(baseBoxType.getEleTy()) &&
              baseBoxType == hlfirBaseType)
            return firBase;
          return fir::ReboxOp::create(builder, loc, hlfirBaseType, firBase,
                                      declareOp.getShape(),
                                      /*slice=*/mlir::Value{});
        } else {
          llvm::SmallVector<mlir::Value> typeParams;
          auto maybeCharType = mlir::dyn_cast<fir::CharacterType>(
              fir::unwrapSequenceType(fir::unwrapPassByRefType(hlfirBaseType)));
          if (!maybeCharType || maybeCharType.hasDynamicLen())
            typeParams.append(declareOp.getTypeparams().begin(),
                              declareOp.getTypeparams().end());
          return fir::EmboxOp::create(builder, loc, hlfirBaseType, firBase,
                                      declareOp.getShape(),
                                      /*slice=*/mlir::Value{}, typeParams);
        }
      };
      if (!mlir::cast<fir::FortranVariableOpInterface>(declareOp.getOperation())
               .isOptional()) {
        hlfirBase = genHlfirBox();
        // If the original base is a box too, we could as well
        // use the HLFIR box as the FIR base: otherwise, the two
        // boxes are "alive" at the same time, and the FIR box
        // is used for accessing the base_addr and the HLFIR box
        // is used for accessing the bounds etc. Using the HLFIR box,
        // that holds the same base_addr at this point, makes
        // the representation a little bit more clear.
        if (hlfirBase.getType() == declareOp.getOriginalBase().getType())
          firBase = hlfirBase;
      } else {
        // Need to conditionally rebox/embox the optional: the input fir.box
        // may be null and the rebox would be illegal. It is also important to
        // preserve the optional aspect: the hlfir fir.box should be null if
        // the entity is absent so that later fir.is_present on the hlfir base
        // are valid.
        mlir::Value isPresent = fir::IsPresentOp::create(
            builder, loc, builder.getI1Type(), firBase);
        hlfirBase =
            builder
                .genIfOp(loc, {hlfirBaseType}, isPresent,
                         /*withElseRegion=*/true)
                .genThen(
                    [&] { fir::ResultOp::create(builder, loc, genHlfirBox()); })
                .genElse([&]() {
                  mlir::Value absent =
                      fir::AbsentOp::create(builder, loc, hlfirBaseType);
                  fir::ResultOp::create(builder, loc, absent);
                })
                .getResults()[0];
      }
    } else if (mlir::isa<fir::BoxCharType>(hlfirBaseType)) {
      assert(declareOp.getTypeparams().size() == 1 &&
             "must contain character length");
      hlfirBase = fir::EmboxCharOp::create(
          rewriter, loc, hlfirBaseType, firBase, declareOp.getTypeparams()[0]);
    } else {
      if (hlfirBaseType != firBase.getType()) {
        declareOp.emitOpError()
            << "unhandled HLFIR variable type '" << hlfirBaseType << "'\n";
        return mlir::failure();
      }
      hlfirBase = firBase;
    }
    rewriter.replaceOp(declareOp, {hlfirBase, firBase});
    return mlir::success();
  }
};

class DesignateOpConversion
    : public mlir::OpRewritePattern<hlfir::DesignateOp> {
  // Helper method to generate the coordinate of the first element
  // of an array section. It is also called for cases of non-section
  // array element addressing.
  static mlir::Value genSubscriptBeginAddr(
      fir::FirOpBuilder &builder, mlir::Location loc,
      hlfir::DesignateOp designate, mlir::Type baseEleTy, mlir::Value base,
      mlir::Value shape,
      const llvm::SmallVector<mlir::Value> &firBaseTypeParameters) {
    assert(!designate.getIndices().empty());
    llvm::SmallVector<mlir::Value> firstElementIndices;
    auto indices = designate.getIndices();
    int i = 0;
    auto attrs = designate.getIsTripletAttr();
    for (auto isTriplet : attrs.asArrayRef()) {
      // Coordinate of the first element are the index and triplets lower
      // bounds.
      firstElementIndices.push_back(indices[i]);
      i = i + (isTriplet ? 3 : 1);
    }

    mlir::Type originalDesignateType = designate.getResult().getType();
    const bool isVolatile = fir::isa_volatile_type(originalDesignateType);
    mlir::Type arrayCoorType = fir::ReferenceType::get(baseEleTy, isVolatile);

    base = fir::ArrayCoorOp::create(builder, loc, arrayCoorType, base, shape,
                                    /*slice=*/mlir::Value{},
                                    firstElementIndices, firBaseTypeParameters);
    return base;
  }

public:
  explicit DesignateOpConversion(mlir::MLIRContext *ctx)
      : OpRewritePattern{ctx} {}

  llvm::LogicalResult
  matchAndRewrite(hlfir::DesignateOp designate,
                  mlir::PatternRewriter &rewriter) const override {
    mlir::Location loc = designate.getLoc();
    fir::FirOpBuilder builder(rewriter, designate.getOperation());

    hlfir::Entity baseEntity(designate.getMemref());

    if (baseEntity.isMutableBox())
      TODO(loc, "hlfir::designate load of pointer or allocatable");

    mlir::Type designateResultType = designate.getResult().getType();
    llvm::SmallVector<mlir::Value> firBaseTypeParameters;
    auto [base, shape] = hlfir::genVariableFirBaseShapeAndParams(
        loc, builder, baseEntity, firBaseTypeParameters);
    const bool isVolatile = fir::isa_volatile_type(designateResultType) ||
                            fir::isa_volatile_type(base.getType());
    mlir::Type baseEleTy = hlfir::getFortranElementType(base.getType());
    mlir::Type resultEleTy = hlfir::getFortranElementType(designateResultType);

    mlir::Value fieldIndex;
    if (designate.getComponent()) {
      mlir::Type baseRecordType = baseEntity.getFortranElementType();
      if (fir::isRecordWithTypeParameters(baseRecordType))
        TODO(loc, "hlfir.designate with a parameterized derived type base");
      fieldIndex = fir::FieldIndexOp::create(
          builder, loc, fir::FieldType::get(builder.getContext()),
          designate.getComponent().value(), baseRecordType,
          /*typeParams=*/mlir::ValueRange{});
      if (baseEntity.isScalar()) {
        // Component refs of scalar base right away:
        // - scalar%scalar_component [substring|complex_part] or
        // - scalar%static_size_array_comp
        // - scalar%array(indices) [substring| complex part]
        mlir::Type componentType =
            mlir::cast<fir::RecordType>(baseEleTy).getType(
                designate.getComponent().value());
        mlir::Type coorTy = fir::ReferenceType::get(componentType, isVolatile);

        base =
            fir::CoordinateOp::create(builder, loc, coorTy, base, fieldIndex);
        if (mlir::isa<fir::BaseBoxType>(componentType)) {
          auto variableInterface = mlir::cast<fir::FortranVariableOpInterface>(
              designate.getOperation());
          if (variableInterface.isAllocatable() ||
              variableInterface.isPointer()) {
            rewriter.replaceOp(designate, base);
            return mlir::success();
          }
          TODO(loc,
               "addressing parameterized derived type automatic components");
        }
        baseEleTy = hlfir::getFortranElementType(componentType);
        shape = designate.getComponentShape();
      }
    }

    if (mlir::isa<fir::BaseBoxType>(designateResultType) ||
        // Convert the component array slices using embox/rebox
        // even if the result is a contiguous array section, e.g.:
        //   hlfir.designate %base{"i"} shape %shape :
        //       (!fir.box<!fir.array<2x!fir.type<_QMtypesTt{i:i32}>>>,
        //        !fir.shape<1>) -> !fir.ref<!fir.array<2xi32>>
        // fir.coordinate_of should probably be a better option, though.
        (fieldIndex && baseEntity.isArray())) {
      // Generate embox or rebox for slicing.
      mlir::Type eleTy = fir::unwrapPassByRefType(designateResultType);
      bool isScalarDesignator = !mlir::isa<fir::SequenceType>(eleTy);
      mlir::Value sourceBox;
      if (isScalarDesignator) {
        // The base box will be used for emboxing the scalar element.
        sourceBox = base;
        // Generate the coordinate of the element.
        base = genSubscriptBeginAddr(builder, loc, designate, baseEleTy, base,
                                     shape, firBaseTypeParameters);
        shape = nullptr;
        // Type information will be taken from the source box,
        // so the type parameters are not needed.
        firBaseTypeParameters.clear();
      }
      llvm::SmallVector<mlir::Value> triples;
      llvm::SmallVector<mlir::Value> sliceFields;
      mlir::Type idxTy = builder.getIndexType();
      auto subscripts = designate.getIndices();
      if (fieldIndex && baseEntity.isArray()) {
        // array%scalar_comp or array%array_comp(indices)
        // Generate triples for array(:, :, ...).
        triples = genFullSliceTriples(builder, loc, baseEntity);
        sliceFields.push_back(fieldIndex);
        // Add indices in the field path for "array%array_comp(indices)"
        // case. The indices of components provided to the sliceOp must
        // be zero based (fir.slice has no knowledge of the component
        // lower bounds). The component lower bounds are applied here.
        if (!subscripts.empty()) {
          llvm::SmallVector<mlir::Value> lbounds = hlfir::genLowerbounds(
              loc, builder, designate.getComponentShape(), subscripts.size());
          for (auto [i, lb] : llvm::zip(subscripts, lbounds)) {
            mlir::Value iIdx = builder.createConvert(loc, idxTy, i);
            mlir::Value lbIdx = builder.createConvert(loc, idxTy, lb);
            sliceFields.emplace_back(
                mlir::arith::SubIOp::create(builder, loc, iIdx, lbIdx));
          }
        }
      } else if (!isScalarDesignator) {
        // Otherwise, this is an array section with triplets.
        auto undef = fir::UndefOp::create(builder, loc, idxTy);
        unsigned i = 0;
        for (auto isTriplet : designate.getIsTriplet()) {
          triples.push_back(subscripts[i++]);
          if (isTriplet) {
            triples.push_back(subscripts[i++]);
            triples.push_back(subscripts[i++]);
          } else {
            triples.push_back(undef);
            triples.push_back(undef);
          }
        }
      }
      llvm::SmallVector<mlir::Value, 2> substring;
      if (!designate.getSubstring().empty()) {
        substring.push_back(designate.getSubstring()[0]);
        mlir::Type idxTy = builder.getIndexType();
        // fir.slice op substring expects the zero based lower bound.
        mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
        substring[0] = builder.createConvert(loc, idxTy, substring[0]);
        substring[0] =
            mlir::arith::SubIOp::create(builder, loc, substring[0], one);
        substring.push_back(designate.getTypeparams()[0]);
      }
      if (designate.getComplexPart()) {
        if (triples.empty())
          triples = genFullSliceTriples(builder, loc, baseEntity);
        sliceFields.push_back(builder.createIntegerConstant(
            loc, idxTy, *designate.getComplexPart()));
      }
      mlir::Value slice;
      if (!triples.empty())
        slice =
            fir::SliceOp::create(builder, loc, triples, sliceFields, substring);
      else
        assert(sliceFields.empty() && substring.empty());

      // If the designate's result type is not a box, then create
      // a box type to be used for the result of the embox/rebox.
      mlir::Type resultType = designateResultType;
      if (!mlir::isa<fir::BaseBoxType>(resultType))
        resultType = fir::wrapInClassOrBoxType(resultType);

      resultType = fir::updateTypeWithVolatility(resultType, isVolatile);

      mlir::Value resultBox;
      if (mlir::isa<fir::BaseBoxType>(base.getType())) {
        resultBox =
            fir::ReboxOp::create(builder, loc, resultType, base, shape, slice);
      } else {
        resultBox =
            fir::EmboxOp::create(builder, loc, resultType, base, shape, slice,
                                 firBaseTypeParameters, sourceBox);
      }

      if (!mlir::isa<fir::BaseBoxType>(designateResultType)) {
        // If the designate's result is not a box, use the raw address
        // as the new result.
        resultBox = fir::BoxAddrOp::create(rewriter, loc, resultBox);
        resultBox = builder.createConvert(loc, designateResultType, resultBox);
      }
      rewriter.replaceOp(designate, resultBox);
      return mlir::success();
    }

    // Otherwise, the result is the address of a scalar, or the address of the
    // first element of a contiguous array section with compile time constant
    // shape. The base may be an array, or a scalar.
    mlir::Type resultAddressType = designateResultType;
    if (auto boxCharType =
            mlir::dyn_cast<fir::BoxCharType>(designateResultType))
      resultAddressType =
          fir::ReferenceType::get(boxCharType.getEleTy(), isVolatile);

    // Array element indexing.
    if (!designate.getIndices().empty()) {
      // - array(indices) [substring|complex_part] or
      // - scalar%array_comp(indices) [substring|complex_part]
      // This may be a ranked contiguous array section in which case
      // The first element address is being computed.
      base = genSubscriptBeginAddr(builder, loc, designate, baseEleTy, base,
                                   shape, firBaseTypeParameters);
    }

    // Scalar substring (potentially on the previously built array element or
    // component reference).
    if (!designate.getSubstring().empty())
      base = fir::factory::CharacterExprHelper{builder, loc}.genSubstringBase(
          base, designate.getSubstring()[0], resultAddressType);

    // Scalar complex part ref
    if (designate.getComplexPart()) {
      // Sequence types should have already been handled by this point
      assert(!mlir::isa<fir::SequenceType>(designateResultType));
      auto index = builder.createIntegerConstant(loc, builder.getIndexType(),
                                                 *designate.getComplexPart());
      auto coorTy = fir::ReferenceType::get(resultEleTy, isVolatile);

      base = fir::CoordinateOp::create(builder, loc, coorTy, base, index);
    }

    // Cast/embox the computed scalar address if needed.
    if (mlir::isa<fir::BoxCharType>(designateResultType)) {
      assert(designate.getTypeparams().size() == 1 &&
             "must have character length");
      auto emboxChar =
          fir::EmboxCharOp::create(builder, loc, designateResultType, base,
                                   designate.getTypeparams()[0]);

      rewriter.replaceOp(designate, emboxChar.getResult());
    } else {
      base = builder.createConvert(loc, designateResultType, base);

      rewriter.replaceOp(designate, base);
    }
    return mlir::success();
  }

private:
  // Generates triple for full slice
  // Used for component and complex part slices when a triple is
  // not specified
  static llvm::SmallVector<mlir::Value>
  genFullSliceTriples(fir::FirOpBuilder &builder, mlir::Location loc,
                      hlfir::Entity baseEntity) {
    llvm::SmallVector<mlir::Value> triples;
    mlir::Type idxTy = builder.getIndexType();
    auto one = builder.createIntegerConstant(loc, idxTy, 1);
    for (auto [lb, ub] : hlfir::genBounds(loc, builder, baseEntity)) {
      triples.push_back(builder.createConvert(loc, idxTy, lb));
      triples.push_back(builder.createConvert(loc, idxTy, ub));
      triples.push_back(one);
    }
    return triples;
  }
};

class ParentComponentOpConversion
    : public mlir::OpRewritePattern<hlfir::ParentComponentOp> {
public:
  explicit ParentComponentOpConversion(mlir::MLIRContext *ctx)
      : OpRewritePattern{ctx} {}

  llvm::LogicalResult
  matchAndRewrite(hlfir::ParentComponentOp parentComponent,
                  mlir::PatternRewriter &rewriter) const override {
    mlir::Location loc = parentComponent.getLoc();
    mlir::Type resultType = parentComponent.getType();
    if (!mlir::isa<fir::BoxType>(parentComponent.getType())) {
      mlir::Value baseAddr = parentComponent.getMemref();
      // Scalar parent component ref without any length type parameters. The
      // input may be a fir.class if it is polymorphic, since this is a scalar
      // and the output will be monomorphic, the base address can be extracted
      // from the fir.class.
      if (mlir::isa<fir::BaseBoxType>(baseAddr.getType()))
        baseAddr = fir::BoxAddrOp::create(rewriter, loc, baseAddr);
      rewriter.replaceOpWithNewOp<fir::ConvertOp>(parentComponent, resultType,
                                                  baseAddr);
      return mlir::success();
    }
    // Array parent component ref or PDTs.
    hlfir::Entity base{parentComponent.getMemref()};
    mlir::Value baseAddr = base.getBase();
    if (!mlir::isa<fir::BaseBoxType>(baseAddr.getType())) {
      // Embox cannot directly be used to address parent components: it expects
      // the output type to match the input type when there are no slices. When
      // the types have at least one component, a slice to the first element can
      // be built, and the result set to the parent component type. Just create
      // a fir.box with the base for now since this covers all cases.
      mlir::Type baseBoxType =
          fir::BoxType::get(base.getElementOrSequenceType());
      assert(!base.hasLengthParameters() &&
             "base must be a box if it has any type parameters");
      baseAddr = fir::EmboxOp::create(
          rewriter, loc, baseBoxType, baseAddr, parentComponent.getShape(),
          /*slice=*/mlir::Value{}, /*typeParams=*/mlir::ValueRange{});
    }
    rewriter.replaceOpWithNewOp<fir::ReboxOp>(parentComponent, resultType,
                                              baseAddr,
                                              /*shape=*/mlir::Value{},
                                              /*slice=*/mlir::Value{});
    return mlir::success();
  }
};

class NoReassocOpConversion
    : public mlir::OpRewritePattern<hlfir::NoReassocOp> {
public:
  explicit NoReassocOpConversion(mlir::MLIRContext *ctx)
      : OpRewritePattern{ctx} {}

  llvm::LogicalResult
  matchAndRewrite(hlfir::NoReassocOp noreassoc,
                  mlir::PatternRewriter &rewriter) const override {
    rewriter.replaceOpWithNewOp<fir::NoReassocOp>(noreassoc,
                                                  noreassoc.getVal());
    return mlir::success();
  }
};

class NullOpConversion : public mlir::OpRewritePattern<hlfir::NullOp> {
public:
  explicit NullOpConversion(mlir::MLIRContext *ctx) : OpRewritePattern{ctx} {}

  llvm::LogicalResult
  matchAndRewrite(hlfir::NullOp nullop,
                  mlir::PatternRewriter &rewriter) const override {
    rewriter.replaceOpWithNewOp<fir::ZeroOp>(nullop, nullop.getType());
    return mlir::success();
  }
};

class GetExtentOpConversion
    : public mlir::OpRewritePattern<hlfir::GetExtentOp> {
public:
  using mlir::OpRewritePattern<hlfir::GetExtentOp>::OpRewritePattern;

  llvm::LogicalResult
  matchAndRewrite(hlfir::GetExtentOp getExtentOp,
                  mlir::PatternRewriter &rewriter) const override {
    mlir::Value shape = getExtentOp.getShape();
    mlir::Operation *shapeOp = shape.getDefiningOp();
    // the hlfir.shape_of operation which led to the creation of this get_extent
    // operation should now have been lowered to a fir.shape operation
    if (auto s = mlir::dyn_cast_or_null<fir::ShapeOp>(shapeOp)) {
      fir::ShapeType shapeTy = mlir::cast<fir::ShapeType>(shape.getType());
      llvm::APInt dim = getExtentOp.getDim();
      uint64_t dimVal = dim.getLimitedValue(shapeTy.getRank());
      mlir::Value extent = s.getExtents()[dimVal];
      fir::FirOpBuilder builder(rewriter, getExtentOp.getOperation());
      extent = builder.createConvert(getExtentOp.getLoc(),
                                     builder.getIndexType(), extent);
      rewriter.replaceOp(getExtentOp, extent);
      return mlir::success();
    }
    return mlir::failure();
  }
};

class ConvertHLFIRtoFIR
    : public hlfir::impl::ConvertHLFIRtoFIRBase<ConvertHLFIRtoFIR> {
public:
  void runOnOperation() override {
    // TODO: like "bufferize-hlfir" pass, runtime signature may be added
    // by this pass. This requires the pass to run on the ModuleOp. It would
    // probably be more optimal to have it run on FuncOp and find a way to
    // generate the signatures in a thread safe way.
    auto module = this->getOperation();
    auto *context = &getContext();
    mlir::RewritePatternSet patterns(context);
    patterns.insert<AssignOpConversion, CopyInOpConversion, CopyOutOpConversion,
                    DeclareOpConversion, DesignateOpConversion,
                    GetExtentOpConversion, NoReassocOpConversion,
                    NullOpConversion, ParentComponentOpConversion>(context);
    mlir::ConversionTarget target(*context);
    target.addIllegalDialect<hlfir::hlfirDialect>();
    target.markUnknownOpDynamicallyLegal(
        [](mlir::Operation *) { return true; });
    if (mlir::failed(mlir::applyPartialConversion(module, target,
                                                  std::move(patterns)))) {
      mlir::emitError(mlir::UnknownLoc::get(context),
                      "failure in HLFIR to FIR conversion pass");
      signalPassFailure();
    }
  }
};

} // namespace
