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