1//===- TargetRegistry.h ---------------------------------------------------===//
2//
3//                     The MCLinker Project
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#ifndef MCLD_SUPPORT_TARGETREGISTRY_H
10#define MCLD_SUPPORT_TARGETREGISTRY_H
11#include <mcld/Support/Target.h>
12#include <llvm/ADT/Triple.h>
13
14#include <string>
15#include <list>
16
17namespace llvm {
18class TargetMachine;
19class MCCodeEmitter;
20class MCContext;
21class AsmPrinter;
22} // namespace of llvm
23
24namespace mcld {
25
26/** \class TargetRegistry
27 *  \brief TargetRegistry is an object adapter of llvm::TargetRegistry
28 */
29class TargetRegistry
30{
31public:
32  typedef std::list<mcld::Target*> TargetListTy;
33  typedef TargetListTy::iterator iterator;
34
35private:
36  static TargetListTy s_TargetList;
37
38public:
39  static iterator begin() { return s_TargetList.begin(); }
40  static iterator end() { return s_TargetList.end(); }
41
42  static size_t size() { return s_TargetList.size(); }
43  static bool empty() { return s_TargetList.empty(); }
44
45  /// RegisterTarget - Register the given target. Attempts to register a
46  /// target which has already been registered will be ignored.
47  ///
48  /// Clients are responsible for ensuring that registration doesn't occur
49  /// while another thread is attempting to access the registry. Typically
50  /// this is done by initializing all targets at program startup.
51  ///
52  /// @param T - The target being registered.
53  static void RegisterTarget(Target& pTarget,
54                             const char* pName,
55                             Target::TripleMatchQualityFnTy pQualityFn);
56
57  /// RegisterTargetMachine - Register a TargetMachine implementation for the
58  /// given target.
59  ///
60  /// @param T - The target being registered.
61  /// @param Fn - A function to construct a TargetMachine for the target.
62  static void RegisterTargetMachine(mcld::Target &T, mcld::Target::TargetMachineCtorTy Fn)
63  {
64    // Ignore duplicate registration.
65    if (!T.TargetMachineCtorFn)
66      T.TargetMachineCtorFn = Fn;
67  }
68
69  /// RegisterMCLinker - Register a MCLinker implementation for the given
70  /// target.
71  ///
72  /// @param T - the target being registered
73  /// @param Fn - A function to create MCLinker for the target
74  static void RegisterMCLinker(mcld::Target &T, mcld::Target::MCLinkerCtorTy Fn)
75  {
76    if (!T.MCLinkerCtorFn)
77      T.MCLinkerCtorFn = Fn;
78  }
79
80  /// RegisterEmulation - Register a emulation function for the target.
81  /// target.
82  ///
83  /// @param T - the target being registered
84  /// @param Fn - A emulation function
85  static void RegisterEmulation(mcld::Target &T, mcld::Target::EmulationFnTy Fn)
86  {
87    if (!T.EmulationFn)
88      T.EmulationFn = Fn;
89  }
90
91  /// RegisterTargetLDBackend - Register a TargetLDBackend implementation for
92  /// the given target.
93  ///
94  /// @param T - The target being registered
95  /// @param Fn - A function to create TargetLDBackend for the target
96  static void RegisterTargetLDBackend(mcld::Target &T, mcld::Target::TargetLDBackendCtorTy Fn)
97  {
98    if (!T.TargetLDBackendCtorFn)
99      T.TargetLDBackendCtorFn = Fn;
100  }
101
102  /// RegisterTargetDiagnosticLineInfo - Register a DiagnosticLineInfo
103  /// implementation for the given target.
104  ///
105  /// @param T - The target being registered
106  /// @param Fn - A function to create DiagnosticLineInfo for the target
107  static void
108  RegisterDiagnosticLineInfo(mcld::Target &T,
109                             mcld::Target::DiagnosticLineInfoCtorTy Fn)
110  {
111    if (!T.DiagnosticLineInfoCtorFn)
112      T.DiagnosticLineInfoCtorFn = Fn;
113  }
114
115  /// lookupTarget - Look up MCLinker target
116  ///
117  /// @param Triple - The Triple string
118  /// @param Error  - The returned error message
119  static const mcld::Target *lookupTarget(const std::string& pTriple,
120                                          std::string& pError);
121
122  /// lookupTarget - Look up MCLinker target by an architecture name
123  /// and a triple. If the architecture name is not empty, then the
124  /// the lookup is done mainly by architecture. Otherwise, the target
125  /// triple is used.
126  ///
127  /// @param pArch   - The architecture name
128  /// @param pTriple - The target triple
129  /// @param pError  - The returned error message
130  static const mcld::Target *lookupTarget(const std::string& pArchName,
131                                          llvm::Triple& pTriple,
132                                          std::string &Error);
133};
134
135/// RegisterTarget - Helper function for registering a target, for use in the
136/// target's initialization function. Usage:
137///
138/// Target TheFooTarget; // The global target instance.
139///
140/// extern "C" void MCLDInitializeFooTargetInfo() {
141///   RegisterTarget<llvm::Foo> X(TheFooTarget, "foo", "Foo description");
142/// }
143template<llvm::Triple::ArchType TargetArchType = llvm::Triple::UnknownArch>
144struct RegisterTarget
145{
146public:
147  RegisterTarget(mcld::Target &pTarget, const char* pName) {
148    // if we've registered one, then return immediately.
149    TargetRegistry::iterator target, ie = TargetRegistry::end();
150    for (target = TargetRegistry::begin(); target != ie; ++target) {
151      if (0 == strcmp((*target)->name(), pName))
152        return;
153    }
154
155    TargetRegistry::RegisterTarget(pTarget, pName, &getTripleMatchQuality);
156  }
157
158  static unsigned int getTripleMatchQuality(const llvm::Triple& pTriple) {
159    if (pTriple.getArch() == TargetArchType)
160      return 20;
161    return 0;
162  }
163};
164
165/// RegisterTargetMachine - Helper template for registering a target machine
166/// implementation, for use in the target machine initialization
167/// function. Usage:
168///
169/// extern "C" void MCLDInitializeFooTarget() {
170///   extern mcld::Target TheFooTarget;
171///   RegisterTargetMachine<mcld::FooTargetMachine> X(TheFooTarget);
172/// }
173template<class TargetMachineImpl>
174struct RegisterTargetMachine
175{
176  RegisterTargetMachine(mcld::Target &T) {
177    TargetRegistry::RegisterTargetMachine(T, &Allocator);
178  }
179
180private:
181  static MCLDTargetMachine *Allocator(const llvm::Target& pLLVMTarget,
182                                      const mcld::Target& pMCLDTarget,
183                                      llvm::TargetMachine& pTM,
184                                      const std::string& pTriple) {
185    return new TargetMachineImpl(pTM, pLLVMTarget, pMCLDTarget, pTriple);
186  }
187};
188
189} //end namespace mcld
190
191#endif
192
193