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