aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/llvm/CodeGen/AsmPrinter.h14
-rw-r--r--include/llvm/CodeGen/Collector.h46
-rw-r--r--include/llvm/CodeGen/Collectors.h5
-rw-r--r--lib/CodeGen/AsmPrinter.cpp37
-rw-r--r--lib/CodeGen/Collector.cpp29
-rw-r--r--lib/CodeGen/Collectors.cpp7
-rw-r--r--lib/CodeGen/OcamlCollector.cpp17
7 files changed, 129 insertions, 26 deletions
diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h
index 1bd2d51..27ea221 100644
--- a/include/llvm/CodeGen/AsmPrinter.h
+++ b/include/llvm/CodeGen/AsmPrinter.h
@@ -18,11 +18,14 @@
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/DenseMap.h"
#include <set>
namespace llvm {
+ class Collector;
class Constant;
class ConstantArray;
+ class GCMetadataPrinter;
class GlobalVariable;
class GlobalAlias;
class MachineConstantPoolEntry;
@@ -48,7 +51,12 @@ namespace llvm {
/// DebugVariable entries into the dwarf table. This is a short term hack
/// that ought be fixed soon.
MachineModuleInfo *MMI;
-
+
+ // GCMetadataPrinters - The garbage collection metadata printer table.
+ typedef DenseMap<Collector*,GCMetadataPrinter*> gcp_map_type;
+ typedef gcp_map_type::iterator gcp_iterator;
+ gcp_map_type GCMetadataPrinters;
+
protected:
// Necessary for external weak linkage support
std::set<const GlobalValue*> ExtWeakSymbols;
@@ -91,6 +99,8 @@ namespace llvm {
AsmPrinter(std::ostream &o, TargetMachine &TM, const TargetAsmInfo *T);
public:
+ virtual ~AsmPrinter();
+
/// SwitchToTextSection - Switch to the specified section of the executable
/// if we are not already in it! If GV is non-null and if the global has an
/// explicitly requested section, we switch to the section indicated for the
@@ -356,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);
};
}
diff --git a/include/llvm/CodeGen/Collector.h b/include/llvm/CodeGen/Collector.h
index 160e523..20b4702 100644
--- a/include/llvm/CodeGen/Collector.h
+++ b/include/llvm/CodeGen/Collector.h
@@ -60,6 +60,7 @@ namespace llvm {
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();
@@ -103,12 +104,9 @@ namespace llvm {
/// is necessary for most collectors.
bool initializeRoots() const { return InitRoots; }
-
- /// 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);
+ /// 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.
///
@@ -128,6 +126,42 @@ namespace llvm {
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/Collectors.h b/include/llvm/CodeGen/Collectors.h
index 0d9e451..1658da1 100644
--- a/include/llvm/CodeGen/Collectors.h
+++ b/include/llvm/CodeGen/Collectors.h
@@ -20,11 +20,16 @@
namespace llvm {
class Collector;
+ 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.
diff --git a/lib/CodeGen/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter.cpp
index 1bc4868..3b2dcb3 100644
--- a/lib/CodeGen/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter.cpp
@@ -18,6 +18,7 @@
#include "llvm/Module.h"
#include "llvm/CodeGen/Collector.h"
#include "llvm/CodeGen/CollectorMetadata.h"
+#include "llvm/CodeGen/Collectors.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
@@ -43,6 +44,12 @@ AsmPrinter::AsmPrinter(std::ostream &o, TargetMachine &tm,
IsInTextSection(false)
{}
+AsmPrinter::~AsmPrinter() {
+ for (gcp_iterator I = GCMetadataPrinters.begin(),
+ E = GCMetadataPrinters.end(); I != E; ++I)
+ delete I->second;
+}
+
std::string AsmPrinter::getSectionForFunction(const Function &F) const {
return TAI->getTextSection();
}
@@ -113,7 +120,8 @@ bool AsmPrinter::doInitialization(Module &M) {
assert(CMM && "AsmPrinter didn't require CollectorModuleMetadata?");
for (CollectorModuleMetadata::iterator I = CMM->begin(),
E = CMM->end(); I != E; ++I)
- (*I)->beginAssembly(O, *this, *TAI);
+ if (GCMetadataPrinter *GCP = GetOrCreateGCPrinter(*I))
+ GCP->beginAssembly(O, *this, *TAI);
if (!M.getModuleInlineAsm().empty())
O << TAI->getCommentString() << " Start of file scope inline assembly\n"
@@ -188,7 +196,8 @@ bool AsmPrinter::doFinalization(Module &M) {
assert(CMM && "AsmPrinter didn't require CollectorModuleMetadata?");
for (CollectorModuleMetadata::iterator I = CMM->end(),
E = CMM->begin(); I != E; )
- (*--I)->finishAssembly(O, *this, *TAI);
+ if (GCMetadataPrinter *GCP = GetOrCreateGCPrinter(*--I))
+ GCP->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.
@@ -1456,3 +1465,27 @@ void AsmPrinter::printVisibility(const std::string& Name,
O << Directive << Name << '\n';
}
}
+
+GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(Collector *C) {
+ if (!C->usesMetadata())
+ return 0;
+
+ gcp_iterator GCPI = GCMetadataPrinters.find(C);
+ if (GCPI != GCMetadataPrinters.end())
+ return GCPI->second;
+
+ const char *Name = C->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;
+ }
+
+ cerr << "no GCMetadataPrinter registered for collector: " << Name << "\n";
+ abort();
+}
diff --git a/lib/CodeGen/Collector.cpp b/lib/CodeGen/Collector.cpp
index 1a1fb7c..6fd0189 100644
--- a/lib/CodeGen/Collector.cpp
+++ b/lib/CodeGen/Collector.cpp
@@ -92,7 +92,8 @@ Collector::Collector() :
CustomReadBarriers(false),
CustomWriteBarriers(false),
CustomRoots(false),
- InitRoots(true)
+ InitRoots(true),
+ UsesMetadata(false)
{}
Collector::~Collector() {
@@ -110,16 +111,6 @@ bool Collector::performCustomLowering(Function &F) {
return 0;
}
-void Collector::beginAssembly(std::ostream &OS, AsmPrinter &AP,
- const TargetAsmInfo &TAI) {
- // Default is no action.
-}
-
-void Collector::finishAssembly(std::ostream &OS, AsmPrinter &AP,
- const TargetAsmInfo &TAI) {
- // Default is no action.
-}
-
CollectorMetadata *Collector::insertFunctionMetadata(const Function &F) {
CollectorMetadata *CM = new CollectorMetadata(F, *this);
Functions.push_back(CM);
@@ -128,6 +119,22 @@ CollectorMetadata *Collector::insertFunctionMetadata(const Function &F) {
// -----------------------------------------------------------------------------
+GCMetadataPrinter::GCMetadataPrinter() { }
+
+GCMetadataPrinter::~GCMetadataPrinter() { }
+
+void GCMetadataPrinter::beginAssembly(std::ostream &OS, AsmPrinter &AP,
+ const TargetAsmInfo &TAI) {
+ // Default is no action.
+}
+
+void GCMetadataPrinter::finishAssembly(std::ostream &OS, AsmPrinter &AP,
+ const TargetAsmInfo &TAI) {
+ // Default is no action.
+}
+
+// -----------------------------------------------------------------------------
+
FunctionPass *llvm::createGCLoweringPass() {
return new LowerIntrinsics();
}
diff --git a/lib/CodeGen/Collectors.cpp b/lib/CodeGen/Collectors.cpp
index e063d47..3b0c554 100644
--- a/lib/CodeGen/Collectors.cpp
+++ b/lib/CodeGen/Collectors.cpp
@@ -19,3 +19,10 @@ 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/OcamlCollector.cpp b/lib/CodeGen/OcamlCollector.cpp
index 9823d24..7f58f58 100644
--- a/lib/CodeGen/OcamlCollector.cpp
+++ b/lib/CodeGen/OcamlCollector.cpp
@@ -27,7 +27,10 @@ namespace {
class VISIBILITY_HIDDEN OcamlCollector : public Collector {
public:
OcamlCollector();
-
+ };
+
+ class VISIBILITY_HIDDEN OcamlGCMetadataPrinter : public GCMetadataPrinter {
+ public:
void beginAssembly(std::ostream &OS, AsmPrinter &AP,
const TargetAsmInfo &TAI);
@@ -40,6 +43,9 @@ namespace {
static CollectorRegistry::Add<OcamlCollector>
X("ocaml", "ocaml 3.10-compatible collector");
+static GCMetadataPrinterRegistry::Add<OcamlGCMetadataPrinter>
+Y("ocaml", "ocaml 3.10-compatible collector");
+
// -----------------------------------------------------------------------------
static void EmitCamlGlobal(const Module &M, std::ostream &OS, AsmPrinter &AP,
@@ -68,10 +74,11 @@ Collector *llvm::createOcamlCollector() {
OcamlCollector::OcamlCollector() {
NeededSafePoints = 1 << GC::PostCall;
+ UsesMetadata = true;
}
-void OcamlCollector::beginAssembly(std::ostream &OS, AsmPrinter &AP,
- const TargetAsmInfo &TAI) {
+void OcamlGCMetadataPrinter::beginAssembly(std::ostream &OS, AsmPrinter &AP,
+ const TargetAsmInfo &TAI) {
AP.SwitchToTextSection(TAI.getTextSection());
EmitCamlGlobal(getModule(), OS, AP, TAI, "code_begin");
@@ -95,8 +102,8 @@ void OcamlCollector::beginAssembly(std::ostream &OS, AsmPrinter &AP,
/// (FrameSize and LiveOffsets would overflow). FrameTablePrinter will abort if
/// either condition is detected in a function which uses the collector.
///
-void OcamlCollector::finishAssembly(std::ostream &OS, AsmPrinter &AP,
- const TargetAsmInfo &TAI) {
+void OcamlGCMetadataPrinter::finishAssembly(std::ostream &OS, AsmPrinter &AP,
+ const TargetAsmInfo &TAI) {
const char *AddressDirective;
int AddressAlignLog;
if (AP.TM.getTargetData()->getPointerSize() == sizeof(int32_t)) {