| //===- TargetRegistry.h ---------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| #ifndef MCLD_TARGET_REGISTRY_H |
| #define MCLD_TARGET_REGISTRY_H |
| #include <llvm/Support/TargetRegistry.h> |
| #include <string> |
| #include <list> |
| |
| namespace llvm { |
| class TargetMachine; |
| class MCCodeEmitter; |
| class MCContext; |
| class AsmPrinter; |
| } // namespace of llvm |
| |
| namespace mcld { |
| |
| class Module; |
| class LinkerConfig; |
| class MemoryArea; |
| class MCLDTargetMachine; |
| class TargetRegistry; |
| class MCLinker; |
| class TargetLDBackend; |
| class AttributeFactory; |
| class InputFactory; |
| class ContextFactory; |
| class DiagnosticLineInfo; |
| |
| //===----------------------------------------------------------------------===// |
| /// Target - mcld::Target is an object adapter of llvm::Target |
| //===----------------------------------------------------------------------===// |
| class Target |
| { |
| friend class mcld::MCLDTargetMachine; |
| friend class mcld::TargetRegistry; |
| public: |
| typedef mcld::MCLDTargetMachine *(*TargetMachineCtorTy)(const mcld::Target &, |
| llvm::TargetMachine &, |
| const std::string&); |
| |
| typedef MCLinker *(*MCLinkerCtorTy)(const std::string& pTriple, |
| LinkerConfig&, |
| Module&, |
| MemoryArea& pOutput); |
| |
| typedef bool (*EmulationFnTy)(const std::string& pTriple, LinkerConfig&); |
| |
| typedef TargetLDBackend *(*TargetLDBackendCtorTy)(const llvm::Target&, |
| const LinkerConfig&); |
| |
| typedef DiagnosticLineInfo *(*DiagnosticLineInfoCtorTy)(const mcld::Target&, |
| const std::string&); |
| |
| public: |
| Target(); |
| |
| void setTarget(const llvm::Target& pTarget) |
| { m_pT = &pTarget; } |
| |
| mcld::MCLDTargetMachine *createTargetMachine(const std::string &pTriple, |
| const std::string &pCPU, const std::string &pFeatures, |
| const llvm::TargetOptions &Options, |
| llvm::Reloc::Model RM = llvm::Reloc::Default, |
| llvm::CodeModel::Model CM = llvm::CodeModel::Default, |
| llvm::CodeGenOpt::Level OL = llvm::CodeGenOpt::Default) const |
| { |
| if (TargetMachineCtorFn && m_pT) { |
| llvm::TargetMachine *tm = m_pT->createTargetMachine(pTriple, pCPU, pFeatures, Options, RM, CM, OL); |
| if (tm) |
| return TargetMachineCtorFn(*this, *tm, pTriple); |
| } |
| return NULL; |
| } |
| |
| /// createMCLinker - create target-specific MCLinker |
| /// |
| /// @return created MCLinker |
| MCLinker *createMCLinker(const std::string &pTriple, |
| LinkerConfig& pConfig, |
| Module& pModule, |
| MemoryArea& pOutput) const { |
| if (!MCLinkerCtorFn) |
| return NULL; |
| return MCLinkerCtorFn(pTriple, pConfig, pModule, pOutput); |
| } |
| |
| /// emulate - given MCLinker default values for the other aspects of the |
| /// target system. |
| bool emulate(const std::string& pTriple, LinkerConfig& pConfig) const { |
| if (!EmulationFn) |
| return false; |
| return EmulationFn(pTriple, pConfig); |
| } |
| |
| /// createLDBackend - create target-specific LDBackend |
| /// |
| /// @return created TargetLDBackend |
| TargetLDBackend* createLDBackend(const LinkerConfig& pConfig) const |
| { |
| if (!TargetLDBackendCtorFn) |
| return NULL; |
| return TargetLDBackendCtorFn(*get(), pConfig); |
| } |
| |
| /// createDiagnosticLineInfo - create target-specific DiagnosticLineInfo |
| DiagnosticLineInfo* createDiagnosticLineInfo(const mcld::Target& pTarget, |
| const std::string& pTriple) const |
| { |
| if (!DiagnosticLineInfoCtorFn) |
| return NULL; |
| return DiagnosticLineInfoCtorFn(pTarget, pTriple); |
| } |
| |
| const llvm::Target* get() const { return m_pT; } |
| |
| private: |
| // ----- function pointers ----- // |
| TargetMachineCtorTy TargetMachineCtorFn; |
| MCLinkerCtorTy MCLinkerCtorFn; |
| EmulationFnTy EmulationFn; |
| TargetLDBackendCtorTy TargetLDBackendCtorFn; |
| DiagnosticLineInfoCtorTy DiagnosticLineInfoCtorFn; |
| |
| // ----- adapted llvm::Target ----- // |
| const llvm::Target* m_pT; |
| }; |
| |
| //===----------------------------------------------------------------------===// |
| /// TargetRegistry - mcld::TargetRegistry is an object adapter of |
| /// llvm::TargetRegistry |
| /// |
| class TargetRegistry |
| { |
| public: |
| typedef std::list<mcld::Target*> TargetListTy; |
| typedef TargetListTy::iterator iterator; |
| |
| private: |
| static TargetListTy s_TargetList; |
| |
| public: |
| static iterator begin() { return s_TargetList.begin(); } |
| static iterator end() { return s_TargetList.end(); } |
| |
| static size_t size() { return s_TargetList.size(); } |
| static bool empty() { return s_TargetList.empty(); } |
| |
| /// RegisterTarget - Register the given target. Attempts to register a |
| /// target which has already been registered will be ignored. |
| /// |
| /// Clients are responsible for ensuring that registration doesn't occur |
| /// while another thread is attempting to access the registry. Typically |
| /// this is done by initializing all targets at program startup. |
| /// |
| /// @param T - The target being registered. |
| static void RegisterTarget(mcld::Target &T); |
| |
| /// RegisterTargetMachine - Register a TargetMachine implementation for the |
| /// given target. |
| /// |
| /// @param T - The target being registered. |
| /// @param Fn - A function to construct a TargetMachine for the target. |
| static void RegisterTargetMachine(mcld::Target &T, mcld::Target::TargetMachineCtorTy Fn) |
| { |
| // Ignore duplicate registration. |
| if (!T.TargetMachineCtorFn) |
| T.TargetMachineCtorFn = Fn; |
| } |
| |
| /// RegisterMCLinker - Register a MCLinker implementation for the given |
| /// target. |
| /// |
| /// @param T - the target being registered |
| /// @param Fn - A function to create MCLinker for the target |
| static void RegisterMCLinker(mcld::Target &T, mcld::Target::MCLinkerCtorTy Fn) |
| { |
| if (!T.MCLinkerCtorFn) |
| T.MCLinkerCtorFn = Fn; |
| } |
| |
| /// RegisterEmulation - Register a emulation function for the target. |
| /// target. |
| /// |
| /// @param T - the target being registered |
| /// @param Fn - A emulation function |
| static void RegisterEmulation(mcld::Target &T, mcld::Target::EmulationFnTy Fn) |
| { |
| if (!T.EmulationFn) |
| T.EmulationFn = Fn; |
| } |
| |
| /// RegisterTargetLDBackend - Register a TargetLDBackend implementation for |
| /// the given target. |
| /// |
| /// @param T - The target being registered |
| /// @param Fn - A function to create TargetLDBackend for the target |
| static void RegisterTargetLDBackend(mcld::Target &T, mcld::Target::TargetLDBackendCtorTy Fn) |
| { |
| if (!T.TargetLDBackendCtorFn) |
| T.TargetLDBackendCtorFn = Fn; |
| } |
| |
| /// RegisterTargetDiagnosticLineInfo - Register a DiagnosticLineInfo |
| /// implementation for the given target. |
| /// |
| /// @param T - The target being registered |
| /// @param Fn - A function to create DiagnosticLineInfo for the target |
| static void |
| RegisterDiagnosticLineInfo(mcld::Target &T, |
| mcld::Target::DiagnosticLineInfoCtorTy Fn) |
| { |
| if (!T.DiagnosticLineInfoCtorFn) |
| T.DiagnosticLineInfoCtorFn = Fn; |
| } |
| |
| /// lookupTarget - Lookup a target based on a llvm::Target. |
| /// |
| /// @param T - The llvm::Target to find |
| static const mcld::Target *lookupTarget(const llvm::Target& T); |
| |
| /// lookupTarget - function wrapper of llvm::TargetRegistry::lookupTarget |
| /// |
| /// @param Triple - The Triple string |
| /// @param Error - The returned error message |
| static const mcld::Target *lookupTarget(const std::string &Triple, |
| std::string &Error); |
| }; |
| |
| /// RegisterTarget - Helper function for registering a target, for use in the |
| /// target's initialization function. Usage: |
| /// |
| /// Target TheFooTarget; // The global target instance. |
| /// |
| /// extern "C" void MCLDInitializeFooTargetInfo() { |
| /// RegisterTarget X(TheFooTarget, "foo", "Foo description"); |
| /// } |
| struct RegisterTarget |
| { |
| RegisterTarget(mcld::Target &T, const char *Name) { |
| llvm::TargetRegistry::iterator TIter, TEnd = llvm::TargetRegistry::end(); |
| // lookup llvm::Target |
| for( TIter=llvm::TargetRegistry::begin(); TIter!=TEnd; ++TIter ) { |
| if( 0==strcmp(TIter->getName(), Name) ) |
| break; |
| } |
| |
| if (TIter != TEnd) |
| T.setTarget(*TIter); |
| |
| TargetRegistry::RegisterTarget(T); |
| } |
| }; |
| |
| /// RegisterTargetMachine - Helper template for registering a target machine |
| /// implementation, for use in the target machine initialization |
| /// function. Usage: |
| /// |
| /// extern "C" void MCLDInitializeFooTarget() { |
| /// extern mcld::Target TheFooTarget; |
| /// RegisterTargetMachine<mcld::FooTargetMachine> X(TheFooTarget); |
| /// } |
| template<class TargetMachineImpl> |
| struct RegisterTargetMachine |
| { |
| RegisterTargetMachine(mcld::Target &T) { |
| TargetRegistry::RegisterTargetMachine(T, &Allocator); |
| } |
| |
| private: |
| static mcld::MCLDTargetMachine *Allocator(const mcld::Target &T, |
| llvm::TargetMachine& TM, |
| const std::string &Triple) { |
| return new TargetMachineImpl(TM, T, Triple); |
| } |
| }; |
| |
| } //end namespace mcld |
| |
| #endif |
| |