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

#include "flang/Optimizer/CodeGen/CodeGen.h"

#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Builder/LowLevelIntrinsics.h"
#include "flang/Optimizer/Builder/Runtime/Trampoline.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/Support/FatalError.h"
#include "flang/Optimizer/Support/InternalNames.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/DialectConversion.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"

namespace fir {
#define GEN_PASS_DEF_BOXEDPROCEDUREPASS
#include "flang/Optimizer/CodeGen/CGPasses.h.inc"
} // namespace fir

#define DEBUG_TYPE "flang-procedure-pointer"

using namespace fir;

namespace {

/// This type converter rewrites all `!fir.boxproc<Func>` types to `Func` types.
class BoxprocTypeRewriter : public mlir::TypeConverter {
public:
  using mlir::TypeConverter::convertType;

  /// Does the type \p ty need to be converted?
  /// Any type that is a `!fir.boxproc` in whole or in part will need to be
  /// converted to a function type to lower the IR to function pointer form in
  /// the default implementation performed in this pass. Other implementations
  /// are possible, so those may convert `!fir.boxproc` to some other type or
  /// not at all depending on the implementation target's characteristics and
  /// preference.
  bool needsConversion(mlir::Type ty) {
    if (mlir::isa<BoxProcType>(ty))
      return true;
    if (auto funcTy = mlir::dyn_cast<mlir::FunctionType>(ty)) {
      for (auto t : funcTy.getInputs())
        if (needsConversion(t))
          return true;
      for (auto t : funcTy.getResults())
        if (needsConversion(t))
          return true;
      return false;
    }
    if (auto tupleTy = mlir::dyn_cast<mlir::TupleType>(ty)) {
      for (auto t : tupleTy.getTypes())
        if (needsConversion(t))
          return true;
      return false;
    }
    if (auto recTy = mlir::dyn_cast<RecordType>(ty)) {
      auto [visited, inserted] = visitedTypes.try_emplace(ty, false);
      if (!inserted)
        return visited->second;
      bool wasAlreadyVisitingRecordType = needConversionIsVisitingRecordType;
      needConversionIsVisitingRecordType = true;
      bool result = false;
      for (auto t : recTy.getTypeList()) {
        if (needsConversion(t.second)) {
          result = true;
          break;
        }
      }
      // Only keep the result cached if the fir.type visited was a "top-level
      // type". Nested types with a recursive reference to the "top-level type"
      // may incorrectly have been resolved as not needed conversions because it
      // had not been determined yet if the "top-level type" needed conversion.
      // This is not an issue to determine the "top-level type" need of
      // conversion, but the result should not be kept and later used in other
      // contexts.
      needConversionIsVisitingRecordType = wasAlreadyVisitingRecordType;
      if (needConversionIsVisitingRecordType)
        visitedTypes.erase(ty);
      else
        visitedTypes.find(ty)->second = result;
      return result;
    }
    if (auto boxTy = mlir::dyn_cast<BaseBoxType>(ty))
      return needsConversion(boxTy.getEleTy());
    if (isa_ref_type(ty))
      return needsConversion(unwrapRefType(ty));
    if (auto t = mlir::dyn_cast<SequenceType>(ty))
      return needsConversion(unwrapSequenceType(ty));
    if (auto t = mlir::dyn_cast<TypeDescType>(ty))
      return needsConversion(t.getOfTy());
    return false;
  }

