Skip to content

Commit 74242ef

Browse files
DavidTrubyyiwu0b11
andcommitted
[flang] Implement GETUID and GETGID intrinsics
GETUID and GETGID are non-standard intrinsics supported by a number of other Fortran compilers. On supported platforms these intrinsics simply call the POSIX getuid() and getgid() functions and return the result. The only platform we support that does not have these is Windows. Windows does not have the same concept of UIDs and GIDs, so on Windows we issue a warning indicating this and return 1 from both functions. Co-authored-by: Yi Wu <[email protected]>
1 parent 1f2a634 commit 74242ef

File tree

16 files changed

+136
-2
lines changed

16 files changed

+136
-2
lines changed

flang/docs/Intrinsics.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,7 @@ This phase currently supports all the intrinsic procedures listed above but the
765765
| Coarray intrinsic functions | COSHAPE |
766766
| Object characteristic inquiry functions | ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, IS_CONTIGUOUS, PRESENT, RANK, SAME_TYPE, STORAGE_SIZE |
767767
| Type inquiry intrinsic functions | BIT_SIZE, DIGITS, EPSILON, HUGE, KIND, MAXEXPONENT, MINEXPONENT, NEW_LINE, PRECISION, RADIX, RANGE, TINY|
768-
| 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 |
768+
| 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, GETUID, GETGID |
769769
| 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, SIGNAL, SLEEP, SYSTEM, SYSTEM_CLOCK |
770770
| Atomic intrinsic subroutines | ATOMIC_ADD |
771771
| Collective intrinsic subroutines | CO_REDUCE |

