173471bf0Spatrick //===- BuiltinGCs.cpp - Boilerplate for our built in GC types -------------===//
273471bf0Spatrick //
373471bf0Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
473471bf0Spatrick // See https://llvm.org/LICENSE.txt for license information.
573471bf0Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
673471bf0Spatrick //
773471bf0Spatrick //===----------------------------------------------------------------------===//
873471bf0Spatrick //
973471bf0Spatrick // This file contains the boilerplate required to define our various built in
1073471bf0Spatrick // gc lowering strategies.
1173471bf0Spatrick //
1273471bf0Spatrick //===----------------------------------------------------------------------===//
1373471bf0Spatrick
1473471bf0Spatrick #include "llvm/IR/BuiltinGCs.h"
1573471bf0Spatrick #include "llvm/IR/GCStrategy.h"
1673471bf0Spatrick #include "llvm/IR/DerivedTypes.h"
1773471bf0Spatrick #include "llvm/Support/Casting.h"
1873471bf0Spatrick
1973471bf0Spatrick using namespace llvm;
2073471bf0Spatrick
2173471bf0Spatrick namespace {
2273471bf0Spatrick
23*d415bd75Srobert /// An example GC which attempts to be compatible with Erlang/OTP garbage
2473471bf0Spatrick /// collector.
2573471bf0Spatrick ///
2673471bf0Spatrick /// The frametable emitter is in ErlangGCPrinter.cpp.
2773471bf0Spatrick class ErlangGC : public GCStrategy {
2873471bf0Spatrick public:
ErlangGC()2973471bf0Spatrick ErlangGC() {
3073471bf0Spatrick NeededSafePoints = true;
3173471bf0Spatrick UsesMetadata = true;
3273471bf0Spatrick }
3373471bf0Spatrick };
3473471bf0Spatrick
3573471bf0Spatrick /// An example GC which attempts to be compatible with Objective Caml 3.10.0
3673471bf0Spatrick ///
3773471bf0Spatrick /// The frametable emitter is in OcamlGCPrinter.cpp.
3873471bf0Spatrick class OcamlGC : public GCStrategy {
3973471bf0Spatrick public:
OcamlGC()4073471bf0Spatrick OcamlGC() {
4173471bf0Spatrick NeededSafePoints = true;
4273471bf0Spatrick UsesMetadata = true;
4373471bf0Spatrick }
4473471bf0Spatrick };
4573471bf0Spatrick
4673471bf0Spatrick /// A GC strategy for uncooperative targets. This implements lowering for the
4773471bf0Spatrick /// llvm.gc* intrinsics for targets that do not natively support them (which
4873471bf0Spatrick /// includes the C backend). Note that the code generated is not quite as
4973471bf0Spatrick /// efficient as algorithms which generate stack maps to identify roots.
5073471bf0Spatrick ///
5173471bf0Spatrick /// In order to support this particular transformation, all stack roots are
5273471bf0Spatrick /// coallocated in the stack. This allows a fully target-independent stack map
5373471bf0Spatrick /// while introducing only minor runtime overhead.
5473471bf0Spatrick class ShadowStackGC : public GCStrategy {
5573471bf0Spatrick public:
56*d415bd75Srobert ShadowStackGC() = default;
5773471bf0Spatrick };
5873471bf0Spatrick
5973471bf0Spatrick /// A GCStrategy which serves as an example for the usage of a statepoint based
6073471bf0Spatrick /// lowering strategy. This GCStrategy is intended to suitable as a default
6173471bf0Spatrick /// implementation usable with any collector which can consume the standard
6273471bf0Spatrick /// stackmap format generated by statepoints, uses the default addrespace to
6373471bf0Spatrick /// distinguish between gc managed and non-gc managed pointers, and has
6473471bf0Spatrick /// reasonable relocation semantics.
6573471bf0Spatrick class StatepointGC : public GCStrategy {
6673471bf0Spatrick public:
StatepointGC()6773471bf0Spatrick StatepointGC() {
6873471bf0Spatrick UseStatepoints = true;
69*d415bd75Srobert UseRS4GC = true;
7073471bf0Spatrick // These options are all gc.root specific, we specify them so that the
7173471bf0Spatrick // gc.root lowering code doesn't run.
7273471bf0Spatrick NeededSafePoints = false;
7373471bf0Spatrick UsesMetadata = false;
7473471bf0Spatrick }
7573471bf0Spatrick
isGCManagedPointer(const Type * Ty) const76*d415bd75Srobert std::optional<bool> isGCManagedPointer(const Type *Ty) const override {
7773471bf0Spatrick // Method is only valid on pointer typed values.
7873471bf0Spatrick const PointerType *PT = cast<PointerType>(Ty);
7973471bf0Spatrick // For the sake of this example GC, we arbitrarily pick addrspace(1) as our
8073471bf0Spatrick // GC managed heap. We know that a pointer into this heap needs to be
8173471bf0Spatrick // updated and that no other pointer does. Note that addrspace(1) is used
8273471bf0Spatrick // only as an example, it has no special meaning, and is not reserved for
8373471bf0Spatrick // GC usage.
8473471bf0Spatrick return (1 == PT->getAddressSpace());
8573471bf0Spatrick }
8673471bf0Spatrick };
8773471bf0Spatrick
8873471bf0Spatrick /// A GCStrategy for the CoreCLR Runtime. The strategy is similar to
8973471bf0Spatrick /// Statepoint-example GC, but differs from it in certain aspects, such as:
9073471bf0Spatrick /// 1) Base-pointers need not be explicitly tracked and reported for
9173471bf0Spatrick /// interior pointers
9273471bf0Spatrick /// 2) Uses a different format for encoding stack-maps
9373471bf0Spatrick /// 3) Location of Safe-point polls: polls are only needed before loop-back
9473471bf0Spatrick /// edges and before tail-calls (not needed at function-entry)
9573471bf0Spatrick ///
9673471bf0Spatrick /// The above differences in behavior are to be implemented in upcoming
9773471bf0Spatrick /// checkins.
9873471bf0Spatrick class CoreCLRGC : public GCStrategy {
9973471bf0Spatrick public:
CoreCLRGC()10073471bf0Spatrick CoreCLRGC() {
10173471bf0Spatrick UseStatepoints = true;
102*d415bd75Srobert UseRS4GC = true;
10373471bf0Spatrick // These options are all gc.root specific, we specify them so that the
10473471bf0Spatrick // gc.root lowering code doesn't run.
10573471bf0Spatrick NeededSafePoints = false;
10673471bf0Spatrick UsesMetadata = false;
10773471bf0Spatrick }
10873471bf0Spatrick
isGCManagedPointer(const Type * Ty) const109*d415bd75Srobert std::optional<bool> isGCManagedPointer(const Type *Ty) const override {
11073471bf0Spatrick // Method is only valid on pointer typed values.
11173471bf0Spatrick const PointerType *PT = cast<PointerType>(Ty);
11273471bf0Spatrick // We pick addrspace(1) as our GC managed heap.
11373471bf0Spatrick return (1 == PT->getAddressSpace());
11473471bf0Spatrick }
11573471bf0Spatrick };
11673471bf0Spatrick
11773471bf0Spatrick } // end anonymous namespace
11873471bf0Spatrick
11973471bf0Spatrick // Register all the above so that they can be found at runtime. Note that
12073471bf0Spatrick // these static initializers are important since the registration list is
12173471bf0Spatrick // constructed from their storage.
12273471bf0Spatrick static GCRegistry::Add<ErlangGC> A("erlang",
12373471bf0Spatrick "erlang-compatible garbage collector");
12473471bf0Spatrick static GCRegistry::Add<OcamlGC> B("ocaml", "ocaml 3.10-compatible GC");
12573471bf0Spatrick static GCRegistry::Add<ShadowStackGC>
12673471bf0Spatrick C("shadow-stack", "Very portable GC for uncooperative code generators");
12773471bf0Spatrick static GCRegistry::Add<StatepointGC> D("statepoint-example",
12873471bf0Spatrick "an example strategy for statepoint");
12973471bf0Spatrick static GCRegistry::Add<CoreCLRGC> E("coreclr", "CoreCLR-compatible GC");
13073471bf0Spatrick
13173471bf0Spatrick // Provide hook to ensure the containing library is fully loaded.
linkAllBuiltinGCs()13273471bf0Spatrick void llvm::linkAllBuiltinGCs() {}
133