From 4d2eb98d420baa9938e597529d98076e7a0ef9b3 Mon Sep 17 00:00:00 2001 From: Gordon Henriksen Date: Sun, 17 Aug 2008 12:08:44 +0000 Subject: [PATCH] Factor GC metadata table assembly generation out of Collector in preparation for splitting AsmPrinter into its own library. llvm-svn: 54880 --- include/llvm/CodeGen/AsmPrinter.h | 14 ++++++++-- include/llvm/CodeGen/Collector.h | 46 +++++++++++++++++++++++++++---- include/llvm/CodeGen/Collectors.h | 5 ++++ lib/CodeGen/AsmPrinter.cpp | 37 +++++++++++++++++++++++-- lib/CodeGen/Collector.cpp | 29 +++++++++++-------- lib/CodeGen/Collectors.cpp | 7 +++++ lib/CodeGen/OcamlCollector.cpp | 17 ++++++++---- 7 files changed, 129 insertions(+), 26 deletions(-) diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 1bd2d517756..27ea22140d5 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 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 gcp_map_type; + typedef gcp_map_type::iterator gcp_iterator; + gcp_map_type GCMetadataPrinters; + protected: // Necessary for external weak linkage support std::set 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 > &CP); - + GCMetadataPrinter *GetOrCreateGCPrinter(Collector *C); }; } diff --git a/include/llvm/CodeGen/Collector.h b/include/llvm/CodeGen/Collector.h index 160e5238b4f..20b470296e1 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 0d9e4516106..1658da1489a 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 CollectorRegistry; + /// The GC assembly printer registry uses all the defaults from Registry. + /// + typedef Registry 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 1bc4868a608..3b2dcb31d29 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 1a1fb7c7338..6fd018961a4 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 e063d47a992..3b0c554daf9 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 9823d24986f..7f58f58c29b 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 X("ocaml", "ocaml 3.10-compatible collector"); +static GCMetadataPrinterRegistry::Add +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)) {