Move ownership of GCStrategy objects to LLVMContext
authorPhilip Reames <listmail@philipreames.com>
Fri, 16 Jan 2015 20:07:33 +0000 (20:07 +0000)
committerPhilip Reames <listmail@philipreames.com>
Fri, 16 Jan 2015 20:07:33 +0000 (20:07 +0000)
Note: This change ended up being slightly more controversial than expected.  Chandler has tentatively okayed this for the moment, but I may be revisiting this in the near future after we settle some high level questions.

Rather than have the GCStrategy object owned by the GCModuleInfo - which is an immutable analysis pass used mainly by gc.root - have it be owned by the LLVMContext. This simplifies the ownership logic (i.e. can you have two instances of the same strategy at once?), but more importantly, allows us to access the GCStrategy in the middle end optimizer. To this end, I add an accessor through Function which becomes the canonical way to get at a GCStrategy instance.

In the near future, this will allows me to move some of the checks from http://reviews.llvm.org/D6808 into the Verifier itself, and to introduce optimization legality predicates for some of the recent additions to InstCombine. (These will follow as separate changes.)

Differential Revision: http://reviews.llvm.org/D6811

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

23 files changed:
include/llvm/CodeGen/GCMetadata.h
include/llvm/CodeGen/GCMetadataPrinter.h
include/llvm/CodeGen/GCStrategy.h [deleted file]
include/llvm/IR/Function.h
include/llvm/IR/GCStrategy.h [new file with mode: 0644]
include/llvm/Support/Registry.h
lib/CodeGen/CMakeLists.txt
lib/CodeGen/ErlangGC.cpp
lib/CodeGen/GCMetadata.cpp
lib/CodeGen/GCRootLowering.cpp
lib/CodeGen/GCStrategy.cpp [deleted file]
lib/CodeGen/OcamlGC.cpp
lib/CodeGen/Passes.cpp
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
lib/CodeGen/SelectionDAG/StatepointLowering.cpp
lib/CodeGen/ShadowStackGC.cpp
lib/CodeGen/StatepointExampleGC.cpp
lib/IR/CMakeLists.txt
lib/IR/Function.cpp
lib/IR/GCStrategy.cpp [new file with mode: 0644]
lib/IR/LLVMContextImpl.cpp
lib/IR/LLVMContextImpl.h

