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