[flang] GETPID runtime and lower intrinsic implementation (#70442)

Runtime function GetPID calls the function getpid
from unistd.h or process.h base on the OS.
This commit is contained in:
Yi Wu 2023-11-13 10:31:36 +00:00 committed by GitHub
parent b070629c10
commit de58aa8372
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 91 additions and 2 deletions

View File

@ -750,7 +750,7 @@ This phase currently supports all the intrinsic procedures listed above but the
| Coarray intrinsic functions | IMAGE_INDEX, COSHAPE |
| Object characteristic inquiry functions | ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, IS_CONTIGUOUS, PRESENT, RANK, SAME_TYPE, STORAGE_SIZE |
| Type inquiry intrinsic functions | BIT_SIZE, DIGITS, EPSILON, HUGE, KIND, MAXEXPONENT, MINEXPONENT, NEW_LINE, PRECISION, RADIX, RANGE, TINY|
| Non-standard intrinsic functions | AND, OR, XOR, SHIFT, ZEXT, IZEXT, COSD, SIND, TAND, ACOSD, ASIND, ATAND, ATAN2D, COMPL, EQV, NEQV, INT8, JINT, JNINT, KNINT, QCMPLX, DREAL, DFLOAT, QEXT, QFLOAT, QREAL, DNUM, NUM, JNUM, KNUM, QNUM, RNUM, RAN, RANF, ILEN, SIZEOF, MCLOCK, SECNDS, COTAN, IBCHNG, ISHA, ISHC, ISHL, IXOR, IARG, IARGC, NARGS, NUMARG, BADDRESS, IADDR, CACHESIZE, EOF, FP_CLASS, INT_PTR_KIND, ISNAN, MALLOC |
| Non-standard intrinsic functions | AND, OR, XOR, SHIFT, ZEXT, IZEXT, COSD, SIND, TAND, ACOSD, ASIND, ATAND, ATAN2D, COMPL, EQV, NEQV, INT8, JINT, JNINT, KNINT, QCMPLX, DREAL, DFLOAT, QEXT, QFLOAT, QREAL, DNUM, NUM, JNUM, KNUM, QNUM, RNUM, RAN, RANF, ILEN, SIZEOF, MCLOCK, SECNDS, COTAN, IBCHNG, ISHA, ISHC, ISHL, IXOR, IARG, IARGC, NARGS, GETPID, NUMARG, BADDRESS, IADDR, CACHESIZE, EOF, FP_CLASS, INT_PTR_KIND, ISNAN, MALLOC |
| Intrinsic subroutines |MVBITS (elemental), CPU_TIME, DATE_AND_TIME, EVENT_QUERY, EXECUTE_COMMAND_LINE, GET_COMMAND, GET_COMMAND_ARGUMENT, GET_ENVIRONMENT_VARIABLE, MOVE_ALLOC, RANDOM_INIT, RANDOM_NUMBER, RANDOM_SEED, SYSTEM_CLOCK |
| Atomic intrinsic subroutines | ATOMIC_ADD |
| Collective intrinsic subroutines | CO_REDUCE |

View File

@ -223,6 +223,8 @@ struct IntrinsicLibrary {
mlir::Value genFraction(mlir::Type resultType,
mlir::ArrayRef<mlir::Value> args);
void genGetCommand(mlir::ArrayRef<fir::ExtendedValue> args);
mlir::Value genGetPID(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args);
void genGetCommandArgument(mlir::ArrayRef<fir::ExtendedValue> args);
void genGetEnvironmentVariable(llvm::ArrayRef<fir::ExtendedValue>);
fir::ExtendedValue genIall(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);

View File

@ -31,6 +31,10 @@ mlir::Value genGetCommand(fir::FirOpBuilder &, mlir::Location,
mlir::Value command, mlir::Value length,
mlir::Value errmsg);
/// Generate a call to the GetPID runtime function which implements the
/// GETPID intrinsic.
mlir::Value genGetPID(fir::FirOpBuilder &, mlir::Location);
/// Generate a call to the GetCommandArgument runtime function which implements
/// the GET_COMMAND_ARGUMENT intrinsic.
/// \p value, \p length and \p errmsg must be fir.box that can be absent (but

View File

@ -25,8 +25,14 @@
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/MLIRContext.h"
#include "llvm/ADT/SmallVector.h"
#include <cstdint>
#include <functional>
#ifdef _WIN32
// On Windows* OS GetCurrentProcessId returns DWORD aka uint32_t
typedef std::uint32_t pid_t;
#endif
// Incomplete type indicating C99 complex ABI in interfaces. Beware, _Complex
// and std::complex are layout compatible, but not compatible in all ABI call
// interfaces (e.g. X86 32 bits). _Complex is not standard C++, so do not use
@ -62,6 +68,14 @@ using FuncTypeBuilderFunc = mlir::FunctionType (*)(mlir::MLIRContext *);
/// standard type `i32` when `sizeof(int)` is 4.
template <typename T>
static constexpr TypeBuilderFunc getModel();
template <>
constexpr TypeBuilderFunc getModel<unsigned int>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::IntegerType::get(context, 8 * sizeof(unsigned int));
};
}
template <>
constexpr TypeBuilderFunc getModel<short int>() {
return [](mlir::MLIRContext *context) -> mlir::Type {

View File

@ -10,9 +10,15 @@
#define FORTRAN_RUNTIME_COMMAND_H_
#include "flang/Runtime/entry-names.h"
#include <cstdint>
#ifdef _WIN32
// On Windows* OS GetCurrentProcessId returns DWORD aka uint32_t
typedef std::uint32_t pid_t;
#else
#include "sys/types.h" //pid_t
#endif
namespace Fortran::runtime {
class Descriptor;
@ -23,6 +29,9 @@ extern "C" {
// integer kind.
std::int32_t RTNAME(ArgumentCount)();
// Calls getpid()
pid_t RTNAME(GetPID)();
// 16.9.82 GET_COMMAND
// Try to get the value of the whole command. All of the parameters are
// optional.

View File

@ -500,6 +500,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{"gamma", {{"x", SameReal}}, SameReal},
{"get_team", {{"level", DefaultInt, Rank::scalar, Optionality::optional}},
TeamType, Rank::scalar, IntrinsicClass::transformationalFunction},
{"getpid", {}, DefaultInt},
{"huge",
{{"x", SameIntOrReal, Rank::anyOrAssumedRank, Optionality::required,
common::Intent::In, {ArgFlag::canBeNull}}},

View File

@ -253,6 +253,7 @@ static constexpr IntrinsicHandler handlers[]{
{"trim_name", asAddr, handleDynamicOptional},
{"errmsg", asBox, handleDynamicOptional}}},
/*isElemental=*/false},
{"getpid", &I::genGetPID},
{"iachar", &I::genIchar},
{"iall",
&I::genIall,
@ -2944,6 +2945,14 @@ void IntrinsicLibrary::genGetCommand(llvm::ArrayRef<fir::ExtendedValue> args) {
}
}
// GETPID
mlir::Value IntrinsicLibrary::genGetPID(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {
assert(args.size() == 0 && "getpid takes no input");
return builder.createConvert(loc, resultType,
fir::runtime::genGetPID(builder, loc));
}
// GET_COMMAND_ARGUMENT
void IntrinsicLibrary::genGetCommandArgument(
llvm::ArrayRef<fir::ExtendedValue> args) {

View File

@ -48,6 +48,14 @@ mlir::Value fir::runtime::genGetCommand(fir::FirOpBuilder &builder,
return builder.create<fir::CallOp>(loc, runtimeFunc, args).getResult(0);
}
mlir::Value fir::runtime::genGetPID(fir::FirOpBuilder &builder,
mlir::Location loc) {
auto runtimeFunc =
fir::runtime::getRuntimeFunc<mkRTKey(GetPID)>(loc, builder);
return builder.create<fir::CallOp>(loc, runtimeFunc).getResult(0);
}
mlir::Value fir::runtime::genGetCommandArgument(
fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value number,
mlir::Value value, mlir::Value length, mlir::Value errmsg) {

View File

@ -15,6 +15,18 @@
#include <cstdlib>
#include <limits>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
// On Windows GetCurrentProcessId returns a DWORD aka uint32_t
#include <processthreadsapi.h>
inline pid_t getpid() { return GetCurrentProcessId(); }
#else
#include <unistd.h> //getpid()
#endif
namespace Fortran::runtime {
std::int32_t RTNAME(ArgumentCount)() {
int argc{executionEnvironment.argc};
@ -25,6 +37,8 @@ std::int32_t RTNAME(ArgumentCount)() {
return 0;
}
pid_t RTNAME(GetPID)() { return getpid(); }
// Returns the length of the \p string. Assumes \p string is valid.
static std::int64_t StringLength(const char *string) {
std::size_t length{std::strlen(string)};

View File

@ -0,0 +1,16 @@
! RUN: bbc -emit-hlfir %s -o - | FileCheck %s
! CHECK-LABEL: func.func @_QPall_args() {
! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "pid", uniq_name = "_QFall_argsEpid"}
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %0 {uniq_name = "_QFall_argsEpid"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_2:.*]] = fir.call @_FortranAGetPID() fastmath<contract> : () -> i32
! CHECK: hlfir.assign %[[VAL_2:.*]] to %[[VAL_1:.*]]#0 : i32, !fir.ref<i32>
! CHECK: return
! CHECK: }
subroutine all_args()
integer :: pid
pid = getpid()
end

View File

@ -44,3 +44,10 @@ TEST_F(RuntimeCallTest, genGetEnvVariable) {
checkCallOp(result.getDefiningOp(), "_FortranAGetEnvVariable", /*nbArgs=*/5,
/*addLocArgs=*/true);
}
TEST_F(RuntimeCallTest, genGetPID) {
mlir::Location loc = firBuilder->getUnknownLoc();
mlir::Value result = fir::runtime::genGetPID(*firBuilder, loc);
checkCallOp(result.getDefiningOp(), "_FortranAGetPID", /*nbArgs=*/0,
/*addLocArgs=*/false);
}

View File

@ -388,6 +388,11 @@ TEST_F(OnlyValidArguments, GetCommandShortLength) {
CheckDescriptorEqInt<short>(length.get(), 51);
}
TEST_F(ZeroArguments, GetPID) {
// pid should always greater than 0, in both linux and windows
EXPECT_GT(RTNAME(GetPID)(), 0);
}
class EnvironmentVariables : public CommandFixture {
protected:
EnvironmentVariables() : CommandFixture(0, nullptr) {