1fe252f8eSValentin Clement //===-- BoxedProcedure.cpp ------------------------------------------------===//
2fe252f8eSValentin Clement //
3fe252f8eSValentin Clement // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe252f8eSValentin Clement // See https://llvm.org/LICENSE.txt for license information.
5fe252f8eSValentin Clement // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe252f8eSValentin Clement //
7fe252f8eSValentin Clement //===----------------------------------------------------------------------===//
8fe252f8eSValentin Clement 
9fe252f8eSValentin Clement #include "PassDetail.h"
10fe252f8eSValentin Clement #include "flang/Optimizer/Builder/FIRBuilder.h"
11fe252f8eSValentin Clement #include "flang/Optimizer/Builder/LowLevelIntrinsics.h"
12fe252f8eSValentin Clement #include "flang/Optimizer/CodeGen/CodeGen.h"
13fe252f8eSValentin Clement #include "flang/Optimizer/Dialect/FIRDialect.h"
14fe252f8eSValentin Clement #include "flang/Optimizer/Dialect/FIROps.h"
15fe252f8eSValentin Clement #include "flang/Optimizer/Dialect/FIRType.h"
16fe252f8eSValentin Clement #include "flang/Optimizer/Support/FIRContext.h"
17fe252f8eSValentin Clement #include "flang/Optimizer/Support/FatalError.h"
18fe252f8eSValentin Clement #include "mlir/IR/PatternMatch.h"
19fe252f8eSValentin Clement #include "mlir/Pass/Pass.h"
20fe252f8eSValentin Clement #include "mlir/Transforms/DialectConversion.h"
21fe252f8eSValentin Clement 
22fe252f8eSValentin Clement #define DEBUG_TYPE "flang-procedure-pointer"
23fe252f8eSValentin Clement 
24fe252f8eSValentin Clement using namespace fir;
25fe252f8eSValentin Clement 
26fe252f8eSValentin Clement namespace {
27fe252f8eSValentin Clement /// Options to the procedure pointer pass.
28fe252f8eSValentin Clement struct BoxedProcedureOptions {
29fe252f8eSValentin Clement   // Lower the boxproc abstraction to function pointers and thunks where
30fe252f8eSValentin Clement   // required.
31fe252f8eSValentin Clement   bool useThunks = true;
32fe252f8eSValentin Clement };
33fe252f8eSValentin Clement 
34fe252f8eSValentin Clement /// This type converter rewrites all `!fir.boxproc<Func>` types to `Func` types.
35fe252f8eSValentin Clement class BoxprocTypeRewriter : public mlir::TypeConverter {
36fe252f8eSValentin Clement public:
37fe252f8eSValentin Clement   using mlir::TypeConverter::convertType;
38fe252f8eSValentin Clement 
39fe252f8eSValentin Clement   /// Does the type \p ty need to be converted?
40fe252f8eSValentin Clement   /// Any type that is a `!fir.boxproc` in whole or in part will need to be
41fe252f8eSValentin Clement   /// converted to a function type to lower the IR to function pointer form in
42fe252f8eSValentin Clement   /// the default implementation performed in this pass. Other implementations
43fe252f8eSValentin Clement   /// are possible, so those may convert `!fir.boxproc` to some other type or
44fe252f8eSValentin Clement   /// not at all depending on the implementation target's characteristics and
45fe252f8eSValentin Clement   /// preference.
needsConversion(mlir::Type ty)46fe252f8eSValentin Clement   bool needsConversion(mlir::Type ty) {
47fe252f8eSValentin Clement     if (ty.isa<BoxProcType>())
48fe252f8eSValentin Clement       return true;
49fe252f8eSValentin Clement     if (auto funcTy = ty.dyn_cast<mlir::FunctionType>()) {
50fe252f8eSValentin Clement       for (auto t : funcTy.getInputs())
51fe252f8eSValentin Clement         if (needsConversion(t))
52fe252f8eSValentin Clement           return true;
53fe252f8eSValentin Clement       for (auto t : funcTy.getResults())
54fe252f8eSValentin Clement         if (needsConversion(t))
55fe252f8eSValentin Clement           return true;
56fe252f8eSValentin Clement       return false;
57fe252f8eSValentin Clement     }
58fe252f8eSValentin Clement     if (auto tupleTy = ty.dyn_cast<mlir::TupleType>()) {
59fe252f8eSValentin Clement       for (auto t : tupleTy.getTypes())
60fe252f8eSValentin Clement         if (needsConversion(t))
61fe252f8eSValentin Clement           return true;
62fe252f8eSValentin Clement       return false;
63fe252f8eSValentin Clement     }
64fe252f8eSValentin Clement     if (auto recTy = ty.dyn_cast<RecordType>()) {
65a370a4ffSjeanPerier       if (llvm::any_of(visitedTypes,
66a370a4ffSjeanPerier                        [&](mlir::Type rt) { return rt == recTy; }))
67a370a4ffSjeanPerier         return false;
68fe252f8eSValentin Clement       bool result = false;
69fe252f8eSValentin Clement       visitedTypes.push_back(recTy);
70fe252f8eSValentin Clement       for (auto t : recTy.getTypeList()) {
71fe252f8eSValentin Clement         if (needsConversion(t.second)) {
72fe252f8eSValentin Clement           result = true;
73fe252f8eSValentin Clement           break;
74fe252f8eSValentin Clement         }
75fe252f8eSValentin Clement       }
76fe252f8eSValentin Clement       visitedTypes.pop_back();
77fe252f8eSValentin Clement       return result;
78fe252f8eSValentin Clement     }
79fe252f8eSValentin Clement     if (auto boxTy = ty.dyn_cast<BoxType>())
80fe252f8eSValentin Clement       return needsConversion(boxTy.getEleTy());
81fe252f8eSValentin Clement     if (isa_ref_type(ty))
82fe252f8eSValentin Clement       return needsConversion(unwrapRefType(ty));
83fe252f8eSValentin Clement     if (auto t = ty.dyn_cast<SequenceType>())
84fe252f8eSValentin Clement       return needsConversion(unwrapSequenceType(ty));
85fe252f8eSValentin Clement     return false;
86fe252f8eSValentin Clement   }
87fe252f8eSValentin Clement 
BoxprocTypeRewriter(mlir::Location location)88a370a4ffSjeanPerier   BoxprocTypeRewriter(mlir::Location location) : loc{location} {
__anonfdb31fde0302(mlir::Type ty) 89fe252f8eSValentin Clement     addConversion([](mlir::Type ty) { return ty; });
90a370a4ffSjeanPerier     addConversion(
__anonfdb31fde0402(BoxProcType boxproc) 91a370a4ffSjeanPerier         [&](BoxProcType boxproc) { return convertType(boxproc.getEleTy()); });
__anonfdb31fde0502(mlir::TupleType tupTy) 92fe252f8eSValentin Clement     addConversion([&](mlir::TupleType tupTy) {
93fe252f8eSValentin Clement       llvm::SmallVector<mlir::Type> memTys;
94fe252f8eSValentin Clement       for (auto ty : tupTy.getTypes())
95fe252f8eSValentin Clement         memTys.push_back(convertType(ty));
96fe252f8eSValentin Clement       return mlir::TupleType::get(tupTy.getContext(), memTys);
97fe252f8eSValentin Clement     });
__anonfdb31fde0602(mlir::FunctionType funcTy) 98fe252f8eSValentin Clement     addConversion([&](mlir::FunctionType funcTy) {
99fe252f8eSValentin Clement       llvm::SmallVector<mlir::Type> inTys;
100fe252f8eSValentin Clement       llvm::SmallVector<mlir::Type> resTys;
101fe252f8eSValentin Clement       for (auto ty : funcTy.getInputs())
102fe252f8eSValentin Clement         inTys.push_back(convertType(ty));
103fe252f8eSValentin Clement       for (auto ty : funcTy.getResults())
104fe252f8eSValentin Clement         resTys.push_back(convertType(ty));
105fe252f8eSValentin Clement       return mlir::FunctionType::get(funcTy.getContext(), inTys, resTys);
106fe252f8eSValentin Clement     });
__anonfdb31fde0702(ReferenceType ty) 107fe252f8eSValentin Clement     addConversion([&](ReferenceType ty) {
108fe252f8eSValentin Clement       return ReferenceType::get(convertType(ty.getEleTy()));
109fe252f8eSValentin Clement     });
__anonfdb31fde0802(PointerType ty) 110fe252f8eSValentin Clement     addConversion([&](PointerType ty) {
111fe252f8eSValentin Clement       return PointerType::get(convertType(ty.getEleTy()));
112fe252f8eSValentin Clement     });
113fe252f8eSValentin Clement     addConversion(
__anonfdb31fde0902(HeapType ty) 114fe252f8eSValentin Clement         [&](HeapType ty) { return HeapType::get(convertType(ty.getEleTy())); });
115fe252f8eSValentin Clement     addConversion(
__anonfdb31fde0a02(BoxType ty) 116fe252f8eSValentin Clement         [&](BoxType ty) { return BoxType::get(convertType(ty.getEleTy())); });
__anonfdb31fde0b02(SequenceType ty) 117fe252f8eSValentin Clement     addConversion([&](SequenceType ty) {
118fe252f8eSValentin Clement       // TODO: add ty.getLayoutMap() as needed.
119fe252f8eSValentin Clement       return SequenceType::get(ty.getShape(), convertType(ty.getEleTy()));
120fe252f8eSValentin Clement     });
__anonfdb31fde0c02(RecordType ty) 121a370a4ffSjeanPerier     addConversion([&](RecordType ty) -> mlir::Type {
122a370a4ffSjeanPerier       if (!needsConversion(ty))
123a370a4ffSjeanPerier         return ty;
124fe252f8eSValentin Clement       // FIR record types can have recursive references, so conversion is a bit
125fe252f8eSValentin Clement       // more complex than the other types. This conversion is not needed
126fe252f8eSValentin Clement       // presently, so just emit a TODO message. Need to consider the uniqued
127a370a4ffSjeanPerier       // name of the record, etc. Also, fir::RecordType::get returns the
128a370a4ffSjeanPerier       // existing type being translated. So finalize() will not change it, and
129a370a4ffSjeanPerier       // the translation would not do anything. So the type needs to be mutated,
130a370a4ffSjeanPerier       // and this might require special care to comply with MLIR infrastructure.
131a370a4ffSjeanPerier 
132a370a4ffSjeanPerier       // TODO: this will be needed to support derived type containing procedure
133a370a4ffSjeanPerier       // pointer components.
134fe252f8eSValentin Clement       fir::emitFatalError(
135a370a4ffSjeanPerier           loc, "not yet implemented: record type with a boxproc type");
136fe252f8eSValentin Clement       return RecordType::get(ty.getContext(), "*fixme*");
137fe252f8eSValentin Clement     });
138fe252f8eSValentin Clement     addArgumentMaterialization(materializeProcedure);
139fe252f8eSValentin Clement     addSourceMaterialization(materializeProcedure);
140fe252f8eSValentin Clement     addTargetMaterialization(materializeProcedure);
141fe252f8eSValentin Clement   }
142fe252f8eSValentin Clement 
materializeProcedure(mlir::OpBuilder & builder,BoxProcType type,mlir::ValueRange inputs,mlir::Location loc)143fe252f8eSValentin Clement   static mlir::Value materializeProcedure(mlir::OpBuilder &builder,
144fe252f8eSValentin Clement                                           BoxProcType type,
145fe252f8eSValentin Clement                                           mlir::ValueRange inputs,
146fe252f8eSValentin Clement                                           mlir::Location loc) {
147fe252f8eSValentin Clement     assert(inputs.size() == 1);
148fe252f8eSValentin Clement     return builder.create<ConvertOp>(loc, unwrapRefType(type.getEleTy()),
149fe252f8eSValentin Clement                                      inputs[0]);
150fe252f8eSValentin Clement   }
151fe252f8eSValentin Clement 
setLocation(mlir::Location location)152a370a4ffSjeanPerier   void setLocation(mlir::Location location) { loc = location; }
153a370a4ffSjeanPerier 
154fe252f8eSValentin Clement private:
155fe252f8eSValentin Clement   llvm::SmallVector<mlir::Type> visitedTypes;
156a370a4ffSjeanPerier   mlir::Location loc;
157fe252f8eSValentin Clement };
158fe252f8eSValentin Clement 
159fe252f8eSValentin Clement /// A `boxproc` is an abstraction for a Fortran procedure reference. Typically,
160fe252f8eSValentin Clement /// Fortran procedures can be referenced directly through a function pointer.
161fe252f8eSValentin Clement /// However, Fortran has one-level dynamic scoping between a host procedure and
162fe252f8eSValentin Clement /// its internal procedures. This allows internal procedures to directly access
163fe252f8eSValentin Clement /// and modify the state of the host procedure's variables.
164fe252f8eSValentin Clement ///
165fe252f8eSValentin Clement /// There are any number of possible implementations possible.
166fe252f8eSValentin Clement ///
167fe252f8eSValentin Clement /// The implementation used here is to convert `boxproc` values to function
168fe252f8eSValentin Clement /// pointers everywhere. If a `boxproc` value includes a frame pointer to the
169fe252f8eSValentin Clement /// host procedure's data, then a thunk will be created at runtime to capture
170fe252f8eSValentin Clement /// the frame pointer during execution. In LLVM IR, the frame pointer is
171fe252f8eSValentin Clement /// designated with the `nest` attribute. The thunk's address will then be used
172fe252f8eSValentin Clement /// as the call target instead of the original function's address directly.
173fe252f8eSValentin Clement class BoxedProcedurePass : public BoxedProcedurePassBase<BoxedProcedurePass> {
174fe252f8eSValentin Clement public:
BoxedProcedurePass()175fe252f8eSValentin Clement   BoxedProcedurePass() { options = {true}; }
BoxedProcedurePass(bool useThunks)176fe252f8eSValentin Clement   BoxedProcedurePass(bool useThunks) { options = {useThunks}; }
177fe252f8eSValentin Clement 
getModule()178fe252f8eSValentin Clement   inline mlir::ModuleOp getModule() { return getOperation(); }
179fe252f8eSValentin Clement 
runOnOperation()180fe252f8eSValentin Clement   void runOnOperation() override final {
181fe252f8eSValentin Clement     if (options.useThunks) {
182fe252f8eSValentin Clement       auto *context = &getContext();
183fe252f8eSValentin Clement       mlir::IRRewriter rewriter(context);
184a370a4ffSjeanPerier       BoxprocTypeRewriter typeConverter(mlir::UnknownLoc::get(context));
185fe252f8eSValentin Clement       mlir::Dialect *firDialect = context->getLoadedDialect("fir");
186fe252f8eSValentin Clement       getModule().walk([&](mlir::Operation *op) {
187a370a4ffSjeanPerier         typeConverter.setLocation(op->getLoc());
188fe252f8eSValentin Clement         if (auto addr = mlir::dyn_cast<BoxAddrOp>(op)) {
189fe252f8eSValentin Clement           auto ty = addr.getVal().getType();
190fe252f8eSValentin Clement           if (typeConverter.needsConversion(ty) ||
191fe252f8eSValentin Clement               ty.isa<mlir::FunctionType>()) {
192fe252f8eSValentin Clement             // Rewrite all `fir.box_addr` ops on values of type `!fir.boxproc`
193fe252f8eSValentin Clement             // or function type to be `fir.convert` ops.
194fe252f8eSValentin Clement             rewriter.setInsertionPoint(addr);
195fe252f8eSValentin Clement             rewriter.replaceOpWithNewOp<ConvertOp>(
196fe252f8eSValentin Clement                 addr, typeConverter.convertType(addr.getType()), addr.getVal());
197fe252f8eSValentin Clement           }
19858ceae95SRiver Riddle         } else if (auto func = mlir::dyn_cast<mlir::func::FuncOp>(op)) {
199fe252f8eSValentin Clement           mlir::FunctionType ty = func.getFunctionType();
200fe252f8eSValentin Clement           if (typeConverter.needsConversion(ty)) {
201fe252f8eSValentin Clement             rewriter.startRootUpdate(func);
202fe252f8eSValentin Clement             auto toTy =
203fe252f8eSValentin Clement                 typeConverter.convertType(ty).cast<mlir::FunctionType>();
204fe252f8eSValentin Clement             if (!func.empty())
205fe252f8eSValentin Clement               for (auto e : llvm::enumerate(toTy.getInputs())) {
206fe252f8eSValentin Clement                 unsigned i = e.index();
207fe252f8eSValentin Clement                 auto &block = func.front();
208fe252f8eSValentin Clement                 block.insertArgument(i, e.value(), func.getLoc());
209fe252f8eSValentin Clement                 block.getArgument(i + 1).replaceAllUsesWith(
210fe252f8eSValentin Clement                     block.getArgument(i));
211fe252f8eSValentin Clement                 block.eraseArgument(i + 1);
212fe252f8eSValentin Clement               }
213fe252f8eSValentin Clement             func.setType(toTy);
214fe252f8eSValentin Clement             rewriter.finalizeRootUpdate(func);
215fe252f8eSValentin Clement           }
216fe252f8eSValentin Clement         } else if (auto embox = mlir::dyn_cast<EmboxProcOp>(op)) {
217fe252f8eSValentin Clement           // Rewrite all `fir.emboxproc` ops to either `fir.convert` or a thunk
218fe252f8eSValentin Clement           // as required.
219fe252f8eSValentin Clement           mlir::Type toTy = embox.getType().cast<BoxProcType>().getEleTy();
220fe252f8eSValentin Clement           rewriter.setInsertionPoint(embox);
221fe252f8eSValentin Clement           if (embox.getHost()) {
222fe252f8eSValentin Clement             // Create the thunk.
223fe252f8eSValentin Clement             auto module = embox->getParentOfType<mlir::ModuleOp>();
224906784a3SJean Perier             fir::KindMapping kindMap = getKindMapping(module);
225906784a3SJean Perier             FirOpBuilder builder(rewriter, kindMap);
226fe252f8eSValentin Clement             auto loc = embox.getLoc();
227fe252f8eSValentin Clement             mlir::Type i8Ty = builder.getI8Type();
228fe252f8eSValentin Clement             mlir::Type i8Ptr = builder.getRefType(i8Ty);
229fe252f8eSValentin Clement             mlir::Type buffTy = SequenceType::get({32}, i8Ty);
230fe252f8eSValentin Clement             auto buffer = builder.create<AllocaOp>(loc, buffTy);
231fe252f8eSValentin Clement             mlir::Value closure =
232fe252f8eSValentin Clement                 builder.createConvert(loc, i8Ptr, embox.getHost());
233fe252f8eSValentin Clement             mlir::Value tramp = builder.createConvert(loc, i8Ptr, buffer);
234fe252f8eSValentin Clement             mlir::Value func =
235fe252f8eSValentin Clement                 builder.createConvert(loc, i8Ptr, embox.getFunc());
236fe252f8eSValentin Clement             builder.create<fir::CallOp>(
237fe252f8eSValentin Clement                 loc, factory::getLlvmInitTrampoline(builder),
238fe252f8eSValentin Clement                 llvm::ArrayRef<mlir::Value>{tramp, func, closure});
239fe252f8eSValentin Clement             auto adjustCall = builder.create<fir::CallOp>(
240fe252f8eSValentin Clement                 loc, factory::getLlvmAdjustTrampoline(builder),
241fe252f8eSValentin Clement                 llvm::ArrayRef<mlir::Value>{tramp});
242fe252f8eSValentin Clement             rewriter.replaceOpWithNewOp<ConvertOp>(embox, toTy,
243fe252f8eSValentin Clement                                                    adjustCall.getResult(0));
244fe252f8eSValentin Clement           } else {
245fe252f8eSValentin Clement             // Just forward the function as a pointer.
246fe252f8eSValentin Clement             rewriter.replaceOpWithNewOp<ConvertOp>(embox, toTy,
247fe252f8eSValentin Clement                                                    embox.getFunc());
248fe252f8eSValentin Clement           }
249fe252f8eSValentin Clement         } else if (auto mem = mlir::dyn_cast<AllocaOp>(op)) {
250fe252f8eSValentin Clement           auto ty = mem.getType();
251fe252f8eSValentin Clement           if (typeConverter.needsConversion(ty)) {
252fe252f8eSValentin Clement             rewriter.setInsertionPoint(mem);
253fe252f8eSValentin Clement             auto toTy = typeConverter.convertType(unwrapRefType(ty));
254fe252f8eSValentin Clement             bool isPinned = mem.getPinned();
255*c715e2ffSKazu Hirata             llvm::StringRef uniqName =
256*c715e2ffSKazu Hirata                 mem.getUniqName().value_or(llvm::StringRef());
257*c715e2ffSKazu Hirata             llvm::StringRef bindcName =
258*c715e2ffSKazu Hirata                 mem.getBindcName().value_or(llvm::StringRef());
259fe252f8eSValentin Clement             rewriter.replaceOpWithNewOp<AllocaOp>(
260fe252f8eSValentin Clement                 mem, toTy, uniqName, bindcName, isPinned, mem.getTypeparams(),
261fe252f8eSValentin Clement                 mem.getShape());
262fe252f8eSValentin Clement           }
263fe252f8eSValentin Clement         } else if (auto mem = mlir::dyn_cast<AllocMemOp>(op)) {
264fe252f8eSValentin Clement           auto ty = mem.getType();
265fe252f8eSValentin Clement           if (typeConverter.needsConversion(ty)) {
266fe252f8eSValentin Clement             rewriter.setInsertionPoint(mem);
267fe252f8eSValentin Clement             auto toTy = typeConverter.convertType(unwrapRefType(ty));
268*c715e2ffSKazu Hirata             llvm::StringRef uniqName =
269*c715e2ffSKazu Hirata                 mem.getUniqName().value_or(llvm::StringRef());
270*c715e2ffSKazu Hirata             llvm::StringRef bindcName =
271*c715e2ffSKazu Hirata                 mem.getBindcName().value_or(llvm::StringRef());
272fe252f8eSValentin Clement             rewriter.replaceOpWithNewOp<AllocMemOp>(
273fe252f8eSValentin Clement                 mem, toTy, uniqName, bindcName, mem.getTypeparams(),
274fe252f8eSValentin Clement                 mem.getShape());
275fe252f8eSValentin Clement           }
276fe252f8eSValentin Clement         } else if (auto coor = mlir::dyn_cast<CoordinateOp>(op)) {
277fe252f8eSValentin Clement           auto ty = coor.getType();
278fe252f8eSValentin Clement           mlir::Type baseTy = coor.getBaseType();
279fe252f8eSValentin Clement           if (typeConverter.needsConversion(ty) ||
280fe252f8eSValentin Clement               typeConverter.needsConversion(baseTy)) {
281fe252f8eSValentin Clement             rewriter.setInsertionPoint(coor);
282fe252f8eSValentin Clement             auto toTy = typeConverter.convertType(ty);
283fe252f8eSValentin Clement             auto toBaseTy = typeConverter.convertType(baseTy);
284fe252f8eSValentin Clement             rewriter.replaceOpWithNewOp<CoordinateOp>(coor, toTy, coor.getRef(),
285fe252f8eSValentin Clement                                                       coor.getCoor(), toBaseTy);
286fe252f8eSValentin Clement           }
287fe252f8eSValentin Clement         } else if (auto index = mlir::dyn_cast<FieldIndexOp>(op)) {
288fe252f8eSValentin Clement           auto ty = index.getType();
289fe252f8eSValentin Clement           mlir::Type onTy = index.getOnType();
290fe252f8eSValentin Clement           if (typeConverter.needsConversion(ty) ||
291fe252f8eSValentin Clement               typeConverter.needsConversion(onTy)) {
292fe252f8eSValentin Clement             rewriter.setInsertionPoint(index);
293fe252f8eSValentin Clement             auto toTy = typeConverter.convertType(ty);
294fe252f8eSValentin Clement             auto toOnTy = typeConverter.convertType(onTy);
295fe252f8eSValentin Clement             rewriter.replaceOpWithNewOp<FieldIndexOp>(
296fe252f8eSValentin Clement                 index, toTy, index.getFieldId(), toOnTy, index.getTypeparams());
297fe252f8eSValentin Clement           }
298fe252f8eSValentin Clement         } else if (auto index = mlir::dyn_cast<LenParamIndexOp>(op)) {
299fe252f8eSValentin Clement           auto ty = index.getType();
300fe252f8eSValentin Clement           mlir::Type onTy = index.getOnType();
301fe252f8eSValentin Clement           if (typeConverter.needsConversion(ty) ||
302fe252f8eSValentin Clement               typeConverter.needsConversion(onTy)) {
303fe252f8eSValentin Clement             rewriter.setInsertionPoint(index);
304fe252f8eSValentin Clement             auto toTy = typeConverter.convertType(ty);
305fe252f8eSValentin Clement             auto toOnTy = typeConverter.convertType(onTy);
306fe252f8eSValentin Clement             rewriter.replaceOpWithNewOp<LenParamIndexOp>(
307c67a8744SValentin Clement                 mem, toTy, index.getFieldId(), toOnTy, index.getTypeparams());
308fe252f8eSValentin Clement           }
309fe252f8eSValentin Clement         } else if (op->getDialect() == firDialect) {
310fe252f8eSValentin Clement           rewriter.startRootUpdate(op);
311fe252f8eSValentin Clement           for (auto i : llvm::enumerate(op->getResultTypes()))
312fe252f8eSValentin Clement             if (typeConverter.needsConversion(i.value())) {
313fe252f8eSValentin Clement               auto toTy = typeConverter.convertType(i.value());
314fe252f8eSValentin Clement               op->getResult(i.index()).setType(toTy);
315fe252f8eSValentin Clement             }
316fe252f8eSValentin Clement           rewriter.finalizeRootUpdate(op);
317fe252f8eSValentin Clement         }
318fe252f8eSValentin Clement       });
319fe252f8eSValentin Clement     }
320fe252f8eSValentin Clement     // TODO: any alternative implementation. Note: currently, the default code
321fe252f8eSValentin Clement     // gen will not be able to handle boxproc and will give an error.
322fe252f8eSValentin Clement   }
323fe252f8eSValentin Clement 
324fe252f8eSValentin Clement private:
325fe252f8eSValentin Clement   BoxedProcedureOptions options;
326fe252f8eSValentin Clement };
327fe252f8eSValentin Clement } // namespace
328fe252f8eSValentin Clement 
createBoxedProcedurePass()329fe252f8eSValentin Clement std::unique_ptr<mlir::Pass> fir::createBoxedProcedurePass() {
330fe252f8eSValentin Clement   return std::make_unique<BoxedProcedurePass>();
331fe252f8eSValentin Clement }
332fe252f8eSValentin Clement 
createBoxedProcedurePass(bool useThunks)333fe252f8eSValentin Clement std::unique_ptr<mlir::Pass> fir::createBoxedProcedurePass(bool useThunks) {
334fe252f8eSValentin Clement   return std::make_unique<BoxedProcedurePass>(useThunks);
335fe252f8eSValentin Clement }
336