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