//===- 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 isGCManagedPointer(const Type *Ty) const override { // Method is only valid on pointer typed values. const PointerType *PT = cast(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 isGCManagedPointer(const Type *Ty) const override { // Method is only valid on pointer typed values. const PointerType *PT = cast(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 A("erlang", "erlang-compatible garbage collector"); static GCRegistry::Add B("ocaml", "ocaml 3.10-compatible GC"); static GCRegistry::Add C("shadow-stack", "Very portable GC for uncooperative code generators"); static GCRegistry::Add D("statepoint-example", "an example strategy for statepoint"); static GCRegistry::Add E("coreclr", "CoreCLR-compatible GC"); // Provide hook to ensure the containing library is fully loaded. void llvm::linkAllBuiltinGCs() {}