xref: /freebsd-src/contrib/llvm-project/llvm/lib/IR/BuiltinGCs.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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