xref: /llvm-project/flang/lib/Optimizer/Builder/Runtime/Transformational.cpp (revision 12ba74e181bd6641b532e271f3bfabf53066b1c0)
1 //===-- Transformational.cpp ------------------------------------*- C++ -*-===//
2 // Generate transformational intrinsic runtime API calls.
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "flang/Optimizer/Builder/Runtime/Transformational.h"
11 #include "flang/Optimizer/Builder/BoxValue.h"
12 #include "flang/Optimizer/Builder/Character.h"
13 #include "flang/Optimizer/Builder/FIRBuilder.h"
14 #include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
15 #include "flang/Optimizer/Support/Utils.h"
16 #include "flang/Runtime/matmul-transpose.h"
17 #include "flang/Runtime/matmul.h"
18 #include "flang/Runtime/transformational.h"
19 #include "mlir/Dialect/Func/IR/FuncOps.h"
20 
21 using namespace Fortran::runtime;
22 
23 /// Placeholder for real*10 version of BesselJn intrinsic.
24 struct ForcedBesselJn_10 {
25   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(BesselJn_10));
26   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
27     return [](mlir::MLIRContext *ctx) {
28       auto ty = mlir::Float80Type::get(ctx);
29       auto boxTy =
30           fir::runtime::getModel<Fortran::runtime::Descriptor &>()(ctx);
31       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
32       auto intTy = mlir::IntegerType::get(ctx, 32);
33       return mlir::FunctionType::get(
34           ctx, {boxTy, intTy, intTy, ty, ty, ty, strTy, intTy}, {});
35     };
36   }
37 };
38 
39 /// Placeholder for real*16 version of BesselJn intrinsic.
40 struct ForcedBesselJn_16 {
41   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(BesselJn_16));
42   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
43     return [](mlir::MLIRContext *ctx) {
44       auto ty = mlir::Float128Type::get(ctx);
45       auto boxTy =
46           fir::runtime::getModel<Fortran::runtime::Descriptor &>()(ctx);
47       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
48       auto intTy = mlir::IntegerType::get(ctx, 32);
49       return mlir::FunctionType::get(
50           ctx, {boxTy, intTy, intTy, ty, ty, ty, strTy, intTy}, {});
51     };
52   }
53 };
54 
55 /// Placeholder for real*10 version of BesselJn intrinsic when `x == 0.0`.
56 struct ForcedBesselJnX0_10 {
57   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(BesselJnX0_10));
58   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
59     return [](mlir::MLIRContext *ctx) {
60       auto boxTy =
61           fir::runtime::getModel<Fortran::runtime::Descriptor &>()(ctx);
62       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
63       auto intTy = mlir::IntegerType::get(ctx, 32);
64       return mlir::FunctionType::get(ctx, {boxTy, intTy, intTy, strTy, intTy},
65                                      {});
66     };
67   }
68 };
69 
70 /// Placeholder for real*16 version of BesselJn intrinsic when `x == 0.0`.
71 struct ForcedBesselJnX0_16 {
72   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(BesselJnX0_16));
73   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
74     return [](mlir::MLIRContext *ctx) {
75       auto boxTy =
76           fir::runtime::getModel<Fortran::runtime::Descriptor &>()(ctx);
77       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
78       auto intTy = mlir::IntegerType::get(ctx, 32);
79       return mlir::FunctionType::get(ctx, {boxTy, intTy, intTy, strTy, intTy},
80                                      {});
81     };
82   }
83 };
84 
85 /// Placeholder for real*10 version of BesselYn intrinsic.
86 struct ForcedBesselYn_10 {
87   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(BesselYn_10));
88   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
89     return [](mlir::MLIRContext *ctx) {
90       auto ty = mlir::Float80Type::get(ctx);
91       auto boxTy =
92           fir::runtime::getModel<Fortran::runtime::Descriptor &>()(ctx);
93       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
94       auto intTy = mlir::IntegerType::get(ctx, 32);
95       return mlir::FunctionType::get(
96           ctx, {boxTy, intTy, intTy, ty, ty, ty, strTy, intTy}, {});
97     };
98   }
99 };
100 
101 /// Placeholder for real*16 version of BesselYn intrinsic.
102 struct ForcedBesselYn_16 {
103   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(BesselYn_16));
104   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
105     return [](mlir::MLIRContext *ctx) {
106       auto ty = mlir::Float128Type::get(ctx);
107       auto boxTy =
108           fir::runtime::getModel<Fortran::runtime::Descriptor &>()(ctx);
109       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
110       auto intTy = mlir::IntegerType::get(ctx, 32);
111       return mlir::FunctionType::get(
112           ctx, {boxTy, intTy, intTy, ty, ty, ty, strTy, intTy}, {});
113     };
114   }
115 };
116 
117 /// Placeholder for real*10 version of BesselYn intrinsic when `x == 0.0`.
118 struct ForcedBesselYnX0_10 {
119   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(BesselYnX0_10));
120   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
121     return [](mlir::MLIRContext *ctx) {
122       auto boxTy =
123           fir::runtime::getModel<Fortran::runtime::Descriptor &>()(ctx);
124       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
125       auto intTy = mlir::IntegerType::get(ctx, 32);
126       return mlir::FunctionType::get(ctx, {boxTy, intTy, intTy, strTy, intTy},
127                                      {});
128     };
129   }
130 };
131 
132 /// Placeholder for real*16 version of BesselYn intrinsic when `x == 0.0`.
133 struct ForcedBesselYnX0_16 {
134   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(BesselYnX0_16));
135   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
136     return [](mlir::MLIRContext *ctx) {
137       auto boxTy =
138           fir::runtime::getModel<Fortran::runtime::Descriptor &>()(ctx);
139       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
140       auto intTy = mlir::IntegerType::get(ctx, 32);
141       return mlir::FunctionType::get(ctx, {boxTy, intTy, intTy, strTy, intTy},
142                                      {});
143     };
144   }
145 };
146 
147 /// Generate call to `BesselJn` intrinsic.
148 void fir::runtime::genBesselJn(fir::FirOpBuilder &builder, mlir::Location loc,
149                                mlir::Value resultBox, mlir::Value n1,
150                                mlir::Value n2, mlir::Value x, mlir::Value bn2,
151                                mlir::Value bn2_1) {
152   mlir::func::FuncOp func;
153   auto xTy = x.getType();
154 
155   if (xTy.isF32())
156     func = fir::runtime::getRuntimeFunc<mkRTKey(BesselJn_4)>(loc, builder);
157   else if (xTy.isF64())
158     func = fir::runtime::getRuntimeFunc<mkRTKey(BesselJn_8)>(loc, builder);
159   else if (xTy.isF80())
160     func = fir::runtime::getRuntimeFunc<ForcedBesselJn_10>(loc, builder);
161   else if (xTy.isF128())
162     func = fir::runtime::getRuntimeFunc<ForcedBesselJn_16>(loc, builder);
163   else
164     fir::intrinsicTypeTODO(builder, xTy, loc, "BESSEL_JN");
165 
166   auto fTy = func.getFunctionType();
167   auto sourceFile = fir::factory::locationToFilename(builder, loc);
168   auto sourceLine =
169       fir::factory::locationToLineNo(builder, loc, fTy.getInput(7));
170   auto args =
171       fir::runtime::createArguments(builder, loc, fTy, resultBox, n1, n2, x,
172                                     bn2, bn2_1, sourceFile, sourceLine);
173   builder.create<fir::CallOp>(loc, func, args);
174 }
175 
176 /// Generate call to `BesselJn` intrinsic. This is used when `x == 0.0`.
177 void fir::runtime::genBesselJnX0(fir::FirOpBuilder &builder, mlir::Location loc,
178                                  mlir::Type xTy, mlir::Value resultBox,
179                                  mlir::Value n1, mlir::Value n2) {
180   mlir::func::FuncOp func;
181 
182   if (xTy.isF32())
183     func = fir::runtime::getRuntimeFunc<mkRTKey(BesselJnX0_4)>(loc, builder);
184   else if (xTy.isF64())
185     func = fir::runtime::getRuntimeFunc<mkRTKey(BesselJnX0_8)>(loc, builder);
186   else if (xTy.isF80())
187     func = fir::runtime::getRuntimeFunc<ForcedBesselJnX0_10>(loc, builder);
188   else if (xTy.isF128())
189     func = fir::runtime::getRuntimeFunc<ForcedBesselJnX0_16>(loc, builder);
190   else
191     fir::intrinsicTypeTODO(builder, xTy, loc, "BESSEL_JN");
192 
193   auto fTy = func.getFunctionType();
194   auto sourceFile = fir::factory::locationToFilename(builder, loc);
195   auto sourceLine =
196       fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
197   auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, n1,
198                                             n2, sourceFile, sourceLine);
199   builder.create<fir::CallOp>(loc, func, args);
200 }
201 
202 /// Generate call to `BesselYn` intrinsic.
203 void fir::runtime::genBesselYn(fir::FirOpBuilder &builder, mlir::Location loc,
204                                mlir::Value resultBox, mlir::Value n1,
205                                mlir::Value n2, mlir::Value x, mlir::Value bn1,
206                                mlir::Value bn1_1) {
207   mlir::func::FuncOp func;
208   auto xTy = x.getType();
209 
210   if (xTy.isF32())
211     func = fir::runtime::getRuntimeFunc<mkRTKey(BesselYn_4)>(loc, builder);
212   else if (xTy.isF64())
213     func = fir::runtime::getRuntimeFunc<mkRTKey(BesselYn_8)>(loc, builder);
214   else if (xTy.isF80())
215     func = fir::runtime::getRuntimeFunc<ForcedBesselYn_10>(loc, builder);
216   else if (xTy.isF128())
217     func = fir::runtime::getRuntimeFunc<ForcedBesselYn_16>(loc, builder);
218   else
219     fir::intrinsicTypeTODO(builder, xTy, loc, "BESSEL_YN");
220 
221   auto fTy = func.getFunctionType();
222   auto sourceFile = fir::factory::locationToFilename(builder, loc);
223   auto sourceLine =
224       fir::factory::locationToLineNo(builder, loc, fTy.getInput(7));
225   auto args =
226       fir::runtime::createArguments(builder, loc, fTy, resultBox, n1, n2, x,
227                                     bn1, bn1_1, sourceFile, sourceLine);
228   builder.create<fir::CallOp>(loc, func, args);
229 }
230 
231 /// Generate call to `BesselYn` intrinsic. This is used when `x == 0.0`.
232 void fir::runtime::genBesselYnX0(fir::FirOpBuilder &builder, mlir::Location loc,
233                                  mlir::Type xTy, mlir::Value resultBox,
234                                  mlir::Value n1, mlir::Value n2) {
235   mlir::func::FuncOp func;
236 
237   if (xTy.isF32())
238     func = fir::runtime::getRuntimeFunc<mkRTKey(BesselYnX0_4)>(loc, builder);
239   else if (xTy.isF64())
240     func = fir::runtime::getRuntimeFunc<mkRTKey(BesselYnX0_8)>(loc, builder);
241   else if (xTy.isF80())
242     func = fir::runtime::getRuntimeFunc<ForcedBesselYnX0_10>(loc, builder);
243   else if (xTy.isF128())
244     func = fir::runtime::getRuntimeFunc<ForcedBesselYnX0_16>(loc, builder);
245   else
246     fir::intrinsicTypeTODO(builder, xTy, loc, "BESSEL_YN");
247 
248   auto fTy = func.getFunctionType();
249   auto sourceFile = fir::factory::locationToFilename(builder, loc);
250   auto sourceLine =
251       fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
252   auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, n1,
253                                             n2, sourceFile, sourceLine);
254   builder.create<fir::CallOp>(loc, func, args);
255 }
256 
257 /// Generate call to Cshift intrinsic
258 void fir::runtime::genCshift(fir::FirOpBuilder &builder, mlir::Location loc,
259                              mlir::Value resultBox, mlir::Value arrayBox,
260                              mlir::Value shiftBox, mlir::Value dimBox) {
261   auto cshiftFunc = fir::runtime::getRuntimeFunc<mkRTKey(Cshift)>(loc, builder);
262   auto fTy = cshiftFunc.getFunctionType();
263   auto sourceFile = fir::factory::locationToFilename(builder, loc);
264   auto sourceLine =
265       fir::factory::locationToLineNo(builder, loc, fTy.getInput(5));
266   auto args =
267       fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox,
268                                     shiftBox, dimBox, sourceFile, sourceLine);
269   builder.create<fir::CallOp>(loc, cshiftFunc, args);
270 }
271 
272 /// Generate call to the vector version of the Cshift intrinsic
273 void fir::runtime::genCshiftVector(fir::FirOpBuilder &builder,
274                                    mlir::Location loc, mlir::Value resultBox,
275                                    mlir::Value arrayBox, mlir::Value shiftBox) {
276   auto cshiftFunc =
277       fir::runtime::getRuntimeFunc<mkRTKey(CshiftVector)>(loc, builder);
278   auto fTy = cshiftFunc.getFunctionType();
279 
280   auto sourceFile = fir::factory::locationToFilename(builder, loc);
281   auto sourceLine =
282       fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
283   auto args = fir::runtime::createArguments(
284       builder, loc, fTy, resultBox, arrayBox, shiftBox, sourceFile, sourceLine);
285   builder.create<fir::CallOp>(loc, cshiftFunc, args);
286 }
287 
288 /// Generate call to Eoshift intrinsic
289 void fir::runtime::genEoshift(fir::FirOpBuilder &builder, mlir::Location loc,
290                               mlir::Value resultBox, mlir::Value arrayBox,
291                               mlir::Value shiftBox, mlir::Value boundBox,
292                               mlir::Value dimBox) {
293   auto eoshiftFunc =
294       fir::runtime::getRuntimeFunc<mkRTKey(Eoshift)>(loc, builder);
295   auto fTy = eoshiftFunc.getFunctionType();
296   auto sourceFile = fir::factory::locationToFilename(builder, loc);
297   auto sourceLine =
298       fir::factory::locationToLineNo(builder, loc, fTy.getInput(6));
299   auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox,
300                                             arrayBox, shiftBox, boundBox,
301                                             dimBox, sourceFile, sourceLine);
302   builder.create<fir::CallOp>(loc, eoshiftFunc, args);
303 }
304 
305 /// Generate call to the vector version of the Eoshift intrinsic
306 void fir::runtime::genEoshiftVector(fir::FirOpBuilder &builder,
307                                     mlir::Location loc, mlir::Value resultBox,
308                                     mlir::Value arrayBox, mlir::Value shiftBox,
309                                     mlir::Value boundBox) {
310   auto eoshiftFunc =
311       fir::runtime::getRuntimeFunc<mkRTKey(EoshiftVector)>(loc, builder);
312   auto fTy = eoshiftFunc.getFunctionType();
313 
314   auto sourceFile = fir::factory::locationToFilename(builder, loc);
315   auto sourceLine =
316       fir::factory::locationToLineNo(builder, loc, fTy.getInput(5));
317 
318   auto args =
319       fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox,
320                                     shiftBox, boundBox, sourceFile, sourceLine);
321   builder.create<fir::CallOp>(loc, eoshiftFunc, args);
322 }
323 
324 /// Define ForcedMatmul<ACAT><AKIND><BCAT><BKIND> models.
325 struct ForcedMatmulTypeModel {
326   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
327     return [](mlir::MLIRContext *ctx) {
328       auto boxRefTy =
329           fir::runtime::getModel<Fortran::runtime::Descriptor &>()(ctx);
330       auto boxTy =
331           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
332       auto strTy = fir::runtime::getModel<const char *>()(ctx);
333       auto intTy = fir::runtime::getModel<int>()(ctx);
334       return mlir::FunctionType::get(
335           ctx, {boxRefTy, boxTy, boxTy, strTy, intTy}, {});
336     };
337   }
338 };
339 
340 #define MATMUL_INSTANCE(ACAT, AKIND, BCAT, BKIND)                              \
341   struct ForcedMatmul##ACAT##AKIND##BCAT##BKIND                                \
342       : public ForcedMatmulTypeModel {                                         \
343     static constexpr const char *name =                                        \
344         ExpandAndQuoteKey(RTNAME(Matmul##ACAT##AKIND##BCAT##BKIND));           \
345   };
346 
347 #define MATMUL_DIRECT_INSTANCE(ACAT, AKIND, BCAT, BKIND)
348 #define MATMUL_FORCE_ALL_TYPES 1
349 
350 #include "flang/Runtime/matmul-instances.inc"
351 
352 /// Generate call to Matmul intrinsic runtime routine.
353 void fir::runtime::genMatmul(fir::FirOpBuilder &builder, mlir::Location loc,
354                              mlir::Value resultBox, mlir::Value matrixABox,
355                              mlir::Value matrixBBox) {
356   mlir::func::FuncOp func;
357   auto boxATy = matrixABox.getType();
358   auto arrATy = fir::dyn_cast_ptrOrBoxEleTy(boxATy);
359   auto arrAEleTy = mlir::cast<fir::SequenceType>(arrATy).getElementType();
360   auto [aCat, aKind] = fir::mlirTypeToCategoryKind(loc, arrAEleTy);
361   auto boxBTy = matrixBBox.getType();
362   auto arrBTy = fir::dyn_cast_ptrOrBoxEleTy(boxBTy);
363   auto arrBEleTy = mlir::cast<fir::SequenceType>(arrBTy).getElementType();
364   auto [bCat, bKind] = fir::mlirTypeToCategoryKind(loc, arrBEleTy);
365 
366 // Unsigned is treated as Integer when both operands are unsigned/integer
367 #define MATMUL_INSTANCE(ACAT, AKIND, BCAT, BKIND)                              \
368   if (!func && aKind == AKIND && bKind == BKIND &&                             \
369       ((aCat == TypeCategory::ACAT && bCat == TypeCategory::BCAT) ||           \
370        ((aCat == TypeCategory::Integer || aCat == TypeCategory::Unsigned) &&   \
371         (bCat == TypeCategory::Integer || bCat == TypeCategory::Unsigned)))) { \
372     func =                                                                     \
373         fir::runtime::getRuntimeFunc<ForcedMatmul##ACAT##AKIND##BCAT##BKIND>(  \
374             loc, builder);                                                     \
375   }
376 
377 #define MATMUL_DIRECT_INSTANCE(ACAT, AKIND, BCAT, BKIND)
378 #define MATMUL_FORCE_ALL_TYPES 1
379 #include "flang/Runtime/matmul-instances.inc"
380 
381   if (!func) {
382     fir::intrinsicTypeTODO2(builder, arrAEleTy, arrBEleTy, loc, "MATMUL");
383   }
384   auto fTy = func.getFunctionType();
385   auto sourceFile = fir::factory::locationToFilename(builder, loc);
386   auto sourceLine =
387       fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
388   auto args =
389       fir::runtime::createArguments(builder, loc, fTy, resultBox, matrixABox,
390                                     matrixBBox, sourceFile, sourceLine);
391   builder.create<fir::CallOp>(loc, func, args);
392 }
393 
394 /// Define ForcedMatmulTranspose<ACAT><AKIND><BCAT><BKIND> models.
395 #define MATMUL_INSTANCE(ACAT, AKIND, BCAT, BKIND)                              \
396   struct ForcedMatmulTranspose##ACAT##AKIND##BCAT##BKIND                       \
397       : public ForcedMatmulTypeModel {                                         \
398     static constexpr const char *name =                                        \
399         ExpandAndQuoteKey(RTNAME(MatmulTranspose##ACAT##AKIND##BCAT##BKIND));  \
400   };
401 
402 #define MATMUL_DIRECT_INSTANCE(ACAT, AKIND, BCAT, BKIND)
403 #define MATMUL_FORCE_ALL_TYPES 1
404 
405 #include "flang/Runtime/matmul-instances.inc"
406 
407 void fir::runtime::genMatmulTranspose(fir::FirOpBuilder &builder,
408                                       mlir::Location loc, mlir::Value resultBox,
409                                       mlir::Value matrixABox,
410                                       mlir::Value matrixBBox) {
411   mlir::func::FuncOp func;
412   auto boxATy = matrixABox.getType();
413   auto arrATy = fir::dyn_cast_ptrOrBoxEleTy(boxATy);
414   auto arrAEleTy = mlir::cast<fir::SequenceType>(arrATy).getElementType();
415   auto [aCat, aKind] = fir::mlirTypeToCategoryKind(loc, arrAEleTy);
416   auto boxBTy = matrixBBox.getType();
417   auto arrBTy = fir::dyn_cast_ptrOrBoxEleTy(boxBTy);
418   auto arrBEleTy = mlir::cast<fir::SequenceType>(arrBTy).getElementType();
419   auto [bCat, bKind] = fir::mlirTypeToCategoryKind(loc, arrBEleTy);
420 
421 #define MATMUL_INSTANCE(ACAT, AKIND, BCAT, BKIND)                              \
422   if (!func && aCat == TypeCategory::ACAT && aKind == AKIND &&                 \
423       bCat == TypeCategory::BCAT && bKind == BKIND) {                          \
424     func = fir::runtime::getRuntimeFunc<                                       \
425         ForcedMatmulTranspose##ACAT##AKIND##BCAT##BKIND>(loc, builder);        \
426   }
427 
428 #define MATMUL_DIRECT_INSTANCE(ACAT, AKIND, BCAT, BKIND)
429 #define MATMUL_FORCE_ALL_TYPES 1
430 #include "flang/Runtime/matmul-instances.inc"
431 
432   if (!func) {
433     fir::intrinsicTypeTODO2(builder, arrAEleTy, arrBEleTy, loc,
434                             "MATMUL-TRANSPOSE");
435   }
436   auto fTy = func.getFunctionType();
437   auto sourceFile = fir::factory::locationToFilename(builder, loc);
438   auto sourceLine =
439       fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
440   auto args =
441       fir::runtime::createArguments(builder, loc, fTy, resultBox, matrixABox,
442                                     matrixBBox, sourceFile, sourceLine);
443   builder.create<fir::CallOp>(loc, func, args);
444 }
445 
446 /// Generate call to Pack intrinsic runtime routine.
447 void fir::runtime::genPack(fir::FirOpBuilder &builder, mlir::Location loc,
448                            mlir::Value resultBox, mlir::Value arrayBox,
449                            mlir::Value maskBox, mlir::Value vectorBox) {
450   auto packFunc = fir::runtime::getRuntimeFunc<mkRTKey(Pack)>(loc, builder);
451   auto fTy = packFunc.getFunctionType();
452   auto sourceFile = fir::factory::locationToFilename(builder, loc);
453   auto sourceLine =
454       fir::factory::locationToLineNo(builder, loc, fTy.getInput(5));
455   auto args =
456       fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox,
457                                     maskBox, vectorBox, sourceFile, sourceLine);
458   builder.create<fir::CallOp>(loc, packFunc, args);
459 }
460 
461 /// Generate call to Reshape intrinsic runtime routine.
462 void fir::runtime::genReshape(fir::FirOpBuilder &builder, mlir::Location loc,
463                               mlir::Value resultBox, mlir::Value sourceBox,
464                               mlir::Value shapeBox, mlir::Value padBox,
465                               mlir::Value orderBox) {
466   auto func = fir::runtime::getRuntimeFunc<mkRTKey(Reshape)>(loc, builder);
467   auto fTy = func.getFunctionType();
468   auto sourceFile = fir::factory::locationToFilename(builder, loc);
469   auto sourceLine =
470       fir::factory::locationToLineNo(builder, loc, fTy.getInput(6));
471   auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox,
472                                             sourceBox, shapeBox, padBox,
473                                             orderBox, sourceFile, sourceLine);
474   builder.create<fir::CallOp>(loc, func, args);
475 }
476 
477 /// Generate call to Spread intrinsic runtime routine.
478 void fir::runtime::genSpread(fir::FirOpBuilder &builder, mlir::Location loc,
479                              mlir::Value resultBox, mlir::Value sourceBox,
480                              mlir::Value dim, mlir::Value ncopies) {
481   auto func = fir::runtime::getRuntimeFunc<mkRTKey(Spread)>(loc, builder);
482   auto fTy = func.getFunctionType();
483   auto sourceFile = fir::factory::locationToFilename(builder, loc);
484   auto sourceLine =
485       fir::factory::locationToLineNo(builder, loc, fTy.getInput(5));
486   auto args =
487       fir::runtime::createArguments(builder, loc, fTy, resultBox, sourceBox,
488                                     dim, ncopies, sourceFile, sourceLine);
489   builder.create<fir::CallOp>(loc, func, args);
490 }
491 
492 /// Generate call to Transpose intrinsic runtime routine.
493 void fir::runtime::genTranspose(fir::FirOpBuilder &builder, mlir::Location loc,
494                                 mlir::Value resultBox, mlir::Value sourceBox) {
495   auto func = fir::runtime::getRuntimeFunc<mkRTKey(Transpose)>(loc, builder);
496   auto fTy = func.getFunctionType();
497   auto sourceFile = fir::factory::locationToFilename(builder, loc);
498   auto sourceLine =
499       fir::factory::locationToLineNo(builder, loc, fTy.getInput(3));
500   auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox,
501                                             sourceBox, sourceFile, sourceLine);
502   builder.create<fir::CallOp>(loc, func, args);
503 }
504 
505 /// Generate call to Unpack intrinsic runtime routine.
506 void fir::runtime::genUnpack(fir::FirOpBuilder &builder, mlir::Location loc,
507                              mlir::Value resultBox, mlir::Value vectorBox,
508                              mlir::Value maskBox, mlir::Value fieldBox) {
509   auto unpackFunc = fir::runtime::getRuntimeFunc<mkRTKey(Unpack)>(loc, builder);
510   auto fTy = unpackFunc.getFunctionType();
511   auto sourceFile = fir::factory::locationToFilename(builder, loc);
512   auto sourceLine =
513       fir::factory::locationToLineNo(builder, loc, fTy.getInput(5));
514   auto args =
515       fir::runtime::createArguments(builder, loc, fTy, resultBox, vectorBox,
516                                     maskBox, fieldBox, sourceFile, sourceLine);
517   builder.create<fir::CallOp>(loc, unpackFunc, args);
518 }
519