[flang-commits] [flang] af63d17 - [flang] GET_COMMAND_ARGUMENT(LENGTH) runtime implementation

Diana Picus via flang-commits flang-commits at lists.llvm.org
Tue Sep 28 01:37:58 PDT 2021


Author: Diana Picus
Date: 2021-09-28T08:32:19Z
New Revision: af63d1791b102ed8bdd8b836ce8ab773c019d1a1

URL: https://github.com/llvm/llvm-project/commit/af63d1791b102ed8bdd8b836ce8ab773c019d1a1
DIFF: https://github.com/llvm/llvm-project/commit/af63d1791b102ed8bdd8b836ce8ab773c019d1a1.diff

LOG: [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

Added: 
    

Modified: 
    flang/include/flang/Runtime/command.h
    flang/runtime/command.cpp
    flang/test/Runtime/no-cpp-dep.c
    flang/unittests/Runtime/CommandTest.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Runtime/command.h b/flang/include/flang/Runtime/command.h
index 5e98b41072918..f5f20a5a4f29a 100644
--- a/flang/include/flang/Runtime/command.h
+++ b/flang/include/flang/Runtime/command.h
@@ -9,9 +9,10 @@
 #ifndef FORTRAN_RUNTIME_COMMAND_H_
 #define FORTRAN_RUNTIME_COMMAND_H_
 
-#include "flang/Runtime/cpp-type.h"
 #include "flang/Runtime/entry-names.h"
 
+#include <cstdint>
+
 namespace Fortran::runtime {
 class Descriptor;
 
@@ -20,7 +21,7 @@ extern "C" {
 //
 // Lowering may need to cast the result to match the precision of the default
 // integer kind.
-CppTypeFor<TypeCategory::Integer, 4> RTNAME(ArgumentCount)();
+std::int32_t RTNAME(ArgumentCount)();
 
 // 16.9.83 GET_COMMAND_ARGUMENT
 // We're breaking up the interface into several 
diff erent functions, since most
@@ -28,14 +29,12 @@ CppTypeFor<TypeCategory::Integer, 4> RTNAME(ArgumentCount)();
 
 // Try to get the value of the n'th argument.
 // Returns a STATUS as described in the standard.
-CppTypeFor<TypeCategory::Integer, 4> RTNAME(ArgumentValue)(
-    CppTypeFor<TypeCategory::Integer, 4> n, const Descriptor *value,
-    const Descriptor *errmsg);
+std::int32_t RTNAME(ArgumentValue)(
+    std::int32_t n, const Descriptor *value, const Descriptor *errmsg);
 
 // Try to get the significant length of the n'th argument.
 // Returns 0 if it doesn't manage.
-CppTypeFor<TypeCategory::Integer, 4> RTNAME(ArgumentLength)(
-    CppTypeFor<TypeCategory::Integer, 4> n);
+std::int64_t RTNAME(ArgumentLength)(std::int32_t n);
 }
 } // namespace Fortran::runtime
 

diff  --git a/flang/runtime/command.cpp b/flang/runtime/command.cpp
index 5d11d6c0c96c8..1a55061749a1c 100644
--- a/flang/runtime/command.cpp
+++ b/flang/runtime/command.cpp
@@ -8,9 +8,10 @@
 
 #include "flang/Runtime/command.h"
 #include "environment.h"
+#include <limits>
 
 namespace Fortran::runtime {
-CppTypeFor<TypeCategory::Integer, 4> RTNAME(ArgumentCount)() {
+std::int32_t RTNAME(ArgumentCount)() {
   int argc{executionEnvironment.argc};
   if (argc > 1) {
     // C counts the command name as one of the arguments, but Fortran doesn't.
@@ -18,4 +19,19 @@ CppTypeFor<TypeCategory::Integer, 4> RTNAME(ArgumentCount)() {
   }
   return 0;
 }
+
+std::int64_t RTNAME(ArgumentLength)(std::int32_t n) {
+  if (n < 0 || n >= executionEnvironment.argc) {
+    return 0;
+  }
+
+  std::size_t length{std::strlen(executionEnvironment.argv[n])};
+  if constexpr (sizeof(std::size_t) <= sizeof(std::int64_t)) {
+    return static_cast<std::int64_t>(length);
+  } else {
+    std::size_t max{std::numeric_limits<std::int64_t>::max()};
+    return length > max ? 0 // Just fail.
+                        : static_cast<std::int64_t>(length);
+  }
+}
 } // namespace Fortran::runtime

diff  --git a/flang/test/Runtime/no-cpp-dep.c b/flang/test/Runtime/no-cpp-dep.c
index 9f3b8b9269eed..9970e098c34ff 100644
--- a/flang/test/Runtime/no-cpp-dep.c
+++ b/flang/test/Runtime/no-cpp-dep.c
@@ -5,19 +5,29 @@ a C compiler.
 
 REQUIRES: c-compiler
 
-RUN: %cc -std=c90 %s -I%include %libruntime %libdecimal -o /dev/null
+RUN: %cc -std=c99 %s -I%include %libruntime %libdecimal -lm -o /dev/null
 */
 
 #include "flang/Runtime/entry-names.h"
+#include <stdint.h>
 
 /*
 Manually add declarations for the runtime functions that we want to make sure
 we're testing. We can't include any headers directly since they likely contain
 C++ code that would explode here.
 */
+struct Descriptor;
+
 double RTNAME(CpuTime)();
 
+void RTNAME(ProgramStart)(int, const char *[], const char *[]);
+int32_t RTNAME(ArgumentCount)();
+int64_t RTNAME(ArgumentLength)(int32_t);
+
 int main() {
   double x = RTNAME(CpuTime)();
-  return x;
+  RTNAME(ProgramStart)(0, 0, 0);
+  int32_t c = RTNAME(ArgumentCount)();
+  int32_t l = RTNAME(ArgumentLength)(0);
+  return x + c + l;
 }

diff  --git a/flang/unittests/Runtime/CommandTest.cpp b/flang/unittests/Runtime/CommandTest.cpp
index 84a05fc34e10b..3841bbe0ed3ba 100644
--- a/flang/unittests/Runtime/CommandTest.cpp
+++ b/flang/unittests/Runtime/CommandTest.cpp
@@ -13,20 +13,61 @@
 
 using namespace Fortran::runtime;
 
-TEST(ArgumentCount, ZeroArguments) {
-  const char *argv[]{"aProgram"};
-  RTNAME(ProgramStart)(1, argv, {});
-  EXPECT_EQ(0, RTNAME(ArgumentCount)());
+class CommandFixture : public ::testing::Test {
+protected:
+  CommandFixture(int argc, const char *argv[]) {
+    RTNAME(ProgramStart)(argc, argv, {});
+  }
+};
+
+static const char *commandOnlyArgv[]{"aProgram"};
+class ZeroArguments : public CommandFixture {
+protected:
+  ZeroArguments() : CommandFixture(1, commandOnlyArgv) {}
+};
+
+TEST_F(ZeroArguments, ArgumentCount) { EXPECT_EQ(0, RTNAME(ArgumentCount)()); }
+
+TEST_F(ZeroArguments, ArgumentLength) {
+  EXPECT_EQ(0, RTNAME(ArgumentLength)(-1));
+  EXPECT_EQ(8, RTNAME(ArgumentLength)(0));
+  EXPECT_EQ(0, RTNAME(ArgumentLength)(1));
 }
 
-TEST(ArgumentCount, OneArgument) {
-  const char *argv[]{"aProgram", "anArgument"};
-  RTNAME(ProgramStart)(2, argv, {});
-  EXPECT_EQ(1, RTNAME(ArgumentCount)());
+static const char *oneArgArgv[]{"aProgram", "anArgumentOfLength20"};
+class OneArgument : public CommandFixture {
+protected:
+  OneArgument() : CommandFixture(2, oneArgArgv) {}
+};
+
+TEST_F(OneArgument, ArgumentCount) { EXPECT_EQ(1, RTNAME(ArgumentCount)()); }
+
+TEST_F(OneArgument, ArgumentLength) {
+  EXPECT_EQ(0, RTNAME(ArgumentLength)(-1));
+  EXPECT_EQ(8, RTNAME(ArgumentLength)(0));
+  EXPECT_EQ(20, RTNAME(ArgumentLength)(1));
+  EXPECT_EQ(0, RTNAME(ArgumentLength)(2));
 }
 
-TEST(ArgumentCount, SeveralArguments) {
-  const char *argv[]{"aProgram", "arg1", "arg2", "arg3", "arg4"};
-  RTNAME(ProgramStart)(5, argv, {});
+static const char *severalArgsArgv[]{
+    "aProgram", "16-char-long-arg", "", "-22-character-long-arg", "o"};
+class SeveralArguments : public CommandFixture {
+protected:
+  SeveralArguments()
+      : CommandFixture(sizeof(severalArgsArgv) / sizeof(*severalArgsArgv),
+            severalArgsArgv) {}
+};
+
+TEST_F(SeveralArguments, ArgumentCount) {
   EXPECT_EQ(4, RTNAME(ArgumentCount)());
 }
+
+TEST_F(SeveralArguments, ArgumentLength) {
+  EXPECT_EQ(0, RTNAME(ArgumentLength)(-1));
+  EXPECT_EQ(8, RTNAME(ArgumentLength)(0));
+  EXPECT_EQ(16, RTNAME(ArgumentLength)(1));
+  EXPECT_EQ(0, RTNAME(ArgumentLength)(2));
+  EXPECT_EQ(22, RTNAME(ArgumentLength)(3));
+  EXPECT_EQ(1, RTNAME(ArgumentLength)(4));
+  EXPECT_EQ(0, RTNAME(ArgumentLength)(5));
+}


        


More information about the flang-commits mailing list