//===- 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/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"

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

using namespace mlir;

static mlir::Value genAllocatableTempFromSourceBox(mlir::Location loc,
                                                   fir::FirOpBuilder &builder,
                                                   mlir::Value sourceBox) {
  assert(sourceBox.getType().isa<fir::BaseBoxType>() &&
         "must be a base box type");
  // Use the runtime to make a quick and dirty temp with the rhs value.
  // Overkill for scalar rhs that could be done in much more clever ways.
  // Note that temp descriptor must have the allocatable flag set so that
  // the runtime will allocate it with the shape and type parameters of
  // the RHS.
  // This has the huge benefit of dealing with all cases, including
  // polymorphic entities.
  mlir::Type fromHeapType = fir::HeapType::get(fir::unwrapRefType(
      sourceBox.getType().cast<fir::BaseBoxType>().getEleTy()));
  mlir::Type fromBoxHeapType = fir::BoxType::get(fromHeapType);
  mlir::Value fromMutableBox =
      fir::factory::genNullBoxStorage(builder, loc, fromBoxHeapType);
  fir::runtime::genAssignTemporary(builder, loc, fromMutableBox, sourceBox);
  mlir::Value copy = builder.create<fir::LoadOp>(loc, fromMutableBox);
  return copy;
}

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} {}

  mlir::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 (rhs.getType().isa<hlfir::ExprType>()) {
      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 = builder.create<fir::AllocaOp>(loc, rhsType);
        builder.create<fir::StoreOp>(loc, rhsVal, temp);
        rhsExv = temp;
      }
      return fir::getBase(builder.createBox(loc, rhsExv));
    };

    if (assignOp.isAllocatableAssignment()) {
      // 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());
      builder.create<fir::StoreOp>(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));

      // 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());
    }
    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(
                [&]() { builder.create<fir::ResultOp>(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 =
                  genAllocatableTempFromSourceBox(loc, builder, inputVariable);
              // Get rid of allocatable flag in the fir.box.
              temp = builder.create<fir::ReboxOp>(loc, resultAddrType, temp,
                                                  /*shape=*/mlir::Value{},
                                                  /*slice=*/mlir::Value{});
              builder.create<fir::ResultOp>(loc, temp);
            })
            .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);
              builder.create<fir::ResultOp>(
                  loc, mlir::ValueRange{res.addr, res.wasCopied});
            })
            .genElse([&] {
              mlir::Value absent =
                  builder.create<fir::AbsentOp>(loc, resultAddrType);
              builder.create<fir::ResultOp>(
                  loc, mlir::ValueRange{absent, isPresent});
            })
            .getResults();
    return {res[0], res[1]};
  }

  mlir::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} {}

  mlir::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();
          if (mlir::Value var = copyOutOp.getVar()) {
            auto mutableBoxTo = builder.createTemporary(loc, var.getType());
            builder.create<fir::StoreOp>(loc, var, mutableBoxTo);
            // 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.
            fir::runtime::genCopyOutAssign(builder, loc, mutableBoxTo, temp,
                                           /*skipToInit=*/true);
          }
          // Destroy components of the temporary (if any).
          fir::runtime::genDerivedTypeDestroyWithoutFinalization(builder, loc,
                                                                 temp);
          mlir::Type heapType =
              fir::HeapType::get(fir::dyn_cast_ptrOrBoxEleTy(temp.getType()));
          mlir::Value tempAddr =
              builder.create<fir::BoxAddrOp>(loc, heapType, temp);

          // Deallocate the top-level entity of the temporary.
          //
          // Note that this FreeMemOp is coupled with the runtime
          // allocation engaged by the code generated by
          // genAllocatableTempFromSourceBox().
          builder.create<fir::FreeMemOp>(loc, tempAddr);
        })
        .end();
    rewriter.eraseOp(copyOutOp);
    return mlir::success();
  }
};

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

  mlir::LogicalResult
  matchAndRewrite(hlfir::DeclareOp declareOp,
                  mlir::PatternRewriter &rewriter) const override {
    mlir::Location loc = declareOp->getLoc();
    mlir::Value memref = declareOp.getMemref();
    fir::FortranVariableFlagsAttr fortranAttrs;
    if (auto attrs = declareOp.getFortranAttrs())
      fortranAttrs =
          fir::FortranVariableFlagsAttr::get(rewriter.getContext(), *attrs);
    auto firDeclareOp = rewriter.create<fir::DeclareOp>(
        loc, memref.getType(), memref, declareOp.getShape(),
        declareOp.getTypeparams(), declareOp.getUniqName(), fortranAttrs);

    // Propagate other attributes from hlfir.declare to fir.declare.
    // OpenACC's acc.declare is one example. Right now, the propagation
    // is verbatim.
    mlir::NamedAttrList elidedAttrs =
        mlir::NamedAttrList{firDeclareOp->getAttrs()};
    for (const mlir::NamedAttribute &attr : declareOp->getAttrs())
      if (!elidedAttrs.get(attr.getName()))
        firDeclareOp->setAttr(attr.getName(), attr.getValue());

    auto firBase = firDeclareOp.getResult();
    mlir::Value hlfirBase;
    mlir::Type hlfirBaseType = declareOp.getBase().getType();
    if (hlfirBaseType.isa<fir::BaseBoxType>()) {
      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 (!firBase.getType().isa<fir::BaseBoxType>()) {
          llvm::SmallVector<mlir::Value> typeParams;
          auto maybeCharType =
              fir::unwrapSequenceType(fir::unwrapPassByRefType(hlfirBaseType))
                  .dyn_cast<fir::CharacterType>();
          if (!maybeCharType || maybeCharType.hasDynamicLen())
            typeParams.append(declareOp.getTypeparams().begin(),
                              declareOp.getTypeparams().end());
          return builder.create<fir::EmboxOp>(
              loc, hlfirBaseType, firBase, declareOp.getShape(),
              /*slice=*/mlir::Value{}, typeParams);
        } else {
          // Rebox so that lower bounds are correct.
          return builder.create<fir::ReboxOp>(loc, hlfirBaseType, firBase,
                                              declareOp.getShape(),
                                              /*slice=*/mlir::Value{});
        }
      };
      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() == firBase.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 =
            builder.create<fir::IsPresentOp>(loc, builder.getI1Type(), firBase);
        hlfirBase = builder
                        .genIfOp(loc, {hlfirBaseType}, isPresent,
                                 /*withElseRegion=*/true)
                        .genThen([&] {
                          builder.create<fir::ResultOp>(loc, genHlfirBox());
                        })
                        .genElse([&]() {
                          mlir::Value absent =
                              builder.create<fir::AbsentOp>(loc, hlfirBaseType);
                          builder.create<fir::ResultOp>(loc, absent);
                        })
                        .getResults()[0];
      }
    } else if (hlfirBaseType.isa<fir::BoxCharType>()) {
      assert(declareOp.getTypeparams().size() == 1 &&
             "must contain character length");
      hlfirBase = rewriter.create<fir::EmboxCharOp>(
          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;
    for (auto isTriplet : designate.getIsTripletAttr().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 arrayCoorType = fir::ReferenceType::get(baseEleTy);
    base = builder.create<fir::ArrayCoorOp>(
        loc, arrayCoorType, base, shape,
        /*slice=*/mlir::Value{}, firstElementIndices, firBaseTypeParameters);
    return base;
  }

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

  mlir::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);
    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 parametrized derived type base");
      fieldIndex = builder.create<fir::FieldIndexOp>(
          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 = baseEleTy.cast<fir::RecordType>().getType(
            designate.getComponent().value());
        mlir::Type coorTy = fir::ReferenceType::get(componentType);
        base = builder.create<fir::CoordinateOp>(loc, coorTy, base, fieldIndex);
        if (componentType.isa<fir::BaseBoxType>()) {
          auto variableInterface = mlir::cast<fir::FortranVariableOpInterface>(
              designate.getOperation());
          if (variableInterface.isAllocatable() ||
              variableInterface.isPointer()) {
            rewriter.replaceOp(designate, base);
            return mlir::success();
          }
          TODO(loc,
               "addressing parametrized derived type automatic components");
        }
        baseEleTy = hlfir::getFortranElementType(componentType);
        shape = designate.getComponentShape();
      } else {
        // array%component[(indices) substring|complex part] cases.
        // Component ref of array bases are dealt with below in embox/rebox.
        assert(designateResultType.isa<fir::BaseBoxType>());
      }
    }

    if (designateResultType.isa<fir::BaseBoxType>()) {
      // Generate embox or rebox.
      mlir::Type eleTy = fir::unwrapPassByRefType(designateResultType);
      bool isScalarDesignator = !eleTy.isa<fir::SequenceType>();
      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(
                builder.create<mlir::arith::SubIOp>(loc, iIdx, lbIdx));
          }
        }
      } else if (!isScalarDesignator) {
        // Otherwise, this is an array section with triplets.
        auto undef = builder.create<fir::UndefOp>(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] =
            builder.create<mlir::arith::SubIOp>(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 =
            builder.create<fir::SliceOp>(loc, triples, sliceFields, substring);
      else
        assert(sliceFields.empty() && substring.empty());
      llvm::SmallVector<mlir::Type> resultType{designateResultType};
      mlir::Value resultBox;
      if (base.getType().isa<fir::BaseBoxType>())
        resultBox =
            builder.create<fir::ReboxOp>(loc, resultType, base, shape, slice);
      else
        resultBox =
            builder.create<fir::EmboxOp>(loc, resultType, base, shape, slice,
                                         firBaseTypeParameters, sourceBox);
      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 = designateResultType.dyn_cast<fir::BoxCharType>())
      resultAddressType = fir::ReferenceType::get(boxCharType.getEleTy());

    // 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(!designateResultType.isa<fir::SequenceType>());
      auto index = builder.createIntegerConstant(loc, builder.getIndexType(),
                                                 *designate.getComplexPart());
      auto coorTy = fir::ReferenceType::get(resultEleTy);
      base = builder.create<fir::CoordinateOp>(loc, coorTy, base, index);
    }

    // Cast/embox the computed scalar address if needed.
    if (designateResultType.isa<fir::BoxCharType>()) {
      assert(designate.getTypeparams().size() == 1 &&
             "must have character length");
      auto emboxChar = builder.create<fir::EmboxCharOp>(
          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} {}

  mlir::LogicalResult
  matchAndRewrite(hlfir::ParentComponentOp parentComponent,
                  mlir::PatternRewriter &rewriter) const override {
    mlir::Location loc = parentComponent.getLoc();
    mlir::Type resultType = parentComponent.getType();
    if (!parentComponent.getType().isa<fir::BoxType>()) {
      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 (baseAddr.getType().isa<fir::BaseBoxType>())
        baseAddr = rewriter.create<fir::BoxAddrOp>(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 (!baseAddr.getType().isa<fir::BaseBoxType>()) {
      // 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 = rewriter.create<fir::EmboxOp>(
          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} {}

  mlir::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} {}

  mlir::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;

  mlir::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 = shape.getType().cast<fir::ShapeType>();
      llvm::APInt dim = getExtentOp.getDim();
      uint64_t dimVal = dim.getLimitedValue(shapeTy.getRank());
      mlir::Value extent = s.getExtents()[dimVal];
      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

std::unique_ptr<mlir::Pass> hlfir::createConvertHLFIRtoFIRPass() {
  return std::make_unique<ConvertHLFIRtoFIR>();
}
