xref: /llvm-project/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp (revision 5a34e6fdceac40da3312d96273e4b5d767f4a481)
118ed49d2STom Eccles //===-- Intrinsics.cpp ----------------------------------------------------===//
218ed49d2STom Eccles //
318ed49d2STom Eccles // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
418ed49d2STom Eccles // See https://llvm.org/LICENSE.txt for license information.
518ed49d2STom Eccles // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
618ed49d2STom Eccles //
718ed49d2STom Eccles //===----------------------------------------------------------------------===//
818ed49d2STom Eccles 
918ed49d2STom Eccles #include "flang/Optimizer/Builder/Runtime/Intrinsics.h"
1018ed49d2STom Eccles #include "flang/Optimizer/Builder/BoxValue.h"
1118ed49d2STom Eccles #include "flang/Optimizer/Builder/FIRBuilder.h"
1218ed49d2STom Eccles #include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
1318ed49d2STom Eccles #include "flang/Optimizer/Dialect/FIROpsSupport.h"
1418ed49d2STom Eccles #include "flang/Parser/parse-tree.h"
15b64c26f3STom Eccles #include "flang/Runtime/extensions.h"
1618ed49d2STom Eccles #include "flang/Runtime/misc-intrinsic.h"
1718ed49d2STom Eccles #include "flang/Runtime/pointer.h"
1818ed49d2STom Eccles #include "flang/Runtime/random.h"
1918ed49d2STom Eccles #include "flang/Runtime/stop.h"
2018ed49d2STom Eccles #include "flang/Runtime/time-intrinsic.h"
2118ed49d2STom Eccles #include "flang/Semantics/tools.h"
2218ed49d2STom Eccles #include "llvm/Support/Debug.h"
2318ed49d2STom Eccles #include <optional>
24afa52de9STom Eccles #include <signal.h>
2518ed49d2STom Eccles 
2618ed49d2STom Eccles #define DEBUG_TYPE "flang-lower-runtime"
2718ed49d2STom Eccles 
2818ed49d2STom Eccles using namespace Fortran::runtime;
2918ed49d2STom Eccles 
30e0738cc6SSlava Zakharin namespace {
31e0738cc6SSlava Zakharin /// Placeholder for real*16 version of RandomNumber Intrinsic
32e0738cc6SSlava Zakharin struct ForcedRandomNumberReal16 {
33e0738cc6SSlava Zakharin   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(RandomNumber16));
34e0738cc6SSlava Zakharin   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
35e0738cc6SSlava Zakharin     return [](mlir::MLIRContext *ctx) {
36e0738cc6SSlava Zakharin       auto boxTy =
37e0738cc6SSlava Zakharin           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
38e0738cc6SSlava Zakharin       auto strTy = fir::runtime::getModel<const char *>()(ctx);
39e0738cc6SSlava Zakharin       auto intTy = fir::runtime::getModel<int>()(ctx);
40e0738cc6SSlava Zakharin       ;
4112ba74e1SValentin Clement (バレンタイン クレメン)       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy}, {});
42e0738cc6SSlava Zakharin     };
43e0738cc6SSlava Zakharin   }
44e0738cc6SSlava Zakharin };
45e0738cc6SSlava Zakharin } // namespace
46e0738cc6SSlava Zakharin 
4718ed49d2STom Eccles mlir::Value fir::runtime::genAssociated(fir::FirOpBuilder &builder,
4818ed49d2STom Eccles                                         mlir::Location loc, mlir::Value pointer,
4918ed49d2STom Eccles                                         mlir::Value target) {
5018ed49d2STom Eccles   mlir::func::FuncOp func =
5118ed49d2STom Eccles       fir::runtime::getRuntimeFunc<mkRTKey(PointerIsAssociatedWith)>(loc,
5218ed49d2STom Eccles                                                                      builder);
5318ed49d2STom Eccles   llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
5418ed49d2STom Eccles       builder, loc, func.getFunctionType(), pointer, target);
5518ed49d2STom Eccles   return builder.create<fir::CallOp>(loc, func, args).getResult(0);
5618ed49d2STom Eccles }
5718ed49d2STom Eccles 
5818ed49d2STom Eccles mlir::Value fir::runtime::genCpuTime(fir::FirOpBuilder &builder,
5918ed49d2STom Eccles                                      mlir::Location loc) {
6018ed49d2STom Eccles   mlir::func::FuncOp func =
6118ed49d2STom Eccles       fir::runtime::getRuntimeFunc<mkRTKey(CpuTime)>(loc, builder);
6218ed49d2STom Eccles   return builder.create<fir::CallOp>(loc, func, std::nullopt).getResult(0);
6318ed49d2STom Eccles }
6418ed49d2STom Eccles 
6518ed49d2STom Eccles void fir::runtime::genDateAndTime(fir::FirOpBuilder &builder,
6618ed49d2STom Eccles                                   mlir::Location loc,
6718ed49d2STom Eccles                                   std::optional<fir::CharBoxValue> date,
6818ed49d2STom Eccles                                   std::optional<fir::CharBoxValue> time,
6918ed49d2STom Eccles                                   std::optional<fir::CharBoxValue> zone,
7018ed49d2STom Eccles                                   mlir::Value values) {
7118ed49d2STom Eccles   mlir::func::FuncOp callee =
7218ed49d2STom Eccles       fir::runtime::getRuntimeFunc<mkRTKey(DateAndTime)>(loc, builder);
7318ed49d2STom Eccles   mlir::FunctionType funcTy = callee.getFunctionType();
7418ed49d2STom Eccles   mlir::Type idxTy = builder.getIndexType();
7518ed49d2STom Eccles   mlir::Value zero;
7618ed49d2STom Eccles   auto splitArg = [&](std::optional<fir::CharBoxValue> arg, mlir::Value &buffer,
7718ed49d2STom Eccles                       mlir::Value &len) {
7818ed49d2STom Eccles     if (arg) {
7918ed49d2STom Eccles       buffer = arg->getBuffer();
8018ed49d2STom Eccles       len = arg->getLen();
8118ed49d2STom Eccles     } else {
8218ed49d2STom Eccles       if (!zero)
8318ed49d2STom Eccles         zero = builder.createIntegerConstant(loc, idxTy, 0);
8418ed49d2STom Eccles       buffer = zero;
8518ed49d2STom Eccles       len = zero;
8618ed49d2STom Eccles     }
8718ed49d2STom Eccles   };
8818ed49d2STom Eccles   mlir::Value dateBuffer;
8918ed49d2STom Eccles   mlir::Value dateLen;
9018ed49d2STom Eccles   splitArg(date, dateBuffer, dateLen);
9118ed49d2STom Eccles   mlir::Value timeBuffer;
9218ed49d2STom Eccles   mlir::Value timeLen;
9318ed49d2STom Eccles   splitArg(time, timeBuffer, timeLen);
9418ed49d2STom Eccles   mlir::Value zoneBuffer;
9518ed49d2STom Eccles   mlir::Value zoneLen;
9618ed49d2STom Eccles   splitArg(zone, zoneBuffer, zoneLen);
9718ed49d2STom Eccles 
9818ed49d2STom Eccles   mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
9918ed49d2STom Eccles   mlir::Value sourceLine =
10018ed49d2STom Eccles       fir::factory::locationToLineNo(builder, loc, funcTy.getInput(7));
10118ed49d2STom Eccles 
10218ed49d2STom Eccles   llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
10318ed49d2STom Eccles       builder, loc, funcTy, dateBuffer, dateLen, timeBuffer, timeLen,
10418ed49d2STom Eccles       zoneBuffer, zoneLen, sourceFile, sourceLine, values);
10518ed49d2STom Eccles   builder.create<fir::CallOp>(loc, callee, args);
10618ed49d2STom Eccles }
10718ed49d2STom Eccles 
108dc8d70acSjiajie zhang void fir::runtime::genEtime(fir::FirOpBuilder &builder, mlir::Location loc,
109dc8d70acSjiajie zhang                             mlir::Value values, mlir::Value time) {
110dc8d70acSjiajie zhang   auto runtimeFunc = fir::runtime::getRuntimeFunc<mkRTKey(Etime)>(loc, builder);
111dc8d70acSjiajie zhang   mlir::FunctionType runtimeFuncTy = runtimeFunc.getFunctionType();
112dc8d70acSjiajie zhang 
113dc8d70acSjiajie zhang   mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
114dc8d70acSjiajie zhang   mlir::Value sourceLine =
115dc8d70acSjiajie zhang       fir::factory::locationToLineNo(builder, loc, runtimeFuncTy.getInput(3));
116dc8d70acSjiajie zhang 
117dc8d70acSjiajie zhang   llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
118dc8d70acSjiajie zhang       builder, loc, runtimeFuncTy, values, time, sourceFile, sourceLine);
119dc8d70acSjiajie zhang   builder.create<fir::CallOp>(loc, runtimeFunc, args);
120dc8d70acSjiajie zhang }
121dc8d70acSjiajie zhang 
12278ccffc0SDavid Truby void fir::runtime::genFree(fir::FirOpBuilder &builder, mlir::Location loc,
12378ccffc0SDavid Truby                            mlir::Value ptr) {
12478ccffc0SDavid Truby   auto runtimeFunc = fir::runtime::getRuntimeFunc<mkRTKey(Free)>(loc, builder);
12578ccffc0SDavid Truby   mlir::Type intPtrTy = builder.getIntPtrType();
12678ccffc0SDavid Truby 
12778ccffc0SDavid Truby   builder.create<fir::CallOp>(loc, runtimeFunc,
12878ccffc0SDavid Truby                               builder.createConvert(loc, intPtrTy, ptr));
12978ccffc0SDavid Truby }
13078ccffc0SDavid Truby 
131856c38d5SDavid Truby mlir::Value fir::runtime::genGetGID(fir::FirOpBuilder &builder,
132856c38d5SDavid Truby                                     mlir::Location loc) {
133856c38d5SDavid Truby   auto runtimeFunc =
134856c38d5SDavid Truby       fir::runtime::getRuntimeFunc<mkRTKey(GetGID)>(loc, builder);
135856c38d5SDavid Truby 
136856c38d5SDavid Truby   return builder.create<fir::CallOp>(loc, runtimeFunc).getResult(0);
137856c38d5SDavid Truby }
138856c38d5SDavid Truby 
139856c38d5SDavid Truby mlir::Value fir::runtime::genGetUID(fir::FirOpBuilder &builder,
140856c38d5SDavid Truby                                     mlir::Location loc) {
141856c38d5SDavid Truby   auto runtimeFunc =
142856c38d5SDavid Truby       fir::runtime::getRuntimeFunc<mkRTKey(GetUID)>(loc, builder);
143856c38d5SDavid Truby 
144856c38d5SDavid Truby   return builder.create<fir::CallOp>(loc, runtimeFunc).getResult(0);
145856c38d5SDavid Truby }
146856c38d5SDavid Truby 
14778ccffc0SDavid Truby mlir::Value fir::runtime::genMalloc(fir::FirOpBuilder &builder,
14878ccffc0SDavid Truby                                     mlir::Location loc, mlir::Value size) {
14978ccffc0SDavid Truby   auto runtimeFunc =
15078ccffc0SDavid Truby       fir::runtime::getRuntimeFunc<mkRTKey(Malloc)>(loc, builder);
15178ccffc0SDavid Truby   auto argTy = runtimeFunc.getArgumentTypes()[0];
15278ccffc0SDavid Truby   return builder
15378ccffc0SDavid Truby       .create<fir::CallOp>(loc, runtimeFunc,
15478ccffc0SDavid Truby                            builder.createConvert(loc, argTy, size))
15578ccffc0SDavid Truby       .getResult(0);
15678ccffc0SDavid Truby }
15778ccffc0SDavid Truby 
15818ed49d2STom Eccles void fir::runtime::genRandomInit(fir::FirOpBuilder &builder, mlir::Location loc,
15918ed49d2STom Eccles                                  mlir::Value repeatable,
16018ed49d2STom Eccles                                  mlir::Value imageDistinct) {
16118ed49d2STom Eccles   mlir::func::FuncOp func =
16218ed49d2STom Eccles       fir::runtime::getRuntimeFunc<mkRTKey(RandomInit)>(loc, builder);
16318ed49d2STom Eccles   llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
16418ed49d2STom Eccles       builder, loc, func.getFunctionType(), repeatable, imageDistinct);
16518ed49d2STom Eccles   builder.create<fir::CallOp>(loc, func, args);
16618ed49d2STom Eccles }
16718ed49d2STom Eccles 
16818ed49d2STom Eccles void fir::runtime::genRandomNumber(fir::FirOpBuilder &builder,
16918ed49d2STom Eccles                                    mlir::Location loc, mlir::Value harvest) {
170e0738cc6SSlava Zakharin   mlir::func::FuncOp func;
171e0738cc6SSlava Zakharin   auto boxEleTy = fir::dyn_cast_ptrOrBoxEleTy(harvest.getType());
172e0738cc6SSlava Zakharin   auto eleTy = fir::unwrapSequenceType(boxEleTy);
173e0738cc6SSlava Zakharin   if (eleTy.isF128()) {
174e0738cc6SSlava Zakharin     func = fir::runtime::getRuntimeFunc<ForcedRandomNumberReal16>(loc, builder);
175e0738cc6SSlava Zakharin   } else {
176e0738cc6SSlava Zakharin     func = fir::runtime::getRuntimeFunc<mkRTKey(RandomNumber)>(loc, builder);
177e0738cc6SSlava Zakharin   }
178e0738cc6SSlava Zakharin 
17918ed49d2STom Eccles   mlir::FunctionType funcTy = func.getFunctionType();
18018ed49d2STom Eccles   mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
18118ed49d2STom Eccles   mlir::Value sourceLine =
18218ed49d2STom Eccles       fir::factory::locationToLineNo(builder, loc, funcTy.getInput(2));
18318ed49d2STom Eccles   llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
18418ed49d2STom Eccles       builder, loc, funcTy, harvest, sourceFile, sourceLine);
18518ed49d2STom Eccles   builder.create<fir::CallOp>(loc, func, args);
18618ed49d2STom Eccles }
18718ed49d2STom Eccles 
18818ed49d2STom Eccles void fir::runtime::genRandomSeed(fir::FirOpBuilder &builder, mlir::Location loc,
18918ed49d2STom Eccles                                  mlir::Value size, mlir::Value put,
19018ed49d2STom Eccles                                  mlir::Value get) {
19118ed49d2STom Eccles   bool sizeIsPresent =
19218ed49d2STom Eccles       !mlir::isa_and_nonnull<fir::AbsentOp>(size.getDefiningOp());
19318ed49d2STom Eccles   bool putIsPresent =
19418ed49d2STom Eccles       !mlir::isa_and_nonnull<fir::AbsentOp>(put.getDefiningOp());
19518ed49d2STom Eccles   bool getIsPresent =
19618ed49d2STom Eccles       !mlir::isa_and_nonnull<fir::AbsentOp>(get.getDefiningOp());
19718ed49d2STom Eccles   mlir::func::FuncOp func;
19818ed49d2STom Eccles   int staticArgCount = sizeIsPresent + putIsPresent + getIsPresent;
19918ed49d2STom Eccles   if (staticArgCount == 0) {
20018ed49d2STom Eccles     func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedDefaultPut)>(loc,
20118ed49d2STom Eccles                                                                        builder);
20218ed49d2STom Eccles     builder.create<fir::CallOp>(loc, func);
20318ed49d2STom Eccles     return;
20418ed49d2STom Eccles   }
20518ed49d2STom Eccles   mlir::FunctionType funcTy;
20618ed49d2STom Eccles   mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
20718ed49d2STom Eccles   mlir::Value sourceLine;
20818ed49d2STom Eccles   mlir::Value argBox;
20918ed49d2STom Eccles   llvm::SmallVector<mlir::Value> args;
21018ed49d2STom Eccles   if (staticArgCount > 1) {
21118ed49d2STom Eccles     func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeed)>(loc, builder);
21218ed49d2STom Eccles     funcTy = func.getFunctionType();
21318ed49d2STom Eccles     sourceLine =
21418ed49d2STom Eccles         fir::factory::locationToLineNo(builder, loc, funcTy.getInput(4));
21518ed49d2STom Eccles     args = fir::runtime::createArguments(builder, loc, funcTy, size, put, get,
21618ed49d2STom Eccles                                          sourceFile, sourceLine);
21718ed49d2STom Eccles     builder.create<fir::CallOp>(loc, func, args);
21818ed49d2STom Eccles     return;
21918ed49d2STom Eccles   }
22018ed49d2STom Eccles   if (sizeIsPresent) {
22118ed49d2STom Eccles     func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedSize)>(loc, builder);
22218ed49d2STom Eccles     argBox = size;
22318ed49d2STom Eccles   } else if (putIsPresent) {
22418ed49d2STom Eccles     func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedPut)>(loc, builder);
22518ed49d2STom Eccles     argBox = put;
22618ed49d2STom Eccles   } else {
22718ed49d2STom Eccles     func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedGet)>(loc, builder);
22818ed49d2STom Eccles     argBox = get;
22918ed49d2STom Eccles   }
23018ed49d2STom Eccles   funcTy = func.getFunctionType();
23118ed49d2STom Eccles   sourceLine = fir::factory::locationToLineNo(builder, loc, funcTy.getInput(2));
23218ed49d2STom Eccles   args = fir::runtime::createArguments(builder, loc, funcTy, argBox, sourceFile,
23318ed49d2STom Eccles                                        sourceLine);
23418ed49d2STom Eccles   builder.create<fir::CallOp>(loc, func, args);
23518ed49d2STom Eccles }
23618ed49d2STom Eccles 
237a5a29a26SMichael Klemm /// generate rename runtime call
238a5a29a26SMichael Klemm void fir::runtime::genRename(fir::FirOpBuilder &builder, mlir::Location loc,
239a5a29a26SMichael Klemm                              mlir::Value path1, mlir::Value path2,
240a5a29a26SMichael Klemm                              mlir::Value status) {
241a5a29a26SMichael Klemm   auto runtimeFunc =
242a5a29a26SMichael Klemm       fir::runtime::getRuntimeFunc<mkRTKey(Rename)>(loc, builder);
243a5a29a26SMichael Klemm   mlir::FunctionType runtimeFuncTy = runtimeFunc.getFunctionType();
244a5a29a26SMichael Klemm 
245a5a29a26SMichael Klemm   mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
246a5a29a26SMichael Klemm   mlir::Value sourceLine =
247a5a29a26SMichael Klemm       fir::factory::locationToLineNo(builder, loc, runtimeFuncTy.getInput(4));
248a5a29a26SMichael Klemm 
249a5a29a26SMichael Klemm   llvm::SmallVector<mlir::Value> args =
250a5a29a26SMichael Klemm       fir::runtime::createArguments(builder, loc, runtimeFuncTy, path1, path2,
251a5a29a26SMichael Klemm                                     status, sourceFile, sourceLine);
252a5a29a26SMichael Klemm   builder.create<fir::CallOp>(loc, runtimeFunc, args);
253a5a29a26SMichael Klemm }
254a5a29a26SMichael Klemm 
25518ed49d2STom Eccles /// generate runtime call to transfer intrinsic with no size argument
25618ed49d2STom Eccles void fir::runtime::genTransfer(fir::FirOpBuilder &builder, mlir::Location loc,
25718ed49d2STom Eccles                                mlir::Value resultBox, mlir::Value sourceBox,
25818ed49d2STom Eccles                                mlir::Value moldBox) {
25918ed49d2STom Eccles 
26018ed49d2STom Eccles   mlir::func::FuncOp func =
26118ed49d2STom Eccles       fir::runtime::getRuntimeFunc<mkRTKey(Transfer)>(loc, builder);
26218ed49d2STom Eccles   mlir::FunctionType fTy = func.getFunctionType();
26318ed49d2STom Eccles   mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
26418ed49d2STom Eccles   mlir::Value sourceLine =
26518ed49d2STom Eccles       fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
26618ed49d2STom Eccles   llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
26718ed49d2STom Eccles       builder, loc, fTy, resultBox, sourceBox, moldBox, sourceFile, sourceLine);
26818ed49d2STom Eccles   builder.create<fir::CallOp>(loc, func, args);
26918ed49d2STom Eccles }
27018ed49d2STom Eccles 
27118ed49d2STom Eccles /// generate runtime call to transfer intrinsic with size argument
27218ed49d2STom Eccles void fir::runtime::genTransferSize(fir::FirOpBuilder &builder,
27318ed49d2STom Eccles                                    mlir::Location loc, mlir::Value resultBox,
27418ed49d2STom Eccles                                    mlir::Value sourceBox, mlir::Value moldBox,
27518ed49d2STom Eccles                                    mlir::Value size) {
27618ed49d2STom Eccles   mlir::func::FuncOp func =
27718ed49d2STom Eccles       fir::runtime::getRuntimeFunc<mkRTKey(TransferSize)>(loc, builder);
27818ed49d2STom Eccles   mlir::FunctionType fTy = func.getFunctionType();
27918ed49d2STom Eccles   mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
28018ed49d2STom Eccles   mlir::Value sourceLine =
28118ed49d2STom Eccles       fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
28218ed49d2STom Eccles   llvm::SmallVector<mlir::Value> args =
28318ed49d2STom Eccles       fir::runtime::createArguments(builder, loc, fTy, resultBox, sourceBox,
28418ed49d2STom Eccles                                     moldBox, sourceFile, sourceLine, size);
28518ed49d2STom Eccles   builder.create<fir::CallOp>(loc, func, args);
28618ed49d2STom Eccles }
28718ed49d2STom Eccles 
28818ed49d2STom Eccles /// generate system_clock runtime call/s
28918ed49d2STom Eccles /// all intrinsic arguments are optional and may appear here as mlir::Value{}
29018ed49d2STom Eccles void fir::runtime::genSystemClock(fir::FirOpBuilder &builder,
29118ed49d2STom Eccles                                   mlir::Location loc, mlir::Value count,
29218ed49d2STom Eccles                                   mlir::Value rate, mlir::Value max) {
29318ed49d2STom Eccles   auto makeCall = [&](mlir::func::FuncOp func, mlir::Value arg) {
29418ed49d2STom Eccles     mlir::Type type = arg.getType();
29518ed49d2STom Eccles     fir::IfOp ifOp{};
29618ed49d2STom Eccles     const bool isOptionalArg =
29718ed49d2STom Eccles         fir::valueHasFirAttribute(arg, fir::getOptionalAttrName());
298fac349a1SChristian Sigg     if (mlir::dyn_cast<fir::PointerType>(type) ||
299fac349a1SChristian Sigg         mlir::dyn_cast<fir::HeapType>(type)) {
30018ed49d2STom Eccles       // Check for a disassociated pointer or an unallocated allocatable.
30118ed49d2STom Eccles       assert(!isOptionalArg && "invalid optional argument");
30218ed49d2STom Eccles       ifOp = builder.create<fir::IfOp>(loc, builder.genIsNotNullAddr(loc, arg),
30318ed49d2STom Eccles                                        /*withElseRegion=*/false);
30418ed49d2STom Eccles     } else if (isOptionalArg) {
30518ed49d2STom Eccles       ifOp = builder.create<fir::IfOp>(
30618ed49d2STom Eccles           loc, builder.create<fir::IsPresentOp>(loc, builder.getI1Type(), arg),
30718ed49d2STom Eccles           /*withElseRegion=*/false);
30818ed49d2STom Eccles     }
30918ed49d2STom Eccles     if (ifOp)
31018ed49d2STom Eccles       builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
31118ed49d2STom Eccles     mlir::Type kindTy = func.getFunctionType().getInput(0);
31218ed49d2STom Eccles     int integerKind = 8;
313fac349a1SChristian Sigg     if (auto intType =
314fac349a1SChristian Sigg             mlir::dyn_cast<mlir::IntegerType>(fir::unwrapRefType(type)))
31518ed49d2STom Eccles       integerKind = intType.getWidth() / 8;
31618ed49d2STom Eccles     mlir::Value kind = builder.createIntegerConstant(loc, kindTy, integerKind);
31718ed49d2STom Eccles     mlir::Value res =
31818ed49d2STom Eccles         builder.create<fir::CallOp>(loc, func, mlir::ValueRange{kind})
31918ed49d2STom Eccles             .getResult(0);
32018ed49d2STom Eccles     mlir::Value castRes =
32118ed49d2STom Eccles         builder.createConvert(loc, fir::dyn_cast_ptrEleTy(type), res);
32218ed49d2STom Eccles     builder.create<fir::StoreOp>(loc, castRes, arg);
32318ed49d2STom Eccles     if (ifOp)
32418ed49d2STom Eccles       builder.setInsertionPointAfter(ifOp);
32518ed49d2STom Eccles   };
32618ed49d2STom Eccles   using fir::runtime::getRuntimeFunc;
32718ed49d2STom Eccles   if (count)
32818ed49d2STom Eccles     makeCall(getRuntimeFunc<mkRTKey(SystemClockCount)>(loc, builder), count);
32918ed49d2STom Eccles   if (rate)
33018ed49d2STom Eccles     makeCall(getRuntimeFunc<mkRTKey(SystemClockCountRate)>(loc, builder), rate);
33118ed49d2STom Eccles   if (max)
33218ed49d2STom Eccles     makeCall(getRuntimeFunc<mkRTKey(SystemClockCountMax)>(loc, builder), max);
33318ed49d2STom Eccles }
334b64c26f3STom Eccles 
335afa52de9STom Eccles // CALL SIGNAL(NUMBER, HANDLER [, STATUS])
336afa52de9STom Eccles // The definition of the SIGNAL intrinsic allows HANDLER to be a function
337afa52de9STom Eccles // pointer or an integer. STATUS can be dynamically optional
338afa52de9STom Eccles void fir::runtime::genSignal(fir::FirOpBuilder &builder, mlir::Location loc,
339afa52de9STom Eccles                              mlir::Value number, mlir::Value handler,
340afa52de9STom Eccles                              mlir::Value status) {
341afa52de9STom Eccles   assert(mlir::isa<mlir::IntegerType>(number.getType()));
342afa52de9STom Eccles   mlir::Type int64 = builder.getIntegerType(64);
343afa52de9STom Eccles   number = builder.create<fir::ConvertOp>(loc, int64, number);
344afa52de9STom Eccles 
345afa52de9STom Eccles   mlir::Type handlerUnwrappedTy = fir::unwrapRefType(handler.getType());
346afa52de9STom Eccles   if (mlir::isa_and_nonnull<mlir::IntegerType>(handlerUnwrappedTy)) {
347afa52de9STom Eccles     // pass the integer as a function pointer like one would to signal(2)
348afa52de9STom Eccles     handler = builder.create<fir::LoadOp>(loc, handler);
349afa52de9STom Eccles     mlir::Type fnPtrTy = fir::LLVMPointerType::get(
350afa52de9STom Eccles         mlir::FunctionType::get(handler.getContext(), {}, {}));
351afa52de9STom Eccles     handler = builder.create<fir::ConvertOp>(loc, fnPtrTy, handler);
352afa52de9STom Eccles   } else {
353afa52de9STom Eccles     assert(mlir::isa<fir::BoxProcType>(handler.getType()));
354afa52de9STom Eccles     handler = builder.create<fir::BoxAddrOp>(loc, handler);
355afa52de9STom Eccles   }
356afa52de9STom Eccles 
357afa52de9STom Eccles   mlir::func::FuncOp func{
358afa52de9STom Eccles       fir::runtime::getRuntimeFunc<mkRTKey(Signal)>(loc, builder)};
359afa52de9STom Eccles   mlir::Value stat =
360afa52de9STom Eccles       builder.create<fir::CallOp>(loc, func, mlir::ValueRange{number, handler})
361afa52de9STom Eccles           ->getResult(0);
362afa52de9STom Eccles 
363afa52de9STom Eccles   // return status code via status argument (if present)
364afa52de9STom Eccles   if (status) {
365afa52de9STom Eccles     assert(mlir::isa<mlir::IntegerType>(fir::unwrapRefType(status.getType())));
366afa52de9STom Eccles     // status might be dynamically optional, so test if it is present
367afa52de9STom Eccles     mlir::Value isPresent =
368afa52de9STom Eccles         builder.create<IsPresentOp>(loc, builder.getI1Type(), status);
369afa52de9STom Eccles     builder.genIfOp(loc, /*results=*/{}, isPresent, /*withElseRegion=*/false)
370afa52de9STom Eccles         .genThen([&]() {
371afa52de9STom Eccles           stat = builder.create<fir::ConvertOp>(
372afa52de9STom Eccles               loc, fir::unwrapRefType(status.getType()), stat);
373afa52de9STom Eccles           builder.create<fir::StoreOp>(loc, stat, status);
374afa52de9STom Eccles         })
375afa52de9STom Eccles         .end();
376afa52de9STom Eccles   }
377afa52de9STom Eccles }
378afa52de9STom Eccles 
379b64c26f3STom Eccles void fir::runtime::genSleep(fir::FirOpBuilder &builder, mlir::Location loc,
380b64c26f3STom Eccles                             mlir::Value seconds) {
381b64c26f3STom Eccles   mlir::Type int64 = builder.getIntegerType(64);
382b64c26f3STom Eccles   seconds = builder.create<fir::ConvertOp>(loc, int64, seconds);
383b64c26f3STom Eccles   mlir::func::FuncOp func{
384b64c26f3STom Eccles       fir::runtime::getRuntimeFunc<mkRTKey(Sleep)>(loc, builder)};
385b64c26f3STom Eccles   builder.create<fir::CallOp>(loc, func, seconds);
386b64c26f3STom Eccles }
387*5a34e6fdSJean-Didier PAILLEUX 
388*5a34e6fdSJean-Didier PAILLEUX /// generate chdir runtime call
389*5a34e6fdSJean-Didier PAILLEUX mlir::Value fir::runtime::genChdir(fir::FirOpBuilder &builder,
390*5a34e6fdSJean-Didier PAILLEUX                                    mlir::Location loc, mlir::Value name) {
391*5a34e6fdSJean-Didier PAILLEUX   mlir::func::FuncOp func{
392*5a34e6fdSJean-Didier PAILLEUX       fir::runtime::getRuntimeFunc<mkRTKey(Chdir)>(loc, builder)};
393*5a34e6fdSJean-Didier PAILLEUX   llvm::SmallVector<mlir::Value> args =
394*5a34e6fdSJean-Didier PAILLEUX       fir::runtime::createArguments(builder, loc, func.getFunctionType(), name);
395*5a34e6fdSJean-Didier PAILLEUX   return builder.create<fir::CallOp>(loc, func, args).getResult(0);
396*5a34e6fdSJean-Didier PAILLEUX }
397