Skip to content

Commit 054eadc

Browse files
DavidTrubyyiwu0b11
andauthored
[flang] Implement GETUID and GETGID intrinsics (llvm#108017)
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 <yi.wu2@arm.com> --------- Co-authored-by: Yi Wu <yi.wu2@arm.com>
1 parent ec08c11 commit 054eadc

File tree

17 files changed

+138
-2
lines changed

17 files changed

+138
-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/Intrinsics.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ void genDateAndTime(fir::FirOpBuilder &, mlir::Location,
4747
void genEtime(fir::FirOpBuilder &builder, mlir::Location loc,
4848
mlir::Value values, mlir::Value time);
4949

50+
mlir::Value genGetUID(fir::FirOpBuilder &, mlir::Location);
51+
mlir::Value genGetGID(fir::FirOpBuilder &, mlir::Location);
52+
5053
void genRandomInit(fir::FirOpBuilder &, mlir::Location, mlir::Value repeatable,
5154
mlir::Value imageDistinct);
5255
void genRandomNumber(fir::FirOpBuilder &, mlir::Location, mlir::Value harvest);

flang/include/flang/Runtime/extensions.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@
2020
#include <cstddef>
2121
#include <cstdint>
2222

23+
#ifdef _WIN32
24+
// UID and GID don't exist on Windows, these exist to avoid errors.
25+
typedef std::uint32_t uid_t;
26+
typedef std::uint32_t gid_t;
27+
#else
28+
#include "sys/types.h" //pid_t
29+
#endif
30+
2331
extern "C" {
2432

2533
// CALL FLUSH(n) antedates the Fortran 2003 FLUSH statement.
@@ -35,6 +43,12 @@ std::int32_t FORTRAN_PROCEDURE_NAME(iargc)();
3543
void FORTRAN_PROCEDURE_NAME(getarg)(
3644
std::int32_t &n, char *arg, std::int64_t length);
3745

46+
// Calls getgid()
47+
gid_t RTNAME(GetGID)();
48+
49+
// Calls getuid()
50+
uid_t RTNAME(GetUID)();
51+
3852
// GNU extension subroutine GETLOG(C).
3953
void FORTRAN_PROCEDURE_NAME(getlog)(char *name, std::int64_t length);
4054

flang/include/flang/Tools/TargetSetup.h

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

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

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/Intrinsics.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,22 @@ void fir::runtime::genEtime(fir::FirOpBuilder &builder, mlir::Location loc,
120120
builder.create<fir::CallOp>(loc, runtimeFunc, args);
121121
}
122122

123+
mlir::Value fir::runtime::genGetGID(fir::FirOpBuilder &builder,
124+
mlir::Location loc) {
125+
auto runtimeFunc =
126+
fir::runtime::getRuntimeFunc<mkRTKey(GetGID)>(loc, builder);
127+
128+
return builder.create<fir::CallOp>(loc, runtimeFunc).getResult(0);
129+
}
130+
131+
mlir::Value fir::runtime::genGetUID(fir::FirOpBuilder &builder,
132+
mlir::Location loc) {
133+
auto runtimeFunc =
134+
fir::runtime::getRuntimeFunc<mkRTKey(GetUID)>(loc, builder);
135+
136+
return builder.create<fir::CallOp>(loc, runtimeFunc).getResult(0);
137+
}
138+
123139
void fir::runtime::genRandomInit(fir::FirOpBuilder &builder, mlir::Location loc,
124140
mlir::Value repeatable,
125141
mlir::Value imageDistinct) {

flang/lib/Semantics/check-call.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2028,6 +2028,22 @@ bool CheckPPCIntrinsic(const Symbol &generic, const Symbol &specific,
20282028
return false;
20292029
}
20302030

2031+
bool CheckWindowsIntrinsic(
2032+
const Symbol &intrinsic, evaluate::FoldingContext &foldingContext) {
2033+
parser::ContextualMessages &messages{foldingContext.messages()};
2034+
// TODO: there are other intrinsics that are unsupported on Windows that
2035+
// should be added here.
2036+
if (intrinsic.name() == "getuid") {
2037+
messages.Say(
2038+
"User IDs do not exist on Windows. This function will always return 1"_warn_en_US);
2039+
}
2040+
if (intrinsic.name() == "getgid") {
2041+
messages.Say(
2042+
"Group IDs do not exist on Windows. This function will always return 1"_warn_en_US);
2043+
}
2044+
return true;
2045+
}
2046+
20312047
bool CheckArguments(const characteristics::Procedure &proc,
20322048
evaluate::ActualArguments &actuals, SemanticsContext &context,
20332049
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
@@ -2916,6 +2916,9 @@ auto ExpressionAnalyzer::GetCalleeAndArguments(const parser::Name &name,
29162916
} else {
29172917
resolution = symbol;
29182918
}
2919+
if (resolution && context_.targetCharacteristics().isOSWindows()) {
2920+
semantics::CheckWindowsIntrinsic(*resolution, GetFoldingContext());
2921+
}
29192922
if (!resolution || resolution->attrs().test(semantics::Attr::INTRINSIC)) {
29202923
auto name{resolution ? resolution->name() : ultimate.name()};
29212924
if (std::optional<SpecificCall> specificCall{context_.intrinsics().Probe(

flang/runtime/extensions.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,24 @@ extern "C" {
5858

5959
namespace Fortran::runtime {
6060

61+
gid_t RTNAME(GetGID)() {
62+
#ifdef _WIN32
63+
// Group IDs don't exist on Windows, return 1 to avoid errors
64+
return 1;
65+
#else
66+
return getgid();
67+
#endif
68+
}
69+
70+
uid_t RTNAME(GetUID)() {
71+
#ifdef _WIN32
72+
// User IDs don't exist on Windows, return 1 to avoid errors
73+
return 1;
74+
#else
75+
return getuid();
76+
#endif
77+
}
78+
6179
void GetUsernameEnvVar(const char *envName, char *arg, std::int64_t length) {
6280
Descriptor name{*Descriptor::Create(
6381
1, std::strlen(envName) + 1, const_cast<char *>(envName), 0)};
@@ -66,6 +84,7 @@ void GetUsernameEnvVar(const char *envName, char *arg, std::int64_t length) {
6684
RTNAME(GetEnvVariable)
6785
(name, &value, nullptr, false, nullptr, __FILE__, __LINE__);
6886
}
87+
6988
namespace io {
7089
// SUBROUTINE FLUSH(N)
7190
// FLUSH N

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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,4 @@ TEST_F(RuntimeCallTest, genGetPID) {
5050
mlir::Value result = fir::runtime::genGetPID(*firBuilder, loc);
5151
checkCallOp(result.getDefiningOp(), "_FortranAGetPID", /*nbArgs=*/0,
5252
/*addLocArgs=*/false);
53-
}
53+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include "flang/Optimizer/Builder/Runtime/Intrinsics.h"
2+
#include "RuntimeCallTestBase.h"
3+
#include "gtest/gtest.h"
4+
5+
TEST_F(RuntimeCallTest, genGetGID) {
6+
mlir::Location loc = firBuilder->getUnknownLoc();
7+
mlir::Value result = fir::runtime::genGetGID(*firBuilder, loc);
8+
checkCallOp(result.getDefiningOp(), "_FortranAGetGID", /*nbArgs=*/0,
9+
/*addLocArgs=*/false);
10+
}
11+
12+
TEST_F(RuntimeCallTest, genGetUID) {
13+
mlir::Location loc = firBuilder->getUnknownLoc();
14+
mlir::Value result = fir::runtime::genGetUID(*firBuilder, loc);
15+
checkCallOp(result.getDefiningOp(), "_FortranAGetUID", /*nbArgs=*/0,
16+
/*addLocArgs=*/false);
17+
}

flang/unittests/Optimizer/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ add_flang_unittest(FlangOptimizerTests
2525
Builder/Runtime/CommandTest.cpp
2626
Builder/Runtime/CharacterTest.cpp
2727
Builder/Runtime/DerivedTest.cpp
28+
Builder/Runtime/IntrinsicsTest.cpp
2829
Builder/Runtime/NumericTest.cpp
2930
Builder/Runtime/RaggedTest.cpp
3031
Builder/Runtime/ReductionTest.cpp

0 commit comments

Comments
 (0)