  BoxprocTypeRewriter(mlir::Location location) : loc{location} {
    addConversion([](mlir::Type ty) { return ty; });
    addConversion(
        [&](BoxProcType boxproc) { return convertType(boxproc.getEleTy()); });
    addConversion([&](mlir::TupleType tupTy) {
      llvm::SmallVector<mlir::Type> memTys;
      for (auto ty : tupTy.getTypes())
        memTys.push_back(convertType(ty));
      return mlir::TupleType::get(tupTy.getContext(), memTys);
    });
    addConversion([&](mlir::FunctionType funcTy) {
      llvm::SmallVector<mlir::Type> inTys;
      llvm::SmallVector<mlir::Type> resTys;
      for (auto ty : funcTy.getInputs())
        inTys.push_back(convertType(ty));
      for (auto ty : funcTy.getResults())
        resTys.push_back(convertType(ty));
      return mlir::FunctionType::get(funcTy.getContext(), inTys, resTys);
    });
    addConversion([&](ReferenceType ty) {
      return ReferenceType::get(convertType(ty.getEleTy()));
    });
    addConversion([&](PointerType ty) {
      return PointerType::get(convertType(ty.getEleTy()));
    });
    addConversion(
        [&](HeapType ty) { return HeapType::get(convertType(ty.getEleTy())); });
    addConversion([&](fir::LLVMPointerType ty) {
      return fir::LLVMPointerType::get(convertType(ty.getEleTy()));
    });
    addConversion(
        [&](BoxType ty) { return BoxType::get(convertType(ty.getEleTy())); });
    addConversion([&](ClassType ty) {
      return ClassType::get(convertType(ty.getEleTy()));
    });
    addConversion([&](SequenceType ty) {
      // TODO: add ty.getLayoutMap() as needed.
      return SequenceType::get(ty.getShape(), convertType(ty.getEleTy()));
    });
    addConversion([&](RecordType ty) -> mlir::Type {
      if (!needsConversion(ty))
        return ty;
      if (auto converted = convertedTypes.lookup(ty))
        return converted;
      auto rec = RecordType::get(ty.getContext(),
                                 ty.getName().str() + boxprocSuffix.str());
      if (rec.isFinalized())
        return rec;
      [[maybe_unused]] auto it = convertedTypes.try_emplace(ty, rec);
      assert(it.second && "expected ty to not be in the map");
      std::vector<RecordType::TypePair> ps = ty.getLenParamList();
      std::vector<RecordType::TypePair> cs;
      for (auto t : ty.getTypeList()) {
        if (needsConversion(t.second))
          cs.emplace_back(t.first, convertType(t.second));
        else
          cs.emplace_back(t.first, t.second);
      }
      rec.finalize(ps, cs);
      rec.pack(ty.isPacked());
      return rec;
    });
    addConversion([&](TypeDescType ty) {
      return TypeDescType::get(convertType(ty.getOfTy()));
    });
    addSourceMaterialization(materializeProcedure);
    addTargetMaterialization(materializeProcedure);
  }

  static mlir::Value materializeProcedure(mlir::OpBuilder &builder,
                                          BoxProcType type,
                                          mlir::ValueRange inputs,
                                          mlir::Location loc) {
    assert(inputs.size() == 1);
    return ConvertOp::create(builder, loc, unwrapRefType(type.getEleTy()),
                             inputs[0]);
  }

