From 2571db23f1b4f2605e3d1c3d3fab5e1ef639f8b4 Mon Sep 17 00:00:00 2001 From: Gordon Henriksen Date: Thu, 27 Sep 2007 19:34:27 +0000 Subject: [PATCH] My previous Registry.h header, as well as Collectors.h, which is the registry for dynamically-loaded garbage collection compiler plugins. llvm-svn: 42415 --- include/llvm/CodeGen/Collectors.h | 36 +++++ include/llvm/Support/Registry.h | 243 ++++++++++++++++++++++++++++++ lib/CodeGen/Collectors.cpp | 21 +++ 3 files changed, 300 insertions(+) create mode 100644 include/llvm/CodeGen/Collectors.h create mode 100644 include/llvm/Support/Registry.h create mode 100644 lib/CodeGen/Collectors.cpp diff --git a/include/llvm/CodeGen/Collectors.h b/include/llvm/CodeGen/Collectors.h new file mode 100644 index 00000000000..18c1546b8c8 --- /dev/null +++ b/include/llvm/CodeGen/Collectors.h @@ -0,0 +1,36 @@ +//===-- Collectors.h - Garbage collector registry -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Gordon Henriksen and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the CollectorRegistry class, which is used to discover +// pluggable garbage collectors. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_COLLECTORS_H +#define LLVM_CODEGEN_COLLECTORS_H + +#include "llvm/Support/Registry.h" + +namespace llvm { + + class Collector; + + /// The collector registry uses all the defaults from Registry. + /// + typedef Registry CollectorRegistry; + + /// Creates an ocaml-compatible garbage collector. + Collector *createOcamlCollector(); + + /// Creates a shadow stack garbage collector. This collector requires no code + /// generator support. + Collector *createShadowStackCollector(); +} + +#endif diff --git a/include/llvm/Support/Registry.h b/include/llvm/Support/Registry.h new file mode 100644 index 00000000000..6f11ef13872 --- /dev/null +++ b/include/llvm/Support/Registry.h @@ -0,0 +1,243 @@ +//=== Registry.h - Linker-supported plugin registries -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Gordon Henriksen and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines a registry template for discovering pluggable modules. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_REGISTRY_H +#define LLVM_SUPPORT_REGISTRY_H + +#include "llvm/Support/CommandLine.h" + +namespace llvm { + /// A simple registry entry which provides only a name, description, and + /// no-argument constructor. + template + class SimpleRegistryEntry { + const char *Name, *Desc; + T *(*Ctor)(); + + public: + SimpleRegistryEntry(const char *N, const char *D, T *(*C)()) + : Name(N), Desc(D), Ctor(C) + {} + + const char *getName() const { return Name; } + const char *getDesc() const { return Desc; } + T *instantiate() const { return Ctor(); } + }; + + + /// Traits for registry entries. If using other than SimpleRegistryEntry, it + /// is necessary to define an alternate traits class. + template + class RegistryTraits { + RegistryTraits(); // Do not implement. + + public: + typedef SimpleRegistryEntry entry; + + /// Accessors for . + /// + static const char *nameof(const entry &Entry) { return Entry.getName(); } + static const char *descof(const entry &Entry) { return Entry.getDesc(); } + }; + + + /// A global registry used in conjunction with static constructors to make + /// pluggable components (like targets or garbage collectors) "just work" when + /// linked with an executable. + template > + class Registry { + public: + typedef U traits; + typedef typename U::entry entry; + + class node; + class listener; + class iterator; + + private: + Registry(); // Do not implement. + + static void Announce(node *); + + friend class node; + static node *Head, *Tail; + + friend class listener; + static listener *ListenerHead, *ListenerTail; + + public: + class iterator; + + + /// Node in linked list of entries. + /// + class node { + friend class iterator; + + node *Next; + const entry& Val; + + public: + node(const entry& V) : Next(0), Val(V) { + if (Tail) + Tail->Next = this; + else + Head = this; + Tail = this; + + Announce(V); + } + }; + + + /// Iterators for registry entries. + /// + class iterator { + const node *Cur; + + public: + explicit iterator(const node *N) : Cur(N) {} + + bool operator==(const iterator &That) const { return Cur == That.Cur; } + bool operator!=(const iterator &That) const { return Cur != That.Cur; } + iterator &operator++() { Cur = Cur->Next; return *this; } + const entry &operator*() const { return Cur->Val; } + const entry *operator->() const { return &Cur->Val; } + }; + + static iterator begin() { return iterator(Head); } + static iterator end() { return iterator(0); } + + + /// Abstract base class for registry listeners, which are informed when new + /// entries are added to the registry. Simply subclass and instantiate: + /// + /// class CollectorPrinter : public Registry::listener { + /// protected: + /// void registered(const Registry::entry &e) { + /// cerr << "collector now available: " << e->getName() << "\n"; + /// } + /// + /// public: + /// CollectorPrinter() { init(); } // Print those already registered. + /// }; + /// + /// CollectorPrinter Printer; + /// + class listener { + listener *Prev, *Next; + + friend void Registry::Announce(const entry &E); + + protected: + /// Called when an entry is added to the registry. + /// + virtual void registered(const entry &) = 0; + + /// Calls 'registered' for each pre-existing entry. + /// + void init() { + for (iterator I = begin(), E = end(); I != E; ++I) + registered(*I); + } + + public: + listener() : Prev(ListenerTail), Next(0) { + if (Prev) + Prev->Next = this; + else + ListenerHead = this; + ListenerTail = this; + } + + virtual ~listener() { + if (Next) + Next->Prev = Prev; + else + ListenerTail = Prev; + if (Prev) + Prev->Next = Next; + else + ListenerHead = Next; + } + }; + + + /// A static registration template. Use like such: + /// + /// Registry::Add + /// X("fancy-gc", "Newfangled garbage collector."); + /// + /// Use of this template requires that: + /// + /// 1. The registered subclass has a default constructor. + // + /// 2. The registry entry type has a constructor compatible with this + /// signature: + /// + /// entry(const char *Name, const char *ShortDesc, T *(*Ctor)()); + /// + /// If you have more elaborate requirements, then copy and modify. + /// + template + class Add { + entry Entry; + node Node; + + static T *CtorFn() { return new V(); } + + public: + Add(const char *Name, const char *Desc) + : Entry(Name, Desc, CtorFn), Node(Entry) {} + }; + + + /// A command-line parser for a registry. Use like such: + /// + /// static cl::opt::entry, false, + /// Registry::Parser> + /// GCOpt("gc", cl::desc("Garbage collector to use."), + /// cl::value_desc()); + /// + /// To make use of the value: + /// + /// Collector *TheCollector = GCOpt->instantiate(); + /// + class Parser : public cl::parser, public listener{ + typedef U traits; + typedef typename U::entry entry; + + protected: + void registered(const entry &E) { + addLiteralOption(traits::nameof(E), &E, traits::descof(E)); + } + + public: + void initialize(cl::Option &O) { + listener::init(); + cl::parser::initialize(O); + } + }; + + + private: + static void Announce(const entry &E) { + for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next) + Cur->registered(E); + } + + }; + +} + +#endif diff --git a/lib/CodeGen/Collectors.cpp b/lib/CodeGen/Collectors.cpp new file mode 100644 index 00000000000..feeebd5075e --- /dev/null +++ b/lib/CodeGen/Collectors.cpp @@ -0,0 +1,21 @@ +//===-- Collectors.cpp - Garbage collector registry -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Gordon Henriksen and 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/Collectors.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;