1fe6060f1SDimitry Andric //===- BuiltinGCs.cpp - Boilerplate for our built in GC types -------------===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric //
9fe6060f1SDimitry Andric // This file contains the boilerplate required to define our various built in
10fe6060f1SDimitry Andric // gc lowering strategies.
11fe6060f1SDimitry Andric //
12fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
13fe6060f1SDimitry Andric
14fe6060f1SDimitry Andric #include "llvm/IR/BuiltinGCs.h"
15fe6060f1SDimitry Andric #include "llvm/IR/GCStrategy.h"
16fe6060f1SDimitry Andric #include "llvm/IR/DerivedTypes.h"
17fe6060f1SDimitry Andric #include "llvm/Support/Casting.h"
18fe6060f1SDimitry Andric
19fe6060f1SDimitry Andric using namespace llvm;
20fe6060f1SDimitry Andric
21fe6060f1SDimitry Andric namespace {
22fe6060f1SDimitry Andric
23*bdd1243dSDimitry Andric /// An example GC which attempts to be compatible with Erlang/OTP garbage
24fe6060f1SDimitry Andric /// collector.
25fe6060f1SDimitry Andric ///
26fe6060f1SDimitry Andric /// The frametable emitter is in ErlangGCPrinter.cpp.
27fe6060f1SDimitry Andric class ErlangGC : public GCStrategy {
28fe6060f1SDimitry Andric public:
ErlangGC()29fe6060f1SDimitry Andric ErlangGC() {
30fe6060f1SDimitry Andric NeededSafePoints = true;
31fe6060f1SDimitry Andric UsesMetadata = true;
32fe6060f1SDimitry Andric }
33fe6060f1SDimitry Andric };
34fe6060f1SDimitry Andric
35fe6060f1SDimitry Andric /// An example GC which attempts to be compatible with Objective Caml 3.10.0
36fe6060f1SDimitry Andric ///
37fe6060f1SDimitry Andric /// The frametable emitter is in OcamlGCPrinter.cpp.
38fe6060f1SDimitry Andric class OcamlGC : public GCStrategy {
39fe6060f1SDimitry Andric public:
OcamlGC()40fe6060f1SDimitry Andric OcamlGC() {
41fe6060f1SDimitry Andric NeededSafePoints = true;
42fe6060f1SDimitry Andric UsesMetadata = true;
43fe6060f1SDimitry Andric }
44fe6060f1SDimitry Andric };
45fe6060f1SDimitry Andric
46fe6060f1SDimitry Andric /// A GC strategy for uncooperative targets. This implements lowering for the
47fe6060f1SDimitry Andric /// llvm.gc* intrinsics for targets that do not natively support them (which
48fe6060f1SDimitry Andric /// includes the C backend). Note that the code generated is not quite as
49fe6060f1SDimitry Andric /// efficient as algorithms which generate stack maps to identify roots.
50fe6060f1SDimitry Andric ///
51fe6060f1SDimitry Andric /// In order to support this particular transformation, all stack roots are
52fe6060f1SDimitry Andric /// coallocated in the stack. This allows a fully target-independent stack map
53fe6060f1SDimitry Andric /// while introducing only minor runtime overhead.
54fe6060f1SDimitry Andric class ShadowStackGC : public GCStrategy {
55fe6060f1SDimitry Andric public:
5681ad6265SDimitry Andric ShadowStackGC() = default;
57fe6060f1SDimitry Andric };
58fe6060f1SDimitry Andric
59fe6060f1SDimitry Andric /// A GCStrategy which serves as an example for the usage of a statepoint based
60fe6060f1SDimitry Andric /// lowering strategy. This GCStrategy is intended to suitable as a default
61fe6060f1SDimitry Andric /// implementation usable with any collector which can consume the standard
62fe6060f1SDimitry Andric /// stackmap format generated by statepoints, uses the default addrespace to
63fe6060f1SDimitry Andric /// distinguish between gc managed and non-gc managed pointers, and has
64fe6060f1SDimitry Andric /// reasonable relocation semantics.
65fe6060f1SDimitry Andric class StatepointGC : public GCStrategy {
66fe6060f1SDimitry Andric public:
StatepointGC()67fe6060f1SDimitry Andric StatepointGC() {
68fe6060f1SDimitry Andric UseStatepoints = true;
69*bdd1243dSDimitry Andric UseRS4GC = true;
70fe6060f1SDimitry Andric // These options are all gc.root specific, we specify them so that the
71fe6060f1SDimitry Andric // gc.root lowering code doesn't run.
72fe6060f1SDimitry Andric NeededSafePoints = false;
73fe6060f1SDimitry Andric UsesMetadata = false;
74fe6060f1SDimitry Andric }
75fe6060f1SDimitry Andric
isGCManagedPointer(const Type * Ty) const76*bdd1243dSDimitry Andric std::optional<bool> isGCManagedPointer(const Type *Ty) const override {
77fe6060f1SDimitry Andric // Method is only valid on pointer typed values.
78fe6060f1SDimitry Andric const PointerType *PT = cast<PointerType>(Ty);
79fe6060f1SDimitry Andric // For the sake of this example GC, we arbitrarily pick addrspace(1) as our
80fe6060f1SDimitry Andric // GC managed heap. We know that a pointer into this heap needs to be
81fe6060f1SDimitry Andric // updated and that no other pointer does. Note that addrspace(1) is used
82fe6060f1SDimitry Andric // only as an example, it has no special meaning, and is not reserved for
83fe6060f1SDimitry Andric // GC usage.
84fe6060f1SDimitry Andric return (1 == PT->getAddressSpace());
85fe6060f1SDimitry Andric }
86fe6060f1SDimitry Andric };
87fe6060f1SDimitry Andric
88fe6060f1SDimitry Andric /// A GCStrategy for the CoreCLR Runtime. The strategy is similar to
89fe6060f1SDimitry Andric /// Statepoint-example GC, but differs from it in certain aspects, such as:
90fe6060f1SDimitry Andric /// 1) Base-pointers need not be explicitly tracked and reported for
91fe6060f1SDimitry Andric /// interior pointers
92fe6060f1SDimitry Andric /// 2) Uses a different format for encoding stack-maps
93fe6060f1SDimitry Andric /// 3) Location of Safe-point polls: polls are only needed before loop-back
94fe6060f1SDimitry Andric /// edges and before tail-calls (not needed at function-entry)
95fe6060f1SDimitry Andric ///
96fe6060f1SDimitry Andric /// The above differences in behavior are to be implemented in upcoming
97fe6060f1SDimitry Andric /// checkins.
98fe6060f1SDimitry Andric class CoreCLRGC : public GCStrategy {
99fe6060f1SDimitry Andric public:
CoreCLRGC()100fe6060f1SDimitry Andric CoreCLRGC() {
101fe6060f1SDimitry Andric UseStatepoints = true;
102*bdd1243dSDimitry Andric UseRS4GC = true;
103fe6060f1SDimitry Andric // These options are all gc.root specific, we specify them so that the
104fe6060f1SDimitry Andric // gc.root lowering code doesn't run.
105fe6060f1SDimitry Andric NeededSafePoints = false;
106fe6060f1SDimitry Andric UsesMetadata = false;
107fe6060f1SDimitry Andric }
108fe6060f1SDimitry Andric
isGCManagedPointer(const Type * Ty) const109*bdd1243dSDimitry Andric std::optional<bool> isGCManagedPointer(const Type *Ty) const override {
110fe6060f1SDimitry Andric // Method is only valid on pointer typed values.
111fe6060f1SDimitry Andric const PointerType *PT = cast<PointerType>(Ty);
112fe6060f1SDimitry Andric // We pick addrspace(1) as our GC managed heap.
113fe6060f1SDimitry Andric return (1 == PT->getAddressSpace());
114fe6060f1SDimitry Andric }
115fe6060f1SDimitry Andric };
116fe6060f1SDimitry Andric
117fe6060f1SDimitry Andric } // end anonymous namespace
118fe6060f1SDimitry Andric
119fe6060f1SDimitry Andric // Register all the above so that they can be found at runtime. Note that
120fe6060f1SDimitry Andric // these static initializers are important since the registration list is
121fe6060f1SDimitry Andric // constructed from their storage.
122fe6060f1SDimitry Andric static GCRegistry::Add<ErlangGC> A("erlang",
123fe6060f1SDimitry Andric "erlang-compatible garbage collector");
124fe6060f1SDimitry Andric static GCRegistry::Add<OcamlGC> B("ocaml", "ocaml 3.10-compatible GC");
125fe6060f1SDimitry Andric static GCRegistry::Add<ShadowStackGC>
126fe6060f1SDimitry Andric C("shadow-stack", "Very portable GC for uncooperative code generators");
127fe6060f1SDimitry Andric static GCRegistry::Add<StatepointGC> D("statepoint-example",
128fe6060f1SDimitry Andric "an example strategy for statepoint");
129fe6060f1SDimitry Andric static GCRegistry::Add<CoreCLRGC> E("coreclr", "CoreCLR-compatible GC");
130fe6060f1SDimitry Andric
131fe6060f1SDimitry Andric // Provide hook to ensure the containing library is fully loaded.
linkAllBuiltinGCs()132fe6060f1SDimitry Andric void llvm::linkAllBuiltinGCs() {}
133