From: Campbell Suter Date: Thu, 22 Dec 2022 14:29:58 +0000 (+0700) Subject: Link the default GC strategies everywhere getGCStrategy is used. X-Git-Tag: upstream/17.0.6~22340 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c40697a1b76d9eed978900db759a66d97fbde70b;p=platform%2Fupstream%2Fllvm.git Link the default GC strategies everywhere getGCStrategy is used. GC strategies are registered using a system of global constructors: any object can include a GCRegistry::Add stataic variable to register a strategy, and that will generate a static constructor which registers this strategy into a global list. This allows shared libraries to easily register their own strategies, but poses a problem related to linking: the default GC strategies (defined and registered in their own file) must obviously be included in LLVM binaries. The previous solution was to define an empty functon in BuiltinGCs.cpp, and call it from LinkAllCodegenComponents.h - this is the solution used for many other codegen components. This header is then included into the llc and lli main source files, ensuring everything gets linked into those binaries. This isn't great for GCStrategy, which we'd like [1] to use in other binaries, notably opt for the RS4GC [2] pass. Instead of doing something specific to opt (for example, adding a call in LinkAllIR), this patch links to the registry function from getGCStrategy, in the assumption that anything that might look up a GC strategy probably also expects the default strategies to exist. [1] https://reviews.llvm.org/D140458 [2] RewriteStatepointsForGC Differential Revision: https://reviews.llvm.org/D140504 --- diff --git a/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h b/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h index d615a5d..565d1c3 100644 --- a/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -14,7 +14,6 @@ #ifndef LLVM_CODEGEN_LINKALLCODEGENCOMPONENTS_H #define LLVM_CODEGEN_LINKALLCODEGENCOMPONENTS_H -#include "llvm/IR/BuiltinGCs.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/SchedulerRegistry.h" #include "llvm/Target/TargetMachine.h" @@ -38,8 +37,6 @@ namespace { (void) llvm::createGreedyRegisterAllocator(); (void) llvm::createDefaultPBQPRegisterAllocator(); - llvm::linkAllBuiltinGCs(); - (void) llvm::createBURRListDAGScheduler(nullptr, llvm::CodeGenOpt::Default); (void) llvm::createSourceListDAGScheduler(nullptr, diff --git a/llvm/lib/IR/GCStrategy.cpp b/llvm/lib/IR/GCStrategy.cpp index 5833dc2..c3e35bd 100644 --- a/llvm/lib/IR/GCStrategy.cpp +++ b/llvm/lib/IR/GCStrategy.cpp @@ -13,6 +13,7 @@ #include "llvm/IR/GCStrategy.h" #include "llvm/ADT/Twine.h" +#include "llvm/IR/BuiltinGCs.h" using namespace llvm; @@ -25,6 +26,16 @@ std::unique_ptr llvm::getGCStrategy(const StringRef Name) { if (S.getName() == Name) return S.instantiate(); + // We need to link all the builtin GCs when LLVM is used as a static library. + // The linker will quite happily remove the static constructors that register + // the builtin GCs if we don't use a function from that object. This function + // does nothing but we need to make sure it is (or at least could be, even + // with all optimisations enabled) called *somewhere*, and this is a good + // place to do that: if the GC strategies are being used then this function + // obviously can't be removed by the linker, and here it won't affect + // performance, since there's about to be a fatal error anyway. + llvm::linkAllBuiltinGCs(); + if (GCRegistry::begin() == GCRegistry::end()) { // In normal operation, the registry should not be empty. There should // be the builtin GCs if nothing else. The most likely scenario here is