From 0ff6e49ca90895891661e0dc3e3fd3182d1e1886 Mon Sep 17 00:00:00 2001 From: Yi Wu Date: Tue, 7 Nov 2023 10:20:02 +0000 Subject: [PATCH 1/3] GETUID runtime and lowering intrinsics Returns the numerical user ID of the current process. The return value of GETUID is an INTEGER of the default kind. --- flang/docs/Intrinsics.md | 2 +- .../flang/Optimizer/Builder/IntrinsicCall.h | 2 ++ .../flang/Optimizer/Builder/Runtime/Command.h | 4 ++++ .../flang/Optimizer/Builder/Runtime/RTBuilder.h | 8 ++++++++ flang/include/flang/Runtime/command.h | 8 ++++++++ flang/lib/Evaluate/intrinsics.cpp | 1 + flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 9 +++++++++ flang/lib/Optimizer/Builder/Runtime/Command.cpp | 8 ++++++++ flang/runtime/command.cpp | 7 +++++++ flang/test/Lower/Intrinsics/getuid.f90 | 14 ++++++++++++++ .../Optimizer/Builder/Runtime/CommandTest.cpp | 7 +++++++ flang/unittests/Runtime/CommandTest.cpp | 5 +++++ 12 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 flang/test/Lower/Intrinsics/getuid.f90 diff --git a/flang/docs/Intrinsics.md b/flang/docs/Intrinsics.md index ab0a940e53e55..1fda824cc8a92 100644 --- a/flang/docs/Intrinsics.md +++ b/flang/docs/Intrinsics.md @@ -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, NUMARG, BADDRESS, IADDR, CACHESIZE, EOF, FP_CLASS, INT_PTR_KIND, ISNAN, MALLOC, GETUID | | 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 | diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h index 06db8cf9e9dc9..6706e8fb7c690 100644 --- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h +++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h @@ -225,6 +225,8 @@ struct IntrinsicLibrary { void genGetCommand(mlir::ArrayRef args); void genGetCommandArgument(mlir::ArrayRef args); void genGetEnvironmentVariable(llvm::ArrayRef); + mlir::Value genGetUID(mlir::Type resultType, + llvm::ArrayRef args); fir::ExtendedValue genIall(mlir::Type, llvm::ArrayRef); /// Lowering for the IAND intrinsic. The IAND intrinsic expects two arguments /// in the llvm::ArrayRef. diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Command.h b/flang/include/flang/Optimizer/Builder/Runtime/Command.h index 9ecdba2c995b7..6686645105c40 100644 --- a/flang/include/flang/Optimizer/Builder/Runtime/Command.h +++ b/flang/include/flang/Optimizer/Builder/Runtime/Command.h @@ -49,5 +49,9 @@ mlir::Value genGetEnvVariable(fir::FirOpBuilder &, mlir::Location, mlir::Value length, mlir::Value trimName, mlir::Value errmsg); +/// Generate a call to the GetUID runtime function which implements the +/// GETUID intrinsic. +mlir::Value genGetUID(fir::FirOpBuilder &, mlir::Location); + } // namespace fir::runtime #endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_COMMAND_H diff --git a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h index b2774263e7a31..830df7ad006b5 100644 --- a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h +++ b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h @@ -62,6 +62,14 @@ using FuncTypeBuilderFunc = mlir::FunctionType (*)(mlir::MLIRContext *); /// standard type `i32` when `sizeof(int)` is 4. template static constexpr TypeBuilderFunc getModel(); + +template <> +constexpr TypeBuilderFunc getModel() { + return [](mlir::MLIRContext *context) -> mlir::Type { + return mlir::IntegerType::get(context, 8 * sizeof(unsigned int)); + }; +} + template <> constexpr TypeBuilderFunc getModel() { return [](mlir::MLIRContext *context) -> mlir::Type { diff --git a/flang/include/flang/Runtime/command.h b/flang/include/flang/Runtime/command.h index ec62893905454..5f5f519e7314a 100644 --- a/flang/include/flang/Runtime/command.h +++ b/flang/include/flang/Runtime/command.h @@ -13,6 +13,10 @@ #include +#ifdef _WIN32 +#else +#include "sys/types.h" +#endif namespace Fortran::runtime { class Descriptor; @@ -47,6 +51,10 @@ std::int32_t RTNAME(GetEnvVariable)(const Descriptor &name, bool trim_name = true, const Descriptor *errmsg = nullptr, const char *sourceFile = nullptr, int line = 0); } + +// Calls getuid() +uid_t RTNAME(GetUID)(); + } // namespace Fortran::runtime #endif // FORTRAN_RUNTIME_COMMAND_H_ diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index c711b4feaca48..122f71b027337 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -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}, + {"getuid", {}, DefaultInt}, {"huge", {{"x", SameIntOrReal, Rank::anyOrAssumedRank, Optionality::required, common::Intent::In, {ArgFlag::canBeNull}}}, diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index fe40fd821f010..4af8fca75da2e 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}, + {"getuid", &I::genGetUID}, {"iachar", &I::genIchar}, {"iall", &I::genIall, @@ -2944,6 +2945,14 @@ void IntrinsicLibrary::genGetCommand(llvm::ArrayRef args) { } } +// GETUID +mlir::Value IntrinsicLibrary::genGetUID(mlir::Type resultType, + llvm::ArrayRef args) { + assert(args.size() == 0 && "getuid takes no input"); + return builder.createConvert(loc, resultType, + fir::runtime::genGetUID(builder, loc)); +} + // GET_COMMAND_ARGUMENT void IntrinsicLibrary::genGetCommandArgument( llvm::ArrayRef args) { diff --git a/flang/lib/Optimizer/Builder/Runtime/Command.cpp b/flang/lib/Optimizer/Builder/Runtime/Command.cpp index f56475a974878..3826ce6cfc393 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Command.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Command.cpp @@ -80,3 +80,11 @@ mlir::Value fir::runtime::genGetEnvVariable(fir::FirOpBuilder &builder, sourceFile, sourceLine); return builder.create(loc, runtimeFunc, args).getResult(0); } + +mlir::Value fir::runtime::genGetUID(fir::FirOpBuilder &builder, + mlir::Location loc) { + auto runtimeFunc = + fir::runtime::getRuntimeFunc(loc, builder); + + return builder.create(loc, runtimeFunc).getResult(0); +} diff --git a/flang/runtime/command.cpp b/flang/runtime/command.cpp index b81a0791c5e57..4a36dc94497d7 100644 --- a/flang/runtime/command.cpp +++ b/flang/runtime/command.cpp @@ -15,6 +15,11 @@ #include #include +#ifdef _WIN32 +#else +#include +#endif + namespace Fortran::runtime { std::int32_t RTNAME(ArgumentCount)() { int argc{executionEnvironment.argc}; @@ -25,6 +30,8 @@ std::int32_t RTNAME(ArgumentCount)() { return 0; } +uid_t RTNAME(GetUID)() { return getuid(); } + // 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/getuid.f90 b/flang/test/Lower/Intrinsics/getuid.f90 new file mode 100644 index 0000000000000..0cc9c154d0b7f --- /dev/null +++ b/flang/test/Lower/Intrinsics/getuid.f90 @@ -0,0 +1,14 @@ +! RUN: bbc -emit-hlfir %s -o - | FileCheck %s + +! CHECK-LABEL: func.func @_QPall_args() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "uid", uniq_name = "_QFall_argsEuid"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %0 {uniq_name = "_QFall_argsEuid"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.call @_FortranAGetUID() fastmath : () -> i32 +! CHECK: hlfir.assign %[[VAL_2:.*]] to %[[VAL_1:.*]]#0 : i32, !fir.ref +! CHECK: return +! CHECK: } + +subroutine all_args() + integer :: uid + uid = getuid() +end \ No newline at end of file diff --git a/flang/unittests/Optimizer/Builder/Runtime/CommandTest.cpp b/flang/unittests/Optimizer/Builder/Runtime/CommandTest.cpp index acc79ae63e9f6..75913d2e0f81b 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, genGetUID) { + mlir::Location loc = firBuilder->getUnknownLoc(); + mlir::Value result = fir::runtime::genGetUID(*firBuilder, loc); + checkCallOp(result.getDefiningOp(), "_FortranAGetUID", /*nbArgs=*/0, + /*addLocArgs=*/false); +} diff --git a/flang/unittests/Runtime/CommandTest.cpp b/flang/unittests/Runtime/CommandTest.cpp index c3571c9684e4b..c8c54b9b6faa1 100644 --- a/flang/unittests/Runtime/CommandTest.cpp +++ b/flang/unittests/Runtime/CommandTest.cpp @@ -227,6 +227,11 @@ TEST_F(ZeroArguments, GetCommandArgument) { TEST_F(ZeroArguments, GetCommand) { CheckCommandValue(commandOnlyArgv, 1); } +TEST_F(ZeroArguments, GetUID) { + // uid should always greater than 0, in both linux and windows + EXPECT_GT(RTNAME(GetUID)(), 0U); +} + static const char *oneArgArgv[]{"aProgram", "anArgumentOfLength20"}; class OneArgument : public CommandFixture { protected: From f650de618d640b76152e46b75789eef0e4114e19 Mon Sep 17 00:00:00 2001 From: Yi Wu Date: Tue, 7 Nov 2023 15:31:38 +0000 Subject: [PATCH 2/3] Add fake support for windows Windows doesn't have getuid or anything Win32 equivalent, and it is also not supported in gfortran. Windows however have "GetTokenInformation" call and querying for the TokenUser information class. It returns user's SID. --- .../flang/Optimizer/Builder/Runtime/Command.h | 8 ++++---- flang/include/flang/Runtime/command.h | 10 ++++++---- flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 16 ++++++++-------- flang/runtime/command.cpp | 1 + flang/unittests/Runtime/CommandTest.cpp | 5 +++-- 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Command.h b/flang/include/flang/Optimizer/Builder/Runtime/Command.h index 6686645105c40..95ed7ea8562e8 100644 --- a/flang/include/flang/Optimizer/Builder/Runtime/Command.h +++ b/flang/include/flang/Optimizer/Builder/Runtime/Command.h @@ -23,6 +23,10 @@ namespace fir::runtime { /// Generate call to COMMAND_ARGUMENT_COUNT intrinsic runtime routine. mlir::Value genCommandArgumentCount(fir::FirOpBuilder &, mlir::Location); +/// Generate a call to the GetUID runtime function which implements the +/// GETUID intrinsic. +mlir::Value genGetUID(fir::FirOpBuilder &, mlir::Location); + /// Generate a call to the GetCommand runtime function which implements the /// GET_COMMAND intrinsic. /// \p command, \p length and \p errmsg must be fir.box that can be absent (but @@ -49,9 +53,5 @@ mlir::Value genGetEnvVariable(fir::FirOpBuilder &, mlir::Location, mlir::Value length, mlir::Value trimName, mlir::Value errmsg); -/// Generate a call to the GetUID runtime function which implements the -/// GETUID intrinsic. -mlir::Value genGetUID(fir::FirOpBuilder &, mlir::Location); - } // namespace fir::runtime #endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_COMMAND_H diff --git a/flang/include/flang/Runtime/command.h b/flang/include/flang/Runtime/command.h index 5f5f519e7314a..e4a5820b57d1e 100644 --- a/flang/include/flang/Runtime/command.h +++ b/flang/include/flang/Runtime/command.h @@ -14,9 +14,11 @@ #include #ifdef _WIN32 +typedef int uid_t; #else -#include "sys/types.h" +#include "sys/types.h" //uid_t #endif + namespace Fortran::runtime { class Descriptor; @@ -27,6 +29,9 @@ extern "C" { // integer kind. std::int32_t RTNAME(ArgumentCount)(); +// Calls getuid() +uid_t RTNAME(GetUID)(); + // 16.9.82 GET_COMMAND // Try to get the value of the whole command. All of the parameters are // optional. @@ -52,9 +57,6 @@ std::int32_t RTNAME(GetEnvVariable)(const Descriptor &name, const char *sourceFile = nullptr, int line = 0); } -// Calls getuid() -uid_t RTNAME(GetUID)(); - } // namespace Fortran::runtime #endif // FORTRAN_RUNTIME_COMMAND_H_ diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index 4af8fca75da2e..971c87452f950 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -2907,6 +2907,14 @@ mlir::Value IntrinsicLibrary::genFraction(mlir::Type resultType, fir::runtime::genFraction(builder, loc, fir::getBase(args[0]))); } +// GETUID +mlir::Value IntrinsicLibrary::genGetUID(mlir::Type resultType, + llvm::ArrayRef args) { + assert(args.size() == 0 && "getuid takes no input"); + return builder.createConvert(loc, resultType, + fir::runtime::genGetUID(builder, loc)); +} + // GET_COMMAND void IntrinsicLibrary::genGetCommand(llvm::ArrayRef args) { assert(args.size() == 4); @@ -2945,14 +2953,6 @@ void IntrinsicLibrary::genGetCommand(llvm::ArrayRef args) { } } -// GETUID -mlir::Value IntrinsicLibrary::genGetUID(mlir::Type resultType, - llvm::ArrayRef args) { - assert(args.size() == 0 && "getuid takes no input"); - return builder.createConvert(loc, resultType, - fir::runtime::genGetUID(builder, loc)); -} - // GET_COMMAND_ARGUMENT void IntrinsicLibrary::genGetCommandArgument( llvm::ArrayRef args) { diff --git a/flang/runtime/command.cpp b/flang/runtime/command.cpp index 4a36dc94497d7..3298e8133cac2 100644 --- a/flang/runtime/command.cpp +++ b/flang/runtime/command.cpp @@ -16,6 +16,7 @@ #include #ifdef _WIN32 +inline uid_t getuid() { return 0; } #else #include #endif diff --git a/flang/unittests/Runtime/CommandTest.cpp b/flang/unittests/Runtime/CommandTest.cpp index c8c54b9b6faa1..80593b3e907be 100644 --- a/flang/unittests/Runtime/CommandTest.cpp +++ b/flang/unittests/Runtime/CommandTest.cpp @@ -228,8 +228,9 @@ TEST_F(ZeroArguments, GetCommandArgument) { TEST_F(ZeroArguments, GetCommand) { CheckCommandValue(commandOnlyArgv, 1); } TEST_F(ZeroArguments, GetUID) { - // uid should always greater than 0, in both linux and windows - EXPECT_GT(RTNAME(GetUID)(), 0U); + CheckMissingArgumentValue(-1); + CheckArgumentValue(commandOnlyArgv[0], 0); + CheckMissingArgumentValue(1); } static const char *oneArgArgv[]{"aProgram", "anArgumentOfLength20"}; From a850ec88081294c935c52b890b20fbc44e28605a Mon Sep 17 00:00:00 2001 From: Yi Wu Date: Fri, 10 Nov 2023 17:02:34 +0000 Subject: [PATCH 3/3] add assert false on windows, better to have compile waring in future Or replace by a printf? So the program won't be terminated by force. --- flang/runtime/command.cpp | 5 ++++- flang/test/Lower/Intrinsics/getuid.f90 | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/flang/runtime/command.cpp b/flang/runtime/command.cpp index 3298e8133cac2..132fe0da06a8b 100644 --- a/flang/runtime/command.cpp +++ b/flang/runtime/command.cpp @@ -16,7 +16,10 @@ #include #ifdef _WIN32 -inline uid_t getuid() { return 0; } +inline uid_t getuid() { + assert(false && "Unimplemented on Windows OS"); + return 0; +} #else #include #endif diff --git a/flang/test/Lower/Intrinsics/getuid.f90 b/flang/test/Lower/Intrinsics/getuid.f90 index 0cc9c154d0b7f..6f67e602dc7ad 100644 --- a/flang/test/Lower/Intrinsics/getuid.f90 +++ b/flang/test/Lower/Intrinsics/getuid.f90 @@ -11,4 +11,4 @@ subroutine all_args() integer :: uid uid = getuid() -end \ No newline at end of file +end