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