//===- 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;
    fir::CUDADataAttributeAttr cudaAttr;
    if (auto attrs = declareOp.getFortranAttrs())
      fortranAttrs =
          fir::FortranVariableFlagsAttr::get(rewriter.getContext(), *attrs);
    if (auto attr = declareOp.getCudaAttr())
      cudaAttr = fir::CUDADataAttributeAttr::get(rewriter.getContext(), *attr);
    auto firDeclareOp = rewriter.create<fir::DeclareOp>(
        loc, memref.getType(), memref, declareOp.getShape(),
        declareOp.getTypeparams(), declareOp.getUniqName(), fortranAttrs,
        cudaAttr);

    // 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>();
}
