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