Skip to content

Commit af63d17

Browse files
committed
[flang] GET_COMMAND_ARGUMENT(LENGTH) runtime implementation
Implement the ArgumentLength entry point of GET_COMMAND_ARGUMENT. Also introduce a fixture for the tests. Note that this also changes the interface for ArgumentLength from returning a 4-byte integer to returning an 8-byte integer. Differential Revision: https://reviews.llvm.org/D109227
1 parent 7394d3b commit af63d17

File tree

4 files changed

+87
-21
lines changed

4 files changed

+87
-21
lines changed

flang/include/flang/Runtime/command.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99
#ifndef FORTRAN_RUNTIME_COMMAND_H_
1010
#define FORTRAN_RUNTIME_COMMAND_H_
1111

12-
#include "flang/Runtime/cpp-type.h"
1312
#include "flang/Runtime/entry-names.h"
1413

14+
#include <cstdint>
15+
1516
namespace Fortran::runtime {
1617
class Descriptor;
1718

@@ -20,22 +21,20 @@ extern "C" {
2021
//
2122
// Lowering may need to cast the result to match the precision of the default
2223
// integer kind.
23-
CppTypeFor<TypeCategory::Integer, 4> RTNAME(ArgumentCount)();
24+
std::int32_t RTNAME(ArgumentCount)();
2425

2526
// 16.9.83 GET_COMMAND_ARGUMENT
2627
// We're breaking up the interface into several different functions, since most
2728
// of the parameters are optional.
2829

2930
// Try to get the value of the n'th argument.
3031
// Returns a STATUS as described in the standard.
31-
CppTypeFor<TypeCategory::Integer, 4> RTNAME(ArgumentValue)(
32-
CppTypeFor<TypeCategory::Integer, 4> n, const Descriptor *value,
33-
const Descriptor *errmsg);
32+
std::int32_t RTNAME(ArgumentValue)(
33+
std::int32_t n, const Descriptor *value, const Descriptor *errmsg);
3434

3535
// Try to get the significant length of the n'th argument.
3636
// Returns 0 if it doesn't manage.
37-
CppTypeFor<TypeCategory::Integer, 4> RTNAME(ArgumentLength)(
38-
CppTypeFor<TypeCategory::Integer, 4> n);
37+
std::int64_t RTNAME(ArgumentLength)(std::int32_t n);
3938
}
4039
} // namespace Fortran::runtime
4140

flang/runtime/command.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,30 @@
88

99
#include "flang/Runtime/command.h"
1010
#include "environment.h"
11+
#include <limits>
1112

