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..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 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..e4a5820b57d1e 100644 --- a/flang/include/flang/Runtime/command.h +++ b/flang/include/flang/Runtime/command.h @@ -13,6 +13,12 @@ #include +#ifdef _WIN32 +typedef int uid_t; +#else +#include "sys/types.h" //uid_t +#endif + namespace Fortran::runtime { class Descriptor; @@ -23,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. @@ -47,6 +56,7 @@ std::int32_t RTNAME(GetEnvVariable)(const Descriptor &name, bool trim_name = true, const Descriptor *errmsg = nullptr, const char *sourceFile = nullptr, int line = 0); } + } // 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..971c87452f950 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, @@ -2906,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); 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..132fe0da06a8b 100644 --- a/flang/runtime/command.cpp +++ b/flang/runtime/command.cpp @@ -15,6 +15,15 @@ #include #include +#ifdef _WIN32 +inline uid_t getuid() { + assert(false && "Unimplemented on Windows OS"); + return 0; +} +#else +#include +#endif + namespace Fortran::runtime { std::int32_t RTNAME(ArgumentCount)() { int argc{executionEnvironment.argc}; @@ -25,6 +34,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..6f67e602dc7ad --- /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 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..80593b3e907be 100644 --- a/flang/unittests/Runtime/CommandTest.cpp +++ b/flang/unittests/Runtime/CommandTest.cpp @@ -227,6 +227,12 @@ TEST_F(ZeroArguments, GetCommandArgument) { TEST_F(ZeroArguments, GetCommand) { CheckCommandValue(commandOnlyArgv, 1); } +TEST_F(ZeroArguments, GetUID) { + CheckMissingArgumentValue(-1); + CheckArgumentValue(commandOnlyArgv[0], 0); + CheckMissingArgumentValue(1); +} + static const char *oneArgArgv[]{"aProgram", "anArgumentOfLength20"}; class OneArgument : public CommandFixture { protected: