[flang] [llvm] [flang-rt] Runtime implementation of extended intrinsic function SECNDS() (PR #152021)

Eugene Epshteyn via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 4 13:51:22 PDT 2025


https://github.com/eugeneepshteyn updated https://github.com/llvm/llvm-project/pull/152021

>From 68a1a813d46719382da3a67a973eb310bccb6e2a Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Mon, 4 Aug 2025 16:00:56 -0400
Subject: [PATCH 1/6] [flang-rt] Runtime implementation of extended intrinsic
 function SECNDS()

---
 flang-rt/lib/runtime/command.cpp         |  7 +++++
 flang-rt/lib/runtime/extensions.cpp      | 39 ++++++++++++++++++++++++
 flang/include/flang/Runtime/command.h    |  2 ++
 flang/include/flang/Runtime/extensions.h |  3 ++
 4 files changed, 51 insertions(+)

diff --git a/flang-rt/lib/runtime/command.cpp b/flang-rt/lib/runtime/command.cpp
index a4e8e31ad0274..40233392f2497 100644
--- a/flang-rt/lib/runtime/command.cpp
+++ b/flang-rt/lib/runtime/command.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "flang/Runtime/command.h"
+#include "flang/Runtime/extensions.h"
 #include "flang-rt/runtime/descriptor.h"
 #include "flang-rt/runtime/environment.h"
 #include "flang-rt/runtime/stat.h"
@@ -309,6 +310,12 @@ std::int32_t RTNAME(Hostnm)(
   return status;
 }
 
+float RTNAME(Secnds)(float* refTime, const char *sourceFile, int line) {
+  Terminator terminator{sourceFile, line};
+  RUNTIME_CHECK(terminator, refTime != nullptr);
+  return FORTRAN_PROCEDURE_NAME(secnds)(refTime);
+}
+
 std::int32_t RTNAME(PutEnv)(
     const char *str, size_t str_length, const char *sourceFile, int line) {
   Terminator terminator{sourceFile, line};
diff --git a/flang-rt/lib/runtime/extensions.cpp b/flang-rt/lib/runtime/extensions.cpp
index f6c39468d5655..4751fb24af849 100644
--- a/flang-rt/lib/runtime/extensions.cpp
+++ b/flang-rt/lib/runtime/extensions.cpp
@@ -303,6 +303,45 @@ void FORTRAN_PROCEDURE_NAME(qsort)(int *array, int *len, int *isize,
 // PERROR(STRING)
 void RTNAME(Perror)(const char *str) { perror(str); }
 
+// GNU extension function SECNDS(refTime)
+float FORTRAN_PROCEDURE_NAME(secnds)(float* refTime) {
+  constexpr float FAIL_SECNDS{1.0f};
+  if (!refTime) {
+    return FAIL_SECNDS;
+  }
+  std::time_t now{std::time(nullptr)};
+  if (now == std::time_t{-1}) {
+    return FAIL_SECNDS;
+  }
+  // In float result, we can only precisely store 2^24 seconds, which
+  // comes out to about 194 days. Thus, need to peek a starting point.
+  // Given the description of this function, midnight of the current
+  // day is the best starting point.
+  static time_t startingPoint{0};
+  if (!startingPoint) {
+    struct tm timeInfo;
+#ifdef _WIN32
+    if (localtime_s(&timeInfo, &now)) {
+      return FAIL_SECNDS;
+    }
+#else
+    if (!localtime_r(&now, &timeInfo)) {
+      return FAIL_SECNDS;
+    }
+#endif
+    // Back to midnight
+    timeInfo.tm_hour = 0;
+    timeInfo.tm_min = 0;
+    timeInfo.tm_sec = 0;
+    startingPoint = std::mktime(&timeInfo);
+    if (startingPoint == std::time_t(-1)) {
+      return FAIL_SECNDS;
+    }
+  }
+  double diffStartingPoint = std::difftime(now, startingPoint);
+  return static_cast<float>(diffStartingPoint) - *refTime;
+}
+
 // GNU extension function TIME()
 std::int64_t RTNAME(time)() { return time(nullptr); }
 
diff --git a/flang/include/flang/Runtime/command.h b/flang/include/flang/Runtime/command.h
index 19b486094da17..21ca1fa8457ee 100644
--- a/flang/include/flang/Runtime/command.h
+++ b/flang/include/flang/Runtime/command.h
@@ -67,6 +67,8 @@ std::int32_t RTNAME(Hostnm)(
 std::int32_t RTNAME(PutEnv)(
     const char *str, size_t str_length, const char *sourceFile, int line);
 
+float RTNAME(Secnds)(float* refTime, const char *sourceFile, int line);
+
 // Calls unlink()
 std::int32_t RTNAME(Unlink)(
     const char *path, size_t pathLength, const char *sourceFile, int line);
diff --git a/flang/include/flang/Runtime/extensions.h b/flang/include/flang/Runtime/extensions.h
index b350204714431..a5bfa8b535286 100644
--- a/flang/include/flang/Runtime/extensions.h
+++ b/flang/include/flang/Runtime/extensions.h
@@ -90,5 +90,8 @@ void RTNAME(Perror)(const char *str);
 // MCLOCK -- returns accumulated time in ticks
 int FORTRAN_PROCEDURE_NAME(mclock)();
 
+// GNU extension subroutine SECNDS(refTime)
+float FORTRAN_PROCEDURE_NAME(secnds)(float* refTime);
+
 } // extern "C"
 #endif // FORTRAN_RUNTIME_EXTENSIONS_H_

>From 716f82d03cb17a493891c2af761cdf4461e5e13a Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Mon, 4 Aug 2025 16:01:50 -0400
Subject: [PATCH 2/6] clang-format

---
 flang-rt/lib/runtime/command.cpp         | 4 ++--
 flang-rt/lib/runtime/extensions.cpp      | 2 +-
 flang/include/flang/Runtime/command.h    | 2 +-
 flang/include/flang/Runtime/extensions.h | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/flang-rt/lib/runtime/command.cpp b/flang-rt/lib/runtime/command.cpp
index 40233392f2497..ade77e9dd8d0f 100644
--- a/flang-rt/lib/runtime/command.cpp
+++ b/flang-rt/lib/runtime/command.cpp
@@ -7,12 +7,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "flang/Runtime/command.h"
-#include "flang/Runtime/extensions.h"
 #include "flang-rt/runtime/descriptor.h"
 #include "flang-rt/runtime/environment.h"
 #include "flang-rt/runtime/stat.h"
 #include "flang-rt/runtime/terminator.h"
 #include "flang-rt/runtime/tools.h"
+#include "flang/Runtime/extensions.h"
 #include <cerrno>
 #include <cstdlib>
 #include <limits>
@@ -310,7 +310,7 @@ std::int32_t RTNAME(Hostnm)(
   return status;
 }
 
-float RTNAME(Secnds)(float* refTime, const char *sourceFile, int line) {
+float RTNAME(Secnds)(float *refTime, const char *sourceFile, int line) {
   Terminator terminator{sourceFile, line};
   RUNTIME_CHECK(terminator, refTime != nullptr);
   return FORTRAN_PROCEDURE_NAME(secnds)(refTime);
diff --git a/flang-rt/lib/runtime/extensions.cpp b/flang-rt/lib/runtime/extensions.cpp
index 4751fb24af849..a5642b628cbfe 100644
--- a/flang-rt/lib/runtime/extensions.cpp
+++ b/flang-rt/lib/runtime/extensions.cpp
@@ -304,7 +304,7 @@ void FORTRAN_PROCEDURE_NAME(qsort)(int *array, int *len, int *isize,
 void RTNAME(Perror)(const char *str) { perror(str); }
 
 // GNU extension function SECNDS(refTime)
-float FORTRAN_PROCEDURE_NAME(secnds)(float* refTime) {
+float FORTRAN_PROCEDURE_NAME(secnds)(float *refTime) {
   constexpr float FAIL_SECNDS{1.0f};
   if (!refTime) {
     return FAIL_SECNDS;
diff --git a/flang/include/flang/Runtime/command.h b/flang/include/flang/Runtime/command.h
index 21ca1fa8457ee..d22c2bc3956fe 100644
--- a/flang/include/flang/Runtime/command.h
+++ b/flang/include/flang/Runtime/command.h
@@ -67,7 +67,7 @@ std::int32_t RTNAME(Hostnm)(
 std::int32_t RTNAME(PutEnv)(
     const char *str, size_t str_length, const char *sourceFile, int line);
 
-float RTNAME(Secnds)(float* refTime, const char *sourceFile, int line);
+float RTNAME(Secnds)(float *refTime, const char *sourceFile, int line);
 
 // Calls unlink()
 std::int32_t RTNAME(Unlink)(
diff --git a/flang/include/flang/Runtime/extensions.h b/flang/include/flang/Runtime/extensions.h
index a5bfa8b535286..355808a846f13 100644
--- a/flang/include/flang/Runtime/extensions.h
+++ b/flang/include/flang/Runtime/extensions.h
@@ -91,7 +91,7 @@ void RTNAME(Perror)(const char *str);
 int FORTRAN_PROCEDURE_NAME(mclock)();
 
 // GNU extension subroutine SECNDS(refTime)
-float FORTRAN_PROCEDURE_NAME(secnds)(float* refTime);
+float FORTRAN_PROCEDURE_NAME(secnds)(float *refTime);
 
 } // extern "C"
 #endif // FORTRAN_RUNTIME_EXTENSIONS_H_

>From 8bbe4ebb083f8a707e75318456ad520fdff3213f Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Mon, 4 Aug 2025 16:05:06 -0400
Subject: [PATCH 3/6] Fixed a typo

---
 flang-rt/lib/runtime/extensions.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/flang-rt/lib/runtime/extensions.cpp b/flang-rt/lib/runtime/extensions.cpp
index a5642b628cbfe..a218456e0cbb4 100644
--- a/flang-rt/lib/runtime/extensions.cpp
+++ b/flang-rt/lib/runtime/extensions.cpp
@@ -314,7 +314,7 @@ float FORTRAN_PROCEDURE_NAME(secnds)(float *refTime) {
     return FAIL_SECNDS;
   }
   // In float result, we can only precisely store 2^24 seconds, which
-  // comes out to about 194 days. Thus, need to peek a starting point.
+  // comes out to about 194 days. Thus, need to pick a starting point.
   // Given the description of this function, midnight of the current
   // day is the best starting point.
   static time_t startingPoint{0};

>From 5f671e74d65d406d3fd576da7fe29dfbcdb904a8 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Mon, 4 Aug 2025 16:06:22 -0400
Subject: [PATCH 4/6] Fixed init form

---
 flang-rt/lib/runtime/extensions.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/flang-rt/lib/runtime/extensions.cpp b/flang-rt/lib/runtime/extensions.cpp
index a218456e0cbb4..cc3be56019b02 100644
--- a/flang-rt/lib/runtime/extensions.cpp
+++ b/flang-rt/lib/runtime/extensions.cpp
@@ -338,7 +338,7 @@ float FORTRAN_PROCEDURE_NAME(secnds)(float *refTime) {
       return FAIL_SECNDS;
     }
   }
-  double diffStartingPoint = std::difftime(now, startingPoint);
+  double diffStartingPoint{std::difftime(now, startingPoint)};
   return static_cast<float>(diffStartingPoint) - *refTime;
 }
 

>From 9c538783b3947458405912de0740d4497b548c40 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Mon, 4 Aug 2025 16:08:33 -0400
Subject: [PATCH 5/6] The failure code should be negative

---
 flang-rt/lib/runtime/extensions.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/flang-rt/lib/runtime/extensions.cpp b/flang-rt/lib/runtime/extensions.cpp
index cc3be56019b02..01cd13dbf84d5 100644
--- a/flang-rt/lib/runtime/extensions.cpp
+++ b/flang-rt/lib/runtime/extensions.cpp
@@ -305,7 +305,7 @@ void RTNAME(Perror)(const char *str) { perror(str); }
 
 // GNU extension function SECNDS(refTime)
 float FORTRAN_PROCEDURE_NAME(secnds)(float *refTime) {
-  constexpr float FAIL_SECNDS{1.0f};
+  constexpr float FAIL_SECNDS{-1.0f};
   if (!refTime) {
     return FAIL_SECNDS;
   }

>From 80b61edbf543a2894466ebc6a9a79265b3674fed Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Mon, 4 Aug 2025 16:19:06 -0400
Subject: [PATCH 6/6] Introduce FAIL_TIME

---
 flang-rt/lib/runtime/extensions.cpp | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/flang-rt/lib/runtime/extensions.cpp b/flang-rt/lib/runtime/extensions.cpp
index 01cd13dbf84d5..e438d335a6658 100644
--- a/flang-rt/lib/runtime/extensions.cpp
+++ b/flang-rt/lib/runtime/extensions.cpp
@@ -305,12 +305,14 @@ void RTNAME(Perror)(const char *str) { perror(str); }
 
 // GNU extension function SECNDS(refTime)
 float FORTRAN_PROCEDURE_NAME(secnds)(float *refTime) {
-  constexpr float FAIL_SECNDS{-1.0f};
+  constexpr float FAIL_SECNDS{-1.0f}; // Failure code for this function
+  // Failure code for time functions that return std::time_t
+  constexpr time_t FAIL_TIME{std::time_t{-1}};
   if (!refTime) {
     return FAIL_SECNDS;
   }
   std::time_t now{std::time(nullptr)};
-  if (now == std::time_t{-1}) {
+  if (now == FAIL_TIME) {
     return FAIL_SECNDS;
   }
   // In float result, we can only precisely store 2^24 seconds, which
@@ -334,7 +336,7 @@ float FORTRAN_PROCEDURE_NAME(secnds)(float *refTime) {
     timeInfo.tm_min = 0;
     timeInfo.tm_sec = 0;
     startingPoint = std::mktime(&timeInfo);
-    if (startingPoint == std::time_t(-1)) {
+    if (startingPoint == FAIL_TIME) {
       return FAIL_SECNDS;
     }
   }



More information about the llvm-commits mailing list