[llvm-commits] [llvm] r44827 - in /llvm/trunk: 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
Gordon Henriksen
gordonhenriksen at mac.com
Mon Dec 10 16:30:17 PST 2007
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;
}
More information about the llvm-commits
mailing list