xref: /freebsd-src/contrib/llvm-project/llvm/lib/IR/BuiltinGCs.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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 
23fe6060f1SDimitry Andric /// An example GC which attempts to be compatibile 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:
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:
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:
56*81ad6265SDimitry 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:
67fe6060f1SDimitry Andric   StatepointGC() {
68fe6060f1SDimitry Andric     UseStatepoints = true;
69fe6060f1SDimitry Andric     // These options are all gc.root specific, we specify them so that the
70fe6060f1SDimitry Andric     // gc.root lowering code doesn't run.
71fe6060f1SDimitry Andric     NeededSafePoints = false;
72fe6060f1SDimitry Andric     UsesMetadata = false;
73fe6060f1SDimitry Andric   }
74fe6060f1SDimitry Andric 
75fe6060f1SDimitry Andric   Optional<bool> isGCManagedPointer(const Type *Ty) const override {
76fe6060f1SDimitry Andric     // Method is only valid on pointer typed values.
77fe6060f1SDimitry Andric     const PointerType *PT = cast<PointerType>(Ty);
78fe6060f1SDimitry Andric     // For the sake of this example GC, we arbitrarily pick addrspace(1) as our
79fe6060f1SDimitry Andric     // GC managed heap.  We know that a pointer into this heap needs to be
80fe6060f1SDimitry Andric     // updated and that no other pointer does.  Note that addrspace(1) is used
81fe6060f1SDimitry Andric     // only as an example, it has no special meaning, and is not reserved for
82fe6060f1SDimitry Andric     // GC usage.
83fe6060f1SDimitry Andric     return (1 == PT->getAddressSpace());
84fe6060f1SDimitry Andric   }
85fe6060f1SDimitry Andric };
86fe6060f1SDimitry Andric 
87fe6060f1SDimitry Andric /// A GCStrategy for the CoreCLR Runtime. The strategy is similar to
88fe6060f1SDimitry Andric /// Statepoint-example GC, but differs from it in certain aspects, such as:
89fe6060f1SDimitry Andric /// 1) Base-pointers need not be explicitly tracked and reported for
90fe6060f1SDimitry Andric ///    interior pointers
91fe6060f1SDimitry Andric /// 2) Uses a different format for encoding stack-maps
92fe6060f1SDimitry Andric /// 3) Location of Safe-point polls: polls are only needed before loop-back
93fe6060f1SDimitry Andric ///    edges and before tail-calls (not needed at function-entry)
94fe6060f1SDimitry Andric ///
95fe6060f1SDimitry Andric /// The above differences in behavior are to be implemented in upcoming
96fe6060f1SDimitry Andric /// checkins.
97fe6060f1SDimitry Andric class CoreCLRGC : public GCStrategy {
98fe6060f1SDimitry Andric public:
99fe6060f1SDimitry Andric   CoreCLRGC() {
100fe6060f1SDimitry Andric     UseStatepoints = true;
101fe6060f1SDimitry Andric     // These options are all gc.root specific, we specify them so that the
102fe6060f1SDimitry Andric     // gc.root lowering code doesn't run.
103fe6060f1SDimitry Andric     NeededSafePoints = false;
104fe6060f1SDimitry Andric     UsesMetadata = false;
105fe6060f1SDimitry Andric   }
106fe6060f1SDimitry Andric 
107fe6060f1SDimitry Andric   Optional<bool> isGCManagedPointer(const Type *Ty) const override {
108fe6060f1SDimitry Andric     // Method is only valid on pointer typed values.
109fe6060f1SDimitry Andric     const PointerType *PT = cast<PointerType>(Ty);
110fe6060f1SDimitry Andric     // We pick addrspace(1) as our GC managed heap.
111fe6060f1SDimitry Andric     return (1 == PT->getAddressSpace());
112fe6060f1SDimitry Andric   }
113fe6060f1SDimitry Andric };
114fe6060f1SDimitry Andric 
115fe6060f1SDimitry Andric } // end anonymous namespace
116fe6060f1SDimitry Andric 
117fe6060f1SDimitry Andric // Register all the above so that they can be found at runtime.  Note that
118fe6060f1SDimitry Andric // these static initializers are important since the registration list is
119fe6060f1SDimitry Andric // constructed from their storage.
120fe6060f1SDimitry Andric static GCRegistry::Add<ErlangGC> A("erlang",
121fe6060f1SDimitry Andric                                    "erlang-compatible garbage collector");
122fe6060f1SDimitry Andric static GCRegistry::Add<OcamlGC> B("ocaml", "ocaml 3.10-compatible GC");
123fe6060f1SDimitry Andric static GCRegistry::Add<ShadowStackGC>
124fe6060f1SDimitry Andric     C("shadow-stack", "Very portable GC for uncooperative code generators");
125fe6060f1SDimitry Andric static GCRegistry::Add<StatepointGC> D("statepoint-example",
126fe6060f1SDimitry Andric                                        "an example strategy for statepoint");
127fe6060f1SDimitry Andric static GCRegistry::Add<CoreCLRGC> E("coreclr", "CoreCLR-compatible GC");
128fe6060f1SDimitry Andric 
129fe6060f1SDimitry Andric // Provide hook to ensure the containing library is fully loaded.
130fe6060f1SDimitry Andric void llvm::linkAllBuiltinGCs() {}
131