aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm16/lib/IR/BuiltinGCs.cpp
blob: 163b0383e22c271d8764b58b76d9754964a3e724 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//===- BuiltinGCs.cpp - Boilerplate for our built in GC types -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains the boilerplate required to define our various built in
// gc lowering strategies.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/BuiltinGCs.h"
#include "llvm/IR/GCStrategy.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/Support/Casting.h"

using namespace llvm;

namespace {

/// An example GC which attempts to be compatible with Erlang/OTP garbage
/// collector.
///
/// The frametable emitter is in ErlangGCPrinter.cpp.
class ErlangGC : public GCStrategy {
public:
  ErlangGC() {
    NeededSafePoints = true;
    UsesMetadata = true;
  }
};

/// An example GC which attempts to be compatible with Objective Caml 3.10.0
///
/// The frametable emitter is in OcamlGCPrinter.cpp.
class OcamlGC : public GCStrategy {
public:
  OcamlGC() {
    NeededSafePoints = true;
    UsesMetadata = true;
  }
};

/// A GC strategy for uncooperative targets.  This implements lowering for the
/// llvm.gc* intrinsics for targets that do not natively support them (which
/// includes the C backend). Note that the code generated is not quite as
/// efficient as algorithms which generate stack maps to identify roots.
///
/// In order to support this particular transformation, all stack roots are
/// coallocated in the stack. This allows a fully target-independent stack map
/// while introducing only minor runtime overhead.
class ShadowStackGC : public GCStrategy {
public:
  ShadowStackGC() = default;
};

/// A GCStrategy which serves as an example for the usage of a statepoint based
/// lowering strategy.  This GCStrategy is intended to suitable as a default
/// implementation usable with any collector which can consume the standard
/// stackmap format generated by statepoints, uses the default addrespace to
/// distinguish between gc managed and non-gc managed pointers, and has
/// reasonable relocation semantics.
class StatepointGC : public GCStrategy {
public:
  StatepointGC() {
    UseStatepoints = true;
    UseRS4GC = true;
    // These options are all gc.root specific, we specify them so that the
    // gc.root lowering code doesn't run.
    NeededSafePoints = false;
    UsesMetadata = false;
  }

  std::optional<bool> isGCManagedPointer(const Type *Ty) const override {
    // Method is only valid on pointer typed values.
    const PointerType *PT = cast<PointerType>(Ty);
    // For the sake of this example GC, we arbitrarily pick addrspace(1) as our
    // GC managed heap.  We know that a pointer into this heap needs to be
    // updated and that no other pointer does.  Note that addrspace(1) is used
    // only as an example, it has no special meaning, and is not reserved for
    // GC usage.
    return (1 == PT->getAddressSpace());
  }
};

/// A GCStrategy for the CoreCLR Runtime. The strategy is similar to
/// Statepoint-example GC, but differs from it in certain aspects, such as:
/// 1) Base-pointers need not be explicitly tracked and reported for
///    interior pointers
/// 2) Uses a different format for encoding stack-maps
/// 3) Location of Safe-point polls: polls are only needed before loop-back
///    edges and before tail-calls (not needed at function-entry)
///
/// The above differences in behavior are to be implemented in upcoming
/// checkins.
class CoreCLRGC : public GCStrategy {
public:
  CoreCLRGC() {
    UseStatepoints = true;
    UseRS4GC = true;
    // These options are all gc.root specific, we specify them so that the
    // gc.root lowering code doesn't run.
    NeededSafePoints = false;
    UsesMetadata = false;
  }

  std::optional<bool> isGCManagedPointer(const Type *Ty) const override {
    // Method is only valid on pointer typed values.
    const PointerType *PT = cast<PointerType>(Ty);
    // We pick addrspace(1) as our GC managed heap.
    return (1 == PT->getAddressSpace());
  }
};

} // end anonymous namespace

// Register all the above so that they can be found at runtime.  Note that
// these static initializers are important since the registration list is
// constructed from their storage.
static GCRegistry::Add<ErlangGC> A("erlang",
                                   "erlang-compatible garbage collector");
static GCRegistry::Add<OcamlGC> B("ocaml", "ocaml 3.10-compatible GC");
static GCRegistry::Add<ShadowStackGC>
    C("shadow-stack", "Very portable GC for uncooperative code generators");
static GCRegistry::Add<StatepointGC> D("statepoint-example",
                                       "an example strategy for statepoint");
static GCRegistry::Add<CoreCLRGC> E("coreclr", "CoreCLR-compatible GC");

// Provide hook to ensure the containing library is fully loaded.
void llvm::linkAllBuiltinGCs() {}