CollectorMetadata and Collector are rejiggered to get along with
authorGordon Henriksen <gordonhenriksen@mac.com>
Tue, 11 Dec 2007 00:30:17 +0000 (00:30 +0000)
committerGordon Henriksen <gordonhenriksen@mac.com>
Tue, 11 Dec 2007 00:30:17 +0000 (00:30 +0000)
per-function collector model. Collector is now the factory for
CollectorMetadata, so the latter may be subclassed.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@44827 91177308-0d34-0410-b5e6-96231b3b80d8

docs/GarbageCollection.html
include/llvm/CodeGen/Collector.h
include/llvm/CodeGen/CollectorMetadata.h
include/llvm/CodeGen/Collectors.h
include/llvm/CodeGen/Passes.h
lib/CodeGen/Collector.cpp
lib/CodeGen/CollectorMetadata.cpp

index 90f42bb1458b76266f177a2aa326c71d7c9bdbc0..4b5bd50aca1c9c0899f9721a5b205086cda095ed 100644 (file)
     </ul>
   </li>
 
     </ul>
   </li>
 
-  <li><a href="#intrinsics">Collection intrinsics</a>
+  <li><a href="#core">Core support</a>
     <ul>
     <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>
     <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 @@ garbage collector implementations in two manners:</p>
 
 <ul>
   <li>Emitting compatible code, including initialization in the main
 
 <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>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>
 
   <li>Linking your final executable with the garbage collector runtime.</li>
 </ul>
 
@@ -211,7 +214,7 @@ garbage collector implementations in two manners:</p>
 <table>
   <tr>
     <th>Collector</th>
 <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>
     <th>Linkage</th>
     <th><tt>gcroot</tt></th>
     <th><tt>gcread</tt></th>
@@ -219,7 +222,7 @@ garbage collector implementations in two manners:</p>
   </tr>
   <tr valign="baseline">
     <td><a href="#semispace">SemiSpace</a></td>
   </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>
     <td>TODO FIXME</td>
     <td>required</td>
     <td>optional</td>
@@ -227,7 +230,7 @@ garbage collector implementations in two manners:</p>
   </tr>
   <tr valign="baseline">
     <td><a href="#ocaml">Ocaml</a></td>
   </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>
     <td><i>provided by ocamlopt</i></td>
     <td>required</td>
     <td>optional</td>
@@ -252,11 +255,12 @@ collectors may require user programs to utilize.</p>
 
 <div class="doc_text">
 
 
 <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
 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>
 
 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 @@ requires no special support from the target code generator.</p>
 program may use <tt>load</tt> and <tt>store</tt> instead of <tt>llvm.gcread</tt>
 and <tt>llvm.gcwrite</tt>.</p>
 
 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>
 compatible runtime.</p>
 
 </div>
@@ -277,8 +281,7 @@ compatible runtime.</p>
 <div class="doc_text">
 
 <p>The SemiSpace runtime implements with the <a href="runtime">suggested
 <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
 
 <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 @@ Enhancements would be welcomed.</p>
 
 <div class="doc_text">
 
 
 <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>
 <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 @@ may use <tt>load</tt> and <tt>store</tt> instead of <tt>llvm.gcread</tt> and
 
 <!-- *********************************************************************** -->
 <div class="doc_section">
 
 <!-- *********************************************************************** -->
 <div class="doc_section">
-  <a name="intrinsics">Collection intrinsics</a>
+  <a name="core">Core support</a>
 </div>
 <!-- *********************************************************************** -->
 
 </div>
 <!-- *********************************************************************** -->
 
@@ -335,6 +339,27 @@ specified by the runtime.</p>
 
 </div>
 
 
 </div>
 
+<!-- ======================================================================= -->
+<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 class="doc_subsection">
   <a name="gcroot">Identifying GC roots on the stack: <tt>llvm.gcroot</tt></a>
