Fix Reactor memory leaks

LLVM has a known leak, which is addressed by this patch:
https://reviews.llvm.org/. With this patch, and making sure that
llvm::shutdown() is called, AppVerifier on Windows, and LSAN on Linux,
report no more load/unload leaks.

Bug: b/175782868
Bug: chromium:972686
Bug: angleproject:5377
Change-Id: If34a00c3a4b845604445f22bdb5889f51bb5a1d6
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/52168
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index bcb5416..18b0c16 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -27,6 +27,7 @@
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Verifier.h"
 #include "llvm/Support/Alignment.h"
+#include "llvm/Support/ManagedStatic.h"
 #include "llvm/Transforms/Coroutines.h"
 #include "llvm/Transforms/IPO.h"
 #include "llvm/Transforms/Scalar.h"
@@ -57,6 +58,9 @@
 
 namespace {
 
+// Used to automatically invoke llvm_shutdown() when driver is unloaded
+llvm::llvm_shutdown_obj llvmShutdownObj;
+
 // This has to be a raw pointer because glibc 2.17 doesn't support __cxa_thread_atexit_impl
 // for destructing objects at exit. See crbug.com/1074222
 thread_local rr::JITBuilder *jit = nullptr;
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index ce4475e..fe53ad7 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -32,6 +32,7 @@
 
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/raw_os_ostream.h"
 
 #include "marl/event.h"
@@ -215,6 +216,9 @@
 
 namespace {
 
+// Used to automatically invoke llvm_shutdown() when driver is unloaded
+llvm::llvm_shutdown_obj llvmShutdownObj;
+
 // Default configuration settings. Must be accessed under mutex lock.
 std::mutex defaultConfigLock;
 rr::Config &defaultConfig()
diff --git a/third_party/llvm-10.0/llvm/lib/Support/ManagedStatic.cpp b/third_party/llvm-10.0/llvm/lib/Support/ManagedStatic.cpp
index 053493f..bfa7e8e 100644
--- a/third_party/llvm-10.0/llvm/lib/Support/ManagedStatic.cpp
+++ b/third_party/llvm-10.0/llvm/lib/Support/ManagedStatic.cpp
@@ -21,6 +21,8 @@
 static std::recursive_mutex *ManagedStaticMutex = nullptr;
 static llvm::once_flag mutex_init_flag;
 
+#if 0
+
 static void initializeMutex() {
   ManagedStaticMutex = new std::recursive_mutex();
 }
@@ -30,6 +32,16 @@
   return ManagedStaticMutex;
 }
 
+#else
+
+// SwiftShader: from https://reviews.llvm.org/D83372
+static std::recursive_mutex *getManagedStaticMutex() {
+  static std::recursive_mutex m;
+  return &m;
+}
+
+#endif
+
 void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
                                               void (*Deleter)(void*)) const {
   assert(Creator);
@@ -76,7 +88,11 @@
 
 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
 void llvm::llvm_shutdown() {
-  std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex());
+  // SwiftShader: from https://reviews.llvm.org/D83372
+  // This may be called after the mutex is destroyed. Instead of fixing this,
+  // don't bother locking the mutex, and require llvm_shutdown to be called from
+  // exactly one thread.
+  // std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex());
 
   while (StaticList)
     StaticList->destroy();
diff --git a/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp b/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp
index 97e7470..34958a2 100644
--- a/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp
+++ b/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp
@@ -21,6 +21,8 @@
 static std::recursive_mutex *ManagedStaticMutex = nullptr;
 LLVM_DEFINE_ONCE_FLAG(mutex_init_flag);
 
+#if 0
+
 static void initializeMutex() {
   ManagedStaticMutex = new std::recursive_mutex();
 }
@@ -33,6 +35,16 @@
   return ManagedStaticMutex;
 }
 
+#else
+
+// SwiftShader: from https://reviews.llvm.org/D83372
+static std::recursive_mutex *getManagedStaticMutex() {
+  static std::recursive_mutex m;
+  return &m;
+}
+
+#endif
+
 void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
                                               void (*Deleter)(void*)) const {
   assert(Creator);
@@ -68,7 +80,11 @@
 
 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
 void llvm::llvm_shutdown() {
-  std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex());
+  // SwiftShader: from https://reviews.llvm.org/D83372
+  // This may be called after the mutex is destroyed. Instead of fixing this,
+  // don't bother locking the mutex, and require llvm_shutdown to be called from
+  // exactly one thread.
+  // std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex());
 
   while (StaticList)
     StaticList->destroy();