[OpenMP] Remove `register_requires` global constructor (#80460)

Summary:
Currently, OpenMP handles the `omp requires` clause by emitting a global
constructor into the runtime for every translation unit that requires
it. However, this is not a great solution because it prevents us from
having a defined order in which the runtime is accessed and used.

This patch changes the approach to no longer use global constructors,
but to instead group the flag with the other offloading entires that we
already handle. This has the effect of still registering each flag per
requires TU, but now we have a single constructor that handles
everything.

This function removes support for the old `__tgt_register_requires` and
replaces it with a warning message. We just had a recent release, and
the OpenMP policy for the past four releases since we switched to LLVM
is that we do not provide strict backwards compatibility between major
LLVM releases now that the library is versioned. This means that a user
will need to recompile if they have an old binary that relied on
`register_requires` having the old behavior. It is important that we
actively deprecate this, as otherwise it would not solve the problem of
having no defined init and shutdown order for `libomptarget`. The
problem of `libomptarget` not having a define init and shutdown order
cascades into a lot of other issues so I have a strong incentive to be
rid of it.

It is worth noting that the current `__tgt_offload_entry` only has space
for a 32-bit integer here. I am planning to overhaul these at some point
as well.

GitOrigin-RevId: cc374d8056990a4c6df44173ad7ef59474ba498b
diff --git a/libomptarget/include/Shared/APITypes.h b/libomptarget/include/Shared/APITypes.h
index 94521b4..e8fc277 100644
--- a/libomptarget/include/Shared/APITypes.h
+++ b/libomptarget/include/Shared/APITypes.h
@@ -30,7 +30,7 @@
   char *name;       // Name of the function or global
   size_t size;      // Size of the entry info (0 if it is a function)
   int32_t flags;    // Flags associated with the entry, e.g. 'link'.
-  int32_t reserved; // Reserved, to be used by the runtime library.
+  int32_t data;     // Extra data associated with the entry.
 };
 
 /// This struct is a record of the device image information
diff --git a/libomptarget/include/omptarget.h b/libomptarget/include/omptarget.h
index 3016467..c4faa23 100644
--- a/libomptarget/include/omptarget.h
+++ b/libomptarget/include/omptarget.h
@@ -92,7 +92,9 @@
   /// Mark the entry global as having a 'link' attribute.
   OMP_DECLARE_TARGET_LINK = 0x01,
   /// Mark the entry global as being an indirectly callable function.
-  OMP_DECLARE_TARGET_INDIRECT = 0x08
+  OMP_DECLARE_TARGET_INDIRECT = 0x08,
+  /// This is an entry corresponding to a requirement to be registered.
+  OMP_REGISTER_REQUIRES = 0x10,
 };
 
 enum TargetAllocTy : int32_t {
diff --git a/libomptarget/src/PluginManager.cpp b/libomptarget/src/PluginManager.cpp
index 0693d4b..34f1f49 100644
--- a/libomptarget/src/PluginManager.cpp
+++ b/libomptarget/src/PluginManager.cpp
@@ -199,6 +199,12 @@
 void PluginManager::registerLib(__tgt_bin_desc *Desc) {
   PM->RTLsMtx.lock();
 
+  // Add in all the OpenMP requirements associated with this binary.
+  for (__tgt_offload_entry &Entry :
+       llvm::make_range(Desc->HostEntriesBegin, Desc->HostEntriesEnd))
+    if (Entry.flags == OMP_REGISTER_REQUIRES)
+      PM->addRequirements(Entry.data);
+
   // Extract the exectuable image and extra information if availible.
   for (int32_t i = 0; i < Desc->NumDeviceImages; ++i)
     PM->addDeviceImage(*Desc, Desc->DeviceImages[i]);
diff --git a/libomptarget/src/interface.cpp b/libomptarget/src/interface.cpp
index 8725e5e..d2707f3 100644
--- a/libomptarget/src/interface.cpp
+++ b/libomptarget/src/interface.cpp
@@ -33,7 +33,9 @@
 ////////////////////////////////////////////////////////////////////////////////
 /// adds requires flags
 EXTERN void __tgt_register_requires(int64_t Flags) {
-  PM->addRequirements(Flags);
+  MESSAGE("The %s function has been removed. Old OpenMP requirements will not "
+          "be handled",
+          __PRETTY_FUNCTION__);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/libomptarget/src/omptarget.cpp b/libomptarget/src/omptarget.cpp
index 821669d..3b3e17f 100644
--- a/libomptarget/src/omptarget.cpp
+++ b/libomptarget/src/omptarget.cpp
@@ -194,7 +194,7 @@
                                         Entry.size) != OFFLOAD_SUCCESS)
               REPORT("Failed to write symbol for USM %s\n", Entry.name);
           }
-        } else {
+        } else if (Entry.addr) {
           if (Device.RTL->get_function(Binary, Entry.name, &DeviceEntry.addr) !=
               OFFLOAD_SUCCESS)
             REPORT("Failed to load kernel %s\n", Entry.name);
diff --git a/libomptarget/test/offloading/requires.c b/libomptarget/test/offloading/requires.c
index cf01a73..2a129a7 100644
--- a/libomptarget/test/offloading/requires.c
+++ b/libomptarget/test/offloading/requires.c
@@ -16,7 +16,34 @@
 // ---------------------------------------------------------------------------
 // Various definitions copied from OpenMP RTL
 
-extern void __tgt_register_requires(int64_t);
+typedef struct {
+  void *addr;
+  char *name;
+  size_t size;
+  int32_t flags;
+  int32_t data;
+} __tgt_offload_entry;
+
+enum Flags {
+  OMP_REGISTER_REQUIRES = 0x10,
+};
+
+typedef struct {
+  void *ImageStart;
+  void *ImageEnd;
+  __tgt_offload_entry *EntriesBegin;
+  __tgt_offload_entry *EntriesEnd;
+} __tgt_device_image;
+
+typedef struct {
+  int32_t NumDeviceImages;
+  __tgt_device_image *DeviceImages;
+  __tgt_offload_entry *HostEntriesBegin;
+  __tgt_offload_entry *HostEntriesEnd;
+} __tgt_bin_desc;
+
+void __tgt_register_lib(__tgt_bin_desc *Desc);
+void __tgt_unregister_lib(__tgt_bin_desc *Desc);
 
 // End of definitions copied from OpenMP RTL.
 // ---------------------------------------------------------------------------
@@ -28,11 +55,17 @@
 
   // This is the 2nd time this function is called so it should print SUCCESS if
   // REQ is compatible with `1` and otherwise cause an error.
-  __tgt_register_requires(1);
-  __tgt_register_requires(REQ);
+  __tgt_offload_entry entries[] = {{NULL, "", 0, OMP_REGISTER_REQUIRES, 1},
+                                   {NULL, "", 0, OMP_REGISTER_REQUIRES, REQ}};
+  __tgt_device_image image = {NULL, NULL, &entries[0], &entries[1] + 1};
+  __tgt_bin_desc bin = {1, &image, &entries[0], &entries[1] + 1};
+
+  __tgt_register_lib(&bin);
 
   printf("SUCCESS");
 
+  __tgt_unregister_lib(&bin);
+
   // clang-format off
   // GOOD: SUCCESS
   // BAD: omptarget fatal error 2: '#pragma omp requires reverse_offload' not used consistently!