TargetRegistry.h revision 22add6ff3426df1a85089fe6a6e1597ee3b6f300
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_TARGET_REGISTRY_H
10#define MCLD_TARGET_REGISTRY_H
11#include <llvm/Support/TargetRegistry.h>
12#include <string>
13#include <list>
14
15namespace llvm {
16class TargetMachine;
17class MCCodeEmitter;
18class MCContext;
19class AsmPrinter;
20} // namespace of llvm
21
22namespace mcld {
23
24class Module;
25class LinkerConfig;
26class MemoryArea;
27class MCLDTargetMachine;
28class TargetRegistry;
29class MCLinker;
30class TargetLDBackend;
31class AttributeFactory;
32class InputFactory;
33class ContextFactory;
34class DiagnosticLineInfo;
35
36//===----------------------------------------------------------------------===//
37/// Target - mcld::Target is an object adapter of llvm::Target
38//===----------------------------------------------------------------------===//
39class Target
40{
41  friend class mcld::MCLDTargetMachine;
42  friend class mcld::TargetRegistry;
43public:
44  typedef mcld::MCLDTargetMachine *(*TargetMachineCtorTy)(const mcld::Target &,
45                                                          llvm::TargetMachine &,
46                                                          const std::string&);
47
48  typedef MCLinker *(*MCLinkerCtorTy)(const std::string& pTriple,
49                                      LinkerConfig&,
50                                      Module&,
51                                      MemoryArea& pOutput);
52
53  typedef bool (*EmulationFnTy)(const std::string& pTriple, LinkerConfig&);
54
55  typedef TargetLDBackend  *(*TargetLDBackendCtorTy)(const llvm::Target&,
56                                                     const LinkerConfig&);
57
58  typedef DiagnosticLineInfo *(*DiagnosticLineInfoCtorTy)(const mcld::Target&,
59                                                          const std::string&);
60
61public:
62  Target();
63
64  void setTarget(const llvm::Target& pTarget)
65  { m_pT = &pTarget; }
66
67  mcld::MCLDTargetMachine *createTargetMachine(const std::string &pTriple,
68                          const std::string &pCPU, const std::string &pFeatures,
69                          const llvm::TargetOptions &Options,
70                          llvm::Reloc::Model RM = llvm::Reloc::Default,
71                          llvm::CodeModel::Model CM = llvm::CodeModel::Default,
72                          llvm::CodeGenOpt::Level OL = llvm::CodeGenOpt::Default) const
73  {
74    if (TargetMachineCtorFn && m_pT) {
75      llvm::TargetMachine *tm = m_pT->createTargetMachine(pTriple, pCPU, pFeatures, Options, RM, CM, OL);
76      if (tm)
77        return TargetMachineCtorFn(*this, *tm, pTriple);
78    }
79    return NULL;
80  }
81
82  /// createMCLinker - create target-specific MCLinker
83  ///
84  /// @return created MCLinker
85  MCLinker *createMCLinker(const std::string &pTriple,
86                           LinkerConfig& pConfig,
87                           Module& pModule,
88                           MemoryArea& pOutput) const {
89    if (!MCLinkerCtorFn)
90      return NULL;
91    return MCLinkerCtorFn(pTriple, pConfig, pModule, pOutput);
92  }
93
94  /// emulate - given MCLinker default values for the other aspects of the
95  /// target system.
96  bool emulate(const std::string& pTriple, LinkerConfig& pConfig) const {
97    if (!EmulationFn)
98      return false;
99    return EmulationFn(pTriple, pConfig);
100  }
101
102  /// createLDBackend - create target-specific LDBackend
103  ///
104  /// @return created TargetLDBackend
105  TargetLDBackend* createLDBackend(const LinkerConfig& pConfig) const
106  {
107    if (!TargetLDBackendCtorFn)
108      return NULL;
109    return TargetLDBackendCtorFn(*get(), pConfig);
110  }
111
112  /// createDiagnosticLineInfo - create target-specific DiagnosticLineInfo
113  DiagnosticLineInfo* createDiagnosticLineInfo(const mcld::Target& pTarget,
114                                               const std::string& pTriple) const
115  {
116    if (!DiagnosticLineInfoCtorFn)
117      return NULL;
118    return DiagnosticLineInfoCtorFn(pTarget, pTriple);
119  }
120
121  const llvm::Target* get() const { return m_pT; }
122
123private:
124  // -----  function pointers  ----- //
125  TargetMachineCtorTy TargetMachineCtorFn;
126  MCLinkerCtorTy MCLinkerCtorFn;
127  EmulationFnTy EmulationFn;
128  TargetLDBackendCtorTy TargetLDBackendCtorFn;
129  DiagnosticLineInfoCtorTy DiagnosticLineInfoCtorFn;
130
131  // -----  adapted llvm::Target  ----- //
132  const llvm::Target* m_pT;
133};
134
135//===----------------------------------------------------------------------===//
136/// TargetRegistry - mcld::TargetRegistry is an object adapter of
137/// llvm::TargetRegistry
138///
139class TargetRegistry
140{
141public:
142  typedef std::list<mcld::Target*> TargetListTy;
143  typedef TargetListTy::iterator iterator;
144
145private:
146  static TargetListTy s_TargetList;
147
148public:
149  static iterator begin() { return s_TargetList.begin(); }
150  static iterator end() { return s_TargetList.end(); }
151
152  static size_t size() { return s_TargetList.size(); }
153  static bool empty() { return s_TargetList.empty(); }
154
155  /// RegisterTarget - Register the given target. Attempts to register a
156  /// target which has already been registered will be ignored.
157  ///
158  /// Clients are responsible for ensuring that registration doesn't occur
159  /// while another thread is attempting to access the registry. Typically
160  /// this is done by initializing all targets at program startup.
161  ///
162  /// @param T - The target being registered.
163  static void RegisterTarget(mcld::Target &T);
164
165  /// RegisterTargetMachine - Register a TargetMachine implementation for the
166  /// given target.
167  ///
168  /// @param T - The target being registered.
169  /// @param Fn - A function to construct a TargetMachine for the target.
170  static void RegisterTargetMachine(mcld::Target &T, mcld::Target::TargetMachineCtorTy Fn)
171  {
172    // Ignore duplicate registration.
173    if (!T.TargetMachineCtorFn)
174      T.TargetMachineCtorFn = Fn;
175  }
176
177  /// RegisterMCLinker - Register a MCLinker implementation for the given
178  /// target.
179  ///
180  /// @param T - the target being registered
181  /// @param Fn - A function to create MCLinker for the target
182  static void RegisterMCLinker(mcld::Target &T, mcld::Target::MCLinkerCtorTy Fn)
183  {
184    if (!T.MCLinkerCtorFn)
185      T.MCLinkerCtorFn = Fn;
186  }
187
188  /// RegisterEmulation - Register a emulation function for the target.
189  /// target.
190  ///
191  /// @param T - the target being registered
192  /// @param Fn - A emulation function
193  static void RegisterEmulation(mcld::Target &T, mcld::Target::EmulationFnTy Fn)
194  {
195    if (!T.EmulationFn)
196      T.EmulationFn = Fn;
197  }
198
199  /// RegisterTargetLDBackend - Register a TargetLDBackend implementation for
200  /// the given target.
201  ///
202  /// @param T - The target being registered
203  /// @param Fn - A function to create TargetLDBackend for the target
204  static void RegisterTargetLDBackend(mcld::Target &T, mcld::Target::TargetLDBackendCtorTy Fn)
205  {
206    if (!T.TargetLDBackendCtorFn)
207      T.TargetLDBackendCtorFn = Fn;
208  }
209
210  /// RegisterTargetDiagnosticLineInfo - Register a DiagnosticLineInfo
211  /// implementation for the given target.
212  ///
213  /// @param T - The target being registered
214  /// @param Fn - A function to create DiagnosticLineInfo for the target
215  static void
216  RegisterDiagnosticLineInfo(mcld::Target &T,
217                             mcld::Target::DiagnosticLineInfoCtorTy Fn)
218  {
219    if (!T.DiagnosticLineInfoCtorFn)
220      T.DiagnosticLineInfoCtorFn = Fn;
221  }
222
223  /// lookupTarget - Lookup a target based on a llvm::Target.
224  ///
225  /// @param T - The llvm::Target to find
226  static const mcld::Target *lookupTarget(const llvm::Target& T);
227
228  /// lookupTarget - function wrapper of llvm::TargetRegistry::lookupTarget
229  ///
230  /// @param Triple - The Triple string
231  /// @param Error  - The returned error message
232  static const mcld::Target *lookupTarget(const std::string &Triple,
233                                          std::string &Error);
234};
235
236/// RegisterTarget - Helper function for registering a target, for use in the
237/// target's initialization function. Usage:
238///
239/// Target TheFooTarget; // The global target instance.
240///
241/// extern "C" void MCLDInitializeFooTargetInfo() {
242///   RegisterTarget X(TheFooTarget, "foo", "Foo description");
243/// }
244struct RegisterTarget
245{
246  RegisterTarget(mcld::Target &T, const char *Name) {
247    llvm::TargetRegistry::iterator TIter, TEnd = llvm::TargetRegistry::end();
248    // lookup llvm::Target
249    for( TIter=llvm::TargetRegistry::begin(); TIter!=TEnd; ++TIter ) {
250      if( 0==strcmp(TIter->getName(), Name) )
251        break;
252    }
253
254    if (TIter != TEnd)
255      T.setTarget(*TIter);
256
257    TargetRegistry::RegisterTarget(T);
258  }
259};
260
261/// RegisterTargetMachine - Helper template for registering a target machine
262/// implementation, for use in the target machine initialization
263/// function. Usage:
264///
265/// extern "C" void MCLDInitializeFooTarget() {
266///   extern mcld::Target TheFooTarget;
267///   RegisterTargetMachine<mcld::FooTargetMachine> X(TheFooTarget);
268/// }
269template<class TargetMachineImpl>
270struct RegisterTargetMachine
271{
272  RegisterTargetMachine(mcld::Target &T) {
273    TargetRegistry::RegisterTargetMachine(T, &Allocator);
274  }
275
276private:
277  static mcld::MCLDTargetMachine *Allocator(const mcld::Target &T,
278                                            llvm::TargetMachine& TM,
279                                            const std::string &Triple) {
280    return new TargetMachineImpl(TM, T, Triple);
281  }
282};
283
284} //end namespace mcld
285
286#endif
287
288