flang/include/flang/Evaluate/target.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ class TargetCharacteristics {
102102
bool isPPC() const { return isPPC_; }
103103
void set_isPPC(bool isPPC = false);
104104

105+
bool isOSWindows() const { return isOSWindows_; }
106+
void set_isOSWindows(bool isOSWindows = false) {
107+
isOSWindows_ = isOSWindows;
108+
};
109+
105110
IeeeFeatures &ieeeFeatures() { return ieeeFeatures_; }
106111
const IeeeFeatures &ieeeFeatures() const { return ieeeFeatures_; }
107112

@@ -111,6 +116,7 @@ class TargetCharacteristics {
111116
std::uint8_t align_[common::TypeCategory_enumSize][maxKind]{};
112117
bool isBigEndian_{false};
113118
bool isPPC_{false};
119+
bool isOSWindows_{false};
114120
bool areSubnormalsFlushedToZero_{false};
115121
Rounding roundingMode_{defaultRounding};
116122
std::size_t procedurePointerByteSize_{8};

flang/include/flang/Optimizer/Builder/IntrinsicCall.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ struct IntrinsicLibrary {
256256
llvm::ArrayRef<mlir::Value> args);
257257
void genGetCommandArgument(mlir::ArrayRef<fir::ExtendedValue> args);
258258
void genGetEnvironmentVariable(llvm::ArrayRef<fir::ExtendedValue>);
259+
mlir::Value genGetGID(mlir::Type resultType,
260+
llvm::ArrayRef<mlir::Value> args);
261+
mlir::Value genGetUID(mlir::Type resultType,
262+
llvm::ArrayRef<mlir::Value> args);
259263
fir::ExtendedValue genIall(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
260264
mlir::Value genIand(mlir::Type, llvm::ArrayRef<mlir::Value>);
261265
fir::ExtendedValue genIany(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);

flang/include/flang/Optimizer/Builder/Runtime/Command.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,8 @@ mlir::Value genGetEnvVariable(fir::FirOpBuilder &, mlir::Location,
5858
mlir::Value genGetCwd(fir::FirOpBuilder &builder, mlir::Location loc,
5959
mlir::Value c);
6060

61+
mlir::Value genGetUID(fir::FirOpBuilder &, mlir::Location);
62+
mlir::Value genGetGID(fir::FirOpBuilder &, mlir::Location);
63+
6164
} // namespace fir::runtime
6265
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_COMMAND_H

flang/include/flang/Runtime/command.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
#ifdef _WIN32
1616
// On Windows* OS GetCurrentProcessId returns DWORD aka uint32_t
1717
typedef std::uint32_t pid_t;
18+
// UID and GID don't exist on Windows, these exist to avoid errors.
19+
typedef std::uint32_t uid_t;
20+
typedef std::uint32_t gid_t;
1821
#else
1922
#include "sys/types.h" //pid_t
2023
#endif
@@ -29,9 +32,15 @@ extern "C" {
2932
// integer kind.
3033
std::int32_t RTNAME(ArgumentCount)();
3134

35+
// Calls getgid()
36+
gid_t RTNAME(GetGID)();
37+
3238
// Calls getpid()
3339
pid_t RTNAME(GetPID)();
3440

41+
// Calls getuid()
42+
uid_t RTNAME(GetUID)();
43+
3544
// 16.9.82 GET_COMMAND
3645
// Try to get the value of the whole command. All of the parameters are
3746
// optional.

flang/include/flang/Tools/TargetSetup.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ namespace Fortran::tools {
5858
if (targetTriple.isPPC())
5959
targetCharacteristics.set_isPPC(true);
6060

61+
if (targetTriple.isOSWindows())
62+
targetCharacteristics.set_isOSWindows(true);
63+
6164
// TODO: use target machine data layout to set-up the target characteristics
6265
// type size and alignment info.
6366
}

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,9 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
523523
{{"c", DefaultChar, Rank::scalar, Optionality::required,
524524
common::Intent::Out}},
525525
TypePattern{IntType, KindCode::greaterOrEqualToKind, 4}},
526+
{"getgid", {}, DefaultInt},
526527
{"getpid", {}, DefaultInt},
528+
{"getuid", {}, DefaultInt},
527529
{"huge",
528530
{{"x", SameIntOrReal, Rank::anyOrAssumedRank, Optionality::required,
529531
common::Intent::In, {ArgFlag::canBeMoldNull}}},

flang/lib/Optimizer/Builder/IntrinsicCall.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,9 @@ static constexpr IntrinsicHandler handlers[]{
293293
&I::genGetCwd,
294294
{{{"c", asBox}, {"status", asAddr, handleDynamicOptional}}},
295295
/*isElemental=*/false},
296+
{"getgid", &I::genGetGID},
296297
{"getpid", &I::genGetPID},
298+
{"getuid", &I::genGetUID},
297299
{"iachar", &I::genIchar},
298300
{"iall",
299301
&I::genIall,
@@ -3650,6 +3652,14 @@ void IntrinsicLibrary::genGetCommand(llvm::ArrayRef<fir::ExtendedValue> args) {
36503652
}
36513653
}
36523654

3655+
// GETGID
3656+
mlir::Value IntrinsicLibrary::genGetGID(mlir::Type resultType,
3657+
llvm::ArrayRef<mlir::Value> args) {
3658+
assert(args.size() == 0 && "getgid takes no input");
3659+
return builder.createConvert(loc, resultType,
3660+
fir::runtime::genGetGID(builder, loc));
3661+
}
3662+
36533663
// GETPID
36543664
mlir::Value IntrinsicLibrary::genGetPID(mlir::Type resultType,
36553665
llvm::ArrayRef<mlir::Value> args) {
@@ -3658,6 +3668,14 @@ mlir::Value IntrinsicLibrary::genGetPID(mlir::Type resultType,
36583668
fir::runtime::genGetPID(builder, loc));
36593669
}
36603670

3671+
// GETUID
3672+
mlir::Value IntrinsicLibrary::genGetUID(mlir::Type resultType,
3673+
llvm::ArrayRef<mlir::Value> args) {
3674+
assert(args.size() == 0 && "getgid takes no input");
3675+
return builder.createConvert(loc, resultType,
3676+
fir::runtime::genGetUID(builder, loc));
3677+
}
3678+
36613679
// GET_COMMAND_ARGUMENT
36623680
void IntrinsicLibrary::genGetCommandArgument(
36633681
llvm::ArrayRef<fir::ExtendedValue> args) {

flang/lib/Optimizer/Builder/Runtime/Command.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ mlir::Value fir::runtime::genGetCommand(fir::FirOpBuilder &builder,
4848
return builder.create<fir::CallOp>(loc, runtimeFunc, args).getResult(0);
4949
}
5050

51+
mlir::Value fir::runtime::genGetGID(fir::FirOpBuilder &builder,
52+
mlir::Location loc) {
53+
auto runtimeFunc =
54+
fir::runtime::getRuntimeFunc<mkRTKey(GetGID)>(loc, builder);
55+
56+
return builder.create<fir::CallOp>(loc, runtimeFunc).getResult(0);
57+
}
58+
5159
mlir::Value fir::runtime::genGetPID(fir::FirOpBuilder &builder,
5260
mlir::Location loc) {
5361
auto runtimeFunc =
@@ -56,6 +64,14 @@ mlir::Value fir::runtime::genGetPID(fir::FirOpBuilder &builder,
5664
return builder.create<fir::CallOp>(loc, runtimeFunc).getResult(0);
5765
}
5866

67+
mlir::Value fir::runtime::genGetUID(fir::FirOpBuilder &builder,
68+
mlir::Location loc) {
69+
auto runtimeFunc =
70+
fir::runtime::getRuntimeFunc<mkRTKey(GetUID)>(loc, builder);
71+
72+
return builder.create<fir::CallOp>(loc, runtimeFunc).getResult(0);
73+
}
74+
5975
mlir::Value fir::runtime::genGetCommandArgument(
6076
fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value number,
6177
mlir::Value value, mlir::Value length, mlir::Value errmsg) {

flang/lib/Semantics/check-call.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2020,6 +2020,20 @@ bool CheckPPCIntrinsic(const Symbol &generic, const Symbol &specific,
20202020
return false;
20212021
}
20222022

2023+
bool CheckWindowsIntrinsic(
2024+
const Symbol &intrinsic, evaluate::FoldingContext &foldingContext) {
2025+
parser::ContextualMessages &messages{foldingContext.messages()};
2026+
if (intrinsic.name() == "getuid") {
2027+
messages.Say(
2028+
"User IDs do not exist on Windows. This function will always return 1"_warn_en_US);
2029+
}
2030+
if (intrinsic.name() == "getgid") {
2031+
messages.Say(
2032+
"Group IDs do not exist on Windows. This function will always return 1"_warn_en_US);
2033+
}
2034+
return true;
2035+
}
2036+
20232037
bool CheckArguments(const characteristics::Procedure &proc,
20242038
evaluate::ActualArguments &actuals, SemanticsContext &context,
20252039
const Scope &scope, bool treatingExternalAsImplicit,

flang/lib/Semantics/check-call.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ bool CheckArguments(const evaluate::characteristics::Procedure &,
4141
bool CheckPPCIntrinsic(const Symbol &generic, const Symbol &specific,
4242
const evaluate::ActualArguments &actuals,
4343
evaluate::FoldingContext &context);
44+
bool CheckWindowsIntrinsic(
45+
const Symbol &intrinsic, evaluate::FoldingContext &context);
4446
bool CheckArgumentIsConstantExprInRange(
4547
const evaluate::ActualArguments &actuals, int index, int lowerBound,
4648
int upperBound, parser::ContextualMessages &messages);

flang/lib/Semantics/expression.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2905,6 +2905,9 @@ auto ExpressionAnalyzer::GetCalleeAndArguments(const parser::Name &name,
29052905
} else {
29062906
resolution = symbol;
29072907
}
2908+
if (resolution && context_.targetCharacteristics().isOSWindows()) {
2909+
semantics::CheckWindowsIntrinsic(*resolution, GetFoldingContext());
2910+
}
29082911
if (!resolution || resolution->attrs().test(semantics::Attr::INTRINSIC)) {
29092912
auto name{resolution ? resolution->name() : ultimate.name()};
29102913
if (std::optional<SpecificCall> specificCall{context_.intrinsics().Probe(

flang/runtime/command.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,26 @@ std::int32_t RTNAME(ArgumentCount)() {
4242
return 0;
4343
}
4444

45+
gid_t RTNAME(GetGID)() {
46+
#ifdef _WIN32
47+
// Group IDs don't exist on Windows, return 1 to avoid errors
48+
return 1;
49+
#else
50+
return getgid();
51+
#endif
52+
}
53+
4554
pid_t RTNAME(GetPID)() { return getpid(); }
4655

56+
uid_t RTNAME(GetUID)() {
57+
#ifdef _WIN32
58+
// User IDs don't exist on Windows, return 1 to avoid errors
59+
return 1;
60+
#else
61+
return getuid();
62+
#endif
63+
}
64+
4765
// Returns the length of the \p string. Assumes \p string is valid.
4866
static std::int64_t StringLength(const char *string) {
4967
std::size_t length{std::strlen(string)};

flang/test/Semantics/windows.f90

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
! RUN: %python %S/test_errors.py %s %flang --target=x86_64-pc-windows-msvc -Werror
2+
! RUN: %python %S/test_errors.py %s %flang --target=aarch64-pc-windows-msvc -Werror
3+
4+
subroutine uid
5+
!WARNING: User IDs do not exist on Windows. This function will always return 1
6+
i = getuid()
7+
end subroutine uid
8+
9+
subroutine gid
10+
!WARNING: Group IDs do not exist on Windows. This function will always return 1
11+
i = getgid()
12+
end subroutine gid

flang/unittests/Optimizer/Builder/Runtime/CommandTest.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,23 @@ TEST_F(RuntimeCallTest, genGetEnvVariable) {
4545
/*addLocArgs=*/true);
4646
}
4747

48+
TEST_F(RuntimeCallTest, genGetGID) {
49+
mlir::Location loc = firBuilder->getUnknownLoc();
50+
mlir::Value result = fir::runtime::genGetGID(*firBuilder, loc);
51+
checkCallOp(result.getDefiningOp(), "_FortranAGetGID", /*nbArgs=*/0,
52+
/*addLocArgs=*/false);
53+
}
54+
4855
TEST_F(RuntimeCallTest, genGetPID) {
4956
mlir::Location loc = firBuilder->getUnknownLoc();
5057
mlir::Value result = fir::runtime::genGetPID(*firBuilder, loc);
5158
checkCallOp(result.getDefiningOp(), "_FortranAGetPID", /*nbArgs=*/0,
5259
/*addLocArgs=*/false);
53-
}
60+
}
61+
62+
TEST_F(RuntimeCallTest, genGetUID) {
63+
mlir::Location loc = firBuilder->getUnknownLoc();
64+
mlir::Value result = fir::runtime::genGetUID(*firBuilder, loc);
65+
checkCallOp(result.getDefiningOp(), "_FortranAGetUID", /*nbArgs=*/0,
66+
/*addLocArgs=*/false);
67+
}

flang/unittests/Runtime/CommandTest.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,11 +689,21 @@ TEST_F(OnlyValidArguments, GetCommandShortLength) {
689689
CheckDescriptorEqInt<short>(length.get(), 51);
690690
}
691691

692+
TEST_F(ZeroArguments, GetGID) {
693+
// gid cannot be negative
694+
EXPECT_GE(RTNAME(GetGID)(), 0u);
695+
}
696+
692697
TEST_F(ZeroArguments, GetPID) {
693698
// pid should always greater than 0, in both linux and windows
694699
EXPECT_GT(RTNAME(GetPID)(), 0);
695700
}
696701

702+
TEST_F(ZeroArguments, GetUID) {
703+
// uid cannot be negative
704+
EXPECT_GE(RTNAME(GetUID)(), 0u);
705+
}
706+
697707
class EnvironmentVariables : public CommandFixture {
698708
protected:
699709
EnvironmentVariables() : CommandFixture(0, nullptr) {

0 commit comments

Comments
 (0)