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