@@ -591,6 +616,10 @@ TODO
 
 <div class="doc_text">
 
 
 <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
 <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 @@ namespace {
   };
   
   CollectorRegistry::Add&lt;MyCollector&gt;
   };
   
   CollectorRegistry::Add&lt;MyCollector&gt;
-  X("mygc", "My custom garbage collector.");
+  X("mygc", "My bespoke garbage collector.");
 }</pre></blockquote>
 
 <p>Using the LLVM makefiles (like the <a
 }</pre></blockquote>
 
 <p>Using the LLVM makefiles (like the <a
@@ -632,20 +661,20 @@ LOADABLE_MODULE = 1
 
 include $(LEVEL)/Makefile.common</pre></blockquote>
 
 
 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
 
 <blockquote><pre
->TheCollector = new MyGC();</pre></blockquote>
-<!-- /FIXME GROSS -->
+>$ cat sample.ll
+define void @f() gc "mygc" {
+entry:
+        ret void
+}
+$ llvm-as &lt; 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>
 
 
 </div>
 
@@ -956,15 +985,18 @@ interest.</p>
 <div class="doc_text">
 
 <blockquote><pre
 <div class="doc_text">
 
 <blockquote><pre
->CollectorMetadata &amp;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-&gt;getFrameSize();
+  size_t RootCount = MD-&gt;roots_size();
+
+  for (CollectorMetadata::roots_iterator RI = MD-&gt;roots_begin(),
+                                         RE = MD-&gt;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
 }</pre></blockquote>
 
 <p>LLVM automatically computes a stack map. All a <tt>Collector</tt> needs to do
@@ -1021,10 +1053,8 @@ public:
     CustomWriteBarriers = true;
   }
   
     CustomWriteBarriers = true;
   }
   
-protected:
-  virtual Pass *createCustomLoweringPass() const {
-    return new MyGCLoweringFunctionPass();
-  }
+  virtual bool initializeCustomLowering(Module &amp;M);
+  virtual bool performCustomLowering(Function &amp;F);
 };</pre></blockquote>
 
 <p>If any of these flags are set, then LLVM suppresses its default lowering for
 };</pre></blockquote>
 
 <p>If any of these flags are set, then LLVM suppresses its default lowering for
@@ -1041,56 +1071,53 @@ pass specified by the collector.</p>
 </ul>
 
 <p>If <tt>CustomReadBarriers</tt> or <tt>CustomWriteBarriers</tt> are specified,
 </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
+&amp;)</tt></a>.</p>
+
+<p>The following can be used as a template:</p>
 
 <blockquote><pre
 
 <blockquote><pre
->#include "llvm/Function.h"
-#include "llvm/Module.h"
+>#include "llvm/Module.h"
 #include "llvm/Instructions.h"
 
 #include "llvm/Instructions.h"
 
