[llvm] [flang-rt] Add the ability to have user supplied callback functions too further customize the runtime environment. (PR #155646)

David Parks via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 27 08:59:15 PDT 2025


https://github.com/d-parks created https://github.com/llvm/llvm-project/pull/155646

Add the ability to have pre and post call back functions to ExecutionEnvironment::Configure() to allow further customization of the flang runtime environment (called from _FortranAStartProgam) in situations where either the desired features/functionality are proprietary or are too specific to be accepted by the flang community.

Example:
Custom constructor object linked with flang objects:
```
#include "flang-rt/runtime/environment.h"
#include "flang/Runtime/entry-names.h"
#include "flang/Runtime/extensions.h"

namespace Fortran::runtime {

// Do something specific to the flang runtime environment prior to the
// core logic of ExecutionEnvironment::Configure().
static void
CustomPreConfigureEnv(int argc, const char *argv[], const char *envp[],
                      const EnvironmentDefaultList *envDefaultList) {
  puts(__func__);
}

// Do something specific to the flang runtime environment after running the
// core logic of ExecutionEnvironment::Configure().
static void
CustomPostConfigureEnv(int argc, const char *argv[], const char *envp[],
                       const EnvironmentDefaultList *envDefaultList) {
  puts(__func__);
}

void __attribute__((constructor)) CustomInitCstor(void) {
  // Possibilities:
  // RTNAME(RegisterConfigureEnv)(&CustomPreConfigureEnv,
  // &CustomPostConfigureEnv); RTNAME(RegisterConfigureEnv)(nullptr,
  // &CustomPostConfigureEnv);
  RTNAME(RegisterConfigureEnv)(&CustomPreConfigureEnv, nullptr);
}
} // namespace Fortran::runtime
```




>From b616c34fe3bc0a8992ffc7dc8eb993b5ed76538c Mon Sep 17 00:00:00 2001
From: David Parks <dparks at nvidia.com>
Date: Wed, 27 Aug 2025 08:22:09 -0700
Subject: [PATCH] [flang-rt] Add the ability to have user supplied callback
 functions to further customize the runtime environment.

	modified:   flang-rt/include/flang-rt/runtime/environment.h
	modified:   flang-rt/lib/runtime/environment.cpp
---
 .../include/flang-rt/runtime/environment.h    | 21 +++++++++++++
 flang-rt/lib/runtime/environment.cpp          | 31 +++++++++++++++++++
 2 files changed, 52 insertions(+)

diff --git a/flang-rt/include/flang-rt/runtime/environment.h b/flang-rt/include/flang-rt/runtime/environment.h
index e579f6012ce86..d90f930ddfe59 100644
--- a/flang-rt/include/flang-rt/runtime/environment.h
+++ b/flang-rt/include/flang-rt/runtime/environment.h
@@ -11,9 +11,22 @@
 
 #include "flang/Common/optional.h"
 #include "flang/Decimal/decimal.h"
+#include "flang/Runtime/entry-names.h"
 
 struct EnvironmentDefaultList;
 
+// ExecutionEnvironment::Configure() allows for optional callback functions
+// to be run pre and post the core logic.
+// Most likely scenario is when a user supplied constructor function is
+// run prior to _QQmain calling RTNAME(ProgramStart)().
+
+extern "C" {
+void RTNAME(RegisterConfigureEnv)(void (*)(int, const char *[], const char *[],
+                                      const EnvironmentDefaultList *),
+    void (*)(
+        int, const char *[], const char *[], const EnvironmentDefaultList *));
+}
+
 namespace Fortran::runtime {
 
 class Terminator;
@@ -42,6 +55,14 @@ struct ExecutionEnvironment {
       ExecutionEnvironment(){};
   void Configure(int argc, const char *argv[], const char *envp[],
       const EnvironmentDefaultList *envDefaults);
+
+  // Optional callback routines to be invoked pre and post
+  // execution environment setup.
+  void (*PreConfigureEnv)(int, const char *[], const char *[],
+      const EnvironmentDefaultList *){nullptr};
+  void (*PostConfigureEnv)(int, const char *[], const char *[],
+      const EnvironmentDefaultList *){nullptr};
+
   const char *GetEnv(
       const char *name, std::size_t name_length, const Terminator &terminator);
 
diff --git a/flang-rt/lib/runtime/environment.cpp b/flang-rt/lib/runtime/environment.cpp
index 0f0564403c0e2..0d8a492b808f6 100644
--- a/flang-rt/lib/runtime/environment.cpp
+++ b/flang-rt/lib/runtime/environment.cpp
@@ -78,6 +78,13 @@ void ExecutionEnvironment::Configure(int ac, const char *av[],
   argc = ac;
   argv = av;
   SetEnvironmentDefaults(envDefaults);
+
+  if (PreConfigureEnv) {
+    // Run an optional callback function prior to the core of the
+    // ExecutionEnvironment() logic.
+    PreConfigureEnv(ac, av, env, envDefaults);
+  }
+
 #ifdef _WIN32
   envp = _environ;
 #else
@@ -173,6 +180,12 @@ void ExecutionEnvironment::Configure(int ac, const char *av[],
   }
 
   // TODO: Set RP/ROUND='PROCESSOR_DEFINED' from environment
+
+  if (PostConfigureEnv) {
+    // Run an optional callback function after the core of the
+    // ExecutionEnvironment() logic.
+    PostConfigureEnv(ac, av, env, envDefaults);
+  }
 }
 
 const char *ExecutionEnvironment::GetEnv(
@@ -249,4 +262,22 @@ std::int32_t ExecutionEnvironment::UnsetEnv(
   return status;
 }
 
+extern "C" {
+
+// User supplied callback functions to further customize the configuration
+// of the runtime environment.
+// The pre and post callback functions are called upon entry and exit
+// of ExecutionEnvironment::Configure() respectively.
+
+void RTNAME(RegisterConfigureEnv)(
+    void (*pre)(int argc, const char *argv[], const char *envp[],
+        const EnvironmentDefaultList *),
+    void (*post)(int argc, const char *argv[], const char *envp[],
+        const EnvironmentDefaultList *)) {
+
+  executionEnvironment.PreConfigureEnv = pre;
+  executionEnvironment.PostConfigureEnv = post;
+}
+} // extern "C"
+
 } // namespace Fortran::runtime



More information about the llvm-commits mailing list