diff --git a/flang/include/flang/Lower/Runtime.h b/flang/include/flang/Lower/Runtime.h --- a/flang/include/flang/Lower/Runtime.h +++ b/flang/include/flang/Lower/Runtime.h @@ -63,42 +63,11 @@ void genUnlockStatement(AbstractConverter &, const parser::UnlockStmt &); void genPauseStatement(AbstractConverter &, const parser::PauseStmt &); -mlir::Value genAssociated(fir::FirOpBuilder &, mlir::Location, - mlir::Value pointer, mlir::Value target); - void genPointerAssociate(fir::FirOpBuilder &, mlir::Location, mlir::Value pointer, mlir::Value target); void genPointerAssociateRemapping(fir::FirOpBuilder &, mlir::Location, mlir::Value pointer, mlir::Value target, mlir::Value bounds); - -mlir::Value genCpuTime(fir::FirOpBuilder &, mlir::Location); -void genDateAndTime(fir::FirOpBuilder &, mlir::Location, - std::optional date, - std::optional time, - std::optional zone, mlir::Value values); - -void genRandomInit(fir::FirOpBuilder &, mlir::Location, mlir::Value repeatable, - mlir::Value imageDistinct); -void genRandomNumber(fir::FirOpBuilder &, mlir::Location, mlir::Value harvest); -void genRandomSeed(fir::FirOpBuilder &, mlir::Location, mlir::Value size, - mlir::Value put, mlir::Value get); - -/// generate runtime call to transfer intrinsic with no size argument -void genTransfer(fir::FirOpBuilder &builder, mlir::Location loc, - mlir::Value resultBox, mlir::Value sourceBox, - mlir::Value moldBox); - -/// generate runtime call to transfer intrinsic with size argument -void genTransferSize(fir::FirOpBuilder &builder, mlir::Location loc, - mlir::Value resultBox, mlir::Value sourceBox, - mlir::Value moldBox, mlir::Value size); - -/// generate system_clock runtime call/s -/// all intrinsic arguments are optional and may appear here as mlir::Value{} -void genSystemClock(fir::FirOpBuilder &, mlir::Location, mlir::Value count, - mlir::Value rate, mlir::Value max); - } // namespace lower } // namespace Fortran diff --git a/flang/include/flang/Lower/Runtime.h b/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h copy from flang/include/flang/Lower/Runtime.h copy to flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h --- a/flang/include/flang/Lower/Runtime.h +++ b/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h @@ -1,4 +1,4 @@ -//===-- Lower/Runtime.h -- Fortran runtime codegen interface ----*- C++ -*-===// +// Builder/Runtime/Intrinsics.h Fortran runtime codegen interface -*- C++ -*-// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -26,42 +26,8 @@ namespace fir { class CharBoxValue; class FirOpBuilder; -} // namespace fir - -namespace Fortran { - -namespace parser { -struct EventPostStmt; -struct EventWaitStmt; -struct LockStmt; -struct PauseStmt; -struct StopStmt; -struct SyncAllStmt; -struct SyncImagesStmt; -struct SyncMemoryStmt; -struct SyncTeamStmt; -struct UnlockStmt; -} // namespace parser - -namespace lower { -class AbstractConverter; - -// Lowering of Fortran statement related runtime (other than IO and maths) - -void genEventPostStatement(AbstractConverter &, const parser::EventPostStmt &); -void genEventWaitStatement(AbstractConverter &, const parser::EventWaitStmt &); -void genLockStatement(AbstractConverter &, const parser::LockStmt &); -void genFailImageStatement(AbstractConverter &); -void genStopStatement(AbstractConverter &, const parser::StopStmt &); -void genSyncAllStatement(AbstractConverter &, const parser::SyncAllStmt &); -void genSyncImagesStatement(AbstractConverter &, - const parser::SyncImagesStmt &); -void genSyncMemoryStatement(AbstractConverter &, - const parser::SyncMemoryStmt &); -void genSyncTeamStatement(AbstractConverter &, const parser::SyncTeamStmt &); -void genUnlockStatement(AbstractConverter &, const parser::UnlockStmt &); -void genPauseStatement(AbstractConverter &, const parser::PauseStmt &); +namespace runtime { mlir::Value genAssociated(fir::FirOpBuilder &, mlir::Location, mlir::Value pointer, mlir::Value target); @@ -98,8 +64,7 @@ /// all intrinsic arguments are optional and may appear here as mlir::Value{} void genSystemClock(fir::FirOpBuilder &, mlir::Location, mlir::Value count, mlir::Value rate, mlir::Value max); - -} // namespace lower -} // namespace Fortran +} // namespace runtime +} // namespace fir #endif // FORTRAN_LOWER_RUNTIME_H diff --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp --- a/flang/lib/Lower/IntrinsicCall.cpp +++ b/flang/lib/Lower/IntrinsicCall.cpp @@ -16,7 +16,6 @@ #include "flang/Lower/IntrinsicCall.h" #include "flang/Common/static-multimap-view.h" #include "flang/Lower/Mangler.h" -#include "flang/Lower/Runtime.h" #include "flang/Lower/Support/Utils.h" #include "flang/Optimizer/Builder/BoxValue.h" #include "flang/Optimizer/Builder/Character.h" @@ -28,6 +27,7 @@ #include "flang/Optimizer/Builder/Runtime/Command.h" #include "flang/Optimizer/Builder/Runtime/Derived.h" #include "flang/Optimizer/Builder/Runtime/Inquiry.h" +#include "flang/Optimizer/Builder/Runtime/Intrinsics.h" #include "flang/Optimizer/Builder/Runtime/Numeric.h" #include "flang/Optimizer/Builder/Runtime/RTBuilder.h" #include "flang/Optimizer/Builder/Runtime/Reduction.h" @@ -2272,7 +2272,7 @@ mlir::Value pointerBoxRef = fir::factory::getMutableIRBox(builder, loc, *pointer); auto pointerBox = builder.create(loc, pointerBoxRef); - return Fortran::lower::genAssociated(builder, loc, pointerBox, targetBox); + return fir::runtime::genAssociated(builder, loc, pointerBox, targetBox); } // BESSEL_JN @@ -2763,7 +2763,7 @@ assert(args.size() == 1); const mlir::Value *arg = args[0].getUnboxed(); assert(arg && "nonscalar cpu_time argument"); - mlir::Value res1 = Fortran::lower::genCpuTime(builder, loc); + mlir::Value res1 = fir::runtime::genCpuTime(builder, loc); mlir::Value res2 = builder.createConvert(loc, fir::dyn_cast_ptrEleTy(arg->getType()), res1); builder.create(loc, res2, *arg); @@ -2823,8 +2823,8 @@ values = builder.create( loc, fir::BoxType::get(builder.getNoneType())); - Fortran::lower::genDateAndTime(builder, loc, charArgs[0], charArgs[1], - charArgs[2], values); + fir::runtime::genDateAndTime(builder, loc, charArgs[0], charArgs[1], + charArgs[2], values); } // DIM @@ -4189,15 +4189,15 @@ // RANDOM_INIT void IntrinsicLibrary::genRandomInit(llvm::ArrayRef args) { assert(args.size() == 2); - Fortran::lower::genRandomInit(builder, loc, fir::getBase(args[0]), - fir::getBase(args[1])); + fir::runtime::genRandomInit(builder, loc, fir::getBase(args[0]), + fir::getBase(args[1])); } // RANDOM_NUMBER void IntrinsicLibrary::genRandomNumber( llvm::ArrayRef args) { assert(args.size() == 1); - Fortran::lower::genRandomNumber(builder, loc, fir::getBase(args[0])); + fir::runtime::genRandomNumber(builder, loc, fir::getBase(args[0])); } // RANDOM_SEED @@ -4212,7 +4212,7 @@ mlir::Value size = getDesc(0); mlir::Value put = getDesc(1); mlir::Value get = getDesc(2); - Fortran::lower::genRandomSeed(builder, loc, size, put, get); + fir::runtime::genRandomSeed(builder, loc, size, put, get); } // REDUCE @@ -4850,8 +4850,8 @@ // SYSTEM_CLOCK void IntrinsicLibrary::genSystemClock(llvm::ArrayRef args) { assert(args.size() == 3); - Fortran::lower::genSystemClock(builder, loc, fir::getBase(args[0]), - fir::getBase(args[1]), fir::getBase(args[2])); + fir::runtime::genSystemClock(builder, loc, fir::getBase(args[0]), + fir::getBase(args[1]), fir::getBase(args[2])); } // TRANSFER @@ -4883,18 +4883,18 @@ mlir::Value resultIrBox = fir::factory::getMutableIRBox(builder, loc, resultMutableBox); - Fortran::lower::genTransfer(builder, loc, resultIrBox, source, mold); + fir::runtime::genTransfer(builder, loc, resultIrBox, source, mold); } else { // The result is a rank one array in this case. mlir::Value resultIrBox = fir::factory::getMutableIRBox(builder, loc, resultMutableBox); if (absentSize) { - Fortran::lower::genTransfer(builder, loc, resultIrBox, source, mold); + fir::runtime::genTransfer(builder, loc, resultIrBox, source, mold); } else { mlir::Value sizeArg = fir::getBase(args[2]); - Fortran::lower::genTransferSize(builder, loc, resultIrBox, source, mold, - sizeArg); + fir::runtime::genTransferSize(builder, loc, resultIrBox, source, mold, + sizeArg); } } return readAndAddCleanUp(resultMutableBox, resultType, "TRANSFER"); diff --git a/flang/lib/Lower/Runtime.cpp b/flang/lib/Lower/Runtime.cpp --- a/flang/lib/Lower/Runtime.cpp +++ b/flang/lib/Lower/Runtime.cpp @@ -177,18 +177,6 @@ builder.create(loc, callee, std::nullopt); } -mlir::Value Fortran::lower::genAssociated(fir::FirOpBuilder &builder, - mlir::Location loc, - mlir::Value pointer, - mlir::Value target) { - mlir::func::FuncOp func = - fir::runtime::getRuntimeFunc(loc, - builder); - llvm::SmallVector args = fir::runtime::createArguments( - builder, loc, func.getFunctionType(), pointer, target); - return builder.create(loc, func, args).getResult(0); -} - void Fortran::lower::genPointerAssociate(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value pointer, @@ -217,203 +205,3 @@ sourceLine); builder.create(loc, func, args).getResult(0); } - -mlir::Value Fortran::lower::genCpuTime(fir::FirOpBuilder &builder, - mlir::Location loc) { - mlir::func::FuncOp func = - fir::runtime::getRuntimeFunc(loc, builder); - return builder.create(loc, func, std::nullopt).getResult(0); -} - -void Fortran::lower::genDateAndTime(fir::FirOpBuilder &builder, - mlir::Location loc, - std::optional date, - std::optional time, - std::optional zone, - mlir::Value values) { - mlir::func::FuncOp callee = - fir::runtime::getRuntimeFunc(loc, builder); - mlir::FunctionType funcTy = callee.getFunctionType(); - mlir::Type idxTy = builder.getIndexType(); - mlir::Value zero; - auto splitArg = [&](std::optional arg, mlir::Value &buffer, - mlir::Value &len) { - if (arg) { - buffer = arg->getBuffer(); - len = arg->getLen(); - } else { - if (!zero) - zero = builder.createIntegerConstant(loc, idxTy, 0); - buffer = zero; - len = zero; - } - }; - mlir::Value dateBuffer; - mlir::Value dateLen; - splitArg(date, dateBuffer, dateLen); - mlir::Value timeBuffer; - mlir::Value timeLen; - splitArg(time, timeBuffer, timeLen); - mlir::Value zoneBuffer; - mlir::Value zoneLen; - splitArg(zone, zoneBuffer, zoneLen); - - mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); - mlir::Value sourceLine = - fir::factory::locationToLineNo(builder, loc, funcTy.getInput(7)); - - llvm::SmallVector args = fir::runtime::createArguments( - builder, loc, funcTy, dateBuffer, dateLen, timeBuffer, timeLen, - zoneBuffer, zoneLen, sourceFile, sourceLine, values); - builder.create(loc, callee, args); -} - -void Fortran::lower::genRandomInit(fir::FirOpBuilder &builder, - mlir::Location loc, mlir::Value repeatable, - mlir::Value imageDistinct) { - mlir::func::FuncOp func = - fir::runtime::getRuntimeFunc(loc, builder); - llvm::SmallVector args = fir::runtime::createArguments( - builder, loc, func.getFunctionType(), repeatable, imageDistinct); - builder.create(loc, func, args); -} - -void Fortran::lower::genRandomNumber(fir::FirOpBuilder &builder, - mlir::Location loc, mlir::Value harvest) { - mlir::func::FuncOp func = - fir::runtime::getRuntimeFunc(loc, builder); - mlir::FunctionType funcTy = func.getFunctionType(); - mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); - mlir::Value sourceLine = - fir::factory::locationToLineNo(builder, loc, funcTy.getInput(2)); - llvm::SmallVector args = fir::runtime::createArguments( - builder, loc, funcTy, harvest, sourceFile, sourceLine); - builder.create(loc, func, args); -} - -void Fortran::lower::genRandomSeed(fir::FirOpBuilder &builder, - mlir::Location loc, mlir::Value size, - mlir::Value put, mlir::Value get) { - bool sizeIsPresent = - !mlir::isa_and_nonnull(size.getDefiningOp()); - bool putIsPresent = - !mlir::isa_and_nonnull(put.getDefiningOp()); - bool getIsPresent = - !mlir::isa_and_nonnull(get.getDefiningOp()); - mlir::func::FuncOp func; - int staticArgCount = sizeIsPresent + putIsPresent + getIsPresent; - if (staticArgCount == 0) { - func = fir::runtime::getRuntimeFunc(loc, - builder); - builder.create(loc, func); - return; - } - mlir::FunctionType funcTy; - mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); - mlir::Value sourceLine; - mlir::Value argBox; - llvm::SmallVector args; - if (staticArgCount > 1) { - func = fir::runtime::getRuntimeFunc(loc, builder); - funcTy = func.getFunctionType(); - sourceLine = - fir::factory::locationToLineNo(builder, loc, funcTy.getInput(4)); - args = fir::runtime::createArguments(builder, loc, funcTy, size, put, get, - sourceFile, sourceLine); - builder.create(loc, func, args); - return; - } - if (sizeIsPresent) { - func = fir::runtime::getRuntimeFunc(loc, builder); - argBox = size; - } else if (putIsPresent) { - func = fir::runtime::getRuntimeFunc(loc, builder); - argBox = put; - } else { - func = fir::runtime::getRuntimeFunc(loc, builder); - argBox = get; - } - funcTy = func.getFunctionType(); - sourceLine = fir::factory::locationToLineNo(builder, loc, funcTy.getInput(2)); - args = fir::runtime::createArguments(builder, loc, funcTy, argBox, sourceFile, - sourceLine); - builder.create(loc, func, args); -} - -/// generate runtime call to transfer intrinsic with no size argument -void Fortran::lower::genTransfer(fir::FirOpBuilder &builder, mlir::Location loc, - mlir::Value resultBox, mlir::Value sourceBox, - mlir::Value moldBox) { - - mlir::func::FuncOp func = - fir::runtime::getRuntimeFunc(loc, builder); - mlir::FunctionType fTy = func.getFunctionType(); - mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); - mlir::Value sourceLine = - fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); - llvm::SmallVector args = fir::runtime::createArguments( - builder, loc, fTy, resultBox, sourceBox, moldBox, sourceFile, sourceLine); - builder.create(loc, func, args); -} - -/// generate runtime call to transfer intrinsic with size argument -void Fortran::lower::genTransferSize(fir::FirOpBuilder &builder, - mlir::Location loc, mlir::Value resultBox, - mlir::Value sourceBox, mlir::Value moldBox, - mlir::Value size) { - mlir::func::FuncOp func = - fir::runtime::getRuntimeFunc(loc, builder); - mlir::FunctionType fTy = func.getFunctionType(); - mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); - mlir::Value sourceLine = - fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); - llvm::SmallVector args = - fir::runtime::createArguments(builder, loc, fTy, resultBox, sourceBox, - moldBox, sourceFile, sourceLine, size); - builder.create(loc, func, args); -} - -/// generate system_clock runtime call/s -/// all intrinsic arguments are optional and may appear here as mlir::Value{} -void Fortran::lower::genSystemClock(fir::FirOpBuilder &builder, - mlir::Location loc, mlir::Value count, - mlir::Value rate, mlir::Value max) { - auto makeCall = [&](mlir::func::FuncOp func, mlir::Value arg) { - mlir::Type type = arg.getType(); - fir::IfOp ifOp{}; - const bool isOptionalArg = - fir::valueHasFirAttribute(arg, fir::getOptionalAttrName()); - if (type.dyn_cast() || type.dyn_cast()) { - // Check for a disassociated pointer or an unallocated allocatable. - assert(!isOptionalArg && "invalid optional argument"); - ifOp = builder.create(loc, builder.genIsNotNullAddr(loc, arg), - /*withElseRegion=*/false); - } else if (isOptionalArg) { - ifOp = builder.create( - loc, builder.create(loc, builder.getI1Type(), arg), - /*withElseRegion=*/false); - } - if (ifOp) - builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); - mlir::Type kindTy = func.getFunctionType().getInput(0); - int integerKind = 8; - if (auto intType = fir::unwrapRefType(type).dyn_cast()) - integerKind = intType.getWidth() / 8; - mlir::Value kind = builder.createIntegerConstant(loc, kindTy, integerKind); - mlir::Value res = - builder.create(loc, func, mlir::ValueRange{kind}) - .getResult(0); - mlir::Value castRes = - builder.createConvert(loc, fir::dyn_cast_ptrEleTy(type), res); - builder.create(loc, castRes, arg); - if (ifOp) - builder.setInsertionPointAfter(ifOp); - }; - using fir::runtime::getRuntimeFunc; - if (count) - makeCall(getRuntimeFunc(loc, builder), count); - if (rate) - makeCall(getRuntimeFunc(loc, builder), rate); - if (max) - makeCall(getRuntimeFunc(loc, builder), max); -} diff --git a/flang/lib/Optimizer/Builder/CMakeLists.txt b/flang/lib/Optimizer/Builder/CMakeLists.txt --- a/flang/lib/Optimizer/Builder/CMakeLists.txt +++ b/flang/lib/Optimizer/Builder/CMakeLists.txt @@ -16,6 +16,7 @@ Runtime/Derived.cpp Runtime/EnvironmentDefaults.cpp Runtime/Inquiry.cpp + Runtime/Intrinsics.cpp Runtime/Numeric.cpp Runtime/Ragged.cpp Runtime/Reduction.cpp diff --git a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp new file mode 100644 --- /dev/null +++ b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp @@ -0,0 +1,238 @@ +//===-- Intrinsics.cpp ----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "flang/Optimizer/Builder/Runtime/Intrinsics.h" +#include "flang/Optimizer/Builder/BoxValue.h" +#include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Builder/Runtime/RTBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" +#include "flang/Optimizer/Dialect/FIROpsSupport.h" +#include "flang/Parser/parse-tree.h" +#include "flang/Runtime/misc-intrinsic.h" +#include "flang/Runtime/pointer.h" +#include "flang/Runtime/random.h" +#include "flang/Runtime/stop.h" +#include "flang/Runtime/time-intrinsic.h" +#include "flang/Semantics/tools.h" +#include "llvm/Support/Debug.h" +#include + +#define DEBUG_TYPE "flang-lower-runtime" + +using namespace Fortran::runtime; + +mlir::Value fir::runtime::genAssociated(fir::FirOpBuilder &builder, + mlir::Location loc, mlir::Value pointer, + mlir::Value target) { + mlir::func::FuncOp func = + fir::runtime::getRuntimeFunc(loc, + builder); + llvm::SmallVector args = fir::runtime::createArguments( + builder, loc, func.getFunctionType(), pointer, target); + return builder.create(loc, func, args).getResult(0); +} + +mlir::Value fir::runtime::genCpuTime(fir::FirOpBuilder &builder, + mlir::Location loc) { + mlir::func::FuncOp func = + fir::runtime::getRuntimeFunc(loc, builder); + return builder.create(loc, func, std::nullopt).getResult(0); +} + +void fir::runtime::genDateAndTime(fir::FirOpBuilder &builder, + mlir::Location loc, + std::optional date, + std::optional time, + std::optional zone, + mlir::Value values) { + mlir::func::FuncOp callee = + fir::runtime::getRuntimeFunc(loc, builder); + mlir::FunctionType funcTy = callee.getFunctionType(); + mlir::Type idxTy = builder.getIndexType(); + mlir::Value zero; + auto splitArg = [&](std::optional arg, mlir::Value &buffer, + mlir::Value &len) { + if (arg) { + buffer = arg->getBuffer(); + len = arg->getLen(); + } else { + if (!zero) + zero = builder.createIntegerConstant(loc, idxTy, 0); + buffer = zero; + len = zero; + } + }; + mlir::Value dateBuffer; + mlir::Value dateLen; + splitArg(date, dateBuffer, dateLen); + mlir::Value timeBuffer; + mlir::Value timeLen; + splitArg(time, timeBuffer, timeLen); + mlir::Value zoneBuffer; + mlir::Value zoneLen; + splitArg(zone, zoneBuffer, zoneLen); + + mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); + mlir::Value sourceLine = + fir::factory::locationToLineNo(builder, loc, funcTy.getInput(7)); + + llvm::SmallVector args = fir::runtime::createArguments( + builder, loc, funcTy, dateBuffer, dateLen, timeBuffer, timeLen, + zoneBuffer, zoneLen, sourceFile, sourceLine, values); + builder.create(loc, callee, args); +} + +void fir::runtime::genRandomInit(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value repeatable, + mlir::Value imageDistinct) { + mlir::func::FuncOp func = + fir::runtime::getRuntimeFunc(loc, builder); + llvm::SmallVector args = fir::runtime::createArguments( + builder, loc, func.getFunctionType(), repeatable, imageDistinct); + builder.create(loc, func, args); +} + +void fir::runtime::genRandomNumber(fir::FirOpBuilder &builder, + mlir::Location loc, mlir::Value harvest) { + mlir::func::FuncOp func = + fir::runtime::getRuntimeFunc(loc, builder); + mlir::FunctionType funcTy = func.getFunctionType(); + mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); + mlir::Value sourceLine = + fir::factory::locationToLineNo(builder, loc, funcTy.getInput(2)); + llvm::SmallVector args = fir::runtime::createArguments( + builder, loc, funcTy, harvest, sourceFile, sourceLine); + builder.create(loc, func, args); +} + +void fir::runtime::genRandomSeed(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value size, mlir::Value put, + mlir::Value get) { + bool sizeIsPresent = + !mlir::isa_and_nonnull(size.getDefiningOp()); + bool putIsPresent = + !mlir::isa_and_nonnull(put.getDefiningOp()); + bool getIsPresent = + !mlir::isa_and_nonnull(get.getDefiningOp()); + mlir::func::FuncOp func; + int staticArgCount = sizeIsPresent + putIsPresent + getIsPresent; + if (staticArgCount == 0) { + func = fir::runtime::getRuntimeFunc(loc, + builder); + builder.create(loc, func); + return; + } + mlir::FunctionType funcTy; + mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); + mlir::Value sourceLine; + mlir::Value argBox; + llvm::SmallVector args; + if (staticArgCount > 1) { + func = fir::runtime::getRuntimeFunc(loc, builder); + funcTy = func.getFunctionType(); + sourceLine = + fir::factory::locationToLineNo(builder, loc, funcTy.getInput(4)); + args = fir::runtime::createArguments(builder, loc, funcTy, size, put, get, + sourceFile, sourceLine); + builder.create(loc, func, args); + return; + } + if (sizeIsPresent) { + func = fir::runtime::getRuntimeFunc(loc, builder); + argBox = size; + } else if (putIsPresent) { + func = fir::runtime::getRuntimeFunc(loc, builder); + argBox = put; + } else { + func = fir::runtime::getRuntimeFunc(loc, builder); + argBox = get; + } + funcTy = func.getFunctionType(); + sourceLine = fir::factory::locationToLineNo(builder, loc, funcTy.getInput(2)); + args = fir::runtime::createArguments(builder, loc, funcTy, argBox, sourceFile, + sourceLine); + builder.create(loc, func, args); +} + +/// generate runtime call to transfer intrinsic with no size argument +void fir::runtime::genTransfer(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value sourceBox, + mlir::Value moldBox) { + + mlir::func::FuncOp func = + fir::runtime::getRuntimeFunc(loc, builder); + mlir::FunctionType fTy = func.getFunctionType(); + mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); + mlir::Value sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); + llvm::SmallVector args = fir::runtime::createArguments( + builder, loc, fTy, resultBox, sourceBox, moldBox, sourceFile, sourceLine); + builder.create(loc, func, args); +} + +/// generate runtime call to transfer intrinsic with size argument +void fir::runtime::genTransferSize(fir::FirOpBuilder &builder, + mlir::Location loc, mlir::Value resultBox, + mlir::Value sourceBox, mlir::Value moldBox, + mlir::Value size) { + mlir::func::FuncOp func = + fir::runtime::getRuntimeFunc(loc, builder); + mlir::FunctionType fTy = func.getFunctionType(); + mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); + mlir::Value sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); + llvm::SmallVector args = + fir::runtime::createArguments(builder, loc, fTy, resultBox, sourceBox, + moldBox, sourceFile, sourceLine, size); + builder.create(loc, func, args); +} + +/// generate system_clock runtime call/s +/// all intrinsic arguments are optional and may appear here as mlir::Value{} +void fir::runtime::genSystemClock(fir::FirOpBuilder &builder, + mlir::Location loc, mlir::Value count, + mlir::Value rate, mlir::Value max) { + auto makeCall = [&](mlir::func::FuncOp func, mlir::Value arg) { + mlir::Type type = arg.getType(); + fir::IfOp ifOp{}; + const bool isOptionalArg = + fir::valueHasFirAttribute(arg, fir::getOptionalAttrName()); + if (type.dyn_cast() || type.dyn_cast()) { + // Check for a disassociated pointer or an unallocated allocatable. + assert(!isOptionalArg && "invalid optional argument"); + ifOp = builder.create(loc, builder.genIsNotNullAddr(loc, arg), + /*withElseRegion=*/false); + } else if (isOptionalArg) { + ifOp = builder.create( + loc, builder.create(loc, builder.getI1Type(), arg), + /*withElseRegion=*/false); + } + if (ifOp) + builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); + mlir::Type kindTy = func.getFunctionType().getInput(0); + int integerKind = 8; + if (auto intType = fir::unwrapRefType(type).dyn_cast()) + integerKind = intType.getWidth() / 8; + mlir::Value kind = builder.createIntegerConstant(loc, kindTy, integerKind); + mlir::Value res = + builder.create(loc, func, mlir::ValueRange{kind}) + .getResult(0); + mlir::Value castRes = + builder.createConvert(loc, fir::dyn_cast_ptrEleTy(type), res); + builder.create(loc, castRes, arg); + if (ifOp) + builder.setInsertionPointAfter(ifOp); + }; + using fir::runtime::getRuntimeFunc; + if (count) + makeCall(getRuntimeFunc(loc, builder), count); + if (rate) + makeCall(getRuntimeFunc(loc, builder), rate); + if (max) + makeCall(getRuntimeFunc(loc, builder), max); +}