1213
namespace Fortran::runtime {
13-
CppTypeFor<TypeCategory::Integer, 4> RTNAME(ArgumentCount)() {
14+
std::int32_t RTNAME(ArgumentCount)() {
1415
int argc{executionEnvironment.argc};
1516
if (argc > 1) {
1617
// C counts the command name as one of the arguments, but Fortran doesn't.
1718
return argc - 1;
1819
}
1920
return 0;
2021
}
22+
23+
std::int64_t RTNAME(ArgumentLength)(std::int32_t n) {
24+
if (n < 0 || n >= executionEnvironment.argc) {
25+
return 0;
26+
}
27+
28+
std::size_t length{std::strlen(executionEnvironment.argv[n])};
29+
if constexpr (sizeof(std::size_t) <= sizeof(std::int64_t)) {
30+
return static_cast<std::int64_t>(length);
31+
} else {
32+
std::size_t max{std::numeric_limits<std::int64_t>::max()};
33+
return length > max ? 0 // Just fail.
34+
: static_cast<std::int64_t>(length);
35+
}
36+
}
2137
} // namespace Fortran::runtime

flang/test/Runtime/no-cpp-dep.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,29 @@ a C compiler.
55
66
REQUIRES: c-compiler
77
8-
RUN: %cc -std=c90 %s -I%include %libruntime %libdecimal -o /dev/null
8+
RUN: %cc -std=c99 %s -I%include %libruntime %libdecimal -lm -o /dev/null
99
*/
1010

1111
#include "flang/Runtime/entry-names.h"
12+
#include <stdint.h>
1213

1314
/*
1415
Manually add declarations for the runtime functions that we want to make sure
1516
we're testing. We can't include any headers directly since they likely contain
1617
C++ code that would explode here.
1718
*/
19+
struct Descriptor;
20+
1821
double RTNAME(CpuTime)();
1922

23+
void RTNAME(ProgramStart)(int, const char *[], const char *[]);
24+
int32_t RTNAME(ArgumentCount)();
25+
int64_t RTNAME(ArgumentLength)(int32_t);
26+
2027
int main() {
2128
double x = RTNAME(CpuTime)();
22-
return x;
29+
RTNAME(ProgramStart)(0, 0, 0);
30+
int32_t c = RTNAME(ArgumentCount)();
31+
int32_t l = RTNAME(ArgumentLength)(0);
32+
return x + c + l;
2333
}

flang/unittests/Runtime/CommandTest.cpp

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,61 @@
1313

1414
using namespace Fortran::runtime;
1515

16-
TEST(ArgumentCount, ZeroArguments) {
17-
const char *argv[]{"aProgram"};
18-
RTNAME(ProgramStart)(1, argv, {});
19-
EXPECT_EQ(0, RTNAME(ArgumentCount)());
16+
class CommandFixture : public ::testing::Test {
17+
protected:
18+
CommandFixture(int argc, const char *argv[]) {
19+
RTNAME(ProgramStart)(argc, argv, {});
20+
}
21+
};
22+
23+
static const char *commandOnlyArgv[]{"aProgram"};
24+
class ZeroArguments : public CommandFixture {
25+
protected:
26+
ZeroArguments() : CommandFixture(1, commandOnlyArgv) {}
27+
};
28+
29+
TEST_F(ZeroArguments, ArgumentCount) { EXPECT_EQ(0, RTNAME(ArgumentCount)()); }
30+
31+
TEST_F(ZeroArguments, ArgumentLength) {
32+
EXPECT_EQ(0, RTNAME(ArgumentLength)(-1));
33+
EXPECT_EQ(8, RTNAME(ArgumentLength)(0));
34+
EXPECT_EQ(0, RTNAME(ArgumentLength)(1));
2035
}
2136

22-
TEST(ArgumentCount, OneArgument) {
23-
const char *argv[]{"aProgram", "anArgument"};
24-
RTNAME(ProgramStart)(2, argv, {});
25-
EXPECT_EQ(1, RTNAME(ArgumentCount)());
37+
static const char *oneArgArgv[]{"aProgram", "anArgumentOfLength20"};
38+
class OneArgument : public CommandFixture {
39+
protected:
40+
OneArgument() : CommandFixture(2, oneArgArgv) {}
41+
};
42+
43+
TEST_F(OneArgument, ArgumentCount) { EXPECT_EQ(1, RTNAME(ArgumentCount)()); }
44+
45+
TEST_F(OneArgument, ArgumentLength) {
46+
EXPECT_EQ(0, RTNAME(ArgumentLength)(-1));
47+
EXPECT_EQ(8, RTNAME(ArgumentLength)(0));
48+
EXPECT_EQ(20, RTNAME(ArgumentLength)(1));
49+
EXPECT_EQ(0, RTNAME(ArgumentLength)(2));
2650
}
2751

28-
TEST(ArgumentCount, SeveralArguments) {
29-
const char *argv[]{"aProgram", "arg1", "arg2", "arg3", "arg4"};
30-
RTNAME(ProgramStart)(5, argv, {});
52+
static const char *severalArgsArgv[]{
53+
"aProgram", "16-char-long-arg", "", "-22-character-long-arg", "o"};
54+
class SeveralArguments : public CommandFixture {
55+
protected:
56+
SeveralArguments()
57+
: CommandFixture(sizeof(severalArgsArgv) / sizeof(*severalArgsArgv),
58+
severalArgsArgv) {}
59+
};
60+
61+
TEST_F(SeveralArguments, ArgumentCount) {
3162
EXPECT_EQ(4, RTNAME(ArgumentCount)());
3263
}
64+
65+
TEST_F(SeveralArguments, ArgumentLength) {
66+
EXPECT_EQ(0, RTNAME(ArgumentLength)(-1));
67+
EXPECT_EQ(8, RTNAME(ArgumentLength)(0));
68+
EXPECT_EQ(16, RTNAME(ArgumentLength)(1));
69+
EXPECT_EQ(0, RTNAME(ArgumentLength)(2));
70+
EXPECT_EQ(22, RTNAME(ArgumentLength)(3));
71+
EXPECT_EQ(1, RTNAME(ArgumentLength)(4));
72+
EXPECT_EQ(0, RTNAME(ArgumentLength)(5));
73+
}

0 commit comments

Comments
 (0)