//===- 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 LinkerScript;
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)(LinkerScript&, 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(LinkerScript& pScript, LinkerConfig& pConfig) const {
if (!EmulationFn)
return false;
return EmulationFn(pScript, 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