mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 13:16:08 +00:00

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
51 lines
2.1 KiB
C++
51 lines
2.1 KiB
C++
//===- GCStrategy.cpp - Garbage Collector Description ---------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the policy object GCStrategy which describes the
|
|
// behavior of a given garbage collector.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/IR/GCStrategy.h"
|
|
#include "llvm/ADT/Twine.h"
|
|
#include "llvm/IR/BuiltinGCs.h"
|
|
|
|
using namespace llvm;
|
|
|
|
LLVM_INSTANTIATE_REGISTRY(GCRegistry)
|
|
|
|
GCStrategy::GCStrategy() = default;
|
|
|
|
std::unique_ptr<GCStrategy> llvm::getGCStrategy(const StringRef Name) {
|
|
for (auto &S : GCRegistry::entries())
|
|
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
|
|
// that we got here without running the initializers used by the Registry
|
|
// itself and it's registration mechanism.
|
|
const std::string error =
|
|
std::string("unsupported GC: ") + Name.str() +
|
|
" (did you remember to link and initialize the library?)";
|
|
report_fatal_error(Twine(error));
|
|
} else
|
|
report_fatal_error(Twine(std::string("unsupported GC: ") + Name.str()));
|
|
}
|