-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[flang] GETPID runtime and lower intrinsic implementation #70442
Conversation
@llvm/pr-subscribers-flang-runtime @llvm/pr-subscribers-flang-fir-hlfir Author: Yi Wu (PAX-12-WU) ChangesRuntime function GetPID calls the function getpid Full diff: https://github.com/llvm/llvm-project/pull/70442.diff 11 Files Affected:
diff --git a/flang/docs/Intrinsics.md b/flang/docs/Intrinsics.md
index ab0a940e53e5538..3726659edabf5d8 100644
--- a/flang/docs/Intrinsics.md
+++ b/flang/docs/Intrinsics.md
@@ -751,7 +751,7 @@ This phase currently supports all the intrinsic procedures listed above but the
| 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 |
-| 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 |
+| Intrinsic subroutines |MVBITS (elemental), CPU_TIME, DATE_AND_TIME, EVENT_QUERY, EXECUTE_COMMAND_LINE, GET_COMMAND, GET_COMMAND_ARGUMENT, GET_ENVIRONMENT_VARIABLE, GETPID, MOVE_ALLOC, RANDOM_INIT, RANDOM_NUMBER, RANDOM_SEED, SYSTEM_CLOCK |
| Atomic intrinsic subroutines | ATOMIC_ADD |
| Collective intrinsic subroutines | CO_REDUCE |
diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
index 06db8cf9e9dc923..5065f11ae9e7264 100644
--- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
+++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
@@ -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>);
diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Command.h b/flang/include/flang/Optimizer/Builder/Runtime/Command.h
index 9ecdba2c995b713..976fb3aa0b6fbb7 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/Command.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/Command.h
@@ -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
diff --git a/flang/include/flang/Runtime/command.h b/flang/include/flang/Runtime/command.h
index ec6289390545479..711cca58240aa8f 100644
--- a/flang/include/flang/Runtime/command.h
+++ b/flang/include/flang/Runtime/command.h
@@ -11,6 +11,7 @@
#include "flang/Runtime/entry-names.h"
+#include "sys/types.h" //pid_t
#include <cstdint>
namespace Fortran::runtime {
@@ -23,6 +24,10 @@ 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.
diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index e4125f6572aa983..ac67663aec3a08a 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -499,6 +499,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}}},
@@ -1880,7 +1881,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
int elementalRank{0};
for (std::size_t j{0}; j < dummies; ++j) {
const IntrinsicDummyArgument &d{dummy[std::min(j, dummyArgPatterns - 1)]};
- if (const ActualArgument *arg{actualForDummy[j]}) {
+ if (const ActualArgument * arg{actualForDummy[j]}) {
bool isAssumedRank{IsAssumedRank(*arg)};
if (isAssumedRank && d.rank != Rank::anyOrAssumedRank &&
d.rank != Rank::arrayOrAssumedRank) {
@@ -2217,7 +2218,8 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
case Rank::locReduced:
case Rank::scalarIfDim:
if (dummy[*dimArg].optionality == Optionality::required) {
- if (const Symbol *whole{
+ if (const Symbol *
+ whole{
UnwrapWholeSymbolOrComponentDataRef(actualForDummy[*dimArg])}) {
if (IsOptional(*whole) || IsAllocatableOrObjectPointer(whole)) {
if (rank == Rank::scalarIfDim || arrayRank.value_or(-1) == 1) {
@@ -2292,7 +2294,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
// Rearrange the actual arguments into dummy argument order.
ActualArguments rearranged(dummies);
for (std::size_t j{0}; j < dummies; ++j) {
- if (ActualArgument *arg{actualForDummy[j]}) {
+ if (ActualArgument * arg{actualForDummy[j]}) {
rearranged[j] = std::move(*arg);
}
}
@@ -2929,7 +2931,7 @@ static bool ApplySpecificChecks(SpecificCall &call, FoldingContext &context) {
ok &= CheckForCoindexedObject(context, call.arguments[3], name, "errmsg");
if (call.arguments[0] && call.arguments[1]) {
for (int j{0}; j < 2; ++j) {
- if (const Symbol *last{GetLastSymbol(call.arguments[j])};
+ if (const Symbol * last{GetLastSymbol(call.arguments[j])};
last && !IsAllocatable(last->GetUltimate())) {
context.messages().Say(call.arguments[j]->sourceLocation(),
"Argument #%d to MOVE_ALLOC must be allocatable"_err_en_US,
@@ -2949,7 +2951,7 @@ static bool ApplySpecificChecks(SpecificCall &call, FoldingContext &context) {
const auto &arg{call.arguments[0]};
if (arg) {
if (const auto *expr{arg->UnwrapExpr()}) {
- if (const Symbol *symbol{UnwrapWholeSymbolDataRef(*expr)}) {
+ if (const Symbol * symbol{UnwrapWholeSymbolDataRef(*expr)}) {
ok = symbol->attrs().test(semantics::Attr::OPTIONAL);
}
}
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index 0a023bc6b21ea03..454d38592a8bc4f 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -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,
@@ -2936,6 +2937,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) {
diff --git a/flang/lib/Optimizer/Builder/Runtime/Command.cpp b/flang/lib/Optimizer/Builder/Runtime/Command.cpp
index f56475a97487835..1d719e7bbd9a2d1 100644
--- a/flang/lib/Optimizer/Builder/Runtime/Command.cpp
+++ b/flang/lib/Optimizer/Builder/Runtime/Command.cpp
@@ -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) {
diff --git a/flang/runtime/command.cpp b/flang/runtime/command.cpp
index b81a0791c5e571b..3f719e80bba2662 100644
--- a/flang/runtime/command.cpp
+++ b/flang/runtime/command.cpp
@@ -14,6 +14,11 @@
#include "flang/Runtime/descriptor.h"
#include <cstdlib>
#include <limits>
+#ifdef _WIN32
+#include <process.h> //getpid()
+#else
+#include <unistd.h> //getpid()
+#endif
namespace Fortran::runtime {
std::int32_t RTNAME(ArgumentCount)() {
@@ -25,6 +30,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)};
diff --git a/flang/test/Lower/Intrinsics/gepid.f90 b/flang/test/Lower/Intrinsics/gepid.f90
new file mode 100644
index 000000000000000..ca5b2ddec50214d
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/gepid.f90
@@ -0,0 +1,15 @@
+! RUN: bbc -emit-fir %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:.*]] = fir.call @_FortranAGetPID() fastmath<contract> : () -> i32
+! CHECK: fir.store %[[VAL_1:.*]] to %[[VAL_0:.*]] : !fir.ref<i32>
+! CHECK: return
+! CHECK: }
+
+subroutine all_args()
+ integer :: pid
+ pid = getpid()
+end
+
+
diff --git a/flang/unittests/Optimizer/Builder/Runtime/CommandTest.cpp b/flang/unittests/Optimizer/Builder/Runtime/CommandTest.cpp
index acc79ae63e9f698..58a151447d5b4f7 100644
--- a/flang/unittests/Optimizer/Builder/Runtime/CommandTest.cpp
+++ b/flang/unittests/Optimizer/Builder/Runtime/CommandTest.cpp
@@ -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);
+}
\ No newline at end of file
diff --git a/flang/unittests/Runtime/CommandTest.cpp b/flang/unittests/Runtime/CommandTest.cpp
index c3571c9684e4b07..9f66c7924c86e3c 100644
--- a/flang/unittests/Runtime/CommandTest.cpp
+++ b/flang/unittests/Runtime/CommandTest.cpp
@@ -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) {
|
I have tried to implement it in // RESULT = GETPID()
pid_t FORTRAN_PROCEDURE_NAME(getpid)() { return RTNAME(GetPID)(); } However, when testing getpid in a file, getpid would return a
|
Looks OK. Please wait for @klausler. |
|
How can I define it as intrinsic function to get a correct result type? I have tried renaming I initially tried in |
Types are determined in semantics. By default, in Fortran, a name with no explicit type is integer if its first letter is in the range I through N, and real otherwise. |
Thanks a lot, if I have understood correctly, I have it defined as a lowering intrinsic function under |
930b62b
to
9aaf5ae
Compare
ac211f4
to
109a072
Compare
174d304
to
b4d44c2
Compare
35d9c4c
to
7cdffc2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM thanks
Runtime function GetPID calls the function getpid from unistd.h or processthreadsapi.h base on the OS. Processthreadsapi.g is supported since Windows XP: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocessid and GetCurrentProcessId returns a DWORD, an unsigned 32-bit int: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/262627d8-3418-4627-9218-4ffe110850b2
Thanks @klausler for the input. I am assuming you meant to add an entry to |
Runtime function GetPID calls the function getpid from unistd.h or process.h base on the OS.
Runtime function GetPID calls the function getpid
from unistd.h or process.h base on the OS.