1aab4263aSValentin Clement //===-- Runtime.cpp -------------------------------------------------------===//
2aab4263aSValentin Clement //
3aab4263aSValentin Clement // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4aab4263aSValentin Clement // See https://llvm.org/LICENSE.txt for license information.
5aab4263aSValentin Clement // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6aab4263aSValentin Clement //
7aab4263aSValentin Clement //===----------------------------------------------------------------------===//
8aab4263aSValentin Clement 
9aab4263aSValentin Clement #include "flang/Lower/Runtime.h"
10aab4263aSValentin Clement #include "flang/Lower/Bridge.h"
11d0b70a07SValentin Clement #include "flang/Lower/StatementContext.h"
12aab4263aSValentin Clement #include "flang/Optimizer/Builder/FIRBuilder.h"
13aab4263aSValentin Clement #include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
145b66cc10SValentin Clement #include "flang/Optimizer/Builder/Todo.h"
15*70ade047Svdonaldson #include "flang/Optimizer/Dialect/FIROpsSupport.h"
16aab4263aSValentin Clement #include "flang/Parser/parse-tree.h"
17a16eddb2SValentin Clement #include "flang/Runtime/misc-intrinsic.h"
1872276bdaSValentin Clement #include "flang/Runtime/pointer.h"
19a1918fdfSValentin Clement #include "flang/Runtime/random.h"
20aab4263aSValentin Clement #include "flang/Runtime/stop.h"
219daf5765SValentin Clement #include "flang/Runtime/time-intrinsic.h"
22aab4263aSValentin Clement #include "flang/Semantics/tools.h"
23aab4263aSValentin Clement #include "llvm/Support/Debug.h"
24aab4263aSValentin Clement 
25aab4263aSValentin Clement #define DEBUG_TYPE "flang-lower-runtime"
26aab4263aSValentin Clement 
27aab4263aSValentin Clement using namespace Fortran::runtime;
28aab4263aSValentin Clement 
29aab4263aSValentin Clement /// Runtime calls that do not return to the caller indicate this condition by
30aab4263aSValentin Clement /// terminating the current basic block with an unreachable op.
genUnreachable(fir::FirOpBuilder & builder,mlir::Location loc)31aab4263aSValentin Clement static void genUnreachable(fir::FirOpBuilder &builder, mlir::Location loc) {
32aab4263aSValentin Clement   builder.create<fir::UnreachableOp>(loc);
33aab4263aSValentin Clement   mlir::Block *newBlock =
34aab4263aSValentin Clement       builder.getBlock()->splitBlock(builder.getInsertionPoint());
35aab4263aSValentin Clement   builder.setInsertionPointToStart(newBlock);
36aab4263aSValentin Clement }
37aab4263aSValentin Clement 
38aab4263aSValentin Clement //===----------------------------------------------------------------------===//
39aab4263aSValentin Clement // Misc. Fortran statements that lower to runtime calls
40aab4263aSValentin Clement //===----------------------------------------------------------------------===//
41aab4263aSValentin Clement 
genStopStatement(Fortran::lower::AbstractConverter & converter,const Fortran::parser::StopStmt & stmt)42aab4263aSValentin Clement void Fortran::lower::genStopStatement(
43aab4263aSValentin Clement     Fortran::lower::AbstractConverter &converter,
44aab4263aSValentin Clement     const Fortran::parser::StopStmt &stmt) {
45aab4263aSValentin Clement   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
46aab4263aSValentin Clement   mlir::Location loc = converter.getCurrentLocation();
47d0b70a07SValentin Clement   Fortran::lower::StatementContext stmtCtx;
48aab4263aSValentin Clement   llvm::SmallVector<mlir::Value> operands;
4958ceae95SRiver Riddle   mlir::func::FuncOp callee;
50aab4263aSValentin Clement   mlir::FunctionType calleeType;
51aab4263aSValentin Clement   // First operand is stop code (zero if absent)
52ca53e049SValentin Clement   if (const auto &code =
53ca53e049SValentin Clement           std::get<std::optional<Fortran::parser::StopCode>>(stmt.t)) {
54d0b70a07SValentin Clement     auto expr =
55d0b70a07SValentin Clement         converter.genExprValue(*Fortran::semantics::GetExpr(*code), stmtCtx);
56ca53e049SValentin Clement     LLVM_DEBUG(llvm::dbgs() << "stop expression: "; expr.dump();
57ca53e049SValentin Clement                llvm::dbgs() << '\n');
58ca53e049SValentin Clement     expr.match(
59ca53e049SValentin Clement         [&](const fir::CharBoxValue &x) {
60a8d48fe0SValentin Clement           callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatementText)>(
61a8d48fe0SValentin Clement               loc, builder);
624a3460a7SRiver Riddle           calleeType = callee.getFunctionType();
63a8d48fe0SValentin Clement           // Creates a pair of operands for the CHARACTER and its LEN.
64a8d48fe0SValentin Clement           operands.push_back(
65a8d48fe0SValentin Clement               builder.createConvert(loc, calleeType.getInput(0), x.getAddr()));
66a8d48fe0SValentin Clement           operands.push_back(
67a8d48fe0SValentin Clement               builder.createConvert(loc, calleeType.getInput(1), x.getLen()));
68ca53e049SValentin Clement         },
69ca53e049SValentin Clement         [&](fir::UnboxedValue x) {
70ca53e049SValentin Clement           callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatement)>(
71ca53e049SValentin Clement               loc, builder);
724a3460a7SRiver Riddle           calleeType = callee.getFunctionType();
73ca53e049SValentin Clement           mlir::Value cast =
74ca53e049SValentin Clement               builder.createConvert(loc, calleeType.getInput(0), x);
75ca53e049SValentin Clement           operands.push_back(cast);
76ca53e049SValentin Clement         },
77ca53e049SValentin Clement         [&](auto) {
78ca53e049SValentin Clement           mlir::emitError(loc, "unhandled expression in STOP");
79ca53e049SValentin Clement           std::exit(1);
80ca53e049SValentin Clement         });
81aab4263aSValentin Clement   } else {
82aab4263aSValentin Clement     callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatement)>(loc, builder);
834a3460a7SRiver Riddle     calleeType = callee.getFunctionType();
84aab4263aSValentin Clement     operands.push_back(
85aab4263aSValentin Clement         builder.createIntegerConstant(loc, calleeType.getInput(0), 0));
86aab4263aSValentin Clement   }
87aab4263aSValentin Clement 
88aab4263aSValentin Clement   // Second operand indicates ERROR STOP
89aab4263aSValentin Clement   bool isError = std::get<Fortran::parser::StopStmt::Kind>(stmt.t) ==
90aab4263aSValentin Clement                  Fortran::parser::StopStmt::Kind::ErrorStop;
91aab4263aSValentin Clement   operands.push_back(builder.createIntegerConstant(
92aab4263aSValentin Clement       loc, calleeType.getInput(operands.size()), isError));
93aab4263aSValentin Clement 
94aab4263aSValentin Clement   // Third operand indicates QUIET (default to false).
95cc306740SValentin Clement   if (const auto &quiet =
96cc306740SValentin Clement           std::get<std::optional<Fortran::parser::ScalarLogicalExpr>>(stmt.t)) {
97cc306740SValentin Clement     const SomeExpr *expr = Fortran::semantics::GetExpr(*quiet);
98cc306740SValentin Clement     assert(expr && "failed getting typed expression");
99d0b70a07SValentin Clement     mlir::Value q = fir::getBase(converter.genExprValue(*expr, stmtCtx));
100cc306740SValentin Clement     operands.push_back(
101cc306740SValentin Clement         builder.createConvert(loc, calleeType.getInput(operands.size()), q));
102aab4263aSValentin Clement   } else {
103aab4263aSValentin Clement     operands.push_back(builder.createIntegerConstant(
104aab4263aSValentin Clement         loc, calleeType.getInput(operands.size()), 0));
105aab4263aSValentin Clement   }
106aab4263aSValentin Clement 
107aab4263aSValentin Clement   builder.create<fir::CallOp>(loc, callee, operands);
108aab4263aSValentin Clement   genUnreachable(builder, loc);
109aab4263aSValentin Clement }
110db01b123SValentin Clement 
genFailImageStatement(Fortran::lower::AbstractConverter & converter)111534b2283SValentin Clement void Fortran::lower::genFailImageStatement(
112534b2283SValentin Clement     Fortran::lower::AbstractConverter &converter) {
113534b2283SValentin Clement   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
114534b2283SValentin Clement   mlir::Location loc = converter.getCurrentLocation();
11558ceae95SRiver Riddle   mlir::func::FuncOp callee =
116534b2283SValentin Clement       fir::runtime::getRuntimeFunc<mkRTKey(FailImageStatement)>(loc, builder);
117534b2283SValentin Clement   builder.create<fir::CallOp>(loc, callee, llvm::None);
118534b2283SValentin Clement   genUnreachable(builder, loc);
119534b2283SValentin Clement }
120534b2283SValentin Clement 
genEventPostStatement(Fortran::lower::AbstractConverter & converter,const Fortran::parser::EventPostStmt &)121534b2283SValentin Clement void Fortran::lower::genEventPostStatement(
122534b2283SValentin Clement     Fortran::lower::AbstractConverter &converter,
123534b2283SValentin Clement     const Fortran::parser::EventPostStmt &) {
124534b2283SValentin Clement   TODO(converter.getCurrentLocation(), "EVENT POST runtime");
125534b2283SValentin Clement }
126534b2283SValentin Clement 
genEventWaitStatement(Fortran::lower::AbstractConverter & converter,const Fortran::parser::EventWaitStmt &)127534b2283SValentin Clement void Fortran::lower::genEventWaitStatement(
128534b2283SValentin Clement     Fortran::lower::AbstractConverter &converter,
129534b2283SValentin Clement     const Fortran::parser::EventWaitStmt &) {
130534b2283SValentin Clement   TODO(converter.getCurrentLocation(), "EVENT WAIT runtime");
131534b2283SValentin Clement }
132534b2283SValentin Clement 
genLockStatement(Fortran::lower::AbstractConverter & converter,const Fortran::parser::LockStmt &)133534b2283SValentin Clement void Fortran::lower::genLockStatement(
134534b2283SValentin Clement     Fortran::lower::AbstractConverter &converter,
135534b2283SValentin Clement     const Fortran::parser::LockStmt &) {
136534b2283SValentin Clement   TODO(converter.getCurrentLocation(), "LOCK runtime");
137534b2283SValentin Clement }
138534b2283SValentin Clement 
genUnlockStatement(Fortran::lower::AbstractConverter & converter,const Fortran::parser::UnlockStmt &)139534b2283SValentin Clement void Fortran::lower::genUnlockStatement(
140534b2283SValentin Clement     Fortran::lower::AbstractConverter &converter,
141534b2283SValentin Clement     const Fortran::parser::UnlockStmt &) {
142534b2283SValentin Clement   TODO(converter.getCurrentLocation(), "UNLOCK runtime");
143534b2283SValentin Clement }
144534b2283SValentin Clement 
genSyncAllStatement(Fortran::lower::AbstractConverter & converter,const Fortran::parser::SyncAllStmt &)145534b2283SValentin Clement void Fortran::lower::genSyncAllStatement(
146534b2283SValentin Clement     Fortran::lower::AbstractConverter &converter,
147534b2283SValentin Clement     const Fortran::parser::SyncAllStmt &) {
148534b2283SValentin Clement   TODO(converter.getCurrentLocation(), "SYNC ALL runtime");
149534b2283SValentin Clement }
150534b2283SValentin Clement 
genSyncImagesStatement(Fortran::lower::AbstractConverter & converter,const Fortran::parser::SyncImagesStmt &)151534b2283SValentin Clement void Fortran::lower::genSyncImagesStatement(
152534b2283SValentin Clement     Fortran::lower::AbstractConverter &converter,
153534b2283SValentin Clement     const Fortran::parser::SyncImagesStmt &) {
154534b2283SValentin Clement   TODO(converter.getCurrentLocation(), "SYNC IMAGES runtime");
155534b2283SValentin Clement }
156534b2283SValentin Clement 
genSyncMemoryStatement(Fortran::lower::AbstractConverter & converter,const Fortran::parser::SyncMemoryStmt &)157534b2283SValentin Clement void Fortran::lower::genSyncMemoryStatement(
158534b2283SValentin Clement     Fortran::lower::AbstractConverter &converter,
159534b2283SValentin Clement     const Fortran::parser::SyncMemoryStmt &) {
160534b2283SValentin Clement   TODO(converter.getCurrentLocation(), "SYNC MEMORY runtime");
161534b2283SValentin Clement }
162534b2283SValentin Clement 
genSyncTeamStatement(Fortran::lower::AbstractConverter & converter,const Fortran::parser::SyncTeamStmt &)163534b2283SValentin Clement void Fortran::lower::genSyncTeamStatement(
164534b2283SValentin Clement     Fortran::lower::AbstractConverter &converter,
165534b2283SValentin Clement     const Fortran::parser::SyncTeamStmt &) {
166534b2283SValentin Clement   TODO(converter.getCurrentLocation(), "SYNC TEAM runtime");
167534b2283SValentin Clement }
168534b2283SValentin Clement 
genPauseStatement(Fortran::lower::AbstractConverter & converter,const Fortran::parser::PauseStmt &)169db01b123SValentin Clement void Fortran::lower::genPauseStatement(
170db01b123SValentin Clement     Fortran::lower::AbstractConverter &converter,
171db01b123SValentin Clement     const Fortran::parser::PauseStmt &) {
172db01b123SValentin Clement   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
173db01b123SValentin Clement   mlir::Location loc = converter.getCurrentLocation();
17458ceae95SRiver Riddle   mlir::func::FuncOp callee =
175db01b123SValentin Clement       fir::runtime::getRuntimeFunc<mkRTKey(PauseStatement)>(loc, builder);
176db01b123SValentin Clement   builder.create<fir::CallOp>(loc, callee, llvm::None);
177db01b123SValentin Clement }
17872276bdaSValentin Clement 
genAssociated(fir::FirOpBuilder & builder,mlir::Location loc,mlir::Value pointer,mlir::Value target)17972276bdaSValentin Clement mlir::Value Fortran::lower::genAssociated(fir::FirOpBuilder &builder,
18072276bdaSValentin Clement                                           mlir::Location loc,
18172276bdaSValentin Clement                                           mlir::Value pointer,
18272276bdaSValentin Clement                                           mlir::Value target) {
18358ceae95SRiver Riddle   mlir::func::FuncOp func =
18472276bdaSValentin Clement       fir::runtime::getRuntimeFunc<mkRTKey(PointerIsAssociatedWith)>(loc,
18572276bdaSValentin Clement                                                                      builder);
18672276bdaSValentin Clement   llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
1874a3460a7SRiver Riddle       builder, loc, func.getFunctionType(), pointer, target);
18872276bdaSValentin Clement   return builder.create<fir::CallOp>(loc, func, args).getResult(0);
18972276bdaSValentin Clement }
190a1918fdfSValentin Clement 
genCpuTime(fir::FirOpBuilder & builder,mlir::Location loc)1919daf5765SValentin Clement mlir::Value Fortran::lower::genCpuTime(fir::FirOpBuilder &builder,
1929daf5765SValentin Clement                                        mlir::Location loc) {
19358ceae95SRiver Riddle   mlir::func::FuncOp func =
1949daf5765SValentin Clement       fir::runtime::getRuntimeFunc<mkRTKey(CpuTime)>(loc, builder);
1959daf5765SValentin Clement   return builder.create<fir::CallOp>(loc, func, llvm::None).getResult(0);
1969daf5765SValentin Clement }
1979daf5765SValentin Clement 
genDateAndTime(fir::FirOpBuilder & builder,mlir::Location loc,llvm::Optional<fir::CharBoxValue> date,llvm::Optional<fir::CharBoxValue> time,llvm::Optional<fir::CharBoxValue> zone,mlir::Value values)1989daf5765SValentin Clement void Fortran::lower::genDateAndTime(fir::FirOpBuilder &builder,
1999daf5765SValentin Clement                                     mlir::Location loc,
2009daf5765SValentin Clement                                     llvm::Optional<fir::CharBoxValue> date,
2019daf5765SValentin Clement                                     llvm::Optional<fir::CharBoxValue> time,
2029daf5765SValentin Clement                                     llvm::Optional<fir::CharBoxValue> zone,
2039daf5765SValentin Clement                                     mlir::Value values) {
20458ceae95SRiver Riddle   mlir::func::FuncOp callee =
2059daf5765SValentin Clement       fir::runtime::getRuntimeFunc<mkRTKey(DateAndTime)>(loc, builder);
2064a3460a7SRiver Riddle   mlir::FunctionType funcTy = callee.getFunctionType();
2079daf5765SValentin Clement   mlir::Type idxTy = builder.getIndexType();
2089daf5765SValentin Clement   mlir::Value zero;
2099daf5765SValentin Clement   auto splitArg = [&](llvm::Optional<fir::CharBoxValue> arg,
2109daf5765SValentin Clement                       mlir::Value &buffer, mlir::Value &len) {
2119daf5765SValentin Clement     if (arg) {
2129daf5765SValentin Clement       buffer = arg->getBuffer();
2139daf5765SValentin Clement       len = arg->getLen();
2149daf5765SValentin Clement     } else {
2159daf5765SValentin Clement       if (!zero)
2169daf5765SValentin Clement         zero = builder.createIntegerConstant(loc, idxTy, 0);
2179daf5765SValentin Clement       buffer = zero;
2189daf5765SValentin Clement       len = zero;
2199daf5765SValentin Clement     }
2209daf5765SValentin Clement   };
2219daf5765SValentin Clement   mlir::Value dateBuffer;
2229daf5765SValentin Clement   mlir::Value dateLen;
2239daf5765SValentin Clement   splitArg(date, dateBuffer, dateLen);
2249daf5765SValentin Clement   mlir::Value timeBuffer;
2259daf5765SValentin Clement   mlir::Value timeLen;
2269daf5765SValentin Clement   splitArg(time, timeBuffer, timeLen);
2279daf5765SValentin Clement   mlir::Value zoneBuffer;
2289daf5765SValentin Clement   mlir::Value zoneLen;
2299daf5765SValentin Clement   splitArg(zone, zoneBuffer, zoneLen);
2309daf5765SValentin Clement 
2319daf5765SValentin Clement   mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
2329daf5765SValentin Clement   mlir::Value sourceLine =
2339daf5765SValentin Clement       fir::factory::locationToLineNo(builder, loc, funcTy.getInput(7));
2349daf5765SValentin Clement 
2359daf5765SValentin Clement   llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
2369daf5765SValentin Clement       builder, loc, funcTy, dateBuffer, dateLen, timeBuffer, timeLen,
2379daf5765SValentin Clement       zoneBuffer, zoneLen, sourceFile, sourceLine, values);
2389daf5765SValentin Clement   builder.create<fir::CallOp>(loc, callee, args);
2399daf5765SValentin Clement }
2409daf5765SValentin Clement 
genRandomInit(fir::FirOpBuilder & builder,mlir::Location loc,mlir::Value repeatable,mlir::Value imageDistinct)241a1918fdfSValentin Clement void Fortran::lower::genRandomInit(fir::FirOpBuilder &builder,
242a1918fdfSValentin Clement                                    mlir::Location loc, mlir::Value repeatable,
243a1918fdfSValentin Clement                                    mlir::Value imageDistinct) {
24458ceae95SRiver Riddle   mlir::func::FuncOp func =
245a1918fdfSValentin Clement       fir::runtime::getRuntimeFunc<mkRTKey(RandomInit)>(loc, builder);
246a1918fdfSValentin Clement   llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
2474a3460a7SRiver Riddle       builder, loc, func.getFunctionType(), repeatable, imageDistinct);
248a1918fdfSValentin Clement   builder.create<fir::CallOp>(loc, func, args);
249a1918fdfSValentin Clement }
250a1918fdfSValentin Clement 
genRandomNumber(fir::FirOpBuilder & builder,mlir::Location loc,mlir::Value harvest)251a1918fdfSValentin Clement void Fortran::lower::genRandomNumber(fir::FirOpBuilder &builder,
252a1918fdfSValentin Clement                                      mlir::Location loc, mlir::Value harvest) {
25358ceae95SRiver Riddle   mlir::func::FuncOp func =
254a1918fdfSValentin Clement       fir::runtime::getRuntimeFunc<mkRTKey(RandomNumber)>(loc, builder);
2554a3460a7SRiver Riddle   mlir::FunctionType funcTy = func.getFunctionType();
256a1918fdfSValentin Clement   mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
257a1918fdfSValentin Clement   mlir::Value sourceLine =
258a1918fdfSValentin Clement       fir::factory::locationToLineNo(builder, loc, funcTy.getInput(2));
259a1918fdfSValentin Clement   llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
260a1918fdfSValentin Clement       builder, loc, funcTy, harvest, sourceFile, sourceLine);
261a1918fdfSValentin Clement   builder.create<fir::CallOp>(loc, func, args);
262a1918fdfSValentin Clement }
263a1918fdfSValentin Clement 
genRandomSeed(fir::FirOpBuilder & builder,mlir::Location loc,int argIndex,mlir::Value argBox)264a1918fdfSValentin Clement void Fortran::lower::genRandomSeed(fir::FirOpBuilder &builder,
265a1918fdfSValentin Clement                                    mlir::Location loc, int argIndex,
266a1918fdfSValentin Clement                                    mlir::Value argBox) {
26758ceae95SRiver Riddle   mlir::func::FuncOp func;
268a1918fdfSValentin Clement   // argIndex is the nth (0-origin) argument in declaration order,
269a1918fdfSValentin Clement   // or -1 if no argument is present.
270a1918fdfSValentin Clement   switch (argIndex) {
271a1918fdfSValentin Clement   case -1:
272a1918fdfSValentin Clement     func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedDefaultPut)>(loc,
273a1918fdfSValentin Clement                                                                        builder);
274a1918fdfSValentin Clement     builder.create<fir::CallOp>(loc, func);
275a1918fdfSValentin Clement     return;
276a1918fdfSValentin Clement   case 0:
277a1918fdfSValentin Clement     func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedSize)>(loc, builder);
278a1918fdfSValentin Clement     break;
279a1918fdfSValentin Clement   case 1:
280a1918fdfSValentin Clement     func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedPut)>(loc, builder);
281a1918fdfSValentin Clement     break;
282a1918fdfSValentin Clement   case 2:
283a1918fdfSValentin Clement     func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedGet)>(loc, builder);
284a1918fdfSValentin Clement     break;
285a1918fdfSValentin Clement   default:
286a1918fdfSValentin Clement     llvm::report_fatal_error("invalid RANDOM_SEED argument index");
287a1918fdfSValentin Clement   }
2884a3460a7SRiver Riddle   mlir::FunctionType funcTy = func.getFunctionType();
289a1918fdfSValentin Clement   mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
290a1918fdfSValentin Clement   mlir::Value sourceLine =
291a1918fdfSValentin Clement       fir::factory::locationToLineNo(builder, loc, funcTy.getInput(2));
292a1918fdfSValentin Clement   llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
293a1918fdfSValentin Clement       builder, loc, funcTy, argBox, sourceFile, sourceLine);
294a1918fdfSValentin Clement   builder.create<fir::CallOp>(loc, func, args);
295a1918fdfSValentin Clement }
296264d9662SValentin Clement 
297a16eddb2SValentin Clement /// generate runtime call to transfer intrinsic with no size argument
genTransfer(fir::FirOpBuilder & builder,mlir::Location loc,mlir::Value resultBox,mlir::Value sourceBox,mlir::Value moldBox)298a16eddb2SValentin Clement void Fortran::lower::genTransfer(fir::FirOpBuilder &builder, mlir::Location loc,
299a16eddb2SValentin Clement                                  mlir::Value resultBox, mlir::Value sourceBox,
300a16eddb2SValentin Clement                                  mlir::Value moldBox) {
301a16eddb2SValentin Clement 
30258ceae95SRiver Riddle   mlir::func::FuncOp func =
303a16eddb2SValentin Clement       fir::runtime::getRuntimeFunc<mkRTKey(Transfer)>(loc, builder);
3044a3460a7SRiver Riddle   mlir::FunctionType fTy = func.getFunctionType();
305a16eddb2SValentin Clement   mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
306a16eddb2SValentin Clement   mlir::Value sourceLine =
307a16eddb2SValentin Clement       fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
308a16eddb2SValentin Clement   llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
309a16eddb2SValentin Clement       builder, loc, fTy, resultBox, sourceBox, moldBox, sourceFile, sourceLine);
310a16eddb2SValentin Clement   builder.create<fir::CallOp>(loc, func, args);
311a16eddb2SValentin Clement }
312a16eddb2SValentin Clement 
313a16eddb2SValentin Clement /// generate runtime call to transfer intrinsic with size argument
genTransferSize(fir::FirOpBuilder & builder,mlir::Location loc,mlir::Value resultBox,mlir::Value sourceBox,mlir::Value moldBox,mlir::Value size)314a16eddb2SValentin Clement void Fortran::lower::genTransferSize(fir::FirOpBuilder &builder,
315a16eddb2SValentin Clement                                      mlir::Location loc, mlir::Value resultBox,
316a16eddb2SValentin Clement                                      mlir::Value sourceBox, mlir::Value moldBox,
317a16eddb2SValentin Clement                                      mlir::Value size) {
31858ceae95SRiver Riddle   mlir::func::FuncOp func =
319a16eddb2SValentin Clement       fir::runtime::getRuntimeFunc<mkRTKey(TransferSize)>(loc, builder);
3204a3460a7SRiver Riddle   mlir::FunctionType fTy = func.getFunctionType();
321a16eddb2SValentin Clement   mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
322a16eddb2SValentin Clement   mlir::Value sourceLine =
323a16eddb2SValentin Clement       fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
324a16eddb2SValentin Clement   llvm::SmallVector<mlir::Value> args =
325a16eddb2SValentin Clement       fir::runtime::createArguments(builder, loc, fTy, resultBox, sourceBox,
326a16eddb2SValentin Clement                                     moldBox, sourceFile, sourceLine, size);
327a16eddb2SValentin Clement   builder.create<fir::CallOp>(loc, func, args);
328a16eddb2SValentin Clement }
329a16eddb2SValentin Clement 
330264d9662SValentin Clement /// generate system_clock runtime call/s
331264d9662SValentin Clement /// all intrinsic arguments are optional and may appear here as mlir::Value{}
genSystemClock(fir::FirOpBuilder & builder,mlir::Location loc,mlir::Value count,mlir::Value rate,mlir::Value max)332264d9662SValentin Clement void Fortran::lower::genSystemClock(fir::FirOpBuilder &builder,
333264d9662SValentin Clement                                     mlir::Location loc, mlir::Value count,
334264d9662SValentin Clement                                     mlir::Value rate, mlir::Value max) {
33558ceae95SRiver Riddle   auto makeCall = [&](mlir::func::FuncOp func, mlir::Value arg) {
336*70ade047Svdonaldson     mlir::Type type = arg.getType();
337*70ade047Svdonaldson     fir::IfOp ifOp{};
338*70ade047Svdonaldson     const bool isOptionalArg =
339*70ade047Svdonaldson         fir::valueHasFirAttribute(arg, fir::getOptionalAttrName());
340*70ade047Svdonaldson     if (type.dyn_cast<fir::PointerType>() || type.dyn_cast<fir::HeapType>()) {
341*70ade047Svdonaldson       // Check for a disassociated pointer or an unallocated allocatable.
342*70ade047Svdonaldson       assert(!isOptionalArg && "invalid optional argument");
343*70ade047Svdonaldson       ifOp = builder.create<fir::IfOp>(loc, builder.genIsNotNullAddr(loc, arg),
344*70ade047Svdonaldson                                        /*withElseRegion=*/false);
345*70ade047Svdonaldson     } else if (isOptionalArg) {
346*70ade047Svdonaldson       ifOp = builder.create<fir::IfOp>(
347*70ade047Svdonaldson           loc, builder.create<fir::IsPresentOp>(loc, builder.getI1Type(), arg),
348*70ade047Svdonaldson           /*withElseRegion=*/false);
349*70ade047Svdonaldson     }
350*70ade047Svdonaldson     if (ifOp)
351*70ade047Svdonaldson       builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
3524a3460a7SRiver Riddle     mlir::Type kindTy = func.getFunctionType().getInput(0);
353264d9662SValentin Clement     int integerKind = 8;
354*70ade047Svdonaldson     if (auto intType = fir::unwrapRefType(type).dyn_cast<mlir::IntegerType>())
355264d9662SValentin Clement       integerKind = intType.getWidth() / 8;
356264d9662SValentin Clement     mlir::Value kind = builder.createIntegerConstant(loc, kindTy, integerKind);
357264d9662SValentin Clement     mlir::Value res =
358264d9662SValentin Clement         builder.create<fir::CallOp>(loc, func, mlir::ValueRange{kind})
359264d9662SValentin Clement             .getResult(0);
360264d9662SValentin Clement     mlir::Value castRes =
361*70ade047Svdonaldson         builder.createConvert(loc, fir::dyn_cast_ptrEleTy(type), res);
362264d9662SValentin Clement     builder.create<fir::StoreOp>(loc, castRes, arg);
363*70ade047Svdonaldson     if (ifOp)
364*70ade047Svdonaldson       builder.setInsertionPointAfter(ifOp);
365264d9662SValentin Clement   };
366264d9662SValentin Clement   using fir::runtime::getRuntimeFunc;
367264d9662SValentin Clement   if (count)
368264d9662SValentin Clement     makeCall(getRuntimeFunc<mkRTKey(SystemClockCount)>(loc, builder), count);
369264d9662SValentin Clement   if (rate)
370264d9662SValentin Clement     makeCall(getRuntimeFunc<mkRTKey(SystemClockCountRate)>(loc, builder), rate);
371264d9662SValentin Clement   if (max)
372264d9662SValentin Clement     makeCall(getRuntimeFunc<mkRTKey(SystemClockCountMax)>(loc, builder), max);
373264d9662SValentin Clement }
374