-namespace {
-  class VISIBILITY_HIDDEN MyGCLoweringFunctionPass : public FunctionPass {
-    static char ID;
-  public:
-    MyGCLoweringFunctionPass() : FunctionPass(intptr_t(&amp;ID)) {}
-    
-    const char *getPassName() const { return "Lower GC Intrinsics"; }
-    
-    bool runOnFunction(Function &amp;F) {
-      Module *M = F.getParent();
-      
-      Function *GCReadInt  = M-&gt;getFunction("llvm.gcread"),
-               *GCWriteInt = M-&gt;getFunction("llvm.gcwrite"),
-               *GCRootInt  = M-&gt;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&lt;CallInst&gt;(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 &amp;M) {
+  return false;
+}
 
 
-  char MyGCLoweringFunctionPass::ID = 0;
+bool MyCollector::performCustomLowering(Function &amp;F) {
+  const Module *M = F.getParent();
+  
+  Function *GCReadInt  = M-&gt;getFunction("llvm.gcread"),
+           *GCWriteInt = M-&gt;getFunction("llvm.gcwrite"),
+           *GCRootInt  = M-&gt;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&lt;CallInst&gt;(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>
 }</pre></blockquote>
 
 </div>
@@ -1130,15 +1157,18 @@ namespace {
 
 <p>It can then use the following routines to access safe points.</p>
 
 
 <p>It can then use the following routines to access safe points.</p>
 
-<blockquote><pre>
-CollectorMetadata &amp;MD = ...;
-size_t PointCount = MD.size();
-
-for (CollectorMetadata::iterator PI = MD.begin(),
-                                 PE = MD.end(); PI != PE; ++PI) {
-  GC::PointKind PointKind = PI-&gt;Kind;
-  unsigned PointNum = PI-&gt;Num;
-}</pre></blockquote>
+<blockquote><pre
+>for (iterator I = begin(), E = end(); I != E; ++I) {
+  CollectorMetadata *MD = *I;
+  size_t PointCount = MD-&gt;size();
+
+  for (CollectorMetadata::iterator PI = MD-&gt;begin(),
+                                   PE = MD-&gt;end(); PI != PE; ++PI) {
+    GC::PointKind PointKind = PI-&gt;Kind;
+    unsigned PointNum = PI-&gt;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
 
 <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 @@ safe point (because only the topmost function has been patched).</p>
 
 <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
 
 <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 {
 
 <blockquote><pre
 >class MyCollector : public Collector {
-  virtual void beginAssembly(Module &amp;M, std::ostream &amp;OS, AsmPrinter &amp;AP,
-                             const TargetAsmInfo &amp;TAI) const;
+public:
+  virtual void beginAssembly(std::ostream &amp;OS, AsmPrinter &amp;AP,
+                             const TargetAsmInfo &amp;TAI);
 
 
-  virtual void finishAssembly(Module &amp;M, CollectorModuleMetadata &amp;MMD,
-                              std::ostream &amp;OS, AsmPrinter &amp;AP,
-                              const TargetAsmInfo &amp;TAI) const;
+  virtual void finishAssembly(std::ostream &amp;OS, AsmPrinter &amp;AP,
+                              const TargetAsmInfo &amp;TAI);
 }</pre></blockquote>
 
 <p>The collector should use <tt>AsmPrinter</tt> and <tt>TargetAsmInfo</tt> to
 }</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"
 
 <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"
 
 #include "llvm/Target/TargetAsmInfo.h"
 
-void MyCollector::finishAssembly(Module &amp;M,
-                                 CollectorModuleMetadata &amp;MMD,
-                                 std::ostream &amp;OS, AsmPrinter &amp;AP,
-                                 const TargetAsmInfo &amp;TAI) const {
+void MyCollector::beginAssembly(std::ostream &amp;OS, AsmPrinter &amp;AP,
+                                const TargetAsmInfo &amp;TAI) {
+  // Nothing to do.
+}
+
+void MyCollector::finishAssembly(std::ostream &amp;OS, AsmPrinter &amp;AP,
+                                 const TargetAsmInfo &amp;TAI) {
   // Set up for emitting addresses.
   const char *AddressDirective;
   int AddressAlignLog;
   // 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 {
     AddressDirective = TAI.getData32bitsDirective();
     AddressAlignLog = 2;
   } else {
@@ -1212,8 +1247,7 @@ void MyCollector::finishAssembly(Module &amp;M,
   AP.SwitchToDataSection(TAI.getDataSection());
   
   // For each function...
   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 &amp;MD = **FI;
     
     // Emit this data structure:
     CollectorMetadata &amp;MD = **FI;
     
     // Emit this data structure:
index 664e13c62b89e3ef8c3dc02fa03ceae4a93adc1d..dbe84ca99987da376d2bbb3c7019533266929cd0 100644 (file)
@@ -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
 // 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.
 //
 // 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.)
 //
 //===----------------------------------------------------------------------===//
 
 //
 //===----------------------------------------------------------------------===//
 
 
 #include "llvm/CodeGen/CollectorMetadata.h"
 #include <iosfwd>
 
 #include "llvm/CodeGen/CollectorMetadata.h"
 #include <iosfwd>
+#include <string>
 
 namespace llvm {
   
 
 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 {
   /// 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.
   protected:
     unsigned NeededSafePoints; //< Bitmask of required safe points.
     bool CustomReadBarriers;   //< Default is to insert loads.
@@ -55,16 +61,20 @@ namespace llvm {
     bool CustomRoots;          //< Default is to pass through to backend.
     bool InitRoots;            //< If set, roots are nulled during lowering.
     
     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();
     
     
   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; }
     /// 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 @@ namespace llvm {
     bool initializeRoots() const { return InitRoots; }
     
     
     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.
     /// 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
 }
 
 #endif
index 9924bd9451bc409a86ced5dfce6518b3097ed2d1..0f958a833867adf9ca2664b1c3be75319731552a 100644 (file)
@@ -9,7 +9,7 @@
 //
 // This file declares the CollectorMetadata and CollectorModuleMetadata classes,
 // which are used as a communication channel from the target code generator
 //
 // 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
 // garbage collectors to be developed independently.
 //
 // The CollectorMetadata class records the data necessary to build a type
 
 #include "llvm/Pass.h"
 #include "llvm/ADT/DenseMap.h"
 
 #include "llvm/Pass.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
 
 namespace llvm {
   
 
 namespace llvm {
   
+  class AsmPrinter;
+  class Collector;
   class Constant;
   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 {
   
   
   namespace GC {
@@ -77,7 +72,7 @@ namespace llvm {
   struct GCRoot {
     int Num;            //< Usually a frame index.
     int StackOffset;    //< Offset from the stack pointer.
   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) {}
   };
     
     GCRoot(int N, Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {}
   };
@@ -93,6 +88,7 @@ namespace llvm {
     
   private:
     const Function &F;
     
   private:
     const Function &F;
+    Collector &C;
     uint64_t FrameSize;
     std::vector<GCRoot> Roots;
     std::vector<GCPoint> SafePoints;
     uint64_t FrameSize;
     std::vector<GCRoot> Roots;
     std::vector<GCPoint> SafePoints;
@@ -107,14 +103,18 @@ namespace llvm {
     // The bit vector is the more compact representation where >3.2% of roots
     // are live per safe point (1.5% on 64-bit hosts).
     
     // 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:
   public:
+    CollectorMetadata(const Function &F, Collector &C);
     ~CollectorMetadata();
     
     ~CollectorMetadata();
     
+    /// getFunction - Return the function to which this metadata applies.
+    /// 
     const Function &getFunction() const { return F; }
     
     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).
     /// 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 @@ namespace llvm {
   /// CollectorModuleMetadata - Garbage collection metadata for a whole module.
   /// 
   class CollectorModuleMetadata : public ImmutablePass {
   /// 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;
     
     
-    Module *Mod;
-    list_type Functions;
-    map_type Map;
+    collector_map_type NameMap;
+    list_type Collectors;
+    function_map_type Map;
+    
+    Collector *getOrCreateCollector(const Module *M, const std::string &Name);
     
   public:
     
   public:
-    typedef list_type::iterator iterator;
+    typedef list_type::const_iterator iterator;
     
     static char ID;
     
     CollectorModuleMetadata();
     ~CollectorModuleMetadata();
     
     
     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();
     
     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);
   };
   
 }
   };
   
 }
index 18c1546b8c88c073eb5027f3dec721bc88a697b7..de8e2e6e421ca20c0813226d6ab00d3e750241a0 100644 (file)
@@ -25,6 +25,9 @@ namespace llvm {
   /// 
   typedef Registry<Collector> CollectorRegistry;
   
   /// 
   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();
   
   /// Creates an ocaml-compatible garbage collector.
   Collector *createOcamlCollector();
   
index f0aa5082fe241f53e27d4265ac548318a6eead12..2286dc6d6bb9163d11506e6288b70d2d1c2de481 100644 (file)
@@ -135,6 +135,24 @@ namespace llvm {
   /// for the Sparc.
   FunctionPass *getRegisterAllocator(TargetMachine &T);
 
   /// 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();
   /// createMachineLICMPass - This pass performs LICM on machine instructions.
   /// 
   FunctionPass *createMachineLICMPass();
index 29dc50420b7931f69431b1061cf6998f50ca8414..67b392889e18681da5347fc79144949fab68a49c 100644 (file)
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/Collector.h"
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/Collector.h"
+#include "llvm/CodeGen/Passes.h"
 #include "llvm/IntrinsicInst.h"
 #include "llvm/Module.h"
 #include "llvm/PassManager.h"
 #include "llvm/IntrinsicInst.h"
 #include "llvm/Module.h"
 #include "llvm/PassManager.h"
@@ -29,38 +30,40 @@ using namespace llvm;
 
 namespace {
   
 
 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 {
   class VISIBILITY_HIDDEN LowerIntrinsics : public FunctionPass {
-    const Collector &Coll;
-    
     /// GCRootInt, GCReadInt, GCWriteInt - The function prototypes for the
     /// llvm.gc* intrinsics.
     Function *GCRootInt, *GCReadInt, *GCWriteInt;
     
     /// 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 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;
     
                                        AllocaInst **Roots, unsigned Count);
     
   public:
     static char ID;
     
-    LowerIntrinsics(const Collector &GC);
+    LowerIntrinsics();
     const char *getPassName() const;
     const char *getPassName() const;
+    void getAnalysisUsage(AnalysisUsage &AU) const;
     
     bool doInitialization(Module &M);
     bool runOnFunction(Function &F);
   };
   
   
     
     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 {
   class VISIBILITY_HIDDEN MachineCodeAnalysis : public MachineFunctionPass {
-    const Collector &Coll;
-    const TargetMachine &Targ;
-    
+    const TargetMachine *TM;
     CollectorMetadata *MD;
     MachineModuleInfo *MMI;
     const TargetInstrInfo *TII;
     CollectorMetadata *MD;
     MachineModuleInfo *MMI;
     const TargetInstrInfo *TII;
@@ -76,7 +79,7 @@ namespace {
   public:
     static char ID;
     
   public:
     static char ID;
     
-    MachineCodeAnalysis(const Collector &C, const TargetMachine &T);
+    MachineCodeAnalysis();
     const char *getPassName() const;
     void getAnalysisUsage(AnalysisUsage &AU) const;
     
     const char *getPassName() const;
     void getAnalysisUsage(AnalysisUsage &AU) const;
     
@@ -87,8 +90,6 @@ namespace {
 
 // -----------------------------------------------------------------------------
 
 
 // -----------------------------------------------------------------------------
 
-const Collector *llvm::TheCollector = 0;
-
 Collector::Collector() :
   NeededSafePoints(0),
   CustomReadBarriers(false),
 Collector::Collector() :
   NeededSafePoints(0),
   CustomReadBarriers(false),
@@ -97,85 +98,85 @@ Collector::Collector() :
   InitRoots(true)
 {}
 
   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();
+Collector::~Collector() {
+  for (iterator I = begin(), E = end(); I != E; ++I)
+    delete *I;
+  
+  Functions.clear();
 }
 }
-
-Pass *Collector::createCustomLoweringPass() const {
-  cerr << "Collector must override createCustomLoweringPass.\n";
+bool Collector::initializeCustomLowering(Module &M) { return false; }
+bool Collector::performCustomLowering(Function &F) {
+  cerr << "gc " << getName() << " must override performCustomLowering.\n";
   abort();
   return 0;
 }
     
   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.
 }
     
   // 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.
 }
   // 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;
 
 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";
 }
     
     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");
 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();
                                                           unsigned Count) {
   // Scroll past alloca instructions.
   BasicBlock::iterator IP = F.getEntryBlock().begin();
@@ -190,11 +191,32 @@ void LowerIntrinsics::InsertRootInitializers(Function &F, AllocaInst **Roots,
         InitedRoots.insert(AI);
   
   // Add root initializers.
         InitedRoots.insert(AI);
   
   // Add root initializers.
+  bool MadeChange = false;
+  
   for (AllocaInst **I = Roots, **E = Roots + Count; I != E; ++I)
   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);
       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
 }
 
 /// CouldBecomeSafePoint - Predicate to conservatively determine whether the
@@ -228,9 +250,24 @@ bool LowerIntrinsics::CouldBecomeSafePoint(Instruction *I) {
 /// runOnFunction - Replace gcread/gcwrite intrinsics with loads and stores.
 /// Leave gcroot intrinsics; the code generator needs to see those.
 bool LowerIntrinsics::runOnFunction(Function &F) {
 /// 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();
   bool LowerWr = !Coll.customWriteBarrier();
   bool LowerRd = !Coll.customReadBarrier();
   bool InitRoots = Coll.initializeRoots();
@@ -268,17 +305,21 @@ bool LowerIntrinsics::runOnFunction(Function &F) {
   }
   
   if (Roots.size())
   }
   
   if (Roots.size())
-    InsertRootInitializers(F, Roots.begin(), Roots.size());
+    MadeChange |= InsertRootInitializers(F, Roots.begin(), Roots.size());
   
   return MadeChange;
 }
 
 // -----------------------------------------------------------------------------
 
   
   return MadeChange;
 }
 
 // -----------------------------------------------------------------------------
 
+FunctionPass *llvm::createGCMachineCodeAnalysisPass() {
+  return new MachineCodeAnalysis();
+}
+
 char MachineCodeAnalysis::ID = 0;
 
 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";
 
 const char *MachineCodeAnalysis::getPassName() const {
   return "Analyze Machine Code For Garbage Collection";
@@ -304,10 +345,10 @@ void MachineCodeAnalysis::VisitCallPoint(MachineBasicBlock::iterator CI) {
   MachineBasicBlock::iterator RAI = CI; 
   ++RAI;                                
   
   MachineBasicBlock::iterator RAI = CI; 
   ++RAI;                                
   
-  if (Coll.needsSafePoint(GC::PreCall))
+  if (MD->getCollector().needsSafePoint(GC::PreCall))
     MD->addSafePoint(GC::PreCall, InsertLabel(*CI->getParent(), CI));
   
     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));
 }
 
     MD->addSafePoint(GC::PostCall, InsertLabel(*CI->getParent(), RAI));
 }
 
@@ -323,7 +364,7 @@ void MachineCodeAnalysis::FindSafePoints(MachineFunction &MF) {
 void MachineCodeAnalysis::FindStackOffsets(MachineFunction &MF) {
   uint64_t StackSize = MFI->getStackSize();
   uint64_t OffsetAdjustment = MFI->getOffsetAdjustment();
 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)
   
   for (CollectorMetadata::roots_iterator RI = MD->roots_begin(),
                                          RE = MD->roots_end(); RI != RE; ++RI)
@@ -332,12 +373,16 @@ void MachineCodeAnalysis::FindStackOffsets(MachineFunction &MF) {
 }
 
 bool MachineCodeAnalysis::runOnMachineFunction(MachineFunction &MF) {
 }
 
 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;
   
     return false;
   
-  MD = getAnalysis<CollectorModuleMetadata>().get(MF.getFunction());
+  TM = &MF.getTarget();
   MMI = &getAnalysis<MachineModuleInfo>();
   MMI = &getAnalysis<MachineModuleInfo>();
-  TII = MF.getTarget().getInstrInfo();
+  TII = TM->getInstrInfo();
   MFI = MF.getFrameInfo();
   
   // Find the size of the stack frame.
   MFI = MF.getFrameInfo();
   
   // Find the size of the stack frame.
index f86ee04c9510b6e1c47b7d61af0e22805effd0e3..57349390b01b8215a32c64717a5b56b762184807 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/CollectorMetadata.h"
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/CollectorMetadata.h"
+#include "llvm/CodeGen/Collector.h"
+#include "llvm/CodeGen/Collectors.h"
 #include "llvm/CodeGen/MachineFrameInfo.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"
 
 #include "llvm/Function.h"
 #include "llvm/Support/Compiler.h"
 
@@ -22,7 +25,7 @@ using namespace llvm;
 
 namespace {
   
 
 namespace {
   
-  class VISIBILITY_HIDDEN Printer : public MachineFunctionPass {
+  class VISIBILITY_HIDDEN Printer : public FunctionPass {
     static char ID;
     std::ostream &OS;
     
     static char ID;
     std::ostream &OS;
     
@@ -32,10 +35,10 @@ namespace {
     const char *getPassName() const;
     void getAnalysisUsage(AnalysisUsage &AU) const;
     
     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:
     static char ID;
     
   public:
@@ -44,7 +47,7 @@ namespace {
     const char *getPassName() const;
     void getAnalysisUsage(AnalysisUsage &AU) const;
     
     const char *getPassName() const;
     void getAnalysisUsage(AnalysisUsage &AU) const;
     
-    bool runOnMachineFunction(MachineFunction &MF);
+    bool runOnFunction(Function &F);
     bool doFinalization(Module &M);
   };
   
     bool doFinalization(Module &M);
   };
   
@@ -55,8 +58,8 @@ namespace {
 
 // -----------------------------------------------------------------------------
 
 
 // -----------------------------------------------------------------------------
 
-CollectorMetadata::CollectorMetadata(const Function &F)
-  : F(F), FrameSize(~0LL) {}
+CollectorMetadata::CollectorMetadata(const Function &F, Collector &C)
+  : F(F), C(C), FrameSize(~0LL) {}
 
 CollectorMetadata::~CollectorMetadata() {}
 
 
 CollectorMetadata::~CollectorMetadata() {}
 
@@ -71,46 +74,71 @@ CollectorModuleMetadata::~CollectorModuleMetadata() {
   clear();
 }
 
   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() {
 }
 
 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;
   for (iterator I = begin(), E = end(); I != E; ++I)
     delete *I;
-  
-  Functions.clear();
-  Map.clear();
+  Collectors.clear();
 }
 
 // -----------------------------------------------------------------------------
 
 char Printer::ID = 0;
 
 }
 
 // -----------------------------------------------------------------------------
 
 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)
   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 {
 
 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>();
 }
   AU.setPreservesAll();
   AU.addRequired<CollectorModuleMetadata>();
 }
@@ -125,9 +153,9 @@ static const char *DescKind(GC::PointKind Kind) {
   }
 }
 
   }
 }
 
-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(),
     
     OS << "GC roots for " << FD->getFunction().getNameStart() << ":\n";
     for (CollectorMetadata::roots_iterator RI = FD->roots_begin(),
@@ -160,11 +188,11 @@ bool Printer::runOnMachineFunction(MachineFunction &MF) {
 
 char Deleter::ID = 0;
 
 
 char Deleter::ID = 0;
 
-Pass *llvm::createCollectorMetadataDeleter() {
+FunctionPass *llvm::createCollectorMetadataDeleter() {
   return new Deleter();
 }
 
   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";
 
 const char *Deleter::getPassName() const {
   return "Delete Garbage Collector Information";
@@ -175,11 +203,13 @@ void Deleter::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.addRequired<CollectorModuleMetadata>();
 }
 
   AU.addRequired<CollectorModuleMetadata>();
 }
 
-bool Deleter::runOnMachineFunction(MachineFunction &MF) {
+bool Deleter::runOnFunction(Function &MF) {
   return false;
 }
 
 bool Deleter::doFinalization(Module &M) {
   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;
 }
   return false;
 }