  void setLocation(mlir::Location location) { loc = location; }

private:
  // Maps to deal with recursive derived types (avoid infinite loops).
  // Caching is also beneficial for apps with big types (dozens of
  // components and or parent types), so the lifetime of the cache
  // is the whole pass.
  llvm::DenseMap<mlir::Type, bool> visitedTypes;
  bool needConversionIsVisitingRecordType = false;
  llvm::DenseMap<mlir::Type, mlir::Type> convertedTypes;
  mlir::Location loc;
};

/// A `boxproc` is an abstraction for a Fortran procedure reference. Typically,
/// Fortran procedures can be referenced directly through a function pointer.
/// However, Fortran has one-level dynamic scoping between a host procedure and
/// its internal procedures. This allows internal procedures to directly access
/// and modify the state of the host procedure's variables.
///
/// There are any number of possible implementations possible.
///
/// The implementation used here is to convert `boxproc` values to function
/// pointers everywhere. If a `boxproc` value includes a frame pointer to the
/// host procedure's data, then a thunk will be created at runtime to capture
/// the frame pointer during execution. In LLVM IR, the frame pointer is
/// designated with the `nest` attribute. The thunk's address will then be used
/// as the call target instead of the original function's address directly.
class BoxedProcedurePass
    : public fir::impl::BoxedProcedurePassBase<BoxedProcedurePass> {
public:
  using BoxedProcedurePassBase<BoxedProcedurePass>::BoxedProcedurePassBase;

  inline mlir::ModuleOp getModule() { return getOperation(); }

  void runOnOperation() override final {
    if (useThunks) {
      auto *context = &getContext();
      mlir::IRRewriter rewriter(context);
      BoxprocTypeRewriter typeConverter(mlir::UnknownLoc::get(context));

      // When using safe trampolines, we need to track handles per
      // function so we can insert FreeTrampoline calls at each return.
      // Process functions individually to manage this state.
      if (useSafeTrampoline) {
        getModule().walk([&](mlir::func::FuncOp funcOp) {
          trampolineHandles.clear();
          trampolineCallableMap.clear();
          processFunction(funcOp, rewriter, typeConverter);
          insertTrampolineFrees(funcOp, rewriter);
        });
        // Also process non-function ops at module level (globals, etc.)
        processModuleLevelOps(rewriter, typeConverter);
      } else {
        getModule().walk([&](mlir::Operation *op) {
          processOp(op, rewriter, typeConverter);
        });
      }
    }
  }

private:
  /// Trampoline handles collected while processing a function.
  /// Each entry is a Value representing the opaque handle returned
  /// by _FortranATrampolineInit, which must be freed before the
  /// function returns.
  llvm::SmallVector<mlir::Value> trampolineHandles;

  /// Cache of trampoline callable addresses keyed by the func SSA value
  /// of the emboxproc. This deduplicates trampolines when the same
  /// internal procedure is emboxed multiple times in one host function.
  llvm::DenseMap<mlir::Value, mlir::Value> trampolineCallableMap;

  /// Process all ops within a function.
  void processFunction(mlir::func::FuncOp funcOp, mlir::IRRewriter &rewriter,
                       BoxprocTypeRewriter &typeConverter) {
    funcOp.walk(
        [&](mlir::Operation *op) { processOp(op, rewriter, typeConverter); });
  }

  /// Process non-function ops at module level (globals, etc.)
  void processModuleLevelOps(mlir::IRRewriter &rewriter,
                             BoxprocTypeRewriter &typeConverter) {
    for (auto &op : getModule().getBody()->getOperations())
      if (!mlir::isa<mlir::func::FuncOp>(op))
        processOp(&op, rewriter, typeConverter);
  }

  /// Insert _FortranATrampolineFree calls before every return in the function.
  void insertTrampolineFrees(mlir::func::FuncOp funcOp,
                             mlir::IRRewriter &rewriter) {
    if (trampolineHandles.empty())
      return;

    auto module{funcOp->getParentOfType<mlir::ModuleOp>()};
    // Insert TrampolineFree calls before every func.return in this function.
    // At this pass stage (after CFGConversion), func.return is the only
    // terminator that exits the function. Other terminators are either
    // intra-function branches (cf.br, cf.cond_br, fir.select*) or
    // fir.unreachable (after STOP/ERROR STOP), which don't need cleanup
    // since the process is terminating.
    funcOp.walk([&](mlir::func::ReturnOp retOp) {
      rewriter.setInsertionPoint(retOp);
      FirOpBuilder builder(rewriter, module);
      auto loc{retOp.getLoc()};
      for (mlir::Value handle : trampolineHandles)
        fir::runtime::genTrampolineFree(builder, loc, handle);
    });
  }

  /// Process a single operation for boxproc type rewriting.
  void processOp(mlir::Operation *op, mlir::IRRewriter &rewriter,
                 BoxprocTypeRewriter &typeConverter) {
    bool opIsValid{true};
    typeConverter.setLocation(op->getLoc());
    if (auto addr = mlir::dyn_cast<BoxAddrOp>(op)) {
      mlir::Type ty{addr.getVal().getType()};
      mlir::Type resTy{addr.getResult().getType()};
      if (llvm::isa<mlir::FunctionType>(ty) ||
          llvm::isa<fir::BoxProcType>(ty)) {
        // Rewrite all `fir.box_addr` ops on values of type `!fir.boxproc`
        // or function type to be `fir.convert` ops.
        rewriter.setInsertionPoint(addr);
        rewriter.replaceOpWithNewOp<ConvertOp>(
            addr, typeConverter.convertType(addr.getType()), addr.getVal());
        opIsValid = false;
      } else if (typeConverter.needsConversion(resTy)) {
        rewriter.startOpModification(op);
        op->getResult(0).setType(typeConverter.convertType(resTy));
        rewriter.finalizeOpModification(op);
      }
    } else if (auto func = mlir::dyn_cast<mlir::func::FuncOp>(op)) {
      mlir::FunctionType ty{func.getFunctionType()};
      if (typeConverter.needsConversion(ty)) {
        rewriter.startOpModification(func);
        auto toTy{
            mlir::cast<mlir::FunctionType>(typeConverter.convertType(ty))};
        if (!func.empty())
          for (auto e : llvm::enumerate(toTy.getInputs())) {
            auto i{static_cast<unsigned>(e.index())};
            auto &block{func.front()};
            block.insertArgument(i, e.value(), func.getLoc());
            block.getArgument(i + 1).replaceAllUsesWith(block.getArgument(i));
            block.eraseArgument(i + 1);
          }
        func.setType(toTy);
        rewriter.finalizeOpModification(func);
      }
    } else if (auto embox = mlir::dyn_cast<EmboxProcOp>(op)) {
      // Rewrite all `fir.emboxproc` ops to either `fir.convert` or a thunk
      // as required.
      mlir::Type toTy{typeConverter.convertType(
          mlir::cast<BoxProcType>(embox.getType()).getEleTy())};
      rewriter.setInsertionPoint(embox);
      if (embox.getHost()) {
        auto module{embox->getParentOfType<mlir::ModuleOp>()};
        auto loc{embox.getLoc()};

        if (useSafeTrampoline) {
          // Runtime trampoline pool path (W^X compliant).
          // Insert Init/Adjust in the function's entry block so the
          // handle dominates all func.return ops where TrampolineFree
          // is emitted. This is necessary because fir.emboxproc may
          // appear inside control flow branches. A cache avoids
          // creating duplicate trampolines for the same internal
          // procedure within a single host function.
          mlir::Value funcVal{embox.getFunc()};
          auto cacheIt{trampolineCallableMap.find(funcVal)};
          if (cacheIt != trampolineCallableMap.end()) {
            rewriter.replaceOpWithNewOp<ConvertOp>(embox, toTy,
                                                   cacheIt->second);
          } else {
            auto parentFunc{embox->getParentOfType<mlir::func::FuncOp>()};
            auto &entryBlock{parentFunc.front()};

            auto savedIP{rewriter.saveInsertionPoint()};

            // Find the right insertion point in the entry block.
            // Walk up from the emboxproc to find its top-level
            // ancestor in the entry block. For an emboxproc directly
            // in the entry block, this is the emboxproc itself.
            // For one inside a structured op (fir.if, fir.do_loop),
            // this is that structured op. For one inside an explicit
            // branch target (cf.cond_br → ^bb1), we fall back to the
            // entry block terminator.
            mlir::Operation *entryAncestor{embox.getOperation()};
            while (entryAncestor->getBlock() != &entryBlock) {
              entryAncestor = entryAncestor->getParentOp();
              if (!entryAncestor ||
                  mlir::isa<mlir::func::FuncOp>(entryAncestor))
                break;
            }
            bool ancestorInEntry{
                entryAncestor &&
                !mlir::isa<mlir::func::FuncOp>(entryAncestor) &&
                entryAncestor->getBlock() == &entryBlock};

            // If the func value is not in the entry block (e.g.,
            // address_of generated inside a structured fir.if),
            // clone it into the entry block.
            mlir::Value funcValInEntry{funcVal};
            if (auto *funcDef{funcVal.getDefiningOp()}) {
              if (funcDef->getBlock() != &entryBlock) {
                if (ancestorInEntry)
                  rewriter.setInsertionPoint(entryAncestor);
                else
                  rewriter.setInsertionPoint(entryBlock.getTerminator());
                auto *cloned{rewriter.clone(*funcDef)};
                funcValInEntry = cloned->getResult(0);
              }
            }

            // The host link (closure pointer) must already be in the entry
            // block. In practice it is always either a function block argument
            // or an alloca emitted at function entry by the lowering — cloning
            // just the defining op would miss any stores that initialise it,
            // producing incorrect code. Assert that invariant rather than
            // attempting a broken clone.
            mlir::Value hostValInEntry{embox.getHost()};
            if (auto *hostDef{embox.getHost().getDefiningOp()}) {
              if (hostDef->getBlock() != &entryBlock) {
                mlir::emitError(loc,
                                "host link value is not defined in the entry "
                                "block of the host function; cannot hoist "
                                "TrampolineInit safely");
                return;
              }
            }

            // Insert Init/Adjust at the determined position.
            FirOpBuilder builder(rewriter, module);
            if (ancestorInEntry)
              builder.setInsertionPoint(entryAncestor);
            else
              builder.setInsertionPoint(entryBlock.getTerminator());
            mlir::Type i8Ty{builder.getI8Type()};
            mlir::Type i8Ptr{builder.getRefType(i8Ty)};

            mlir::Value nullPtr{builder.createNullConstant(loc, i8Ptr)};
            mlir::Value closure{
                builder.createConvert(loc, i8Ptr, hostValInEntry)};
            mlir::Value func{builder.createConvert(loc, i8Ptr, funcValInEntry)};

            // _FortranATrampolineInit(nullptr, func, closure) -> handle
            mlir::Value handle{fir::runtime::genTrampolineInit(
                builder, loc, nullPtr, func, closure)};

            // _FortranATrampolineAdjust(handle) -> callable address
            mlir::Value callableAddr{
                fir::runtime::genTrampolineAdjust(builder, loc, handle)};

            trampolineHandles.push_back(handle);
            trampolineCallableMap[funcVal] = callableAddr;

            rewriter.restoreInsertionPoint(savedIP);
            rewriter.replaceOpWithNewOp<ConvertOp>(embox, toTy, callableAddr);
          }
        } else {
          // Legacy stack-based trampoline path.
          FirOpBuilder builder(rewriter, module);
          mlir::Type i8Ty{builder.getI8Type()};
          mlir::Type i8Ptr{builder.getRefType(i8Ty)};
          const auto triple{fir::getTargetTriple(module)};
          // For PPC32 and PPC64, the thunk is populated by a call to
          // __trampoline_setup, which is defined in
          // compiler-rt/lib/builtins/trampoline_setup.c and requires the
          // thunk size greater than 32 bytes.  For AArch64, RISCV and
          // x86_64, the thunk setup doesn't go through
          // __trampoline_setup and fits in 32 bytes.
          fir::SequenceType::Extent thunkSize{triple.getTrampolineSize()};
          mlir::Type buffTy{SequenceType::get({thunkSize}, i8Ty)};
          auto buffer{AllocaOp::create(builder, loc, buffTy)};
          mlir::Value closure{
              builder.createConvert(loc, i8Ptr, embox.getHost())};
          mlir::Value tramp{builder.createConvert(loc, i8Ptr, buffer)};
          mlir::Value func{builder.createConvert(loc, i8Ptr, embox.getFunc())};
          fir::CallOp::create(
              builder, loc, factory::getLlvmInitTrampoline(builder),
              llvm::ArrayRef<mlir::Value>{tramp, func, closure});
          auto adjustCall{fir::CallOp::create(
              builder, loc, factory::getLlvmAdjustTrampoline(builder),
              llvm::ArrayRef<mlir::Value>{tramp})};
          rewriter.replaceOpWithNewOp<ConvertOp>(embox, toTy,
                                                 adjustCall.getResult(0));
        }
        opIsValid = false;
      } else {
        // Just forward the function as a pointer.
        rewriter.replaceOpWithNewOp<ConvertOp>(embox, toTy, embox.getFunc());
        opIsValid = false;
      }
    } else if (auto global = mlir::dyn_cast<GlobalOp>(op)) {
      auto ty{global.getType()};
      if (typeConverter.needsConversion(ty)) {
        rewriter.startOpModification(global);
        auto toTy{typeConverter.convertType(ty)};
        global.setType(toTy);
        rewriter.finalizeOpModification(global);
      }
    } else if (auto mem = mlir::dyn_cast<AllocaOp>(op)) {
      auto ty{mem.getType()};
      if (typeConverter.needsConversion(ty)) {
        rewriter.setInsertionPoint(mem);
        auto toTy{typeConverter.convertType(unwrapRefType(ty))};
        bool isPinned{mem.getPinned()};
        llvm::StringRef uniqName{mem.getUniqName().value_or(llvm::StringRef())};
        llvm::StringRef bindcName{
            mem.getBindcName().value_or(llvm::StringRef())};
        rewriter.replaceOpWithNewOp<AllocaOp>(mem, toTy, uniqName, bindcName,
                                              isPinned, mem.getTypeparams(),
                                              mem.getShape());
        opIsValid = false;
      }
    } else if (auto mem = mlir::dyn_cast<AllocMemOp>(op)) {
      auto ty{mem.getType()};
      if (typeConverter.needsConversion(ty)) {
        rewriter.setInsertionPoint(mem);
        auto toTy{typeConverter.convertType(unwrapRefType(ty))};
        llvm::StringRef uniqName{mem.getUniqName().value_or(llvm::StringRef())};
        llvm::StringRef bindcName{
            mem.getBindcName().value_or(llvm::StringRef())};
        rewriter.replaceOpWithNewOp<AllocMemOp>(mem, toTy, uniqName, bindcName,
                                                mem.getTypeparams(),
                                                mem.getShape());
        opIsValid = false;
      }
    } else if (auto coor = mlir::dyn_cast<CoordinateOp>(op)) {
      auto ty{coor.getType()};
      mlir::Type baseTy{coor.getBaseType()};
      if (typeConverter.needsConversion(ty) ||
          typeConverter.needsConversion(baseTy)) {
        rewriter.setInsertionPoint(coor);
        auto toTy{typeConverter.convertType(ty)};
        auto toBaseTy{typeConverter.convertType(baseTy)};
        rewriter.replaceOpWithNewOp<CoordinateOp>(coor, toTy, coor.getRef(),
                                                  coor.getCoor(), toBaseTy,
                                                  coor.getFieldIndicesAttr());
        opIsValid = false;
      }
    } else if (auto index = mlir::dyn_cast<FieldIndexOp>(op)) {
      auto ty{index.getType()};
      mlir::Type onTy{index.getOnType()};
      if (typeConverter.needsConversion(ty) ||
          typeConverter.needsConversion(onTy)) {
        rewriter.setInsertionPoint(index);
        auto toTy{typeConverter.convertType(ty)};
        auto toOnTy{typeConverter.convertType(onTy)};
        rewriter.replaceOpWithNewOp<FieldIndexOp>(
            index, toTy, index.getFieldId(), toOnTy, index.getTypeparams());
        opIsValid = false;
      }
    } else if (auto index = mlir::dyn_cast<LenParamIndexOp>(op)) {
      auto ty{index.getType()};
      mlir::Type onTy{index.getOnType()};
      if (typeConverter.needsConversion(ty) ||
          typeConverter.needsConversion(onTy)) {
        rewriter.setInsertionPoint(index);
        auto toTy{typeConverter.convertType(ty)};
        auto toOnTy{typeConverter.convertType(onTy)};
        rewriter.replaceOpWithNewOp<LenParamIndexOp>(
            index, toTy, index.getFieldId(), toOnTy, index.getTypeparams());
        opIsValid = false;
      }
    } else {
      rewriter.startOpModification(op);
      // Convert the operands if needed
      for (auto i : llvm::enumerate(op->getResultTypes()))
        if (typeConverter.needsConversion(i.value())) {
          auto toTy{typeConverter.convertType(i.value())};
          op->getResult(i.index()).setType(toTy);
        }

      // Convert the type attributes if needed
      for (const mlir::NamedAttribute &attr : op->getAttrDictionary())
        if (auto tyAttr = llvm::dyn_cast<mlir::TypeAttr>(attr.getValue()))
          if (typeConverter.needsConversion(tyAttr.getValue())) {
            auto toTy{typeConverter.convertType(tyAttr.getValue())};
            op->setAttr(attr.getName(), mlir::TypeAttr::get(toTy));
          }
      rewriter.finalizeOpModification(op);
    }
    // Ensure block arguments are updated if needed.
    if (opIsValid && op->getNumRegions() != 0) {
      rewriter.startOpModification(op);
      for (mlir::Region &region : op->getRegions())
        for (mlir::Block &block : region.getBlocks())
          for (mlir::BlockArgument blockArg : block.getArguments())
            if (typeConverter.needsConversion(blockArg.getType())) {
              mlir::Type toTy{typeConverter.convertType(blockArg.getType())};
              blockArg.setType(toTy);
            }
      rewriter.finalizeOpModification(op);
    }
  }
};
} // namespace
