diff options
38 files changed, 524 insertions, 678 deletions
diff --git a/bindings/ocaml/llvm/llvm.ml b/bindings/ocaml/llvm/llvm.ml index 67bb232..ded6380 100644 --- a/bindings/ocaml/llvm/llvm.ml +++ b/bindings/ocaml/llvm/llvm.ml @@ -366,8 +366,8 @@ external is_intrinsic : llvalue -> bool = "llvm_is_intrinsic" external function_call_conv : llvalue -> int = "llvm_function_call_conv" external set_function_call_conv : int -> llvalue -> unit = "llvm_set_function_call_conv" -external collector : llvalue -> string option = "llvm_collector" -external set_collector : string option -> llvalue -> unit = "llvm_set_collector" +external gc : llvalue -> string option = "llvm_gc" +external set_gc : string option -> llvalue -> unit = "llvm_set_gc" external function_begin : llmodule -> (llmodule, llvalue) llpos = "llvm_function_begin" external function_succ : llvalue -> (llmodule, llvalue) llpos diff --git a/bindings/ocaml/llvm/llvm.mli b/bindings/ocaml/llvm/llvm.mli index 1f4c4a5..fc2919e 100644 --- a/bindings/ocaml/llvm/llvm.mli +++ b/bindings/ocaml/llvm/llvm.mli @@ -921,14 +921,14 @@ external function_call_conv : llvalue -> int = "llvm_function_call_conv" external set_function_call_conv : int -> llvalue -> unit = "llvm_set_function_call_conv" -(** [collector f] returns [Some name] if the function [f] has a garbage +(** [gc f] returns [Some name] if the function [f] has a garbage collection algorithm specified and [None] otherwise. - See the method [llvm::Function::getCollector]. *) -external collector : llvalue -> string option = "llvm_collector" + See the method [llvm::Function::getGC]. *) +external gc : llvalue -> string option = "llvm_gc" -(** [set_collector gc f] sets the collection algorithm for the function [f] to - [gc]. See the method [llvm::Function::setCollector]. *) -external set_collector : string option -> llvalue -> unit = "llvm_set_collector" +(** [set_gc gc f] sets the collection algorithm for the function [f] to + [gc]. See the method [llvm::Function::setGC]. *) +external set_gc : string option -> llvalue -> unit = "llvm_set_gc" (** {7 Operations on params} *) diff --git a/bindings/ocaml/llvm/llvm_ocaml.c b/bindings/ocaml/llvm/llvm_ocaml.c index 94bd374..f09d6cd 100644 --- a/bindings/ocaml/llvm/llvm_ocaml.c +++ b/bindings/ocaml/llvm/llvm_ocaml.c @@ -643,13 +643,13 @@ CAMLprim value llvm_set_function_call_conv(value Id, LLVMValueRef Fn) { } /* llvalue -> string option */ -CAMLprim value llvm_collector(LLVMValueRef Fn) { - const char *Collector; +CAMLprim value llvm_gc(LLVMValueRef Fn) { + const char *GC; CAMLparam0(); CAMLlocal2(Name, Option); - if ((Collector = LLVMGetCollector(Fn))) { - Name = copy_string(Collector); + if ((GC = LLVMGetGC(Fn))) { + Name = copy_string(GC); Option = alloc(1, 0); Field(Option, 0) = Name; @@ -660,8 +660,8 @@ CAMLprim value llvm_collector(LLVMValueRef Fn) { } /* string option -> llvalue -> unit */ -CAMLprim value llvm_set_collector(value GC, LLVMValueRef Fn) { - LLVMSetCollector(Fn, GC == Val_int(0)? 0 : String_val(Field(GC, 0))); +CAMLprim value llvm_set_gc(value GC, LLVMValueRef Fn) { + LLVMSetGC(Fn, GC == Val_int(0)? 0 : String_val(Field(GC, 0))); return Val_unit; } diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 7fa91cd..9ff1251 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -411,8 +411,8 @@ void LLVMDeleteFunction(LLVMValueRef Fn); unsigned LLVMGetIntrinsicID(LLVMValueRef Fn); unsigned LLVMGetFunctionCallConv(LLVMValueRef Fn); void LLVMSetFunctionCallConv(LLVMValueRef Fn, unsigned CC); -const char *LLVMGetCollector(LLVMValueRef Fn); -void LLVMSetCollector(LLVMValueRef Fn, const char *Coll); +const char *LLVMGetGC(LLVMValueRef Fn); +void LLVMSetGC(LLVMValueRef Fn, const char *Name); /* Operations on parameters */ unsigned LLVMCountParams(LLVMValueRef Fn); diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index 50af9d5..12607dc 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -60,7 +60,7 @@ namespace bitc { /// MODULE_CODE_PURGEVALS: [numvals] MODULE_CODE_PURGEVALS = 10, - MODULE_CODE_COLLECTORNAME = 11 // COLLECTORNAME: [strchr x N] + MODULE_CODE_GCNAME = 11 // GCNAME: [strchr x N] }; /// PARAMATTR blocks have code for defining a parameter attribute set. diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 27ea221..5292153 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -22,7 +22,7 @@ #include <set> namespace llvm { - class Collector; + class GCStrategy; class Constant; class ConstantArray; class GCMetadataPrinter; @@ -53,7 +53,7 @@ namespace llvm { MachineModuleInfo *MMI; // GCMetadataPrinters - The garbage collection metadata printer table. - typedef DenseMap<Collector*,GCMetadataPrinter*> gcp_map_type; + typedef DenseMap<GCStrategy*,GCMetadataPrinter*> gcp_map_type; typedef gcp_map_type::iterator gcp_iterator; gcp_map_type GCMetadataPrinters; @@ -366,7 +366,7 @@ namespace llvm { void EmitXXStructorList(Constant *List); void EmitConstantPool(unsigned Alignment, const char *Section, std::vector<std::pair<MachineConstantPoolEntry,unsigned> > &CP); - GCMetadataPrinter *GetOrCreateGCPrinter(Collector *C); + GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy *C); }; } diff --git a/include/llvm/CodeGen/GCMedataPrinter.h b/include/llvm/CodeGen/GCMedataPrinter.h deleted file mode 100644 index 20b4702..0000000 --- a/include/llvm/CodeGen/GCMedataPrinter.h +++ /dev/null @@ -1,167 +0,0 @@ -//===-- llvm/CodeGen/Collector.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. -// -//===----------------------------------------------------------------------===// -// -// Collector records sufficient information about a machine function to enable -// accurate garbage collectors. Specifically: -// -// - Safe points -// Garbage collection is only possible at certain points in code. Code -// generators should record 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 generic information should used by ABI-specific passes to emit support -// tables for the runtime garbage collector. -// -// MachineCodeAnalysis identifies the GC safe points in the machine code. (Roots -// are identified in SelectionDAGISel.) -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_COLLECTOR_H -#define LLVM_CODEGEN_COLLECTOR_H - -#include "llvm/CodeGen/CollectorMetadata.h" -#include <iosfwd> -#include <string> - -namespace llvm { - - /// 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. - 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: - 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 the collector requires the given kind of safe point. By default, - /// none are recorded. - bool needsSafePoint(GC::PointKind Kind) const { - return (NeededSafePoints & 1 << Kind) != 0; - } - - /// By default, write barriers are replaced with simple store instructions. - /// If true, then addPassesToCustomLowerIntrinsics must instead process - /// them. - bool customWriteBarrier() const { return CustomWriteBarriers; } - - /// By default, read barriers are replaced with simple load instructions. - /// If true, then addPassesToCustomLowerIntrinsics must instead process - /// them. - bool customReadBarrier() const { return CustomReadBarriers; } - - /// By default, roots are left for the code generator. If Custom, then - /// addPassesToCustomLowerIntrinsics must add passes to delete them. - bool customRoots() const { return CustomRoots; } - - /// If set, gcroot intrinsics should initialize their allocas to null. This - /// is necessary for most collectors. - bool initializeRoots() const { return InitRoots; } - - /// If set, appropriate metadata tables must be emitted by the back-end - /// (assembler, JIT, or otherwise). - bool usesMetadata() const { return UsesMetadata; } - - /// 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); - }; - - // GCMetadataPrinter - Emits GC metadata as assembly code. - class GCMetadataPrinter { - public: - typedef Collector::list_type list_type; - typedef Collector::iterator iterator; - - private: - Collector *Coll; - - friend class AsmPrinter; - - protected: - // May only be subclassed. - GCMetadataPrinter(); - - // Do not implement. - GCMetadataPrinter(const GCMetadataPrinter &); - GCMetadataPrinter &operator=(const GCMetadataPrinter &); - - public: - Collector &getCollector() { return *Coll; } - const Module &getModule() const { return Coll->getModule(); } - - iterator begin() { return Coll->begin(); } - iterator end() { return Coll->end(); } - - /// beginAssembly/finishAssembly - Emit module metadata as assembly code. - virtual void beginAssembly(std::ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI); - - virtual void finishAssembly(std::ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI); - - virtual ~GCMetadataPrinter(); - }; - -} - -#endif diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h index 1fb3b50..e94aba3 100644 --- a/include/llvm/CodeGen/GCMetadata.h +++ b/include/llvm/CodeGen/GCMetadata.h @@ -1,4 +1,4 @@ -//===-- CollectorMetadata.h - Garbage collector metadata ------------------===// +//===-- GCMetadata.h - Garbage collector metadata -------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,33 +7,31 @@ // //===----------------------------------------------------------------------===// // -// This file declares the CollectorMetadata and CollectorModuleMetadata classes, -// which are used as a communication channel from the target code generator -// to the target garbage collectors. This interface allows code generators and -// garbage collectors to be developed independently. +// This file declares the GCFunctionInfo and GCModuleInfo classes, which are +// used as a communication channel from the target code generator 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 -// accurate stack map. Roots are specified in the LLVM IR using the llvm.gcroot -// intrinsic, which the code generator understands. The code generator records -// the stack offset for each GC root. Safe points are generated by the code -// generator according to the collector's declared needs (generally at function -// calls). +// The GCFunctionInfo class logs the data necessary to build a type accurate +// stack map. The code generator outputs: +// +// - Safe points as specified by the GCStrategy's NeededSafePoints. +// - Stack offsets for GC roots, as specified by calls to llvm.gcroot // -// Safe points and roots are sufficient to build type-accurate stack maps. As a -// refinement, liveness analysis calculates the set of live roots at each safe -// point. Liveness analysis is not presently performed, so all roots are assumed -// live. +// As a refinement, liveness analysis calculates the set of live roots at each +// safe point. Liveness analysis is not presently performed by the code +// generator, so all roots are assumed live. // -// CollectorModuleMetadata simply collects CollectorMetadata structures for each -// Function as it is compiled. This is necessary for collectors which must emit -// a stack map for the entire compilation unit. CollectorMetadata outlives the -// MachineFunction from which it is derived, so must not refer to any code -// generator data structures. +// GCModuleInfo simply collects GCFunctionInfo instances for each Function as +// they are compiled. This accretion is necessary for collectors which must emit +// a stack map for the compilation unit as a whole. Therefore, GCFunctionInfo +// outlives the MachineFunction from which it is derived and must not refer to +// any code generator data structures. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_COLLECTORMETADATA_H -#define LLVM_CODEGEN_COLLECTORMETADATA_H +#ifndef LLVM_CODEGEN_GCMETADATA_H +#define LLVM_CODEGEN_GCMETADATA_H #include "llvm/Pass.h" #include "llvm/ADT/DenseMap.h" @@ -42,7 +40,7 @@ namespace llvm { class AsmPrinter; - class Collector; + class GCStrategy; class Constant; class TargetAsmInfo; @@ -78,9 +76,9 @@ namespace llvm { }; - /// CollectorMetadata - Garbage collection metadata for a function. + /// GCFunctionInfo - Garbage collection metadata for a single function. /// - class CollectorMetadata { + class GCFunctionInfo { public: typedef std::vector<GCPoint>::iterator iterator; typedef std::vector<GCRoot>::iterator roots_iterator; @@ -88,7 +86,7 @@ namespace llvm { private: const Function &F; - Collector &C; + GCStrategy &S; uint64_t FrameSize; std::vector<GCRoot> Roots; std::vector<GCPoint> SafePoints; @@ -104,20 +102,20 @@ namespace llvm { // are live per safe point (1.5% on 64-bit hosts). public: - CollectorMetadata(const Function &F, Collector &C); - ~CollectorMetadata(); + GCFunctionInfo(const Function &F, GCStrategy &S); + ~GCFunctionInfo(); /// getFunction - Return the function to which this metadata applies. /// const Function &getFunction() const { return F; } - /// getCollector - Return the collector for the function. + /// getStrategy - Return the GC strategy for the function. /// - Collector &getCollector() { return C; } + GCStrategy &getStrategy() { return S; } /// 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). + /// stack object ID for the alloca (if the code generator is + // using MachineFrameInfo). void addStackRoot(int Num, Constant *Metadata) { Roots.push_back(GCRoot(Num, Metadata)); } @@ -154,39 +152,39 @@ namespace llvm { }; - /// CollectorModuleMetadata - Garbage collection metadata for a whole module. + /// GCModuleInfo - Garbage collection metadata for a whole module. /// - class CollectorModuleMetadata : public ImmutablePass { - typedef StringMap<Collector*> collector_map_type; - typedef std::vector<Collector*> list_type; - typedef DenseMap<const Function*,CollectorMetadata*> function_map_type; + class GCModuleInfo : public ImmutablePass { + typedef StringMap<GCStrategy*> strategy_map_type; + typedef std::vector<GCStrategy*> list_type; + typedef DenseMap<const Function*,GCFunctionInfo*> finfo_map_type; - collector_map_type NameMap; - list_type Collectors; - function_map_type Map; + strategy_map_type StrategyMap; + list_type StrategyList; + finfo_map_type FInfoMap; - Collector *getOrCreateCollector(const Module *M, const std::string &Name); + GCStrategy *getOrCreateStrategy(const Module *M, const std::string &Name); public: typedef list_type::const_iterator iterator; static char ID; - CollectorModuleMetadata(); - ~CollectorModuleMetadata(); + GCModuleInfo(); + ~GCModuleInfo(); - /// clear - Used to delete module metadata. The metadata deleter pass calls - /// this. + /// clear - Resets the pass. The metadata deleter pass calls this. + /// void clear(); - /// begin/end - Iterators for collectors. + /// begin/end - Iterators for used strategies. /// - iterator begin() const { return Collectors.begin(); } - iterator end() const { return Collectors.end(); } + iterator begin() const { return StrategyList.begin(); } + iterator end() const { return StrategyList.end(); } /// get - Look up function metadata. /// - CollectorMetadata &get(const Function &F); + GCFunctionInfo &getFunctionInfo(const Function &F); }; } diff --git a/include/llvm/CodeGen/GCMetadataPrinter.h b/include/llvm/CodeGen/GCMetadataPrinter.h new file mode 100644 index 0000000..1ab138a --- /dev/null +++ b/include/llvm/CodeGen/GCMetadataPrinter.h @@ -0,0 +1,77 @@ +//===-- llvm/CodeGen/GCMetadataPrinter.h - Prints asm GC tables -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The abstract base class GCMetadataPrinter supports writing GC metadata tables +// as assembly code. This is a separate class from GCStrategy in order to allow +// users of the LLVM JIT to avoid linking with the AsmWriter. +// +// Subclasses of GCMetadataPrinter must be registered using the +// GCMetadataPrinterRegistry. This is separate from the GCStrategy itself +// because these subclasses are logically plugins for the AsmWriter. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GCMETADATAPRINTER_H +#define LLVM_CODEGEN_GCMETADATAPRINTER_H + +#include "llvm/CodeGen/GCMetadata.h" +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/Support/Registry.h" +#include <iosfwd> +#include <string> + +namespace llvm { + + class GCMetadataPrinter; + + /// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the + /// defaults from Registry. + typedef Registry<GCMetadataPrinter> GCMetadataPrinterRegistry; + + /// GCMetadataPrinter - Emits GC metadata as assembly code. + /// + class GCMetadataPrinter { + public: + typedef GCStrategy::list_type list_type; + typedef GCStrategy::iterator iterator; + + private: + GCStrategy *S; + + friend class AsmPrinter; + + protected: + // May only be subclassed. + GCMetadataPrinter(); + + // Do not implement. + GCMetadataPrinter(const GCMetadataPrinter &); + GCMetadataPrinter &operator=(const GCMetadataPrinter &); + + public: + GCStrategy &getStrategy() { return *S; } + const Module &getModule() const { return S->getModule(); } + + /// begin/end - Iterate over the collected function metadata. + iterator begin() { return S->begin(); } + iterator end() { return S->end(); } + + /// beginAssembly/finishAssembly - Emit module metadata as assembly code. + virtual void beginAssembly(std::ostream &OS, AsmPrinter &AP, + const TargetAsmInfo &TAI); + + virtual void finishAssembly(std::ostream &OS, AsmPrinter &AP, + const TargetAsmInfo &TAI); + + virtual ~GCMetadataPrinter(); + }; + +} + +#endif diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h index dea0785..80249bc 100644 --- a/include/llvm/CodeGen/GCStrategy.h +++ b/include/llvm/CodeGen/GCStrategy.h @@ -1,4 +1,4 @@ -//===-- llvm/CodeGen/Collector.h - Garbage collection -----------*- C++ -*-===// +//===-- llvm/CodeGen/GCStrategy.h - Garbage collection ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,12 +7,18 @@ // //===----------------------------------------------------------------------===// // -// Collector records sufficient information about a machine function to enable -// accurate garbage collectors. Specifically: +// 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. +// +// When requested, the GCStrategy will be populated with data about each +// function which uses it. Specifically: // // - Safe points -// Garbage collection is only possible at certain points in code. Code -// generators should record 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 @@ -22,33 +28,37 @@ // When a reference to a GC-allocated object exists on the stack, it must be // stored in an alloca registered with llvm.gcoot. // -// This generic information should used by ABI-specific passes to emit support -// tables for the runtime garbage collector. -// -// MachineCodeAnalysis identifies the GC safe points in the machine code. (Roots -// are identified in SelectionDAGISel.) +// This information can used to emit the metadata tables which are required by +// the target garbage collector runtime. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_COLLECTOR_H -#define LLVM_CODEGEN_COLLECTOR_H +#ifndef LLVM_CODEGEN_GCSTRATEGY_H +#define LLVM_CODEGEN_GCSTRATEGY_H #include "llvm/CodeGen/GCMetadata.h" +#include "llvm/Support/Registry.h" #include <iosfwd> #include <string> namespace llvm { - /// Collector describes a garbage collector's code generation requirements, - /// and provides overridable hooks for those needs which cannot be abstractly - /// described. - class Collector { + class GCStrategy; + + /// The GC strategy registry uses all the defaults from Registry. + /// + typedef Registry<GCStrategy> GCRegistry; + + /// GCStrategy describes a garbage collector algorithm's code generation + /// requirements, and provides overridable hooks for those needs which cannot + /// be abstractly described. + class GCStrategy { public: - typedef std::vector<CollectorMetadata*> list_type; + typedef std::vector<GCFunctionInfo*> list_type; typedef list_type::iterator iterator; private: - friend class CollectorModuleMetadata; + friend class GCModuleInfo; const Module *M; std::string Name; @@ -63,49 +73,51 @@ namespace llvm { bool UsesMetadata; //< If set, backend must emit metadata tables. public: - Collector(); + GCStrategy(); - virtual ~Collector(); + virtual ~GCStrategy(); - /// getName - The name of the collector, for debugging. + /// getName - The name of the GC strategy, for debugging. /// const std::string &getName() const { return Name; } - /// getModule - The module upon which the collector is operating. + /// getModule - The module within which the GC strategy is operating. /// const Module &getModule() const { return *M; } - /// True if this collector requires safe points of any kind. By default, - /// none are recorded. + /// needsSafePoitns - True if safe points of any kind are required. By + // default, none are recorded. bool needsSafePoints() const { return NeededSafePoints != 0; } - /// True if the collector requires the given kind of safe point. By default, - /// none are recorded. + /// needsSafePoint(Kind) - 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, write barriers are replaced with simple store instructions. - /// If true, then addPassesToCustomLowerIntrinsics must instead process - /// them. + /// customWriteBarrier - 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 addPassesToCustomLowerIntrinsics must instead process - /// them. + /// customReadBarrier - By default, read barriers are replaced with simple + /// load instructions. If true, then + /// performCustomLowering must instead lower them. bool customReadBarrier() const { return CustomReadBarriers; } - /// By default, roots are left for the code generator. If Custom, then - /// addPassesToCustomLowerIntrinsics must add passes to delete them. + /// customRoots - 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. This - /// is necessary for most collectors. + /// initializeRoots - 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). + /// usesMetadata - If set, appropriate metadata tables must be emitted by + /// the back-end (assembler, JIT, or otherwise). bool usesMetadata() const { return UsesMetadata; } /// begin/end - Iterators for function metadata. @@ -115,53 +127,17 @@ namespace llvm { /// insertFunctionMetadata - Creates metadata for a function. /// - CollectorMetadata *insertFunctionMetadata(const Function &F); + GCFunctionInfo *insertFunctionInfo(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 + /// 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. virtual bool initializeCustomLowering(Module &F); virtual bool performCustomLowering(Function &F); }; - // GCMetadataPrinter - Emits GC metadata as assembly code. - class GCMetadataPrinter { - public: - typedef Collector::list_type list_type; - typedef Collector::iterator iterator; - - private: - Collector *Coll; - - friend class AsmPrinter; - - protected: - // May only be subclassed. - GCMetadataPrinter(); - - // Do not implement. - GCMetadataPrinter(const GCMetadataPrinter &); - GCMetadataPrinter &operator=(const GCMetadataPrinter &); - - public: - Collector &getCollector() { return *Coll; } - const Module &getModule() const { return Coll->getModule(); } - - iterator begin() { return Coll->begin(); } - iterator end() { return Coll->end(); } - - /// beginAssembly/finishAssembly - Emit module metadata as assembly code. - virtual void beginAssembly(std::ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI); - - virtual void finishAssembly(std::ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI); - - virtual ~GCMetadataPrinter(); - }; - } #endif diff --git a/include/llvm/CodeGen/GCs.h b/include/llvm/CodeGen/GCs.h index 7850ddc..c407b61 100644 --- a/include/llvm/CodeGen/GCs.h +++ b/include/llvm/CodeGen/GCs.h @@ -1,4 +1,4 @@ -//===-- Collectors.h - Garbage collector registry -------------------------===// +//===-- GCs.h - Garbage collector linkage hacks ---------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,41 +7,29 @@ // //===----------------------------------------------------------------------===// // -// This file declares the CollectorRegistry class, which is used to discover -// pluggable garbage collectors. +// This file contains hack functions to force linking in the GC components. // //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_GCS_H #define LLVM_CODEGEN_GCS_H -#include "llvm/Support/Registry.h" - namespace llvm { - - class Collector; + class GCStrategy; class GCMetadataPrinter; - /// The collector registry uses all the defaults from Registry. - /// - typedef Registry<Collector> CollectorRegistry; - - /// The GC assembly printer registry uses all the defaults from Registry. - /// - typedef Registry<GCMetadataPrinter> GCMetadataPrinterRegistry; - /// 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(); + void linkOcamlGC(); /// Creates an ocaml-compatible metadata printer. - GCMetadataPrinter *createOcamlMetadataPrinter(); + void linkOcamlGCPrinter(); /// Creates a shadow stack garbage collector. This collector requires no code /// generator support. - Collector *createShadowStackCollector(); + void linkShadowStackGC(); } #endif diff --git a/include/llvm/CodeGen/LinkAllAsmWriterComponents.h b/include/llvm/CodeGen/LinkAllAsmWriterComponents.h index 0dc94ea..a1ba565 100644 --- a/include/llvm/CodeGen/LinkAllAsmWriterComponents.h +++ b/include/llvm/CodeGen/LinkAllAsmWriterComponents.h @@ -20,14 +20,14 @@ namespace { struct ForceAsmWriterLinking { ForceAsmWriterLinking() { - // We must reference the passes in such a way that compilers will not + // We must reference the plug-ins in such a way that compilers will not // delete it all as dead code, even with whole program optimization, // yet is effectively a NO-OP. As the compiler isn't smart enough // to know that getenv() never returns -1, this will do the job. if (std::getenv("bar") != (char*) -1) return; - (void) llvm::createOcamlMetadataPrinter(); + llvm::linkOcamlGCPrinter(); } } ForceAsmWriterLinking; // Force link by creating a global definition. diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index 2fb01bf..9ee22d4 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -36,8 +36,8 @@ namespace { (void) llvm::createSimpleRegisterCoalescer(); - (void) llvm::createOcamlCollector(); - (void) llvm::createShadowStackCollector(); + llvm::linkOcamlGC(); + llvm::linkShadowStackGC(); (void) llvm::createBURRListDAGScheduler(NULL, NULL, NULL, false); (void) llvm::createTDRRListDAGScheduler(NULL, NULL, NULL, false); diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 412e9e3..ff1f505 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -152,7 +152,7 @@ namespace llvm { FunctionPass *getRegisterAllocator(TargetMachine &T); /// IntrinsicLowering Pass - Performs target-independent LLVM IR - /// transformations for highly portable collectors. + /// transformations for highly portable strategies. FunctionPass *createGCLoweringPass(); /// MachineCodeAnalysis Pass - Target-independent pass to mark safe points in @@ -161,13 +161,13 @@ namespace llvm { /// folding). FunctionPass *createGCMachineCodeAnalysisPass(); - /// Deleter Pass - Releases collector metadata. + /// Deleter Pass - Releases GC metadata. /// - FunctionPass *createCollectorMetadataDeleter(); + FunctionPass *createGCInfoDeleter(); - /// Creates a pass to print collector metadata. + /// Creates a pass to print GC metadata. /// - FunctionPass *createCollectorMetadataPrinter(std::ostream &OS); + FunctionPass *createGCInfoPrinter(std::ostream &OS); /// createMachineLICMPass - This pass performs LICM on machine instructions. /// diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index 7471039..77e75c0 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -29,7 +29,7 @@ namespace llvm { class TargetLowering; class FunctionLoweringInfo; class HazardRecognizer; - class CollectorMetadata; + class GCFunctionInfo; class ScheduleDAG; /// SelectionDAGISel - This is the common base class used for SelectionDAG-based @@ -41,13 +41,13 @@ public: SelectionDAG *CurDAG; MachineBasicBlock *BB; AliasAnalysis *AA; - CollectorMetadata *GCI; + GCFunctionInfo *GFI; bool Fast; std::vector<SDNode*> TopOrder; static char ID; explicit SelectionDAGISel(TargetLowering &tli, bool fast = false) : - FunctionPass((intptr_t)&ID), TLI(tli), GCI(0), Fast(fast), DAGSize(0) {} + FunctionPass((intptr_t)&ID), TLI(tli), GFI(), Fast(fast), DAGSize(0) {} TargetLowering &getTargetLowering() { return TLI; } diff --git a/include/llvm/Function.h b/include/llvm/Function.h index 9954418..04e0535 100644 --- a/include/llvm/Function.h +++ b/include/llvm/Function.h @@ -148,12 +148,12 @@ public: /// void setParamAttrs(const PAListPtr &attrs) { ParamAttrs = attrs; } - /// hasCollector/getCollector/setCollector/clearCollector - The name of the - /// garbage collection algorithm to use during code generation. - bool hasCollector() const; - const char *getCollector() const; - void setCollector(const char *Str); - void clearCollector(); + /// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm + /// to use during code generation. + bool hasGC() const; + const char *getGC() const; + void setGC(const char *Str); + void clearGC(); /// @brief Determine whether the function has the given attribute. bool paramHasAttr(unsigned i, ParameterAttributes attr) const { diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index 9f317d8..d9b8499 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -2393,7 +2393,7 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')' delete $8; } if ($10) { - Fn->setCollector($10->c_str()); + Fn->setGC($10->c_str()); delete $10; } diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index f7796a6..a842bd3 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -892,7 +892,7 @@ bool BitcodeReader::ParseModule(const std::string &ModuleID) { SmallVector<uint64_t, 64> Record; std::vector<std::string> SectionTable; - std::vector<std::string> CollectorTable; + std::vector<std::string> GCTable; // Read all the records for this module. while (!Stream.AtEndOfStream()) { @@ -1019,11 +1019,11 @@ bool BitcodeReader::ParseModule(const std::string &ModuleID) { SectionTable.push_back(S); break; } - case bitc::MODULE_CODE_COLLECTORNAME: { // SECTIONNAME: [strchr x N] + case bitc::MODULE_CODE_GCNAME: { // SECTIONNAME: [strchr x N] std::string S; if (ConvertToString(Record, 0, S)) - return Error("Invalid MODULE_CODE_COLLECTORNAME record"); - CollectorTable.push_back(S); + return Error("Invalid MODULE_CODE_GCNAME record"); + GCTable.push_back(S); break; } // GLOBALVAR: [pointer type, isconst, initid, @@ -1070,7 +1070,7 @@ bool BitcodeReader::ParseModule(const std::string &ModuleID) { break; } // FUNCTION: [type, callingconv, isproto, linkage, paramattr, - // alignment, section, visibility, collector] + // alignment, section, visibility, gc] case bitc::MODULE_CODE_FUNCTION: { if (Record.size() < 8) return Error("Invalid MODULE_CODE_FUNCTION record"); @@ -1098,9 +1098,9 @@ bool BitcodeReader::ParseModule(const std::string &ModuleID) { } Func->setVisibility(GetDecodedVisibility(Record[7])); if (Record.size() > 8 && Record[8]) { - if (Record[8]-1 > CollectorTable.size()) - return Error("Invalid collector ID"); - Func->setCollector(CollectorTable[Record[8]-1].c_str()); + if (Record[8]-1 > GCTable.size()) + return Error("Invalid GC ID"); + Func->setGC(GCTable[Record[8]-1].c_str()); } ValueList.push_back(Func); diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 2c585b1..b5fb607 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -303,10 +303,10 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, WriteStringRecord(bitc::MODULE_CODE_ASM, M->getModuleInlineAsm(), 0/*TODO*/, Stream); - // Emit information about sections and collectors, computing how many there - // are. Also compute the maximum alignment value. + // Emit information about sections and GC, computing how many there are. Also + // compute the maximum alignment value. std::map<std::string, unsigned> SectionMap; - std::map<std::string, unsigned> CollectorMap; + std::map<std::string, unsigned> GCMap; unsigned MaxAlignment = 0; unsigned MaxGlobalType = 0; for (Module::const_global_iterator GV = M->global_begin(),E = M->global_end(); @@ -333,13 +333,13 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, Entry = SectionMap.size(); } } - if (F->hasCollector()) { - // Same for collector names. - unsigned &Entry = CollectorMap[F->getCollector()]; + if (F->hasGC()) { + // Same for GC names. + unsigned &Entry = GCMap[F->getGC()]; if (!Entry) { - WriteStringRecord(bitc::MODULE_CODE_COLLECTORNAME, F->getCollector(), + WriteStringRecord(bitc::MODULE_CODE_GCNAME, F->getGC(), 0/*TODO*/, Stream); - Entry = CollectorMap.size(); + Entry = GCMap.size(); } } } @@ -401,7 +401,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, // Emit the function proto information. for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { // FUNCTION: [type, callingconv, isproto, paramattr, - // linkage, alignment, section, visibility, collector] + // linkage, alignment, section, visibility, gc] Vals.push_back(VE.getTypeID(F->getType())); Vals.push_back(F->getCallingConv()); Vals.push_back(F->isDeclaration()); @@ -410,7 +410,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, Vals.push_back(Log2_32(F->getAlignment())+1); Vals.push_back(F->hasSection() ? SectionMap[F->getSection()] : 0); Vals.push_back(getEncodedVisibility(F)); - Vals.push_back(F->hasCollector() ? CollectorMap[F->getCollector()] : 0); + Vals.push_back(F->hasGC() ? GCMap[F->getGC()] : 0); unsigned AbbrevToUse = 0; Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse); diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index de31840..380b3bc 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -16,9 +16,7 @@ #include "llvm/DerivedTypes.h" #include "llvm/Constants.h" #include "llvm/Module.h" -#include "llvm/CodeGen/GCStrategy.h" -#include "llvm/CodeGen/GCMetadata.h" -#include "llvm/CodeGen/GCs.h" +#include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h" @@ -110,18 +108,17 @@ void AsmPrinter::SwitchToDataSection(const char *NewSection, void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const { MachineFunctionPass::getAnalysisUsage(AU); - AU.addRequired<CollectorModuleMetadata>(); + AU.addRequired<GCModuleInfo>(); } bool AsmPrinter::doInitialization(Module &M) { Mang = new Mangler(M, TAI->getGlobalPrefix()); - CollectorModuleMetadata *CMM = getAnalysisToUpdate<CollectorModuleMetadata>(); - assert(CMM && "AsmPrinter didn't require CollectorModuleMetadata?"); - for (CollectorModuleMetadata::iterator I = CMM->begin(), - E = CMM->end(); I != E; ++I) - if (GCMetadataPrinter *GCP = GetOrCreateGCPrinter(*I)) - GCP->beginAssembly(O, *this, *TAI); + GCModuleInfo *MI = getAnalysisToUpdate<GCModuleInfo>(); + assert(MI && "AsmPrinter didn't require GCModuleInfo?"); + for (GCModuleInfo::iterator I = MI->begin(), E = MI->end(); I != E; ++I) + if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*I)) + MP->beginAssembly(O, *this, *TAI); if (!M.getModuleInlineAsm().empty()) O << TAI->getCommentString() << " Start of file scope inline assembly\n" @@ -192,12 +189,11 @@ bool AsmPrinter::doFinalization(Module &M) { } } - CollectorModuleMetadata *CMM = getAnalysisToUpdate<CollectorModuleMetadata>(); - assert(CMM && "AsmPrinter didn't require CollectorModuleMetadata?"); - for (CollectorModuleMetadata::iterator I = CMM->end(), - E = CMM->begin(); I != E; ) - if (GCMetadataPrinter *GCP = GetOrCreateGCPrinter(*--I)) - GCP->finishAssembly(O, *this, *TAI); + GCModuleInfo *MI = getAnalysisToUpdate<GCModuleInfo>(); + assert(MI && "AsmPrinter didn't require GCModuleInfo?"); + for (GCModuleInfo::iterator I = MI->end(), E = MI->begin(); I != E; ) + if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*--I)) + MP->finishAssembly(O, *this, *TAI); // If we don't have any trampolines, then we don't require stack memory // to be executable. Some targets have a directive to declare this. @@ -1466,26 +1462,26 @@ void AsmPrinter::printVisibility(const std::string& Name, } } -GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(Collector *C) { - if (!C->usesMetadata()) +GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) { + if (!S->usesMetadata()) return 0; - gcp_iterator GCPI = GCMetadataPrinters.find(C); + gcp_iterator GCPI = GCMetadataPrinters.find(S); if (GCPI != GCMetadataPrinters.end()) return GCPI->second; - const char *Name = C->getName().c_str(); + const char *Name = S->getName().c_str(); for (GCMetadataPrinterRegistry::iterator I = GCMetadataPrinterRegistry::begin(), E = GCMetadataPrinterRegistry::end(); I != E; ++I) if (strcmp(Name, I->getName()) == 0) { - GCMetadataPrinter *GCP = I->instantiate(); - GCP->Coll = C; - GCMetadataPrinters.insert(std::make_pair(C, GCP)); - return GCP; + GCMetadataPrinter *GMP = I->instantiate(); + GMP->S = S; + GCMetadataPrinters.insert(std::make_pair(S, GMP)); + return GMP; } - cerr << "no GCMetadataPrinter registered for collector: " << Name << "\n"; + cerr << "no GCMetadataPrinter registered for GC: " << Name << "\n"; abort(); } diff --git a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp index efa7f67..42f1a0f 100644 --- a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp @@ -1,4 +1,4 @@ -//===-- OcamlCollector.cpp - Ocaml frametable emitter ---------------------===// +//===-- OcamlGCPrinter.cpp - Ocaml frametable emitter ---------------------===// // // The LLVM Compiler Infrastructure // @@ -7,13 +7,13 @@ // //===----------------------------------------------------------------------===// // -// This file implements lowering for the llvm.gc* intrinsics compatible with -// Objective Caml 3.10.0, which uses a liveness-accurate static stack map. +// This file implements printing the assembly code for an Ocaml frametable. // //===----------------------------------------------------------------------===// #include "llvm/CodeGen/GCs.h" #include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/GCStrategy.h" #include "llvm/Module.h" #include "llvm/Target/TargetAsmInfo.h" @@ -38,9 +38,7 @@ namespace { static GCMetadataPrinterRegistry::Add<OcamlGCMetadataPrinter> Y("ocaml", "ocaml 3.10-compatible collector"); -GCMetadataPrinter *llvm::createOcamlMetadataPrinter() { - return new OcamlGCMetadataPrinter(); -} +void llvm::linkOcamlGCPrinter() { } static void EmitCamlGlobal(const Module &M, std::ostream &OS, AsmPrinter &AP, const TargetAsmInfo &TAI, const char *Id) { @@ -85,7 +83,7 @@ void OcamlGCMetadataPrinter::beginAssembly(std::ostream &OS, AsmPrinter &AP, /// /// Note that this precludes programs from stack frames larger than 64K /// (FrameSize and LiveOffsets would overflow). FrameTablePrinter will abort if -/// either condition is detected in a function which uses the collector. +/// either condition is detected in a function which uses the GC. /// void OcamlGCMetadataPrinter::finishAssembly(std::ostream &OS, AsmPrinter &AP, const TargetAsmInfo &TAI) { @@ -111,33 +109,32 @@ void OcamlGCMetadataPrinter::finishAssembly(std::ostream &OS, AsmPrinter &AP, AP.SwitchToDataSection(TAI.getDataSection()); EmitCamlGlobal(getModule(), OS, AP, TAI, "frametable"); - for (iterator FI = begin(), FE = end(); FI != FE; ++FI) { - CollectorMetadata &MD = **FI; + for (iterator I = begin(), IE = end(); I != IE; ++I) { + GCFunctionInfo &FI = **I; + + uint64_t FrameSize = FI.getFrameSize(); + if (FrameSize >= 1<<16) { + cerr << "Function '" << FI.getFunction().getNameStart() + << "' is too large for the ocaml GC! " + << "Frame size " << FrameSize << " >= 65536.\n"; + cerr << "(" << uintptr_t(&FI) << ")\n"; + abort(); // Very rude! + } OS << "\t" << TAI.getCommentString() << " live roots for " - << MD.getFunction().getNameStart() << "\n"; + << FI.getFunction().getNameStart() << "\n"; - for (CollectorMetadata::iterator PI = MD.begin(), - PE = MD.end(); PI != PE; ++PI) { - - uint64_t FrameSize = MD.getFrameSize(); - if (FrameSize >= 1<<16) { - cerr << "Function '" << MD.getFunction().getNameStart() - << "' is too large for the ocaml collector! " - << "Frame size " << FrameSize << " >= 65536.\n"; - abort(); // Very rude! - } - - size_t LiveCount = MD.live_size(PI); + for (GCFunctionInfo::iterator J = FI.begin(), JE = FI.end(); J != JE; ++J) { + size_t LiveCount = FI.live_size(J); if (LiveCount >= 1<<16) { - cerr << "Function '" << MD.getFunction().getNameStart() - << "' is too large for the ocaml collector! " + cerr << "Function '" << FI.getFunction().getNameStart() + << "' is too large for the ocaml GC! " << "Live root count " << LiveCount << " >= 65536.\n"; abort(); // Very rude! } OS << AddressDirective - << TAI.getPrivateGlobalPrefix() << "label" << PI->Num; + << TAI.getPrivateGlobalPrefix() << "label" << J->Num; AP.EOL("call return address"); AP.EmitInt16(FrameSize); @@ -146,14 +143,13 @@ void OcamlGCMetadataPrinter::finishAssembly(std::ostream &OS, AsmPrinter &AP, AP.EmitInt16(LiveCount); AP.EOL("live root count"); - for (CollectorMetadata::live_iterator LI = MD.live_begin(PI), - LE = MD.live_end(PI); - LI != LE; ++LI) { - assert(LI->StackOffset < 1<<16 && + for (GCFunctionInfo::live_iterator K = FI.live_begin(J), + KE = FI.live_end(J); K != KE; ++K) { + assert(K->StackOffset < 1<<16 && "GC root stack offset is outside of fixed stack frame and out " - "of range for Ocaml collector!"); + "of range for ocaml GC!"); - OS << "\t.word\t" << LI->StackOffset; + OS << "\t.word\t" << K->StackOffset; AP.EOL("stack offset"); } diff --git a/lib/CodeGen/GCMetadata.cpp b/lib/CodeGen/GCMetadata.cpp index 0b5c6f0..efb89e1 100644 --- a/lib/CodeGen/GCMetadata.cpp +++ b/lib/CodeGen/GCMetadata.cpp @@ -1,4 +1,4 @@ -//===-- CollectorMetadata.cpp - Garbage collector metadata ----------------===// +//===-- GCMetadata.cpp - Garbage collector metadata -----------------------===// // // The LLVM Compiler Infrastructure // @@ -7,14 +7,12 @@ // //===----------------------------------------------------------------------===// // -// This file implements the CollectorMetadata and CollectorModuleMetadata -// classes. +// This file implements the GCFunctionInfo class and GCModuleInfo pass. // //===----------------------------------------------------------------------===// #include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/GCStrategy.h" -#include "llvm/CodeGen/GCs.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/Pass.h" #include "llvm/CodeGen/Passes.h" @@ -53,79 +51,80 @@ namespace { } -static RegisterPass<CollectorModuleMetadata> +static RegisterPass<GCModuleInfo> X("collector-metadata", "Create Garbage Collector Module Metadata"); // ----------------------------------------------------------------------------- -CollectorMetadata::CollectorMetadata(const Function &F, Collector &C) - : F(F), C(C), FrameSize(~0LL) {} +GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S) + : F(F), S(S), FrameSize(~0LL) {} -CollectorMetadata::~CollectorMetadata() {} +GCFunctionInfo::~GCFunctionInfo() {} // ----------------------------------------------------------------------------- -char CollectorModuleMetadata::ID = 0; +char GCModuleInfo::ID = 0; -CollectorModuleMetadata::CollectorModuleMetadata() +GCModuleInfo::GCModuleInfo() : ImmutablePass((intptr_t)&ID) {} -CollectorModuleMetadata::~CollectorModuleMetadata() { +GCModuleInfo::~GCModuleInfo() { clear(); } -Collector *CollectorModuleMetadata:: -getOrCreateCollector(const Module *M, const std::string &Name) { +GCStrategy *GCModuleInfo::getOrCreateStrategy(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()) + strategy_map_type::iterator NMI = + StrategyMap.find(Start, Start + Name.size()); + if (NMI != StrategyMap.end()) return NMI->getValue(); - for (CollectorRegistry::iterator I = CollectorRegistry::begin(), - E = CollectorRegistry::end(); I != E; ++I) { + for (GCRegistry::iterator I = GCRegistry::begin(), + E = GCRegistry::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; + GCStrategy *S = I->instantiate(); + S->M = M; + S->Name = Name; + StrategyMap.GetOrCreateValue(Start, Start + Name.size()).setValue(S); + StrategyList.push_back(S); + return S; } } - cerr << "unsupported collector: " << Name << "\n"; + cerr << "unsupported GC: " << Name << "\n"; abort(); } -CollectorMetadata &CollectorModuleMetadata::get(const Function &F) { +GCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) { assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!"); - assert(F.hasCollector()); + assert(F.hasGC()); - function_map_type::iterator I = Map.find(&F); - if (I != Map.end()) + finfo_map_type::iterator I = FInfoMap.find(&F); + if (I != FInfoMap.end()) return *I->second; - - Collector *C = getOrCreateCollector(F.getParent(), F.getCollector()); - CollectorMetadata *MD = C->insertFunctionMetadata(F); - Map[&F] = MD; - return *MD; + + GCStrategy *S = getOrCreateStrategy(F.getParent(), F.getGC()); + GCFunctionInfo *GFI = S->insertFunctionInfo(F); + FInfoMap[&F] = GFI; + return *GFI; } -void CollectorModuleMetadata::clear() { - Map.clear(); - NameMap.clear(); +void GCModuleInfo::clear() { + FInfoMap.clear(); + StrategyMap.clear(); for (iterator I = begin(), E = end(); I != E; ++I) delete *I; - Collectors.clear(); + StrategyList.clear(); } // ----------------------------------------------------------------------------- char Printer::ID = 0; -FunctionPass *llvm::createCollectorMetadataPrinter(std::ostream &OS) { +FunctionPass *llvm::createGCInfoPrinter(std::ostream &OS) { return new Printer(OS); } @@ -139,7 +138,7 @@ const char *Printer::getPassName() const { void Printer::getAnalysisUsage(AnalysisUsage &AU) const { FunctionPass::getAnalysisUsage(AU); AU.setPreservesAll(); - AU.addRequired<CollectorModuleMetadata>(); + AU.addRequired<GCModuleInfo>(); } static const char *DescKind(GC::PointKind Kind) { @@ -153,23 +152,22 @@ static const char *DescKind(GC::PointKind Kind) { } bool Printer::runOnFunction(Function &F) { - if (F.hasCollector()) { - CollectorMetadata *FD = &getAnalysis<CollectorModuleMetadata>().get(F); + if (!F.hasGC()) { + GCFunctionInfo *FD = &getAnalysis<GCModuleInfo>().getFunctionInfo(F); OS << "GC roots for " << FD->getFunction().getNameStart() << ":\n"; - for (CollectorMetadata::roots_iterator RI = FD->roots_begin(), - RE = FD->roots_end(); - RI != RE; ++RI) + for (GCFunctionInfo::roots_iterator RI = FD->roots_begin(), + RE = FD->roots_end(); RI != RE; ++RI) OS << "\t" << RI->Num << "\t" << RI->StackOffset << "[sp]\n"; OS << "GC safe points for " << FD->getFunction().getNameStart() << ":\n"; - for (CollectorMetadata::iterator PI = FD->begin(), - PE = FD->end(); PI != PE; ++PI) { + for (GCFunctionInfo::iterator PI = FD->begin(), + PE = FD->end(); PI != PE; ++PI) { OS << "\tlabel " << PI->Num << ": " << DescKind(PI->Kind) << ", live = {"; - for (CollectorMetadata::live_iterator RI = FD->live_begin(PI), - RE = FD->live_end(PI);;) { + for (GCFunctionInfo::live_iterator RI = FD->live_begin(PI), + RE = FD->live_end(PI);;) { OS << " " << RI->Num; if (++RI == RE) break; @@ -187,7 +185,7 @@ bool Printer::runOnFunction(Function &F) { char Deleter::ID = 0; -FunctionPass *llvm::createCollectorMetadataDeleter() { +FunctionPass *llvm::createGCInfoDeleter() { return new Deleter(); } @@ -199,7 +197,7 @@ const char *Deleter::getPassName() const { void Deleter::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); - AU.addRequired<CollectorModuleMetadata>(); + AU.addRequired<GCModuleInfo>(); } bool Deleter::runOnFunction(Function &MF) { @@ -207,8 +205,8 @@ bool Deleter::runOnFunction(Function &MF) { } bool Deleter::doFinalization(Module &M) { - CollectorModuleMetadata *CMM = getAnalysisToUpdate<CollectorModuleMetadata>(); - assert(CMM && "Deleter didn't require CollectorModuleMetadata?!"); - CMM->clear(); + GCModuleInfo *GMI = getAnalysisToUpdate<GCModuleInfo>(); + assert(GMI && "Deleter didn't require GCModuleInfo?!"); + GMI->clear(); return false; } diff --git a/lib/CodeGen/GCMetadataPrinter.cpp b/lib/CodeGen/GCMetadataPrinter.cpp index b16d873..07ec0bd 100644 --- a/lib/CodeGen/GCMetadataPrinter.cpp +++ b/lib/CodeGen/GCMetadataPrinter.cpp @@ -1,4 +1,4 @@ -//===-- Collector.cpp - Garbage collection infrastructure -----------------===// +//===-- GCMetadataPrinter.cpp - Garbage collection infrastructure ---------===// // // The LLVM Compiler Infrastructure // @@ -7,15 +7,25 @@ // //===----------------------------------------------------------------------===// // -// This file implements target- and collector-independent garbage collection -// infrastructure. +// This file implements the abstract base class GCMetadataPrinter. // //===----------------------------------------------------------------------===// -#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/CodeGen/GCMetadataPrinter.h" using namespace llvm; +// ----------------------------------------------------------------------------- + +template<> GCMetadataPrinterRegistry::node *GCMetadataPrinterRegistry::Head = 0; +template<> GCMetadataPrinterRegistry::node *GCMetadataPrinterRegistry::Tail = 0; +template<> GCMetadataPrinterRegistry::listener * +GCMetadataPrinterRegistry::ListenerHead = 0; +template<> GCMetadataPrinterRegistry::listener * +GCMetadataPrinterRegistry::ListenerTail = 0; + +// ----------------------------------------------------------------------------- + GCMetadataPrinter::GCMetadataPrinter() { } GCMetadataPrinter::~GCMetadataPrinter() { } diff --git a/lib/CodeGen/GCStrategy.cpp b/lib/CodeGen/GCStrategy.cpp index f5cb9ab..2666775 100644 --- a/lib/CodeGen/GCStrategy.cpp +++ b/lib/CodeGen/GCStrategy.cpp @@ -1,4 +1,4 @@ -//===-- Collector.cpp - Garbage collection infrastructure -----------------===// +//===-- GCStrategy.cpp - Garbage collection infrastructure -----------------===// // // The LLVM Compiler Infrastructure // @@ -10,6 +10,9 @@ // This file implements target- and collector-independent garbage collection // infrastructure. // +// MachineCodeAnalysis identifies the GC safe points in the machine code. Roots +// are identified in SelectionDAGISel. +// //===----------------------------------------------------------------------===// #include "llvm/CodeGen/GCStrategy.h" @@ -31,13 +34,13 @@ namespace { /// 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 + /// directed by the GCStrategy. It also performs automatic root initialization /// and custom intrinsic lowering. class VISIBILITY_HIDDEN LowerIntrinsics : public FunctionPass { - static bool NeedsDefaultLoweringPass(const Collector &C); - static bool NeedsCustomLoweringPass(const Collector &C); + static bool NeedsDefaultLoweringPass(const GCStrategy &C); + static bool NeedsCustomLoweringPass(const GCStrategy &C); static bool CouldBecomeSafePoint(Instruction *I); - bool PerformDefaultLowering(Function &F, Collector &Coll); + bool PerformDefaultLowering(Function &F, GCStrategy &Coll); static bool InsertRootInitializers(Function &F, AllocaInst **Roots, unsigned Count); @@ -56,10 +59,10 @@ namespace { /// 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. + /// GCMetadata record for each function. class VISIBILITY_HIDDEN MachineCodeAnalysis : public MachineFunctionPass { const TargetMachine *TM; - CollectorMetadata *MD; + GCFunctionInfo *FI; MachineModuleInfo *MMI; const TargetInstrInfo *TII; MachineFrameInfo *MFI; @@ -85,7 +88,14 @@ namespace { // ----------------------------------------------------------------------------- -Collector::Collector() : +template<> GCRegistry::node *GCRegistry::Head = 0; +template<> GCRegistry::node *GCRegistry::Tail = 0; +template<> GCRegistry::listener *GCRegistry::ListenerHead = 0; +template<> GCRegistry::listener *GCRegistry::ListenerTail = 0; + +// ----------------------------------------------------------------------------- + +GCStrategy::GCStrategy() : NeededSafePoints(0), CustomReadBarriers(false), CustomWriteBarriers(false), @@ -94,26 +104,26 @@ Collector::Collector() : UsesMetadata(false) {} -Collector::~Collector() { +GCStrategy::~GCStrategy() { for (iterator I = begin(), E = end(); I != E; ++I) delete *I; Functions.clear(); } -bool Collector::initializeCustomLowering(Module &M) { return false; } +bool GCStrategy::initializeCustomLowering(Module &M) { return false; } -bool Collector::performCustomLowering(Function &F) { +bool GCStrategy::performCustomLowering(Function &F) { cerr << "gc " << getName() << " must override performCustomLowering.\n"; abort(); return 0; } - -CollectorMetadata *Collector::insertFunctionMetadata(const Function &F) { - CollectorMetadata *CM = new CollectorMetadata(F, *this); - Functions.push_back(CM); - return CM; -} + +GCFunctionInfo *GCStrategy::insertFunctionInfo(const Function &F) { + GCFunctionInfo *FI = new GCFunctionInfo(F, *this); + Functions.push_back(FI); + return FI; +} // ----------------------------------------------------------------------------- @@ -132,7 +142,7 @@ const char *LowerIntrinsics::getPassName() const { void LowerIntrinsics::getAnalysisUsage(AnalysisUsage &AU) const { FunctionPass::getAnalysisUsage(AU); - AU.addRequired<CollectorModuleMetadata>(); + AU.addRequired<GCModuleInfo>(); } /// doInitialization - If this module uses the GC intrinsics, find them now. @@ -141,15 +151,14 @@ bool LowerIntrinsics::doInitialization(Module &M) { // 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!?"); + GCModuleInfo *MI = getAnalysisToUpdate<GCModuleInfo>(); + assert(MI && "LowerIntrinsics didn't require GCModuleInfo!?"); for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - if (!I->isDeclaration() && I->hasCollector()) - CMM->get(*I); // Instantiate the Collector. + if (!I->isDeclaration() && I->hasGC()) + MI->getFunctionInfo(*I); // Instantiate the GC strategy. bool MadeChange = false; - for (CollectorModuleMetadata::iterator I = CMM->begin(), - E = CMM->end(); I != E; ++I) + for (GCModuleInfo::iterator I = MI->begin(), E = MI->end(); I != E; ++I) if (NeedsCustomLoweringPass(**I)) if ((*I)->initializeCustomLowering(M)) MadeChange = true; @@ -185,7 +194,7 @@ bool LowerIntrinsics::InsertRootInitializers(Function &F, AllocaInst **Roots, return MadeChange; } -bool LowerIntrinsics::NeedsDefaultLoweringPass(const Collector &C) { +bool LowerIntrinsics::NeedsDefaultLoweringPass(const GCStrategy &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() @@ -193,7 +202,7 @@ bool LowerIntrinsics::NeedsDefaultLoweringPass(const Collector &C) { || C.initializeRoots(); } -bool LowerIntrinsics::NeedsCustomLoweringPass(const Collector &C) { +bool LowerIntrinsics::NeedsCustomLoweringPass(const GCStrategy &C) { // Custom lowering is only necessary if enabled for some action. return C.customWriteBarrier() || C.customReadBarrier() @@ -232,26 +241,27 @@ bool LowerIntrinsics::CouldBecomeSafePoint(Instruction *I) { /// Leave gcroot intrinsics; the code generator needs to see those. bool LowerIntrinsics::runOnFunction(Function &F) { // Quick exit for functions that do not use GC. - if (!F.hasCollector()) return false; + if (!F.hasGC()) + return false; - CollectorMetadata &MD = getAnalysis<CollectorModuleMetadata>().get(F); - Collector &Coll = MD.getCollector(); + GCFunctionInfo &FI = getAnalysis<GCModuleInfo>().getFunctionInfo(F); + GCStrategy &S = FI.getStrategy(); bool MadeChange = false; - if (NeedsDefaultLoweringPass(Coll)) - MadeChange |= PerformDefaultLowering(F, Coll); + if (NeedsDefaultLoweringPass(S)) + MadeChange |= PerformDefaultLowering(F, S); - if (NeedsCustomLoweringPass(Coll)) - MadeChange |= Coll.performCustomLowering(F); + if (NeedsCustomLoweringPass(S)) + MadeChange |= S.performCustomLowering(F); return MadeChange; } -bool LowerIntrinsics::PerformDefaultLowering(Function &F, Collector &Coll) { - bool LowerWr = !Coll.customWriteBarrier(); - bool LowerRd = !Coll.customReadBarrier(); - bool InitRoots = Coll.initializeRoots(); +bool LowerIntrinsics::PerformDefaultLowering(Function &F, GCStrategy &S) { + bool LowerWr = !S.customWriteBarrier(); + bool LowerRd = !S.customReadBarrier(); + bool InitRoots = S.initializeRoots(); SmallVector<AllocaInst*,32> Roots; @@ -320,7 +330,7 @@ void MachineCodeAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { MachineFunctionPass::getAnalysisUsage(AU); AU.setPreservesAll(); AU.addRequired<MachineModuleInfo>(); - AU.addRequired<CollectorModuleMetadata>(); + AU.addRequired<GCModuleInfo>(); } unsigned MachineCodeAnalysis::InsertLabel(MachineBasicBlock &MBB, @@ -336,11 +346,11 @@ void MachineCodeAnalysis::VisitCallPoint(MachineBasicBlock::iterator CI) { MachineBasicBlock::iterator RAI = CI; ++RAI; - if (MD->getCollector().needsSafePoint(GC::PreCall)) - MD->addSafePoint(GC::PreCall, InsertLabel(*CI->getParent(), CI)); + if (FI->getStrategy().needsSafePoint(GC::PreCall)) + FI->addSafePoint(GC::PreCall, InsertLabel(*CI->getParent(), CI)); - if (MD->getCollector().needsSafePoint(GC::PostCall)) - MD->addSafePoint(GC::PostCall, InsertLabel(*CI->getParent(), RAI)); + if (FI->getStrategy().needsSafePoint(GC::PostCall)) + FI->addSafePoint(GC::PostCall, InsertLabel(*CI->getParent(), RAI)); } void MachineCodeAnalysis::FindSafePoints(MachineFunction &MF) { @@ -357,18 +367,19 @@ void MachineCodeAnalysis::FindStackOffsets(MachineFunction &MF) { uint64_t OffsetAdjustment = MFI->getOffsetAdjustment(); uint64_t OffsetOfLocalArea = TM->getFrameInfo()->getOffsetOfLocalArea(); - for (CollectorMetadata::roots_iterator RI = MD->roots_begin(), - RE = MD->roots_end(); RI != RE; ++RI) + for (GCFunctionInfo::roots_iterator RI = FI->roots_begin(), + RE = FI->roots_end(); RI != RE; ++RI) RI->StackOffset = MFI->getObjectOffset(RI->Num) + StackSize - OffsetOfLocalArea + OffsetAdjustment; } bool MachineCodeAnalysis::runOnMachineFunction(MachineFunction &MF) { // Quick exit for functions that do not use GC. - if (!MF.getFunction()->hasCollector()) return false; + if (!MF.getFunction()->hasGC()) + return false; - MD = &getAnalysis<CollectorModuleMetadata>().get(*MF.getFunction()); - if (!MD->getCollector().needsSafePoints()) + FI = &getAnalysis<GCModuleInfo>().getFunctionInfo(*MF.getFunction()); + if (!FI->getStrategy().needsSafePoints()) return false; TM = &MF.getTarget(); @@ -377,7 +388,7 @@ bool MachineCodeAnalysis::runOnMachineFunction(MachineFunction &MF) { MFI = MF.getFrameInfo(); // Find the size of the stack frame. - MD->setFrameSize(MFI->getStackSize()); + FI->setFrameSize(MFI->getStackSize()); // Find all safe points. FindSafePoints(MF); diff --git a/lib/CodeGen/GCs.cpp b/lib/CodeGen/GCs.cpp deleted file mode 100644 index 1247253..0000000 --- a/lib/CodeGen/GCs.cpp +++ /dev/null @@ -1,28 +0,0 @@ -//===-- Collectors.cpp - Garbage collector registry -----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the static data members of the CollectorRegistry class. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CodeGen/GCs.h" - -using namespace llvm; - -template<> CollectorRegistry::node *CollectorRegistry::Head = 0; -template<> CollectorRegistry::node *CollectorRegistry::Tail = 0; -template<> CollectorRegistry::listener *CollectorRegistry::ListenerHead = 0; -template<> CollectorRegistry::listener *CollectorRegistry::ListenerTail = 0; - -template<> GCMetadataPrinterRegistry::node *GCMetadataPrinterRegistry::Head = 0; -template<> GCMetadataPrinterRegistry::node *GCMetadataPrinterRegistry::Tail = 0; -template<> GCMetadataPrinterRegistry::listener * -GCMetadataPrinterRegistry::ListenerHead = 0; -template<> GCMetadataPrinterRegistry::listener * -GCMetadataPrinterRegistry::ListenerTail = 0; diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index d420ffb..938e1ae 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -133,7 +133,7 @@ LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, PM.add(createMachineFunctionPrinterPass(cerr)); if (PrintGCInfo) - PM.add(createCollectorMetadataPrinter(*cerr)); + PM.add(createGCInfoPrinter(*cerr)); // Fold redundant debug labels. PM.add(createDebugLabelFoldingPass()); @@ -173,7 +173,7 @@ bool LLVMTargetMachine::addPassesToEmitFileFinish(PassManagerBase &PM, if (MCE) addSimpleCodeEmitter(PM, Fast, PrintEmittedAsm, *MCE); - PM.add(createCollectorMetadataDeleter()); + PM.add(createGCInfoDeleter()); // Delete machine code for this function PM.add(createMachineCodeDeleter()); @@ -274,14 +274,14 @@ bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM, PM.add(createMachineFunctionPrinterPass(cerr)); if (PrintGCInfo) - PM.add(createCollectorMetadataPrinter(*cerr)); + PM.add(createGCInfoPrinter(*cerr)); if (addPreEmitPass(PM, Fast) && PrintMachineCode) PM.add(createMachineFunctionPrinterPass(cerr)); addCodeEmitter(PM, Fast, PrintEmittedAsm, MCE); - PM.add(createCollectorMetadataDeleter()); + PM.add(createGCInfoDeleter()); // Delete machine code for this function PM.add(createMachineCodeDeleter()); diff --git a/lib/CodeGen/OcamlGC.cpp b/lib/CodeGen/OcamlGC.cpp index 88499cb..0b90444 100644 --- a/lib/CodeGen/OcamlGC.cpp +++ b/lib/CodeGen/OcamlGC.cpp @@ -1,4 +1,4 @@ -//===-- OcamlCollector.cpp - Ocaml frametable emitter ---------------------===// +//===-- OcamlGC.cpp - Ocaml frametable GC strategy ------------------------===// // // The LLVM Compiler Infrastructure // @@ -9,38 +9,29 @@ // // This file implements lowering for the llvm.gc* intrinsics compatible with // Objective Caml 3.10.0, which uses a liveness-accurate static stack map. +// +// The frametable emitter is in OcamlGCPrinter.cpp. // //===----------------------------------------------------------------------===// #include "llvm/CodeGen/GCs.h" -#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/GCStrategy.h" -#include "llvm/Module.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetMachine.h" using namespace llvm; namespace { - - class VISIBILITY_HIDDEN OcamlCollector : public Collector { + class VISIBILITY_HIDDEN OcamlGC : public GCStrategy { public: - OcamlCollector(); + OcamlGC(); }; - } -static CollectorRegistry::Add<OcamlCollector> -X("ocaml", "ocaml 3.10-compatible collector"); - -// ----------------------------------------------------------------------------- +static GCRegistry::Add<OcamlGC> +X("ocaml", "ocaml 3.10-compatible GC"); -Collector *llvm::createOcamlCollector() { - return new OcamlCollector(); -} +void llvm::linkOcamlGC() { } -OcamlCollector::OcamlCollector() { +OcamlGC::OcamlGC() { NeededSafePoints = 1 << GC::PostCall; UsesMetadata = true; } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 012e7d0..f4e31f7 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -27,6 +27,7 @@ #include "llvm/IntrinsicInst.h" #include "llvm/ParameterAttributes.h" #include "llvm/CodeGen/GCStrategy.h" +#include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -601,15 +602,15 @@ public: /// FunctionLoweringInfo &FuncInfo; - /// GCI - Garbage collection metadata for the function. - CollectorMetadata *GCI; + /// GFI - Garbage collection metadata for the function. + GCFunctionInfo *GFI; SelectionDAGLowering(SelectionDAG &dag, TargetLowering &tli, AliasAnalysis &aa, FunctionLoweringInfo &funcinfo, - CollectorMetadata *gci) + GCFunctionInfo *gfi) : TLI(tli), DAG(dag), TD(DAG.getTarget().getTargetData()), AA(aa), - FuncInfo(funcinfo), GCI(gci) { + FuncInfo(funcinfo), GFI(gfi) { } /// getRoot - Return the current virtual root of the Selection DAG, @@ -3485,18 +3486,18 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { } case Intrinsic::gcroot: - if (GCI) { + if (GFI) { Value *Alloca = I.getOperand(1); Constant *TypeMap = cast<Constant>(I.getOperand(2)); FrameIndexSDNode *FI = cast<FrameIndexSDNode>(getValue(Alloca).Val); - GCI->addStackRoot(FI->getIndex(), TypeMap); + GFI->addStackRoot(FI->getIndex(), TypeMap); } return 0; case Intrinsic::gcread: case Intrinsic::gcwrite: - assert(0 && "Collector failed to lower gcread/gcwrite intrinsics!"); + assert(0 && "GC failed to lower gcread/gcwrite intrinsics!"); return 0; case Intrinsic::flt_rounds: { @@ -4878,7 +4879,7 @@ unsigned SelectionDAGISel::MakeReg(MVT VT) { void SelectionDAGISel::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired<AliasAnalysis>(); - AU.addRequired<CollectorModuleMetadata>(); + AU.addRequired<GCModuleInfo>(); AU.setPreservesAll(); } @@ -4887,10 +4888,10 @@ bool SelectionDAGISel::runOnFunction(Function &Fn) { AA = &getAnalysis<AliasAnalysis>(); MachineFunction &MF = MachineFunction::construct(&Fn, TLI.getTargetMachine()); - if (MF.getFunction()->hasCollector()) - GCI = &getAnalysis<CollectorModuleMetadata>().get(*MF.getFunction()); + if (MF.getFunction()->hasGC()) + GFI = &getAnalysis<GCModuleInfo>().getFunctionInfo(*MF.getFunction()); else - GCI = 0; + GFI = 0; RegInfo = &MF.getRegInfo(); DOUT << "\n\n\n=== " << Fn.getName() << "\n"; @@ -5089,7 +5090,7 @@ static void CheckDAGForTailCallsAndFixThem(SelectionDAG &DAG, void SelectionDAGISel::BuildSelectionDAG(SelectionDAG &DAG, BasicBlock *LLVMBB, std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate, FunctionLoweringInfo &FuncInfo) { - SelectionDAGLowering SDL(DAG, TLI, *AA, FuncInfo, GCI); + SelectionDAGLowering SDL(DAG, TLI, *AA, FuncInfo, GFI); // Lower any arguments needed in this block if this is the entry block. if (LLVMBB == &LLVMBB->getParent()->getEntryBlock()) @@ -5504,7 +5505,7 @@ SelectionDAGISel::FinishBasicBlock(BasicBlock *LLVMBB, MachineFunction &MF, getAnalysisToUpdate<MachineModuleInfo>(), NodeAllocator); CurDAG = &HSDAG; - SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo, GCI); + SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo, GFI); // Set the current basic block to the mbb we wish to insert the code into BB = BitTestCases[i].Parent; HSDL.setCurrentBasicBlock(BB); @@ -5519,7 +5520,7 @@ SelectionDAGISel::FinishBasicBlock(BasicBlock *LLVMBB, MachineFunction &MF, getAnalysisToUpdate<MachineModuleInfo>(), NodeAllocator); CurDAG = &BSDAG; - SelectionDAGLowering BSDL(BSDAG, TLI, *AA, FuncInfo, GCI); + SelectionDAGLowering BSDL(BSDAG, TLI, *AA, FuncInfo, GFI); // Set the current basic block to the mbb we wish to insert the code into BB = BitTestCases[i].Cases[j].ThisBB; BSDL.setCurrentBasicBlock(BB); @@ -5578,7 +5579,7 @@ SelectionDAGISel::FinishBasicBlock(BasicBlock *LLVMBB, MachineFunction &MF, getAnalysisToUpdate<MachineModuleInfo>(), NodeAllocator); CurDAG = &HSDAG; - SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo, GCI); + SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo, GFI); // Set the current basic block to the mbb we wish to insert the code into BB = JTCases[i].first.HeaderBB; HSDL.setCurrentBasicBlock(BB); @@ -5592,7 +5593,7 @@ SelectionDAGISel::FinishBasicBlock(BasicBlock *LLVMBB, MachineFunction &MF, getAnalysisToUpdate<MachineModuleInfo>(), NodeAllocator); CurDAG = &JSDAG; - SelectionDAGLowering JSDL(JSDAG, TLI, *AA, FuncInfo, GCI); + SelectionDAGLowering JSDL(JSDAG, TLI, *AA, FuncInfo, GFI); // Set the current basic block to the mbb we wish to insert the code into BB = JTCases[i].second.MBB; JSDL.setCurrentBasicBlock(BB); @@ -5642,7 +5643,7 @@ SelectionDAGISel::FinishBasicBlock(BasicBlock *LLVMBB, MachineFunction &MF, getAnalysisToUpdate<MachineModuleInfo>(), NodeAllocator); CurDAG = &SDAG; - SelectionDAGLowering SDL(SDAG, TLI, *AA, FuncInfo, GCI); + SelectionDAGLowering SDL(SDAG, TLI, *AA, FuncInfo, GFI); // Set the current basic block to the mbb we wish to insert the code into BB = SwitchCases[i].ThisBB; diff --git a/lib/CodeGen/ShadowStackGC.cpp b/lib/CodeGen/ShadowStackGC.cpp index 850c005..cf0e6dd 100644 --- a/lib/CodeGen/ShadowStackGC.cpp +++ b/lib/CodeGen/ShadowStackGC.cpp @@ -1,4 +1,4 @@ -//===-- ShadowStackCollector.cpp - GC support for uncooperative targets ---===// +//===-- ShadowStackGC.cpp - GC support for uncooperative targets ----------===// // // The LLVM Compiler Infrastructure // @@ -9,7 +9,7 @@ // // This file implements lowering for the llvm.gc* intrinsics for targets that do // not natively support them (which includes the C backend). Note that the code -// generated is not quite as efficient as collectors which generate stack maps +// generated is not quite as efficient as algorithms which generate stack maps // to identify roots. // // This pass implements the code transformation described in this paper: @@ -17,7 +17,7 @@ // Fergus Henderson, ISMM, 2002 // // In runtime/GC/SemiSpace.cpp is a prototype runtime which is compatible with -// this collector. +// ShadowStackGC. // // In order to support this particular transformation, all stack roots are // coallocated in the stack. This allows a fully target-independent stack map @@ -37,7 +37,7 @@ using namespace llvm; namespace { - class VISIBILITY_HIDDEN ShadowStackCollector : public Collector { + class VISIBILITY_HIDDEN ShadowStackGC : public GCStrategy { /// RootChain - This is the global linked-list that contains the chain of GC /// roots. GlobalVariable *Head; @@ -51,7 +51,7 @@ namespace { std::vector<std::pair<CallInst*,AllocaInst*> > Roots; public: - ShadowStackCollector(); + ShadowStackGC(); bool initializeCustomLowering(Module &M); bool performCustomLowering(Function &F); @@ -69,9 +69,8 @@ namespace { } -static CollectorRegistry::Add<ShadowStackCollector> -Y("shadow-stack", - "Very portable collector for uncooperative code generators"); +static GCRegistry::Add<ShadowStackGC> +X("shadow-stack", "Very portable GC for uncooperative code generators"); namespace { /// EscapeEnumerator - This is a little algorithm to find all escape points @@ -173,21 +172,18 @@ namespace { } } }; - } // ----------------------------------------------------------------------------- -Collector *llvm::createShadowStackCollector() { - return new ShadowStackCollector(); -} +void llvm::linkShadowStackGC() { } -ShadowStackCollector::ShadowStackCollector() : Head(0), StackEntryTy(0) { +ShadowStackGC::ShadowStackGC() : Head(0), StackEntryTy(0) { InitRoots = true; CustomRoots = true; } -Constant *ShadowStackCollector::GetFrameMap(Function &F) { +Constant *ShadowStackGC::GetFrameMap(Function &F) { // doInitialization creates the abstract type of this value. Type *VoidPtr = PointerType::getUnqual(Type::Int8Ty); @@ -242,7 +238,7 @@ Constant *ShadowStackCollector::GetFrameMap(Function &F) { return ConstantExpr::getGetElementPtr(GV, GEPIndices, 2); } -const Type* ShadowStackCollector::GetConcreteStackEntryType(Function &F) { +const Type* ShadowStackGC::GetConcreteStackEntryType(Function &F) { // doInitialization creates the generic version of this type. std::vector<const Type*> EltTys; EltTys.push_back(StackEntryTy); @@ -259,7 +255,7 @@ const Type* ShadowStackCollector::GetConcreteStackEntryType(Function &F) { /// doInitialization - If this module uses the GC intrinsics, find them now. If /// not, exit fast. -bool ShadowStackCollector::initializeCustomLowering(Module &M) { +bool ShadowStackGC::initializeCustomLowering(Module &M) { // struct FrameMap { // int32_t NumRoots; // Number of roots in stack frame. // int32_t NumMeta; // Number of metadata descriptors. May be < NumRoots. @@ -307,13 +303,13 @@ bool ShadowStackCollector::initializeCustomLowering(Module &M) { return true; } -bool ShadowStackCollector::IsNullValue(Value *V) { +bool ShadowStackGC::IsNullValue(Value *V) { if (Constant *C = dyn_cast<Constant>(V)) return C->isNullValue(); return false; } -void ShadowStackCollector::CollectRoots(Function &F) { +void ShadowStackGC::CollectRoots(Function &F) { // FIXME: Account for original alignment. Could fragment the root array. // Approach 1: Null initialize empty slots at runtime. Yuck. // Approach 2: Emit a map of the array instead of just a count. @@ -341,8 +337,8 @@ void ShadowStackCollector::CollectRoots(Function &F) { } GetElementPtrInst * -ShadowStackCollector::CreateGEP(IRBuilder<> &B, Value *BasePtr, - int Idx, int Idx2, const char *Name) { +ShadowStackGC::CreateGEP(IRBuilder<> &B, Value *BasePtr, + int Idx, int Idx2, const char *Name) { Value *Indices[] = { ConstantInt::get(Type::Int32Ty, 0), ConstantInt::get(Type::Int32Ty, Idx), ConstantInt::get(Type::Int32Ty, Idx2) }; @@ -354,8 +350,8 @@ ShadowStackCollector::CreateGEP(IRBuilder<> &B, Value *BasePtr, } GetElementPtrInst * -ShadowStackCollector::CreateGEP(IRBuilder<> &B, Value *BasePtr, - int Idx, const char *Name) { +ShadowStackGC::CreateGEP(IRBuilder<> &B, Value *BasePtr, + int Idx, const char *Name) { Value *Indices[] = { ConstantInt::get(Type::Int32Ty, 0), ConstantInt::get(Type::Int32Ty, Idx) }; Value *Val = B.CreateGEP(BasePtr, Indices, Indices + 2, Name); @@ -366,7 +362,7 @@ ShadowStackCollector::CreateGEP(IRBuilder<> &B, Value *BasePtr, } /// runOnFunction - Insert code to maintain the shadow stack. -bool ShadowStackCollector::performCustomLowering(Function &F) { +bool ShadowStackGC::performCustomLowering(Function &F) { // Find calls to llvm.gcroot. CollectRoots(F); @@ -405,9 +401,10 @@ bool ShadowStackCollector::performCustomLowering(Function &F) { OriginalAlloca->replaceAllUsesWith(SlotPtr); } - // Move past the original stores inserted by Collector::InitRoots. This isn't - // really necessary (the collector would never see the intermediate state), - // but it's nicer not to push the half-initialized entry onto the stack. + // Move past the original stores inserted by GCStrategy::InitRoots. This isn't + // really necessary (the collector would never see the intermediate state at + // runtime), but it's nicer not to push the half-initialized entry onto the + // shadow stack. while (isa<StoreInst>(IP)) ++IP; AtEntry.SetInsertPoint(IP->getParent(), IP); diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 0017eb9..2661b1b 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -3386,6 +3386,6 @@ bool CTargetMachine::addPassesToEmitWholeFile(PassManager &PM, PM.add(createCFGSimplificationPass()); // clean up after lower invoke. PM.add(new CBackendNameAllUsedStructsAndMergeFunctions()); PM.add(new CWriter(o)); - PM.add(createCollectorMetadataDeleter()); + PM.add(createGCInfoDeleter()); return false; } diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp index ce86452..b359659 100644 --- a/lib/Target/CppBackend/CPPBackend.cpp +++ b/lib/Target/CppBackend/CPPBackend.cpp @@ -1603,9 +1603,9 @@ namespace { Out << ");"; nl(Out); } - if (F->hasCollector()) { + if (F->hasGC()) { printCppName(F); - Out << "->setCollector(\"" << F->getCollector() << "\");"; + Out << "->setGC(\"" << F->getGC() << "\");"; nl(Out); } if (is_inline) { diff --git a/lib/Target/MSIL/MSILWriter.cpp b/lib/Target/MSIL/MSILWriter.cpp index 2b7e69e..99c1e9f 100644 --- a/lib/Target/MSIL/MSILWriter.cpp +++ b/lib/Target/MSIL/MSILWriter.cpp @@ -1660,6 +1660,6 @@ bool MSILTarget::addPassesToEmitWholeFile(PassManager &PM, std::ostream &o, PM.add(createCFGSimplificationPass()); PM.add(new MSILModule(Writer->UsedTypes,Writer->TD)); PM.add(Writer); - PM.add(createCollectorMetadataDeleter()); + PM.add(createGCInfoDeleter()); return false; } diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp index a198356..fe82073 100644 --- a/lib/Transforms/Utils/InlineFunction.cpp +++ b/lib/Transforms/Utils/InlineFunction.cpp @@ -208,10 +208,10 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG, const TargetData *TD) { // 1. If the caller has no GC, then the callee's GC must be propagated to the // caller. // 2. If the caller has a differing GC, it is invalid to inline. - if (CalledFunc->hasCollector()) { - if (!Caller->hasCollector()) - Caller->setCollector(CalledFunc->getCollector()); - else if (CalledFunc->getCollector() != Caller->getCollector()) + if (CalledFunc->hasGC()) { + if (!Caller->hasGC()) + Caller->setGC(CalledFunc->getGC()); + else if (CalledFunc->getGC() != Caller->getGC()) return false; } diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 282f47b..f16ae08 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -1184,8 +1184,8 @@ void AssemblyWriter::printFunction(const Function *F) { Out << " section \"" << F->getSection() << '"'; if (F->getAlignment()) Out << " align " << F->getAlignment(); - if (F->hasCollector()) - Out << " gc \"" << F->getCollector() << '"'; + if (F->hasGC()) + Out << " gc \"" << F->getGC() << '"'; if (F->isDeclaration()) { Out << "\n"; diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp index bc7137b..8517a41 100644 --- a/lib/VMCore/Core.cpp +++ b/lib/VMCore/Core.cpp @@ -719,17 +719,17 @@ void LLVMSetFunctionCallConv(LLVMValueRef Fn, unsigned CC) { return unwrap<Function>(Fn)->setCallingConv(CC); } -const char *LLVMGetCollector(LLVMValueRef Fn) { +const char *LLVMGetGC(LLVMValueRef Fn) { Function *F = unwrap<Function>(Fn); - return F->hasCollector()? F->getCollector() : 0; + return F->hasGC()? F->getGC() : 0; } -void LLVMSetCollector(LLVMValueRef Fn, const char *Coll) { +void LLVMSetGC(LLVMValueRef Fn, const char *GC) { Function *F = unwrap<Function>(Fn); - if (Coll) - F->setCollector(Coll); + if (GC) + F->setGC(GC); else - F->clearCollector(); + F->clearGC(); } /*--.. Operations on parameters ............................................--*/ diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index f819a18..c1a96de 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -182,8 +182,8 @@ Function::~Function() { ArgumentList.clear(); delete SymTab; - // Remove the function from the on-the-side collector table. - clearCollector(); + // Remove the function from the on-the-side GC table. + clearGC(); } void Function::BuildLazyArguments() const { @@ -240,39 +240,39 @@ void Function::removeParamAttr(unsigned i, ParameterAttributes attr) { setParamAttrs(PAL); } -// Maintain the collector name for each function in an on-the-side table. This -// saves allocating an additional word in Function for programs which do not use -// GC (i.e., most programs) at the cost of increased overhead for clients which -// do use GC. -static DenseMap<const Function*,PooledStringPtr> *CollectorNames; -static StringPool *CollectorNamePool; +// Maintain the GC name for each function in an on-the-side table. This saves +// allocating an additional word in Function for programs which do not use GC +// (i.e., most programs) at the cost of increased overhead for clients which do +// use GC. +static DenseMap<const Function*,PooledStringPtr> *GCNames; +static StringPool *GCNamePool; -bool Function::hasCollector() const { - return CollectorNames && CollectorNames->count(this); +bool Function::hasGC() const { + return GCNames && GCNames->count(this); } -const char *Function::getCollector() const { - assert(hasCollector() && "Function has no collector"); - return *(*CollectorNames)[this]; +const char *Function::getGC() const { + assert(hasGC() && "Function has no collector"); + return *(*GCNames)[this]; } -void Function::setCollector(const char *Str) { - if (!CollectorNamePool) - CollectorNamePool = new StringPool(); - if (!CollectorNames) - CollectorNames = new DenseMap<const Function*,PooledStringPtr>(); - (*CollectorNames)[this] = CollectorNamePool->intern(Str); +void Function::setGC(const char *Str) { + if (!GCNamePool) + GCNamePool = new StringPool(); + if (!GCNames) + GCNames = new DenseMap<const Function*,PooledStringPtr>(); + (*GCNames)[this] = GCNamePool->intern(Str); } -void Function::clearCollector() { - if (CollectorNames) { - CollectorNames->erase(this); - if (CollectorNames->empty()) { - delete CollectorNames; - CollectorNames = 0; - if (CollectorNamePool->empty()) { - delete CollectorNamePool; - CollectorNamePool = 0; +void Function::clearGC() { + if (GCNames) { + GCNames->erase(this); + if (GCNames->empty()) { + delete GCNames; + GCNames = 0; + if (GCNamePool->empty()) { + delete GCNamePool; + GCNamePool = 0; } } } @@ -286,8 +286,10 @@ void Function::copyAttributesFrom(const GlobalValue *Src) { const Function *SrcF = cast<Function>(Src); setCallingConv(SrcF->getCallingConv()); setParamAttrs(SrcF->getParamAttrs()); - if (SrcF->hasCollector()) - setCollector(SrcF->getCollector()); + if (SrcF->hasGC()) + setGC(SrcF->getGC()); + else + clearGC(); } /// getIntrinsicID - This method returns the ID number of the specified diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index b1b413c..fb48814 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -1308,8 +1308,8 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { break; } - Assert1(CI.getParent()->getParent()->hasCollector(), - "Enclosing function does not specify a collector algorithm.", + Assert1(CI.getParent()->getParent()->hasGC(), + "Enclosing function does not use GC.", &CI); } break; case Intrinsic::init_trampoline: diff --git a/test/Bindings/Ocaml/vmcore.ml b/test/Bindings/Ocaml/vmcore.ml index 24846b6..4dc1965 100644 --- a/test/Bindings/Ocaml/vmcore.ml +++ b/test/Bindings/Ocaml/vmcore.ml @@ -569,16 +569,16 @@ let test_functions () = insist (CallConv.fast = function_call_conv fn); ignore (build_unreachable (builder_at_end (entry_block fn))); - begin group "collector"; + begin group "gc"; (* RUN: grep {Fn6.*gc.*shadowstack} < %t.ll *) let fn = define_function "Fn6" ty m in - insist (None = collector fn); - set_collector (Some "ocaml") fn; - insist (Some "ocaml" = collector fn); - set_collector None fn; - insist (None = collector fn); - set_collector (Some "shadowstack") fn; + insist (None = gc fn); + set_gc (Some "ocaml") fn; + insist (Some "ocaml" = gc fn); + set_gc None fn; + insist (None = gc fn); + set_gc (Some "shadowstack") fn; ignore (build_unreachable (builder_at_end (entry_block fn))); end; |