#include <llvm/Support/PrettyStackTrace.h>
#include <llvm/ExecutionEngine/ObjectCache.h>
#include <llvm/Support/TargetSelect.h>
+#include <llvm/CodeGen/SelectionDAGNodes.h>
#if LLVM_VERSION_MAJOR >= 15
#include <llvm/Support/MemoryBuffer.h>
#endif
#include "lp_bld_misc.h"
#include "lp_bld_debug.h"
+static void lp_run_atexit_for_destructors(void);
+
namespace {
class LLVMEnsureMultithreaded {
}
}
#endif
+ lp_run_atexit_for_destructors();
}
extern "C" void
M->setOverrideStackAlignment(align);
#endif
}
+
+using namespace llvm;
+
+class GallivmRunAtExitForStaticDestructors : public SDNode
+{
+public:
+ /* getSDVTList (protected) calls getValueTypeList (private), which contains static variables. */
+ GallivmRunAtExitForStaticDestructors(): SDNode(0, 0, DebugLoc(), getSDVTList(MVT::Other))
+ {
+ }
+};
+
+static void
+lp_run_atexit_for_destructors(void)
+{
+ /* LLVM >= 16 registers static variable destructors on the first compile, which gcc
+ * implements by calling atexit there. Before that, u_queue registers its atexit
+ * handler to kill all threads. Since exit() runs atexit handlers in the reverse order,
+ * the LLVM destructors are called first while shader compiler threads may still be
+ * running, which crashes in LLVM in SelectionDAG.cpp.
+ *
+ * The solution is to run the code that declares the LLVM static variables first,
+ * so that atexit for LLVM is registered first and u_queue is registered after that,
+ * which ensures that all u_queue threads are terminated before LLVM destructors are
+ * called.
+ *
+ * This just executes the code that declares static variables.
+ */
+ GallivmRunAtExitForStaticDestructors();
+}