index c7f1ab87fcb1171f7bcbe4c1cf7e059c90178c05..6922b70bd9a4c3c82294cc0c08dcc25605990546 100644 (file)
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/IR/DebugLoc.h"
+#include "llvm/IR/GCStrategy.h"
 #include "llvm/Pass.h"
 #include <memory>
 
 namespace llvm {
   class AsmPrinter;
-  class GCStrategy;
   class Constant;
   class MCSymbol;
 
-  namespace GC {
-    /// PointKind - The type of a collector-safe point.
-    ///
-    enum PointKind {
-      Loop,    ///< Instr is a loop (backwards branch).
-      Return,  ///< Instr is a return instruction.
-      PreCall, ///< Instr is a call instruction.
-      PostCall ///< Instr is the return address of a call.
-    };
-  }
-
   /// GCPoint - Metadata for a collector-safe point in machine code.
   ///
   struct GCPoint {
@@ -163,14 +152,9 @@ namespace llvm {
   /// Records both the function level information used by GCRoots and a
   /// cache of the 'active' gc strategy objects for the current Module.
   class GCModuleInfo : public ImmutablePass {
-    typedef StringMap<GCStrategy*> strategy_map_type;
-    typedef std::vector<std::unique_ptr<GCStrategy>> list_type;
-
-    strategy_map_type StrategyMap;
-    list_type StrategyList;
-
-    GCStrategy *getOrCreateStrategy(const Module *M, const std::string &Name);
-
+    /// A list of GCStrategies which are active in this Module.  These are
+    /// not owning pointers.
+    std::vector<GCStrategy*> StrategyList;
   public:
     /// List of per function info objects.  In theory, Each of these
     /// may be associated with a different GC.
@@ -190,7 +174,7 @@ namespace llvm {
     finfo_map_type FInfoMap;
   public:
 
-    typedef list_type::const_iterator iterator;
+    typedef std::vector<GCStrategy*>::const_iterator iterator;
 
     static char ID;
 
index 25fafba93f8b653db12410a9fe6d6038076f8ef7..6010cb8a4f3de00cbe34fae8ffcfefe92b2cbcfd 100644 (file)
@@ -21,7 +21,7 @@
 #define LLVM_CODEGEN_GCMETADATAPRINTER_H
 
 #include "llvm/CodeGen/GCMetadata.h"
-#include "llvm/CodeGen/GCStrategy.h"
+#include "llvm/IR/GCStrategy.h"
 #include "llvm/Support/Registry.h"
 
 namespace llvm {
diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h
deleted file mode 100644 (file)
index bdd1446..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-//===-- llvm/CodeGen/GCStrategy.h - Garbage collection ----------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// GCStrategy coordinates code generation algorithms and implements some itself
-// in order to generate code compatible with a target code generator as
-// specified in a function's 'gc' attribute. Algorithms are enabled by setting
-// flags in a subclass's constructor, and some virtual methods can be
-// overridden.
-//
-// GCStrategy is relevant for implementations using either gc.root or
-// gc.statepoint based lowering strategies, but is currently focused mostly on
-// options for gc.root.  This will change over time.
-// 
-// When requested by a subclass of GCStrategy, the gc.root implementation will
-// populate GCModuleInfo and GCFunctionInfo with that about each Function in
-// the Module that opts in to garbage collection.  Specifically:
-// 
-// - Safe points
-//   Garbage collection is generally only possible at certain points in code.
-//   GCStrategy can request that the collector insert such points:
-//
-//     - At and after any call to a subroutine
-//     - Before returning from the current function
-//     - Before backwards branches (loops)
-// 
-// - Roots
-//   When a reference to a GC-allocated object exists on the stack, it must be
-//   stored in an alloca registered with llvm.gcoot.
-//
-// This information can used to emit the metadata tables which are required by
-// the target garbage collector runtime.
-//
-// When used with gc.statepoint, information about safepoint and roots can be
-// found in the binary StackMap section after code generation.  Safepoint
-// placement is currently the responsibility of the frontend, though late
-// insertion support is planned.  gc.statepoint does not currently support
-// custom stack map formats; such can be generated by parsing the standard
-// stack map section if desired.
-// 
-// The read and write barrier support can be used with either implementation.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CODEGEN_GCSTRATEGY_H
-#define LLVM_CODEGEN_GCSTRATEGY_H
-
-#include "llvm/ADT/Optional.h"
-#include "llvm/CodeGen/GCMetadata.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/Support/Registry.h"
-#include <string>
-
-namespace llvm {
-  /// GCStrategy describes a garbage collector algorithm's code generation
-  /// requirements, and provides overridable hooks for those needs which cannot
-  /// be abstractly described.  GCStrategy objects currently must be looked up
-  /// through the GCModuleInfo analysis pass.  They are owned by the analysis
-  /// pass and recreated every time that pass is invalidated.
-  class GCStrategy {
-  private:
-    std::string Name;
-    friend class GCModuleInfo;
-    
-  protected:
-    bool UseStatepoints;       /// Uses gc.statepoints as opposed to gc.roots,
-                               /// if set, none of the other options can be
-                               /// anything but their default values.
-
-    unsigned NeededSafePoints; ///< Bitmask of required safe points.
-    bool CustomReadBarriers;   ///< Default is to insert loads.
-    bool CustomWriteBarriers;  ///< Default is to insert stores.
-    bool CustomRoots;          ///< Default is to pass through to backend.
-    bool InitRoots;            ///< If set, roots are nulled during lowering.
-    bool UsesMetadata;         ///< If set, backend must emit metadata tables.
-    
-  public:
-    GCStrategy();
-    virtual ~GCStrategy() {}
-    
-    /// Return the name of the GC strategy.  This is the value of the collector
-    /// name string specified on functions which use this strategy.
-    const std::string &getName() const { return Name; }
-
-    /// By default, write barriers are replaced with simple store
-    /// instructions. If true, then performCustomLowering must instead lower
-    /// them. 
-    bool customWriteBarrier() const { return CustomWriteBarriers; }
-    
-    /// By default, read barriers are replaced with simple load
-    /// instructions. If true, then performCustomLowering must instead lower
-    /// them. 
-    bool customReadBarrier() const { return CustomReadBarriers; }
-
-    /// Returns true if this strategy is expecting the use of gc.statepoints,
-    /// and false otherwise.
-    bool useStatepoints() const { return UseStatepoints; }
-
-    /** @name Statepoint Specific Properties */
-    ///@{
-
-    /// If the value specified can be reliably distinguished, returns true for
-    /// pointers to GC managed locations and false for pointers to non-GC 
-    /// managed locations.  Note a GCStrategy can always return 'None' (i.e. an
-    /// empty optional indicating it can't reliably distinguish.   
-    virtual Optional<bool> isGCManagedPointer(const Value *V) const {
-      return None;
-    }
-    ///@}
-
-    /** @name GCRoot Specific Properties
-     * These properties and overrides only apply to collector strategies using
-     * GCRoot. 
-     */
-    ///@{
-
-    /// True if safe points of any kind are required. By default, none are
-    /// recorded. 
-    bool needsSafePoints() const {
-      return NeededSafePoints != 0;
-    }
-    
-    /// True if the given kind of safe point is required. By default, none are
-    /// recorded. 
-    bool needsSafePoint(GC::PointKind Kind) const {
-      return (NeededSafePoints & 1 << Kind) != 0;
-    }
-        
-    /// By default, roots are left for the code generator so it can generate a
-    /// stack map. If true, then performCustomLowering must delete them.
-    bool customRoots() const { return CustomRoots; }
-
-    /// If set, gcroot intrinsics should initialize their allocas to null
-    /// before the first use. This is necessary for most GCs and is enabled by
-    /// default. 
-    bool initializeRoots() const { return InitRoots; }
-    
-    /// If set, appropriate metadata tables must be emitted by the back-end
-    /// (assembler, JIT, or otherwise). For statepoint, this method is
-    /// currently unsupported.  The stackmap information can be found in the
-    /// StackMap section as described in the documentation.
-    bool usesMetadata() const { return UsesMetadata; }
-
-    ///@}
-    
-    /// initializeCustomLowering/performCustomLowering - If any of the actions
-    /// are set to custom, performCustomLowering must be overriden to transform
-    /// the corresponding actions to LLVM IR. initializeCustomLowering is
-    /// optional to override. These are the only GCStrategy methods through
-    /// which the LLVM IR can be modified.  These methods apply mostly to
-    /// gc.root based implementations, but can be overriden to provide custom
-    /// barrier lowerings with gc.statepoint as well.
-    ///@{
-    virtual bool initializeCustomLowering(Module &F) {
-      // No changes made
-      return false;
-    }
-    virtual bool performCustomLowering(Function &F) {
-      llvm_unreachable("GCStrategy subclass specified a configuration which"
-                       "requires a custom lowering without providing one");
-    }
-  };
-
-  /// Subclasses of GCStrategy are made available for use during compilation by
-  /// adding them to the global GCRegistry.  This can done either within the
-  /// LLVM source tree or via a loadable plugin.  An example registeration
-  /// would be:
-  /// static GCRegistry::Add<CustomGC> X("custom-name",
-  ///        "my custom supper fancy gc strategy");
-  /// 
-  /// Note that to use a custom GCMetadataPrinter w/gc.roots, you must also
-  /// register your GCMetadataPrinter subclass with the
-  /// GCMetadataPrinterRegistery as well. 
-  typedef Registry<GCStrategy> GCRegistry;
-}
-
-#endif
index 51403281e964e6927eced0db01859002cde9e517..e9d0806eaddde185231d4c04cce9b5e62dea0ac2 100644 (file)
@@ -29,6 +29,7 @@
 namespace llvm {
 
 class FunctionType;
+class GCStrategy;  
 class LLVMContext;
 
 // Traits for intrusive list of basic blocks...
@@ -225,6 +226,10 @@ public:
   void setGC(const char *Str);
   void clearGC();
 
+  /// Returns the GCStrategy associated with the specified garbage collector
+  /// algorithm or nullptr if one is not set.
+  GCStrategy *getGCStrategy() const;
+
   /// @brief adds the attribute to the list of attributes.
   void addAttribute(unsigned i, Attribute::AttrKind attr);
 
diff --git a/include/llvm/IR/GCStrategy.h b/include/llvm/IR/GCStrategy.h
new file mode 100644 (file)
index 0000000..1cd107b
--- /dev/null
@@ -0,0 +1,196 @@
+//===-- llvm/IR/GCStrategy.h - Garbage collection ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// GCStrategy coordinates code generation algorithms and implements some itself
+// in order to generate code compatible with a target code generator as
+// specified in a function's 'gc' attribute. Algorithms are enabled by setting
+// flags in a subclass's constructor, and some virtual methods can be
+// overridden.
+//
+// GCStrategy is relevant for implementations using either gc.root or
+// gc.statepoint based lowering strategies, but is currently focused mostly on
+// options for gc.root.  This will change over time.
+// 
+// When requested by a subclass of GCStrategy, the gc.root implementation will
+// populate GCModuleInfo and GCFunctionInfo with that about each Function in
+// the Module that opts in to garbage collection.  Specifically:
+// 
+// - Safe points
+//   Garbage collection is generally only possible at certain points in code.
+//   GCStrategy can request that the collector insert such points:
+//
+//     - At and after any call to a subroutine
+//     - Before returning from the current function
+//     - Before backwards branches (loops)
+// 
+// - Roots
+//   When a reference to a GC-allocated object exists on the stack, it must be
+//   stored in an alloca registered with llvm.gcoot.
+//
+// This information can used to emit the metadata tables which are required by
+// the target garbage collector runtime.
+//
+// When used with gc.statepoint, information about safepoint and roots can be
+// found in the binary StackMap section after code generation.  Safepoint
+// placement is currently the responsibility of the frontend, though late
+// insertion support is planned.  gc.statepoint does not currently support
+// custom stack map formats; such can be generated by parsing the standard
+// stack map section if desired.
+// 
+// The read and write barrier support can be used with either implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_GCSTRATEGY_H
+#define LLVM_IR_GCSTRATEGY_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/IR/Value.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Registry.h"
+#include <string>
+
+namespace llvm {
+  namespace GC {
+    /// PointKind - The type of a collector-safe point.
+    ///
+    enum PointKind {
+      Loop,    ///< Instr is a loop (backwards branch).
+      Return,  ///< Instr is a return instruction.
+      PreCall, ///< Instr is a call instruction.
+      PostCall ///< Instr is the return address of a call.
+    };
+  }
+
+  
+  /// GCStrategy describes a garbage collector algorithm's code generation
+  /// requirements, and provides overridable hooks for those needs which cannot
+  /// be abstractly described.  GCStrategy objects must be looked up through
+  /// the Function.  The objects themselves are owned by the Context and must
+  /// be immutable.
+  class GCStrategy {
+  private:
+    std::string Name;
+    friend class LLVMContextImpl;
+    
+  protected:
+    bool UseStatepoints;       /// Uses gc.statepoints as opposed to gc.roots,
+                               /// if set, none of the other options can be
+                               /// anything but their default values.
+
+    unsigned NeededSafePoints; ///< Bitmask of required safe points.
+    bool CustomReadBarriers;   ///< Default is to insert loads.
+    bool CustomWriteBarriers;  ///< Default is to insert stores.
+    bool CustomRoots;          ///< Default is to pass through to backend.
+    bool InitRoots;            ///< If set, roots are nulled during lowering.
+    bool UsesMetadata;         ///< If set, backend must emit metadata tables.
+    
+  public:
+    GCStrategy();
+    virtual ~GCStrategy() {}
+    
+    /// Return the name of the GC strategy.  This is the value of the collector
+    /// name string specified on functions which use this strategy.
+    const std::string &getName() const { return Name; }
+
+    /// By default, write barriers are replaced with simple store
+    /// instructions. If true, then performCustomLowering must instead lower
+    /// them. 
+    bool customWriteBarrier() const { return CustomWriteBarriers; }
+    
+    /// By default, read barriers are replaced with simple load
+    /// instructions. If true, then performCustomLowering must instead lower
+    /// them. 
+    bool customReadBarrier() const { return CustomReadBarriers; }
+
+    /// Returns true if this strategy is expecting the use of gc.statepoints,
+    /// and false otherwise.
+    bool useStatepoints() const { return UseStatepoints; }
+
+    /** @name Statepoint Specific Properties */
+    ///@{
+
+    /// If the value specified can be reliably distinguished, returns true for
+    /// pointers to GC managed locations and false for pointers to non-GC 
+    /// managed locations.  Note a GCStrategy can always return 'None' (i.e. an
+    /// empty optional indicating it can't reliably distinguish.   
+    virtual Optional<bool> isGCManagedPointer(const Value *V) const {
+      return None;
+    }
+    ///@}
+
+    /** @name GCRoot Specific Properties
+     * These properties and overrides only apply to collector strategies using
+     * GCRoot. 
+     */
+    ///@{
+
+    /// True if safe points of any kind are required. By default, none are
+    /// recorded. 
+    bool needsSafePoints() const {
+      return NeededSafePoints != 0;
+    }
+    
+    /// True if the given kind of safe point is required. By default, none are
+    /// recorded. 
+    bool needsSafePoint(GC::PointKind Kind) const {
+      return (NeededSafePoints & 1 << Kind) != 0;
+    }
+        
+    /// By default, roots are left for the code generator so it can generate a
+    /// stack map. If true, then performCustomLowering must delete them.
+    bool customRoots() const { return CustomRoots; }
+
+    /// If set, gcroot intrinsics should initialize their allocas to null
+    /// before the first use. This is necessary for most GCs and is enabled by
+    /// default. 
+    bool initializeRoots() const { return InitRoots; }
+    
+    /// If set, appropriate metadata tables must be emitted by the back-end
+    /// (assembler, JIT, or otherwise). For statepoint, this method is
+    /// currently unsupported.  The stackmap information can be found in the
+    /// StackMap section as described in the documentation.
+    bool usesMetadata() const { return UsesMetadata; }
+
+    ///@}
+    
+    /// initializeCustomLowering/performCustomLowering - If any of the actions
+    /// are set to custom, performCustomLowering must be overriden to transform
+    /// the corresponding actions to LLVM IR. initializeCustomLowering is
+    /// optional to override. These are the only GCStrategy methods through
+    /// which the LLVM IR can be modified.  These methods apply mostly to
+    /// gc.root based implementations, but can be overriden to provide custom
+    /// barrier lowerings with gc.statepoint as well.
+    ///@{
+    virtual bool initializeCustomLowering(Module &F) {
+      // No changes made
+      return false;
+    }
+    virtual bool performCustomLowering(Function &F) {
+      llvm_unreachable("GCStrategy subclass specified a configuration which"
+                       "requires a custom lowering without providing one");
+    }
+  };
+
+  /// Subclasses of GCStrategy are made available for use during compilation by
+  /// adding them to the global GCRegistry.  This can done either within the
+  /// LLVM source tree or via a loadable plugin.  An example registeration
+  /// would be:
+  /// static GCRegistry::Add<CustomGC> X("custom-name",
+  ///        "my custom supper fancy gc strategy");
+  /// 
+  /// Note that to use a custom GCMetadataPrinter w/gc.roots, you must also
+  /// register your GCMetadataPrinter subclass with the
+  /// GCMetadataPrinterRegistery as well. 
+  typedef Registry<GCStrategy> GCRegistry;
+}
+
+#endif
index e21269b2f1d529271710ea1a1414f12aa6bd90fc..51db8cfb15b60db1f8fe6663a7f8ea7a20575b2f 100644 (file)
@@ -120,6 +120,10 @@ namespace llvm {
     static iterator begin() { return iterator(Head); }
     static iterator end()   { return iterator(nullptr); }
 
+    static iterator_range<iterator> entries() {
+      return iterator_range<iterator>(begin(), end());
+    }
+
 
     /// Abstract base class for registry listeners, which are informed when new
     /// entries are added to the registry. Simply subclass and instantiate:
index f0b2dfe365b73b59007ce310541b51ac7f86563f..7f7f5225180c5874019d9e9a5e45281de6a06311 100644 (file)
@@ -23,7 +23,6 @@ add_llvm_library(LLVMCodeGen
   GCMetadata.cpp
   GCMetadataPrinter.cpp
   GCRootLowering.cpp
-  GCStrategy.cpp
   GlobalMerge.cpp
   IfConversion.cpp
   InlineSpiller.cpp
index 5f2b3a0983262edc141890506e1bd73ce8e762a4..ec2c2e8daf23715e9cb038aa1a18229bb51ec838 100644 (file)
@@ -15,8 +15,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/GCs.h"
-#include "llvm/CodeGen/GCStrategy.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/IR/GCStrategy.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/Target/TargetInstrInfo.h"
index 6101c679a5d33655bb5f00c21a1ef0779a958d51..6f4fa11d6d9fcd3df7388b6de3867ef93297be96 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/GCMetadata.h"
-#include "llvm/CodeGen/GCStrategy.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/IR/Function.h"
+#include "llvm/IR/GCStrategy.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/Debug.h"
@@ -61,27 +61,6 @@ GCModuleInfo::GCModuleInfo()
   initializeGCModuleInfoPass(*PassRegistry::getPassRegistry());
 }
 
-GCStrategy *GCModuleInfo::getOrCreateStrategy(const Module *M,
-                                              const std::string &Name) {
-  strategy_map_type::iterator NMI = StrategyMap.find(Name);
-  if (NMI != StrategyMap.end())
-    return NMI->getValue();
-  
-  for (GCRegistry::iterator I = GCRegistry::begin(),
-                            E = GCRegistry::end(); I != E; ++I) {
-    if (Name == I->getName()) {
-      std::unique_ptr<GCStrategy> S = I->instantiate();
-      S->Name = Name;
-      StrategyMap[Name] = S.get();
-      StrategyList.push_back(std::move(S));
-      return StrategyList.back().get();
-    }
-  }
-  dbgs() << "unsupported GC: " << Name << "\n";
-  llvm_unreachable(nullptr);
-}
-
 GCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) {
   assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!");
   assert(F.hasGC());
@@ -90,7 +69,15 @@ GCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) {
   if (I != FInfoMap.end())
     return *I->second;
   
-  GCStrategy *S = getOrCreateStrategy(F.getParent(), F.getGC());
+  GCStrategy *S = F.getGCStrategy();
+  if (!S) {
+    std::string error = std::string("unsupported GC: ") + F.getGC();
+    report_fatal_error(error);
+  }
+  // Save the fact this strategy is associated with this module.  Note that
+  // these are non-owning references, the GCStrategy remains owned by the
+  // Context. 
+  StrategyList.push_back(S);
   Functions.push_back(make_unique<GCFunctionInfo>(F, *S));
   GCFunctionInfo *GFI = Functions.back().get();
   FInfoMap[&F] = GFI;
@@ -100,7 +87,6 @@ GCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) {
 void GCModuleInfo::clear() {
   Functions.clear();
   FInfoMap.clear();
-  StrategyMap.clear();
   StrategyList.clear();
 }
 
index 9bda7b8493ff25e11a9126a7553af3efd6eb5045..8ff08ece76e41e485b63e76a899c38a2dfa1889c 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/CodeGen/GCStrategy.h"
+#include "llvm/CodeGen/GCMetadata.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/IR/Dominators.h"
+#include "llvm/IR/GCStrategy.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Debug.h"
diff --git a/lib/CodeGen/GCStrategy.cpp b/lib/CodeGen/GCStrategy.cpp
deleted file mode 100644 (file)
index 2b687d9..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-//===-- GCStrategy.cpp - Garbage Collector Description --------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the policy object GCStrategy which describes the
-// behavior of a given garbage collector.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/CodeGen/GCStrategy.h"
-
-using namespace llvm;
-
-GCStrategy::GCStrategy()
-    : UseStatepoints(false), NeededSafePoints(0), CustomReadBarriers(false),
-      CustomWriteBarriers(false), CustomRoots(false),
-      InitRoots(true), UsesMetadata(false) {}
index 48db200c513cd2a54d6767d017848e97d5e03897..c5c78529ece349b0e410d877617806bd0ef07ec9 100644 (file)
@@ -15,7 +15,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/GCs.h"
-#include "llvm/CodeGen/GCStrategy.h"
+#include "llvm/IR/GCStrategy.h"
 
 using namespace llvm;
 
index 28e9f847a9d746dee460e8ab0c0e70da4d0a4ba6..88cee03fa161866fb658201476d471dc39f14a1a 100644 (file)
@@ -14,7 +14,6 @@
 
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/Analysis/Passes.h"
-#include "llvm/CodeGen/GCStrategy.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/RegAllocRegistry.h"
 #include "llvm/IR/IRPrintingPasses.h"
index 6b3ad5f69b09df753cce6ed89a697b5d4cac14b1..a8db35c3a98792081f050c10131ba9af61063fb3 100644 (file)
@@ -26,7 +26,6 @@
 #include "llvm/CodeGen/FastISel.h"
 #include "llvm/CodeGen/FunctionLoweringInfo.h"
 #include "llvm/CodeGen/GCMetadata.h"
-#include "llvm/CodeGen/GCStrategy.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
@@ -41,6 +40,7 @@
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Function.h"
+#include "llvm/IR/GCStrategy.h"
 #include "llvm/IR/GlobalVariable.h"
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/Instructions.h"
index 7ee06fc153b2121acff765ca4a18bd3809f5f9f7..6a0a07970a8066ec0ceaf4f1ff74f0593c81c286 100644 (file)
@@ -24,7 +24,6 @@
 #include "llvm/CodeGen/FastISel.h"
 #include "llvm/CodeGen/FunctionLoweringInfo.h"
 #include "llvm/CodeGen/GCMetadata.h"
-#include "llvm/CodeGen/GCStrategy.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
@@ -36,6 +35,7 @@
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/Function.h"
+#include "llvm/IR/GCStrategy.h"
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
index 33c20d3f21958bf773152d223026d14766890f51..94f09bdc2f964761c5be1e5d6c9f9f0a655dce5d 100644 (file)
 #include "SelectionDAGBuilder.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/GCMetadata.h"
 #include "llvm/CodeGen/FunctionLoweringInfo.h"
-#include "llvm/CodeGen/GCStrategy.h"
 #include "llvm/CodeGen/SelectionDAG.h"
 #include "llvm/CodeGen/StackMaps.h"
 #include "llvm/IR/CallingConv.h"
+#include "llvm/IR/GCStrategy.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Intrinsics.h"
index 0be00f0e7ce5eaf7eda8cb9784ad7ccda369b68d..181cb8c435c8584e9deb3a32a5e998719f7542b3 100644 (file)
@@ -27,8 +27,8 @@
 
 #include "llvm/CodeGen/GCs.h"
 #include "llvm/ADT/StringExtras.h"
-#include "llvm/CodeGen/GCStrategy.h"
 #include "llvm/IR/CallSite.h"
+#include "llvm/IR/GCStrategy.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Module.h"
index 09b74ca1d2dd267c302d091b3e3a524d3a116c82..e20b270f42d54f3afeeae36404adba5c78ad8850 100644 (file)
@@ -16,7 +16,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/CodeGen/GCStrategy.h"
+#include "llvm/IR/GCStrategy.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Value.h"
 
index 1a210e05827546445c2a7607648f4f37f378214f..621c7ca922429aa1fc0a8eda4081a687ec767215 100644 (file)
@@ -17,6 +17,7 @@ add_llvm_library(LLVMCore
   Dominators.cpp
   Function.cpp
   GCOV.cpp
+  GCStrategy.cpp
   GVMaterializer.cpp
   Globals.cpp
   IRBuilder.cpp
index 070513edef22d75670934d516c2f646ad3b114b1..ddfbaf7a187c0653252fdc88e34cf17a846a4f34 100644 (file)
@@ -386,6 +386,12 @@ void Function::clearGC() {
   }
 }
 
+GCStrategy *Function::getGCStrategy() const {
+  // Lookup the GCStrategy (which is owned by the Context), given the name of
+  // the GC in question.
+  return getContext().pImpl->getGCStrategy(getGC());
+}
+
 /// copyAttributesFrom - copy all additional attributes (those not needed to
 /// create a Function) from the Function Src to this one.
 void Function::copyAttributesFrom(const GlobalValue *Src) {
diff --git a/lib/IR/GCStrategy.cpp b/lib/IR/GCStrategy.cpp
new file mode 100644 (file)
index 0000000..18723a0
--- /dev/null
@@ -0,0 +1,22 @@
+//===-- GCStrategy.cpp - Garbage Collector Description --------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the policy object GCStrategy which describes the
+// behavior of a given garbage collector.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/GCStrategy.h"
+
+using namespace llvm;
+
+GCStrategy::GCStrategy()
+    : UseStatepoints(false), NeededSafePoints(0), CustomReadBarriers(false),
+      CustomWriteBarriers(false), CustomRoots(false),
+      InitRoots(true), UsesMetadata(false) {}
index 01a0e6c98a6ca9564e6490553df0d8683e6901d8..01a786dbfda0b7582e9ab757090d536d3c921152 100644 (file)
@@ -15,6 +15,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/IR/Attributes.h"
 #include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/GCStrategy.h"
 #include "llvm/IR/Module.h"
 #include <algorithm>
 using namespace llvm;
@@ -182,3 +183,26 @@ void InsertValueConstantExpr::anchor() { }
 void GetElementPtrConstantExpr::anchor() { }
 
 void CompareConstantExpr::anchor() { }
+
+GCStrategy *LLVMContextImpl::getGCStrategy(const StringRef Name) {
+  // TODO: Arguably, just doing a linear search would be faster for small N
+  auto NMI = GCStrategyMap.find(Name);
+  if (NMI != GCStrategyMap.end())
+    return NMI->getValue();
+  
+  for (auto& Entry : GCRegistry::entries()) {
+    if (Name == Entry.getName()) {
+      std::unique_ptr<GCStrategy> S = Entry.instantiate();
+      S->Name = Name;
+      GCStrategyMap[Name] = S.get();
+      GCStrategyList.push_back(std::move(S));
+      return GCStrategyList.back().get();
+    }
+  }
+
+  // No GCStrategy found for that name, error reporting is the job of our
+  // callers. 
+  return nullptr;
+}
+
+
index 6ebc567f808ff1788a0eb2bdfa8e0fcd61d4f7a8..45f86093f5205a318c449c72b1b7685ad9825d1f 100644 (file)
@@ -41,6 +41,7 @@ class ConstantFP;
 class DiagnosticInfoOptimizationRemark;
 class DiagnosticInfoOptimizationRemarkMissed;
 class DiagnosticInfoOptimizationRemarkAnalysis;
+class GCStrategy;
 class LLVMContext;
 class Type;
 class Value;
@@ -389,6 +390,17 @@ public:
 
   int getOrAddScopeRecordIdxEntry(MDNode *N, int ExistingIdx);
   int getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,int ExistingIdx);
+
+  /// An owning list of all GCStrategies which have been created
+  SmallVector<std::unique_ptr<GCStrategy>, 1> GCStrategyList;
+  /// A helper map to speedup lookups into the above list
+  StringMap<GCStrategy*> GCStrategyMap;
+
+  /// Lookup the GCStrategy object associated with the given gc name.  If one
+  /// can't be found, returns nullptr.  The lifetime of the returned objects
+  /// is dictated by the lifetime of the associated context.  No caller should
+  /// attempt to delete the returned objects.
+  GCStrategy *getGCStrategy(const StringRef Name);
   
   LLVMContextImpl(LLVMContext &C);
   ~LLVMContextImpl();