+<p>For collectors with barriers or unusual treatment of stack roots, these
+flags allow the collector to perform any required transformation on the LLVM
+IR:</p>
+
+<blockquote><pre
+>class MyCollector : public Collector {
+public:
+ MyCollector() {
+ CustomRoots = true;
+ CustomReadBarriers = true;
+ CustomWriteBarriers = true;
+ }
+
+protected:
+ virtual Pass *createCustomLoweringPass() const {
+ return new MyGCLoweringFunctionPass();
+ }
+};</pre></blockquote>
+
+<p>If any of these flags are set, then LLVM suppresses its default lowering for
+the corresponding intrinsics and instead passes them on to a custom lowering
+pass specified by the collector.</p>
+
+<p>LLVM's default action for each intrinsic is as follows:</p>
+
+<ul>
+ <li><tt>llvm.gcroot</tt>: Pass through to the code generator to generate a
+ stack map.</li>
+ <li><tt>llvm.gcread</tt>: Substitute a <tt>load</tt> instruction.</li>
+ <li><tt>llvm.gcwrite</tt>: Substitute a <tt>store</tt> instruction.</li>
+</ul>
+
+<p>If <tt>CustomReadBarriers</tt> or <tt>CustomWriteBarriers</tt> are specified,
+the custom lowering pass <strong>must</strong> eliminate the corresponding
+barriers.</p>
+
+<p>This template can be used as a starting point for a lowering pass:</p>
+
+<blockquote><pre
+>#include "llvm/Function.h"
+#include "llvm/Module.h"
+#include "llvm/Instructions.h"
+
+namespace {
+ class VISIBILITY_HIDDEN MyGCLoweringFunctionPass : public FunctionPass {
+ static char ID;
+ public:
+ MyGCLoweringFunctionPass() : FunctionPass(intptr_t(&ID)) {}
+
+ const char *getPassName() const { return "Lower GC Intrinsics"; }
+
+ bool runOnFunction(Function &F) {
+ Module *M = F.getParent();
+
+ Function *GCReadInt = M->getFunction("llvm.gcread"),
+ *GCWriteInt = M->getFunction("llvm.gcwrite"),
+ *GCRootInt = M->getFunction("llvm.gcroot");
+
+ bool MadeChange = false;
+
+ for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
+ for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;)
+ if (CallInst *CI = dyn_cast<CallInst>(II++))
+ if (Function *F = CI->getCalledFunction())
+ if (F == GCWriteInt) {
+ // Handle llvm.gcwrite.
+ CI->eraseFromParent();
+ MadeChange = true;
+ } else if (F == GCReadInt) {
+ // Handle llvm.gcread.
+ CI->eraseFromParent();
+ MadeChange = true;
+ } else if (F == GCRootInt) {
+ // Handle llvm.gcroot.
+ CI->eraseFromParent();
+ MadeChange = true;
+ }
+
+ return MadeChange;
+ }
+ };
+
+ char MyGCLoweringFunctionPass::ID = 0;
+}</pre></blockquote>
+
+</div>
+
+
+<!-- ======================================================================= -->
+<div class="doc_subsection">
+ <a name="safe-points">Generating safe points: <tt>NeededSafePoints</tt></a>
+</div>
+
+<div class="doc_text">
+
+<p>LLVM can compute four kinds of safe points:</p>
+
+<blockquote><pre
+>namespace GC {
+ /// PointKind - The type of a collector-safe point.
+ ///
+ enum PointKind {
+ Loop, //< Instr is a loop (backwards branch).
+ Return, //< Instr is a return instruction.
+ PreCall, //< Instr is a call instruction.
+ PostCall //< Instr is the return address of a call.
+ };
+}</pre></blockquote>
+
+<p>A collector can request any combination of the four by setting the
+<tt>NeededSafePoints</tt> mask:</p>
+
+<blockquote><pre
+>MyCollector::MyCollector() {
+ NeededSafePoints = 1 << GC::Loop
+ | 1 << GC::Return
+ | 1 << GC::PreCall
+ | 1 << GC::PostCall;
+}</pre></blockquote>
+
+<p>It can then use the following routines to access safe points.</p>
+
+<blockquote><pre>
+CollectorMetadata &MD = ...;
+size_t PointCount = MD.size();
+
+for (CollectorMetadata::iterator PI = MD.begin(),
+ PE = MD.end(); PI != PE; ++PI) {
+ GC::PointKind PointKind = PI->Kind;
+ unsigned PointNum = PI->Num;
+}</pre></blockquote>
+
+<p>Almost every collector requires <tt>PostCall</tt> safe points, since these
+correspond to the moments when the function is suspended during a call to a
+subroutine.</p>
+
+<p>Threaded programs generally require <tt>Loop</tt> safe points to guarantee
+that the application will reach a safe point within a bounded amount of time,
+even if it is executing a long-running loop which contains no function
+calls.</p>
+
+<p>Threaded collectors may also require <tt>Return</tt> and <tt>PreCall</tt>
+safe points to implement "stop the world" techniques using self-modifying code,
+where it is important that the program not exit the function without reaching a
+safe point (because only the topmost function has been patched).</p>
+
+</div>
+
+
+<!-- ======================================================================= -->
+<div class="doc_subsection">
+ <a name="assembly">Emitting assembly code:
+ <tt>beginAssembly</tt> and <tt>finishAssembly</tt></a>
+</div>
+
+<div class="doc_text">
+
+<p>LLVM allows a collector to print arbitrary assembly code before and after
+the rest of a module's assembly code. From the latter callback, the collector
+can print stack maps from <tt>CollectorModuleMetadata</tt> populated by the code
+generator.</p>
+
+<p>Note that LLVM does not currently support garbage collection code generation
+in the JIT, nor using the object writers.</p>
+
+<blockquote><pre
+>class MyCollector : public Collector {
+ virtual void beginAssembly(Module &M, std::ostream &OS, AsmPrinter &AP,
+ const TargetAsmInfo &TAI) const;
+
+ virtual void finishAssembly(Module &M, CollectorModuleMetadata &MMD,
+ std::ostream &OS, AsmPrinter &AP,
+ const TargetAsmInfo &TAI) const;
+}</pre></blockquote>
+
+<p>The collector should use <tt>AsmPrinter</tt> and <tt>TargetAsmInfo</tt> to
+print portable assembly code to the <tt>std::ostream</tt>. The collector may
+access the stack maps for the entire module using the methods of
+<tt>CollectorModuleMetadata</tt>. Here's a realistic example:</p>
+
+<blockquote><pre
+>#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/Function.h"
+#include "llvm/Target/TargetAsmInfo.h"
+
+void MyCollector::finishAssembly(Module &M,
+ CollectorModuleMetadata &MMD,
+ std::ostream &OS, AsmPrinter &AP,
+ const TargetAsmInfo &TAI) const {
+ // Set up for emitting addresses.
+ const char *AddressDirective;
+ int AddressAlignLog;
+ if (TAI.getAddressSize() == sizeof(int32_t)) {
+ AddressDirective = TAI.getData32bitsDirective();
+ AddressAlignLog = 2;
+ } else {
+ AddressDirective = TAI.getData64bitsDirective();
+ AddressAlignLog = 3;
+ }
+
+ // Put this in the data section.
+ AP.SwitchToDataSection(TAI.getDataSection());
+
+ // For each function...
+ for (CollectorModuleMetadata::iterator FI = MMD.begin(),
+ FE = MMD.end(); FI != FE; ++FI) {
+ CollectorMetadata &MD = **FI;
+
+ // Emit this data structure:
+ //
+ // struct {
+ // int32_t PointCount;
+ // struct {
+ // void *SafePointAddress;
+ // int32_t LiveCount;
+ // int32_t LiveOffsets[LiveCount];
+ // } Points[PointCount];
+ // } __gcmap_<FUNCTIONNAME>;
+
+ // Align to address width.
+ AP.EmitAlignment(AddressAlignLog);
+
+ // Emit the symbol by which the stack map can be found.
+ std::string Symbol;
+ Symbol += TAI.getGlobalPrefix();
+ Symbol += "__gcmap_";
+ Symbol += MD.getFunction().getName();
+ if (const char *GlobalDirective = TAI.getGlobalDirective())
+ OS << GlobalDirective << Symbol << "\n";
+ OS << TAI.getGlobalPrefix() << Symbol << ":\n";
+
+ // Emit PointCount.
+ AP.EmitInt32(MD.size());
+ AP.EOL("safe point count");
+
+ // And each safe point...
+ for (CollectorMetadata::iterator PI = MD.begin(),
+ PE = MD.end(); PI != PE; ++PI) {
+ // Align to address width.
+ AP.EmitAlignment(AddressAlignLog);
+
+ // Emit the address of the safe point.
+ OS << AddressDirective
+ << TAI.getPrivateGlobalPrefix() << "label" << PI->Num;
+ AP.EOL("safe point address");
+
+ // Emit the stack frame size.
+ AP.EmitInt32(MD.getFrameSize());
+ AP.EOL("stack frame size");
+
+ // Emit the number of live roots in the function.
+ AP.EmitInt32(MD.live_size(PI));
+ AP.EOL("live root count");
+
+ // And for each live root...
+ for (CollectorMetadata::live_iterator LI = MD.live_begin(PI),
+ LE = MD.live_end(PI);
+ LI != LE; ++LI) {
+ // Print its offset within the stack frame.
+ AP.EmitInt32(LI->StackOffset);
+ AP.EOL("stack offset");
+ }
+ }
+ }
+}
+</pre></blockquote>
+
+</div>
+
+
+<!-- *********************************************************************** -->
+<div class="doc_section">
+ <a name="runtime-impl">Implementing a collector runtime</a>
+</div>
+<!-- *********************************************************************** -->
+
+<div class="doc_text">
+
+<p>Implementing a garbage collector for LLVM is fairly straightforward. The
+LLVM garbage collectors are provided in a form that makes them easy to link into
+the language-specific runtime that a language front-end would use. They require
+functionality from the language-specific runtime to get information about <a
+href="#gcdescriptors">where pointers are located in heap objects</a>.</p>
+
+<p>The implementation must include the
+<a href="#allocate"><tt>llvm_gc_allocate</tt></a> and
+<a href="#explicit"><tt>llvm_gc_collect</tt></a> functions. To do this, it will
+probably have to <a href="#traceroots">trace through the roots
+from the stack</a> and understand the <a href="#gcdescriptors">GC descriptors
+for heap objects</a>. Luckily, there are some <a href="#gcimpls">example
+implementations</a> available.