Author: gordon Date: Mon Dec 10 18:30:17 2007 New Revision: 44827 URL: http://llvm.org/viewvc/llvm-project?rev=44827&view=rev Log: CollectorMetadata and Collector are rejiggered to get along with per-function collector model. Collector is now the factory for CollectorMetadata, so the latter may be subclassed.
Modified: llvm/trunk/docs/GarbageCollection.html llvm/trunk/include/llvm/CodeGen/Collector.h llvm/trunk/include/llvm/CodeGen/CollectorMetadata.h llvm/trunk/include/llvm/CodeGen/Collectors.h llvm/trunk/include/llvm/CodeGen/Passes.h llvm/trunk/lib/CodeGen/Collector.cpp llvm/trunk/lib/CodeGen/CollectorMetadata.cpp Modified: llvm/trunk/docs/GarbageCollection.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/GarbageCollection.html?rev=44827&r1=44826&r2=44827&view=diff ============================================================================== --- llvm/trunk/docs/GarbageCollection.html (original) +++ llvm/trunk/docs/GarbageCollection.html Mon Dec 10 18:30:17 2007 @@ -36,8 +36,10 @@ </ul> </li> - <li><a href="#intrinsics">Collection intrinsics</a> + <li><a href="#core">Core support</a> <ul> + <li><a href="#gcattr">Specifying GC code generation: + <tt>gc "..."</tt></a></li> <li><a href="#gcroot">Identifying GC roots on the stack: <tt>llvm.gcroot</tt></a></li> <li><a href="#barriers">Reading and writing references in the heap</a> @@ -198,11 +200,12 @@ <ul> <li>Emitting compatible code, including initialization in the main - program.</li> + program if necessary.</li> <li>Loading a compiler plugin if the collector is not statically linked with your compiler. For <tt>llc</tt>, use the <tt>-load</tt> option.</li> - <li>Selecting the collection algorithm with <tt>llc -gc=</tt> or by setting - <tt>llvm::TheCollector</tt>.</li> + <li>Selecting the collection algorithm by applying the <tt>gc "..."</tt> + attribute to your garbage collected functions, or equivalently with + the <tt>setCollector</tt> method.</li> <li>Linking your final executable with the garbage collector runtime.</li> </ul> @@ -211,7 +214,7 @@ <table> <tr> <th>Collector</th> - <th><tt>llc</tt> arguments</th> + <th><tt>gc</tt> attribute</th> <th>Linkage</th> <th><tt>gcroot</tt></th> <th><tt>gcread</tt></th> @@ -219,7 +222,7 @@ </tr> <tr valign="baseline"> <td><a href="#semispace">SemiSpace</a></td> - <td><tt>-gc=shadow-stack</tt></td> + <td><tt>gc "shadow-stack"</tt></td> <td>TODO FIXME</td> <td>required</td> <td>optional</td> @@ -227,7 +230,7 @@ </tr> <tr valign="baseline"> <td><a href="#ocaml">Ocaml</a></td> - <td><tt>-gc=ocaml</tt></td> + <td><tt>gc "ocaml"</tt></td> <td><i>provided by ocamlopt</i></td> <td>required</td> <td>optional</td> @@ -252,11 +255,12 @@ <div class="doc_text"> -<p>The ShadowStack collector is invoked with <tt>llc -gc=shadow-stack</tt>. +<p>The ShadowStack backend is invoked with the <tt>gc "shadow-stack"</tt> +function attribute. Unlike many collectors which rely on a cooperative code generator to generate stack maps, this algorithm carefully maintains a linked list of stack root descriptors [<a href="#henderson02">Henderson2002</a>]. This so-called "shadow -stack," mirrors the machine stack. Maintaining this data structure is slower +stack" mirrors the machine stack. Maintaining this data structure is slower than using stack maps, but has a significant portability advantage because it requires no special support from the target code generator.</p> @@ -264,7 +268,7 @@ program may use <tt>load</tt> and <tt>store</tt> instead of <tt>llvm.gcread</tt> and <tt>llvm.gcwrite</tt>.</p> -<p>The ShadowStack collector is a compiler plugin only. It must be paired with a +<p>ShadowStack is a code generator plugin only. It must be paired with a compatible runtime.</p> </div> @@ -277,8 +281,7 @@ <div class="doc_text"> <p>The SemiSpace runtime implements with the <a href="runtime">suggested -runtime interface</a> and is compatible the ShadowStack collector's code -generation.</p> +runtime interface</a> and is compatible the ShadowStack backend.</p> <p>SemiSpace is a very simple copying collector. When it starts up, it allocates two blocks of memory for the heap. It uses a simple bump-pointer @@ -302,7 +305,8 @@ <div class="doc_text"> -<p>The ocaml collector is invoked with <tt>llc -gc=ocaml</tt>. It supports the +<p>The ocaml backend is invoked with the <tt>gc "ocaml"</tt> function attribute. +It supports the <a href="http://caml.inria.fr/">Objective Caml</a> language runtime by emitting a type-accurate stack map in the form of an ocaml 3.10.0-compatible frametable. The linkage requirements are satisfied automatically by the <tt>ocamlopt</tt> @@ -317,7 +321,7 @@ <!-- *********************************************************************** --> <div class="doc_section"> - <a name="intrinsics">Collection intrinsics</a> + <a name="core">Core support</a> </div> <!-- *********************************************************************** --> @@ -337,6 +341,27 @@ <!-- ======================================================================= --> <div class="doc_subsection"> + <a name="gcattr">Specifying GC code generation: <tt>gc "..."</tt></a> +</div> + +<div class="doc_code"><tt> + define <i>ty</i> @<i>name</i>(...) <u>gc "<i>collector</i>"</u> { ... +</tt></div> + +<div class="doc_text"> + +<p>The <tt>gc</tt> function attribute is used to specify the desired collector +algorithm to the compiler. It is equivalent to specify the collector name +programmatically using the <tt>setCollector</tt> method of +<tt>Function</tt>.</p> + +<p>Specifying the collector on a per-function basis allows LLVM to link together +programs which use different garbage collection algorithms.</p> + +</div> + +<!-- ======================================================================= --> +<div class="doc_subsection"> <a name="gcroot">Identifying GC roots on the stack: <tt>llvm.gcroot</tt></a> </div> @@ -591,6 +616,10 @@ <div class="doc_text"> +<p>User code specifies which collector plugin to use with the <tt>gc</tt> +function attribute or, equivalently, with the <tt>setCollector</tt> method of +<tt>Function</tt>.</p> + <p>To implement a collector plugin, it is necessary to subclass <tt>llvm::Collector</tt>, which can be accomplished in a few lines of boilerplate code. LLVM's infrastructure provides access to several important @@ -616,7 +645,7 @@ }; CollectorRegistry::Add<MyCollector> - X("mygc", "My custom garbage collector."); + X("mygc", "My bespoke garbage collector."); }</pre></blockquote> <p>Using the LLVM makefiles (like the <a @@ -632,20 +661,20 @@ include $(LEVEL)/Makefile.common</pre></blockquote> -<blockquote><pre -></pre></blockquote> - -<p>Once the plugin is compiled, user code may be compiled using <tt>llc --load=<var>MyGC.so</var> -gc=mygc</tt> (though <var>MyGC.so</var> may have some -other platform-specific extension).</p> - -<!-- BEGIN FIXME: Gross --> -<p>To use a collector in a tool other than <tt>llc</tt>, simply assign a -<tt>Collector</tt> to the <tt>llvm::TheCollector</tt> variable:</p> +<p>Once the plugin is compiled, code using it may be compiled using <tt>llc +-load=<var>MyGC.so</var></tt> (though <var>MyGC.so</var> may have some other +platform-specific extension):</p> <blockquote><pre ->TheCollector = new MyGC();</pre></blockquote> -<!-- /FIXME GROSS --> +>$ cat sample.ll +define void @f() gc "mygc" { +entry: + ret void +} +$ llvm-as < sample.ll | llc -load=MyGC.so</pre></blockquote> + +<p>It is also possible to statically link the collector plugin into tools, such +as a language-specific compiler front-end.</p> </div> @@ -956,15 +985,18 @@ <div class="doc_text"> <blockquote><pre ->CollectorMetadata &MD = ...; -unsigned FrameSize = MD.getFrameSize(); -size_t RootCount = MD.roots_size(); - -for (CollectorMetadata::roots_iterator RI = MD.roots_begin(), - RE = MD.roots_end(); RI != RE; ++RI) { - int RootNum = RI->Num; - int RootStackOffset = RI->StackOffset; - Constant *RootMetadata = RI->Metadata; +>for (iterator I = begin(), E = end(); I != E; ++I) { + CollectorMetadata *MD = *I; + unsigned FrameSize = MD->getFrameSize(); + size_t RootCount = MD->roots_size(); + + for (CollectorMetadata::roots_iterator RI = MD->roots_begin(), + RE = MD->roots_end(); + RI != RE; ++RI) { + int RootNum = RI->Num; + int RootStackOffset = RI->StackOffset; + Constant *RootMetadata = RI->Metadata; + } }</pre></blockquote> <p>LLVM automatically computes a stack map. All a <tt>Collector</tt> needs to do @@ -1021,10 +1053,8 @@ CustomWriteBarriers = true; } -protected: - virtual Pass *createCustomLoweringPass() const { - return new MyGCLoweringFunctionPass(); - } + virtual bool initializeCustomLowering(Module &M); + virtual bool performCustomLowering(Function &F); };</pre></blockquote> <p>If any of these flags are set, then LLVM suppresses its default lowering for @@ -1041,56 +1071,53 @@ </ul> <p>If <tt>CustomReadBarriers</tt> or <tt>CustomWriteBarriers</tt> are specified, -the custom lowering pass <strong>must</strong> eliminate the corresponding -barriers.</p> +then <tt>performCustomLowering</tt> <strong>must</strong> eliminate the +corresponding barriers.</p> -<p>This template can be used as a starting point for a lowering pass:</p> +<p><tt>performCustomLowering</tt>, must comply with the same restrictions as <a +href="WritingAnLLVMPass.html#runOnFunction"><tt>runOnFunction</tt></a>, and +that <tt>initializeCustomLowering</tt> has the same semantics as <a +href="WritingAnLLVMPass.html#doInitialization_mod"><tt>doInitialization(Module +&)</tt></a>.</p> + +<p>The following can be used as a template:</p> <blockquote><pre ->#include "llvm/Function.h" -#include "llvm/Module.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; - } - }; +bool MyCollector::initializeCustomLowering(Module &M) { + return false; +} - char MyGCLoweringFunctionPass::ID = 0; +bool MyCollector::performCustomLowering(Function &F) { + const 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; }</pre></blockquote> </div> @@ -1130,15 +1157,18 @@ <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> +<blockquote><pre +>for (iterator I = begin(), E = end(); I != E; ++I) { + CollectorMetadata *MD = *I; + 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 @@ -1167,40 +1197,45 @@ <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> +can print stack maps built 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> +<p>Note that LLVM does not currently have analogous APIs to support 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; +public: + virtual void beginAssembly(std::ostream &OS, AsmPrinter &AP, + const TargetAsmInfo &TAI); - virtual void finishAssembly(Module &M, CollectorModuleMetadata &MMD, - std::ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI) const; + virtual void finishAssembly(std::ostream &OS, AsmPrinter &AP, + const TargetAsmInfo &TAI); }</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> +print portable assembly code to the <tt>std::ostream</tt>. The collector itself +contains the stack map for the entire module, and may access the +<tt>CollectorMetadata</tt> using its own <tt>begin()</tt> and <tt>end()</tt> +methods. Here's a realistic example:</p> <blockquote><pre >#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/Function.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetAsmInfo.h" -void MyCollector::finishAssembly(Module &M, - CollectorModuleMetadata &MMD, - std::ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI) const { +void MyCollector::beginAssembly(std::ostream &OS, AsmPrinter &AP, + const TargetAsmInfo &TAI) { + // Nothing to do. +} + +void MyCollector::finishAssembly(std::ostream &OS, AsmPrinter &AP, + const TargetAsmInfo &TAI) { // Set up for emitting addresses. const char *AddressDirective; int AddressAlignLog; - if (TAI.getAddressSize() == sizeof(int32_t)) { + if (AP.TM.getTargetData()->getPointerSize() == sizeof(int32_t)) { AddressDirective = TAI.getData32bitsDirective(); AddressAlignLog = 2; } else { @@ -1212,8 +1247,7 @@ AP.SwitchToDataSection(TAI.getDataSection()); // For each function... - for (CollectorModuleMetadata::iterator FI = MMD.begin(), - FE = MMD.end(); FI != FE; ++FI) { + for (iterator FI = begin(), FE = end(); FI != FE; ++FI) { CollectorMetadata &MD = **FI; // Emit this data structure: Modified: llvm/trunk/include/llvm/CodeGen/Collector.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Collector.h?rev=44827&r1=44826&r2=44827&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/Collector.h (original) +++ llvm/trunk/include/llvm/CodeGen/Collector.h Mon Dec 10 18:30:17 2007 @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// GCInfo records sufficient information about a machine function to enable +// Collector records sufficient information about a machine function to enable // accurate garbage collectors. Specifically: // // - Safe points @@ -25,8 +25,8 @@ // This generic information should used by ABI-specific passes to emit support // tables for the runtime garbage collector. // -// GCSafePointPass identifies the GC safe points in the machine code. (Roots are -// identified in SelectionDAGISel.) +// MachineCodeAnalysis identifies the GC safe points in the machine code. (Roots +// are identified in SelectionDAGISel.) // //===----------------------------------------------------------------------===// @@ -35,19 +35,25 @@ #include "llvm/CodeGen/CollectorMetadata.h" #include <iosfwd> +#include <string> namespace llvm { - class AsmPrinter; - class FunctionPassManager; - class PassManager; - class TargetAsmInfo; - - /// Collector describes a garbage collector's code generation requirements, /// and provides overridable hooks for those needs which cannot be abstractly /// described. class Collector { + public: + typedef std::vector<CollectorMetadata*> list_type; + typedef list_type::iterator iterator; + + private: + friend class CollectorModuleMetadata; + const Module *M; + std::string Name; + + list_type Functions; + protected: unsigned NeededSafePoints; //< Bitmask of required safe points. bool CustomReadBarriers; //< Default is to insert loads. @@ -55,16 +61,20 @@ bool CustomRoots; //< Default is to pass through to backend. bool InitRoots; //< If set, roots are nulled during lowering. - /// If any of the actions are set to Custom, this is expected to be - /// overriden to create a transform to lower those actions to LLVM IR. - virtual Pass *createCustomLoweringPass() const; - public: Collector(); virtual ~Collector(); + /// getName - The name of the collector, for debugging. + /// + const std::string &getName() const { return Name; } + + /// getModule - The module upon which the collector is operating. + /// + const Module &getModule() const { return *M; } + /// True if this collector requires safe points of any kind. By default, /// none are recorded. bool needsSafePoints() const { return NeededSafePoints != 0; } @@ -94,40 +104,30 @@ bool initializeRoots() const { return InitRoots; } - /// Adds LLVM IR transforms to handle collection intrinsics. By default, - /// read- and write barriers are replaced with direct memory accesses, and - /// roots are passed on to the code generator. - void addLoweringPasses(FunctionPassManager &PM) const; - - /// Same as addLoweringPasses(FunctionPassManager &), except uses a - /// PassManager for compatibility with unusual backends (such as MSIL or - /// CBackend). - void addLoweringPasses(PassManager &PM) const; - - /// Adds target-independent MachineFunction pass to mark safe points. This - /// is added very late during code generation, just prior to output, and - /// importantly after all CFG transformations (like branch folding). - void addGenericMachineCodePass(FunctionPassManager &PM, - const TargetMachine &TM, bool Fast) const; - /// beginAssembly/finishAssembly - Emit module metadata as assembly code. - virtual void beginAssembly(Module &M, std::ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI) const; - virtual void finishAssembly(Module &M, CollectorModuleMetadata &CMM, - std::ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI) const; - - private: - bool NeedsDefaultLoweringPass() const; - bool NeedsCustomLoweringPass() const; - + virtual void beginAssembly(std::ostream &OS, AsmPrinter &AP, + const TargetAsmInfo &TAI); + virtual void finishAssembly(std::ostream &OS, AsmPrinter &AP, + const TargetAsmInfo &TAI); + + /// begin/end - Iterators for function metadata. + /// + iterator begin() { return Functions.begin(); } + iterator end() { return Functions.end(); } + + /// insertFunctionMetadata - Creates metadata for a function. + /// + CollectorMetadata *insertFunctionMetadata(const Function &F); + + /// initializeCustomLowering/performCustomLowering - If any of the actions + /// are set to custom, performCustomLowering must be overriden to create a + /// transform to lower those actions to LLVM IR. initializeCustomLowering + /// is optional to override. These are the only Collector methods through + /// which the LLVM IR can be modified. + virtual bool initializeCustomLowering(Module &F); + virtual bool performCustomLowering(Function &F); }; - - /// If set, the code generator should generate garbage collection as specified - /// by the collector properties. - extern const Collector *TheCollector; // FIXME: Find a better home! - } #endif Modified: llvm/trunk/include/llvm/CodeGen/CollectorMetadata.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/CollectorMetadata.h?rev=44827&r1=44826&r2=44827&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/CollectorMetadata.h (original) +++ llvm/trunk/include/llvm/CodeGen/CollectorMetadata.h Mon Dec 10 18:30:17 2007 @@ -9,7 +9,7 @@ // // This file declares the CollectorMetadata and CollectorModuleMetadata classes, // which are used as a communication channel from the target code generator -// to the target garbage collector. This interface allows code generators and +// to the target garbage collectors. This interface allows code generators and // garbage collectors to be developed independently. // // The CollectorMetadata class records the data necessary to build a type @@ -37,19 +37,14 @@ #include "llvm/Pass.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" namespace llvm { + class AsmPrinter; + class Collector; class Constant; - - - /// Creates a pass to print collector metadata. - /// - Pass *createCollectorMetadataPrinter(std::ostream &OS); - - /// Creates a pass to destroy collector metadata. - /// - Pass *createCollectorMetadataDeleter(); + class TargetAsmInfo; namespace GC { @@ -77,7 +72,7 @@ struct GCRoot { int Num; //< Usually a frame index. int StackOffset; //< Offset from the stack pointer. - Constant *Metadata; //< From the call to llvm.gcroot. + Constant *Metadata; //< Metadata straight from the call to llvm.gcroot. GCRoot(int N, Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {} }; @@ -93,6 +88,7 @@ private: const Function &F; + Collector &C; uint64_t FrameSize; std::vector<GCRoot> Roots; std::vector<GCPoint> SafePoints; @@ -107,14 +103,18 @@ // The bit vector is the more compact representation where >3.2% of roots // are live per safe point (1.5% on 64-bit hosts). - friend class CollectorModuleMetadata; - CollectorMetadata(const Function &F); - public: + CollectorMetadata(const Function &F, Collector &C); ~CollectorMetadata(); + /// getFunction - Return the function to which this metadata applies. + /// const Function &getFunction() const { return F; } + /// getCollector - Return the collector for the function. + /// + Collector &getCollector() { return C; } + /// addStackRoot - Registers a root that lives on the stack. Num is the /// stack object ID for the alloca (if the code generator is using /// MachineFrameInfo). @@ -157,37 +157,36 @@ /// CollectorModuleMetadata - Garbage collection metadata for a whole module. /// class CollectorModuleMetadata : public ImmutablePass { - typedef std::vector<CollectorMetadata*> list_type; - typedef DenseMap<const Function*,CollectorMetadata*> map_type; + typedef StringMap<Collector*> collector_map_type; + typedef std::vector<Collector*> list_type; + typedef DenseMap<const Function*,CollectorMetadata*> function_map_type; + + collector_map_type NameMap; + list_type Collectors; + function_map_type Map; - Module *Mod; - list_type Functions; - map_type Map; + Collector *getOrCreateCollector(const Module *M, const std::string &Name); public: - typedef list_type::iterator iterator; + typedef list_type::const_iterator iterator; static char ID; CollectorModuleMetadata(); ~CollectorModuleMetadata(); - /// clear - Used to delete module metadata. Collector invokes this as - /// necessary. + /// clear - Used to delete module metadata. The metadata deleter pass calls + /// this. void clear(); - /// begin/end - Iterators for function metadata. - /// - iterator begin() { return Functions.begin(); } - iterator end() { return Functions.end(); } - - /// insert - Creates metadata for a function. + /// begin/end - Iterators for collectors. /// - CollectorMetadata& insert(const Function *F); + iterator begin() const { return Collectors.begin(); } + iterator end() const { return Collectors.end(); } - /// get - Looks up existing function metadata. + /// get - Look up function metadata. /// - CollectorMetadata* get(const Function *F) const; + CollectorMetadata &get(const Function &F); }; } Modified: llvm/trunk/include/llvm/CodeGen/Collectors.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Collectors.h?rev=44827&r1=44826&r2=44827&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/Collectors.h (original) +++ llvm/trunk/include/llvm/CodeGen/Collectors.h Mon Dec 10 18:30:17 2007 @@ -25,6 +25,9 @@ /// typedef Registry<Collector> CollectorRegistry; + /// FIXME: Collector instances are not useful on their own. These no longer + /// serve any purpose except to link in the plugins. + /// Creates an ocaml-compatible garbage collector. Collector *createOcamlCollector(); Modified: llvm/trunk/include/llvm/CodeGen/Passes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=44827&r1=44826&r2=44827&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/Passes.h (original) +++ llvm/trunk/include/llvm/CodeGen/Passes.h Mon Dec 10 18:30:17 2007 @@ -135,6 +135,24 @@ /// for the Sparc. FunctionPass *getRegisterAllocator(TargetMachine &T); + /// IntrinsicLowering Pass - Performs target-independent LLVM IR + /// transformations for highly portable collectors. + FunctionPass *createGCLoweringPass(); + + /// MachineCodeAnalysis Pass - Target-independent pass to mark safe points in + /// machine code. Must be added very late during code generation, just prior + /// to output, and importantly after all CFG transformations (such as branch + /// folding). + FunctionPass *createGCMachineCodeAnalysisPass(); + + /// Deleter Pass - Releases collector metadata. + /// + FunctionPass *createCollectorMetadataDeleter(); + + /// Creates a pass to print collector metadata. + /// + FunctionPass *createCollectorMetadataPrinter(std::ostream &OS); + /// createMachineLICMPass - This pass performs LICM on machine instructions. /// FunctionPass *createMachineLICMPass(); Modified: llvm/trunk/lib/CodeGen/Collector.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/Collector.cpp?rev=44827&r1=44826&r2=44827&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/Collector.cpp (original) +++ llvm/trunk/lib/CodeGen/Collector.cpp Mon Dec 10 18:30:17 2007 @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/Collector.h" +#include "llvm/CodeGen/Passes.h" #include "llvm/IntrinsicInst.h" #include "llvm/Module.h" #include "llvm/PassManager.h" @@ -29,38 +30,40 @@ namespace { - /// This pass rewrites calls to the llvm.gcread or llvm.gcwrite intrinsics, - /// replacing them with simple loads and stores as directed by the Collector. - /// This is useful for most garbage collectors. + /// LowerIntrinsics - This pass rewrites calls to the llvm.gcread or + /// llvm.gcwrite intrinsics, replacing them with simple loads and stores as + /// directed by the Collector. It also performs automatic root initialization + /// and custom intrinsic lowering. class VISIBILITY_HIDDEN LowerIntrinsics : public FunctionPass { - const Collector &Coll; - /// GCRootInt, GCReadInt, GCWriteInt - The function prototypes for the /// llvm.gc* intrinsics. Function *GCRootInt, *GCReadInt, *GCWriteInt; + static bool NeedsDefaultLoweringPass(const Collector &C); + static bool NeedsCustomLoweringPass(const Collector &C); static bool CouldBecomeSafePoint(Instruction *I); - static void InsertRootInitializers(Function &F, + bool PerformDefaultLowering(Function &F, Collector &Coll); + static bool InsertRootInitializers(Function &F, AllocaInst **Roots, unsigned Count); public: static char ID; - LowerIntrinsics(const Collector &GC); + LowerIntrinsics(); const char *getPassName() const; + void getAnalysisUsage(AnalysisUsage &AU) const; bool doInitialization(Module &M); bool runOnFunction(Function &F); }; - /// This is a target-independent pass over the machine function representation - /// to identify safe points for the garbage collector in the machine code. It - /// inserts labels at safe points and populates the GCInfo class. + /// MachineCodeAnalysis - This is a target-independent pass over the machine + /// function representation to identify safe points for the garbage collector + /// in the machine code. It inserts labels at safe points and populates a + /// CollectorMetadata record for each function. class VISIBILITY_HIDDEN MachineCodeAnalysis : public MachineFunctionPass { - const Collector &Coll; - const TargetMachine &Targ; - + const TargetMachine *TM; CollectorMetadata *MD; MachineModuleInfo *MMI; const TargetInstrInfo *TII; @@ -76,7 +79,7 @@ public: static char ID; - MachineCodeAnalysis(const Collector &C, const TargetMachine &T); + MachineCodeAnalysis(); const char *getPassName() const; void getAnalysisUsage(AnalysisUsage &AU) const; @@ -87,8 +90,6 @@ // ----------------------------------------------------------------------------- -const Collector *llvm::TheCollector = 0; - Collector::Collector() : NeededSafePoints(0), CustomReadBarriers(false), @@ -97,85 +98,85 @@ InitRoots(true) {} -Collector::~Collector() {} - -void Collector::addLoweringPasses(FunctionPassManager &PM) const { - if (NeedsDefaultLoweringPass()) - PM.add(new LowerIntrinsics(*this)); - - if (NeedsCustomLoweringPass()) - PM.add(createCustomLoweringPass()); -} - -void Collector::addLoweringPasses(PassManager &PM) const { - if (NeedsDefaultLoweringPass()) - PM.add(new LowerIntrinsics(*this)); - - if (NeedsCustomLoweringPass()) - PM.add(createCustomLoweringPass()); -} - -void Collector::addGenericMachineCodePass(FunctionPassManager &PM, - const TargetMachine &TM, - bool Fast) const { - if (needsSafePoints()) - PM.add(new MachineCodeAnalysis(*this, TM)); -} - -bool Collector::NeedsDefaultLoweringPass() const { - // Default lowering is necessary only if read or write barriers have a default - // action. The default for roots is no action. - return !customWriteBarrier() - || !customReadBarrier() - || initializeRoots(); -} - -bool Collector::NeedsCustomLoweringPass() const { - // Custom lowering is only necessary if enabled for some action. - return customWriteBarrier() - || customReadBarrier() - || customRoots(); -} - -Pass *Collector::createCustomLoweringPass() const { - cerr << "Collector must override createCustomLoweringPass.\n"; +Collector::~Collector() { + for (iterator I = begin(), E = end(); I != E; ++I) + delete *I; + + Functions.clear(); +} + +bool Collector::initializeCustomLowering(Module &M) { return false; } + +bool Collector::performCustomLowering(Function &F) { + cerr << "gc " << getName() << " must override performCustomLowering.\n"; abort(); return 0; } -void Collector::beginAssembly(Module &M, std::ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI) const { +void Collector::beginAssembly(std::ostream &OS, AsmPrinter &AP, + const TargetAsmInfo &TAI) { // Default is no action. } -void Collector::finishAssembly(Module &M, CollectorModuleMetadata &CMM, - std::ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI) const { +void Collector::finishAssembly(std::ostream &OS, AsmPrinter &AP, + const TargetAsmInfo &TAI) { // Default is no action. } + +CollectorMetadata *Collector::insertFunctionMetadata(const Function &F) { + CollectorMetadata *CM = new CollectorMetadata(F, *this); + Functions.push_back(CM); + return CM; +} // ----------------------------------------------------------------------------- +FunctionPass *llvm::createGCLoweringPass() { + return new LowerIntrinsics(); +} + char LowerIntrinsics::ID = 0; -LowerIntrinsics::LowerIntrinsics(const Collector &C) - : FunctionPass((intptr_t)&ID), Coll(C), +LowerIntrinsics::LowerIntrinsics() + : FunctionPass((intptr_t)&ID), GCRootInt(0), GCReadInt(0), GCWriteInt(0) {} const char *LowerIntrinsics::getPassName() const { return "Lower Garbage Collection Instructions"; } -/// doInitialization - If this module uses the GC intrinsics, find them now. If -/// not, this pass does not do anything. +void LowerIntrinsics::getAnalysisUsage(AnalysisUsage &AU) const { + FunctionPass::getAnalysisUsage(AU); + AU.addRequired<CollectorModuleMetadata>(); +} + +/// doInitialization - If this module uses the GC intrinsics, find them now. bool LowerIntrinsics::doInitialization(Module &M) { GCReadInt = M.getFunction("llvm.gcread"); GCWriteInt = M.getFunction("llvm.gcwrite"); GCRootInt = M.getFunction("llvm.gcroot"); - return false; + + // FIXME: This is rather antisocial in the context of a JIT since it performs + // work against the entire module. But this cannot be done at + // runFunction time (initializeCustomLowering likely needs to change + // the module). + CollectorModuleMetadata *CMM = getAnalysisToUpdate<CollectorModuleMetadata>(); + assert(CMM && "LowerIntrinsics didn't require CollectorModuleMetadata!?"); + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (I->hasCollector()) + CMM->get(*I); // Instantiate the Collector. + + bool MadeChange = false; + for (CollectorModuleMetadata::iterator I = CMM->begin(), + E = CMM->end(); I != E; ++I) + if (NeedsCustomLoweringPass(**I)) + if ((*I)->initializeCustomLowering(M)) + MadeChange = true; + + return MadeChange; } -void LowerIntrinsics::InsertRootInitializers(Function &F, AllocaInst **Roots, +bool LowerIntrinsics::InsertRootInitializers(Function &F, AllocaInst **Roots, unsigned Count) { // Scroll past alloca instructions. BasicBlock::iterator IP = F.getEntryBlock().begin(); @@ -190,11 +191,32 @@ InitedRoots.insert(AI); // Add root initializers. + bool MadeChange = false; + for (AllocaInst **I = Roots, **E = Roots + Count; I != E; ++I) - if (!InitedRoots.count(*I)) + if (!InitedRoots.count(*I)) { new StoreInst(ConstantPointerNull::get(cast<PointerType>( cast<PointerType>((*I)->getType())->getElementType())), *I, IP); + MadeChange = true; + } + + return MadeChange; +} + +bool LowerIntrinsics::NeedsDefaultLoweringPass(const Collector &C) { + // Default lowering is necessary only if read or write barriers have a default + // action. The default for roots is no action. + return !C.customWriteBarrier() + || !C.customReadBarrier() + || C.initializeRoots(); +} + +bool LowerIntrinsics::NeedsCustomLoweringPass(const Collector &C) { + // Custom lowering is only necessary if enabled for some action. + return C.customWriteBarrier() + || C.customReadBarrier() + || C.customRoots(); } /// CouldBecomeSafePoint - Predicate to conservatively determine whether the @@ -228,9 +250,24 @@ /// runOnFunction - Replace gcread/gcwrite intrinsics with loads and stores. /// Leave gcroot intrinsics; the code generator needs to see those. bool LowerIntrinsics::runOnFunction(Function &F) { - // Quick exit for programs that do not declare the intrinsics. - if (!GCReadInt && !GCWriteInt && !GCRootInt) return false; + // Quick exit for functions that do not use GC. + if (!F.hasCollector()) return false; + + CollectorMetadata &MD = getAnalysis<CollectorModuleMetadata>().get(F); + Collector &Coll = MD.getCollector(); + + bool MadeChange = false; + + if (NeedsDefaultLoweringPass(Coll)) + MadeChange |= PerformDefaultLowering(F, Coll); + + if (NeedsCustomLoweringPass(Coll)) + MadeChange |= Coll.performCustomLowering(F); + return MadeChange; +} + +bool LowerIntrinsics::PerformDefaultLowering(Function &F, Collector &Coll) { bool LowerWr = !Coll.customWriteBarrier(); bool LowerRd = !Coll.customReadBarrier(); bool InitRoots = Coll.initializeRoots(); @@ -268,17 +305,21 @@ } if (Roots.size()) - InsertRootInitializers(F, Roots.begin(), Roots.size()); + MadeChange |= InsertRootInitializers(F, Roots.begin(), Roots.size()); return MadeChange; } // ----------------------------------------------------------------------------- +FunctionPass *llvm::createGCMachineCodeAnalysisPass() { + return new MachineCodeAnalysis(); +} + char MachineCodeAnalysis::ID = 0; -MachineCodeAnalysis::MachineCodeAnalysis(const Collector &C, const TargetMachine &T) - : MachineFunctionPass(intptr_t(&ID)), Coll(C), Targ(T) {} +MachineCodeAnalysis::MachineCodeAnalysis() + : MachineFunctionPass(intptr_t(&ID)) {} const char *MachineCodeAnalysis::getPassName() const { return "Analyze Machine Code For Garbage Collection"; @@ -304,10 +345,10 @@ MachineBasicBlock::iterator RAI = CI; ++RAI; - if (Coll.needsSafePoint(GC::PreCall)) + if (MD->getCollector().needsSafePoint(GC::PreCall)) MD->addSafePoint(GC::PreCall, InsertLabel(*CI->getParent(), CI)); - if (Coll.needsSafePoint(GC::PostCall)) + if (MD->getCollector().needsSafePoint(GC::PostCall)) MD->addSafePoint(GC::PostCall, InsertLabel(*CI->getParent(), RAI)); } @@ -323,7 +364,7 @@ void MachineCodeAnalysis::FindStackOffsets(MachineFunction &MF) { uint64_t StackSize = MFI->getStackSize(); uint64_t OffsetAdjustment = MFI->getOffsetAdjustment(); - uint64_t OffsetOfLocalArea = Targ.getFrameInfo()->getOffsetOfLocalArea(); + uint64_t OffsetOfLocalArea = TM->getFrameInfo()->getOffsetOfLocalArea(); for (CollectorMetadata::roots_iterator RI = MD->roots_begin(), RE = MD->roots_end(); RI != RE; ++RI) @@ -332,12 +373,16 @@ } bool MachineCodeAnalysis::runOnMachineFunction(MachineFunction &MF) { - if (!Coll.needsSafePoints()) + // Quick exit for functions that do not use GC. + if (!MF.getFunction()->hasCollector()) return false; + + MD = &getAnalysis<CollectorModuleMetadata>().get(*MF.getFunction()); + if (!MD->getCollector().needsSafePoints()) return false; - MD = getAnalysis<CollectorModuleMetadata>().get(MF.getFunction()); + TM = &MF.getTarget(); MMI = &getAnalysis<MachineModuleInfo>(); - TII = MF.getTarget().getInstrInfo(); + TII = TM->getInstrInfo(); MFI = MF.getFrameInfo(); // Find the size of the stack frame. Modified: llvm/trunk/lib/CodeGen/CollectorMetadata.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CollectorMetadata.cpp?rev=44827&r1=44826&r2=44827&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/CollectorMetadata.cpp (original) +++ llvm/trunk/lib/CodeGen/CollectorMetadata.cpp Mon Dec 10 18:30:17 2007 @@ -13,8 +13,11 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/CollectorMetadata.h" +#include "llvm/CodeGen/Collector.h" +#include "llvm/CodeGen/Collectors.h" #include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Pass.h" +#include "llvm/CodeGen/Passes.h" #include "llvm/Function.h" #include "llvm/Support/Compiler.h" @@ -22,7 +25,7 @@ namespace { - class VISIBILITY_HIDDEN Printer : public MachineFunctionPass { + class VISIBILITY_HIDDEN Printer : public FunctionPass { static char ID; std::ostream &OS; @@ -32,10 +35,10 @@ const char *getPassName() const; void getAnalysisUsage(AnalysisUsage &AU) const; - bool runOnMachineFunction(MachineFunction &MF); + bool runOnFunction(Function &F); }; - class VISIBILITY_HIDDEN Deleter : public MachineFunctionPass { + class VISIBILITY_HIDDEN Deleter : public FunctionPass { static char ID; public: @@ -44,7 +47,7 @@ const char *getPassName() const; void getAnalysisUsage(AnalysisUsage &AU) const; - bool runOnMachineFunction(MachineFunction &MF); + bool runOnFunction(Function &F); bool doFinalization(Module &M); }; @@ -55,8 +58,8 @@ // ----------------------------------------------------------------------------- -CollectorMetadata::CollectorMetadata(const Function &F) - : F(F), FrameSize(~0LL) {} +CollectorMetadata::CollectorMetadata(const Function &F, Collector &C) + : F(F), C(C), FrameSize(~0LL) {} CollectorMetadata::~CollectorMetadata() {} @@ -71,46 +74,71 @@ clear(); } -CollectorMetadata& CollectorModuleMetadata::insert(const Function *F) { - assert(Map.find(F) == Map.end() && "Function GC metadata already exists!"); - CollectorMetadata *FMD = new CollectorMetadata(*F); - Functions.push_back(FMD); - Map[F] = FMD; - return *FMD; +Collector *CollectorModuleMetadata:: +getOrCreateCollector(const Module *M, const std::string &Name) { + const char *Start = Name.c_str(); + + collector_map_type::iterator NMI = NameMap.find(Start, Start + Name.size()); + if (NMI != NameMap.end()) + return NMI->getValue(); + + for (CollectorRegistry::iterator I = CollectorRegistry::begin(), + E = CollectorRegistry::end(); I != E; ++I) { + if (strcmp(Start, I->getName()) == 0) { + Collector *C = I->instantiate(); + C->M = M; + C->Name = Name; + NameMap.GetOrCreateValue(Start, Start + Name.size()).setValue(C); + Collectors.push_back(C); + return C; + } + } + + cerr << "unsupported collector: " << Name << "\n"; + abort(); } -CollectorMetadata* CollectorModuleMetadata::get(const Function *F) const { - map_type::iterator I = Map.find(F); - if (I == Map.end()) - return 0; - return I->second; +CollectorMetadata &CollectorModuleMetadata::get(const Function &F) { + assert(F.hasCollector()); + function_map_type::iterator I = Map.find(&F); + if (I != Map.end()) + return *I->second; + + Collector *C = getOrCreateCollector(F.getParent(), F.getCollector()); + CollectorMetadata *MD = C->insertFunctionMetadata(F); + Map[&F] = MD; + return *MD; } void CollectorModuleMetadata::clear() { + Map.clear(); + + // TODO: StringMap should provide a clear method. + while (!NameMap.empty()) + NameMap.erase(NameMap.begin()); + for (iterator I = begin(), E = end(); I != E; ++I) delete *I; - - Functions.clear(); - Map.clear(); + Collectors.clear(); } // ----------------------------------------------------------------------------- char Printer::ID = 0; -Pass *llvm::createCollectorMetadataPrinter(std::ostream &OS) { +FunctionPass *llvm::createCollectorMetadataPrinter(std::ostream &OS) { return new Printer(OS); } Printer::Printer(std::ostream &OS) - : MachineFunctionPass(intptr_t(&ID)), OS(OS) {} + : FunctionPass(intptr_t(&ID)), OS(OS) {} const char *Printer::getPassName() const { return "Print Garbage Collector Information"; } void Printer::getAnalysisUsage(AnalysisUsage &AU) const { - MachineFunctionPass::getAnalysisUsage(AU); + FunctionPass::getAnalysisUsage(AU); AU.setPreservesAll(); AU.addRequired<CollectorModuleMetadata>(); } @@ -125,9 +153,9 @@ } } -bool Printer::runOnMachineFunction(MachineFunction &MF) { - if (CollectorMetadata *FD = - getAnalysis<CollectorModuleMetadata>().get(MF.getFunction())) { +bool Printer::runOnFunction(Function &F) { + if (F.hasCollector()) { + CollectorMetadata *FD = &getAnalysis<CollectorModuleMetadata>().get(F); OS << "GC roots for " << FD->getFunction().getNameStart() << ":\n"; for (CollectorMetadata::roots_iterator RI = FD->roots_begin(), @@ -160,11 +188,11 @@ char Deleter::ID = 0; -Pass *llvm::createCollectorMetadataDeleter() { +FunctionPass *llvm::createCollectorMetadataDeleter() { return new Deleter(); } -Deleter::Deleter() : MachineFunctionPass(intptr_t(&ID)) {} +Deleter::Deleter() : FunctionPass(intptr_t(&ID)) {} const char *Deleter::getPassName() const { return "Delete Garbage Collector Information"; @@ -175,11 +203,13 @@ AU.addRequired<CollectorModuleMetadata>(); } -bool Deleter::runOnMachineFunction(MachineFunction &MF) { +bool Deleter::runOnFunction(Function &MF) { return false; } bool Deleter::doFinalization(Module &M) { - getAnalysis<CollectorModuleMetadata>().clear(); + CollectorModuleMetadata *CMM = getAnalysisToUpdate<CollectorModuleMetadata>(); + assert(CMM && "Deleter didn't require CollectorModuleMetadata?!"); + CMM->clear(); return false; } _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits