Factor commonality in triple match routines into helper template for registering
[oota-llvm.git] / include / llvm / Target / TargetRegistry.h
1 //===-- Target/TargetRegistry.h - Target Registration -----------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file exposes the TargetRegistry interface, which tools can use to access
11 // the appropriate target specific classes (TargetMachine, AsmPrinter, etc.)
12 // which have been registered.
13 //
14 // Target specific class implementations should register themselves using the
15 // appropriate TargetRegistry interfaces.
16 //
17 //===----------------------------------------------------------------------===//
18
19 #ifndef LLVM_TARGET_TARGETREGISTRY_H
20 #define LLVM_TARGET_TARGETREGISTRY_H
21
22 #include "llvm/ADT/Triple.h"
23 // FIXME: We shouldn't need this header, but we need it until there is a
24 // different interface to get the TargetAsmInfo.
25 #include "llvm/Target/TargetMachine.h"
26 #include <string>
27 #include <cassert>
28
29 namespace llvm {
30   class FunctionPass;
31   class Module;
32   class TargetAsmParser;
33   class TargetMachine;
34   class formatted_raw_ostream;
35
36   /// Target - Wrapper for Target specific information.
37   ///
38   /// For registration purposes, this is a POD type so that targets can be
39   /// registered without the use of static constructors.
40   ///
41   /// Targets should implement a single global instance of this class (which
42   /// will be zero initialized), and pass that instance to the TargetRegistry as
43   /// part of their initialization.
44   class Target {
45   private:
46     typedef unsigned (*TripleMatchQualityFnTy)(const std::string &TT);
47
48     typedef TargetMachine *(*TargetMachineCtorTy)(const Target &,
49                                                   const Module &, 
50                                                   const std::string &);
51     typedef FunctionPass *(*AsmPrinterCtorTy)(formatted_raw_ostream &,
52                                               TargetMachine &,
53                                               bool);
54     typedef TargetAsmParser *(*AsmParserCtorTy)(const Target &);
55
56     friend struct TargetRegistry;
57
58     /// Next - The next registered target in the linked list, maintained by the
59     /// TargetRegistry.
60     Target *Next;
61
62     /// TripleMatchQualityFn - The target function for rating the match quality
63     /// of a triple.
64     TripleMatchQualityFnTy TripleMatchQualityFn;
65
66     /// Name - The target name.
67     const char *Name;
68
69     /// ShortDesc - A short description of the target.
70     const char *ShortDesc;
71
72     /// HasJIT - Whether this target supports the JIT.
73     bool HasJIT;
74
75     /// TargetMachineCtorFn - Construction function for this target's
76     /// TargetMachine, if registered.
77     TargetMachineCtorTy TargetMachineCtorFn;
78
79     /// AsmPrinterCtorFn - Construction function for this target's AsmPrinter,
80     /// if registered.
81     AsmPrinterCtorTy AsmPrinterCtorFn;
82
83     /// AsmParserCtorFn - Construction function for this target's AsmParser,
84     /// if registered.
85     AsmParserCtorTy AsmParserCtorFn;
86
87   public:
88     // getNext - Return the next registered target.
89     const Target *getNext() const { return Next; }
90
91     /// getName - Get the target name.
92     const char *getName() const { return Name; }
93
94     /// getShortDescription - Get a short description of the target.
95     const char *getShortDescription() const { return ShortDesc; }
96
97     bool hasJIT() const { return HasJIT; }
98
99     /// hasTargetMachine - Check if this target supports code generation.
100     bool hasTargetMachine() const { return TargetMachineCtorFn != 0; }
101
102     /// hasAsmPrinter - Check if this target supports .s printing.
103     bool hasAsmPrinter() const { return AsmPrinterCtorFn != 0; }
104
105     /// hasAsmParser - Check if this target supports .s parsing.
106     bool hasAsmParser() const { return AsmParserCtorFn != 0; }
107
108     /// createTargetMachine - Create a target specific machine implementation.
109     TargetMachine *createTargetMachine(const Module &M,
110                                        const std::string &Features) const {
111       if (!TargetMachineCtorFn)
112         return 0;
113       return TargetMachineCtorFn(*this, M, Features);
114     }
115
116     /// createAsmPrinter - Create a target specific assembly printer pass.
117     FunctionPass *createAsmPrinter(formatted_raw_ostream &OS,
118                                    TargetMachine &M,
119                                    bool Verbose) const {
120       if (!AsmPrinterCtorFn)
121         return 0;
122       return AsmPrinterCtorFn(OS, M, Verbose);
123     }
124
125     /// createAsmParser - Create a target specific assembly parser.
126     TargetAsmParser *createAsmParser() const {
127       if (!AsmParserCtorFn)
128         return 0;
129       return AsmParserCtorFn(*this);
130     }
131   };
132
133   /// TargetRegistry - Generic interface to target specific features.
134   //
135   // FIXME: Provide Target* iterator.
136   struct TargetRegistry {
137     class iterator {
138       const Target *Current;
139       explicit iterator(Target *T) : Current(T) {}
140       friend struct TargetRegistry;
141     public:
142       iterator(const iterator &I) : Current(I.Current) {}
143       iterator() : Current(0) {}
144
145       bool operator==(const iterator &x) const {
146         return Current == x.Current;
147       }
148       bool operator!=(const iterator &x) const {
149         return !operator==(x);
150       }
151
152       // Iterator traversal: forward iteration only
153       iterator &operator++() {          // Preincrement
154         assert(Current && "Cannot increment end iterator!");
155         Current = Current->getNext();
156         return *this;
157       }
158       iterator operator++(int) {        // Postincrement
159         iterator tmp = *this; 
160         ++*this; 
161         return tmp;
162       }
163
164       const Target &operator*() const {
165         assert(Current && "Cannot dereference end iterator!");
166         return *Current;
167       }
168
169       const Target *operator->() const {
170         return &operator*();
171       }
172     };
173
174     /// @name Registry Access
175     /// @{
176
177     static iterator begin();
178
179     static iterator end() { return iterator(); }
180
181     /// lookupTarget - Lookup a target based on a target triple.
182     ///
183     /// \param Triple - The triple to use for finding a target.
184     /// \param FallbackToHost - If true and no target is found for the given
185     /// \arg Triple, then the host's triple will be used.
186     /// \param RequireJIT - Require the target to support JIT compilation.
187     /// \param Error - On failure, an error string describing why no target was
188     /// found.
189     static const Target *lookupTarget(const std::string &Triple,
190                                       bool FallbackToHost,
191                                       bool RequireJIT,
192                                       std::string &Error);
193
194     /// getClosestTargetForJIT - Pick the best target that is compatible with
195     /// the current host.  If no close target can be found, this returns null
196     /// and sets the Error string to a reason.
197     ///
198     /// Mainted for compatibility through 2.6.
199     static const Target *getClosestTargetForJIT(std::string &Error) {
200       return lookupTarget("", true, true, Error);
201     }
202
203     /// @}
204     /// @name Target Registration
205     /// @{
206
207     /// RegisterTarget - Register the given target. Attempts to register a
208     /// target which has already been registered will be ignored.
209     /// 
210     /// Clients are responsible for ensuring that registration doesn't occur
211     /// while another thread is attempting to access the registry. Typically
212     /// this is done by initializing all targets at program startup.
213     ///
214     /// @param T - The target being registered.
215     /// @param Name - The target name. This should be a static string.
216     /// @param ShortDesc - A short target description. This should be a static
217     /// string. 
218     /// @param TQualityFn - The triple match quality computation function for
219     /// this target.
220     /// @param HasJIT - Whether the target supports JIT code
221     /// generation.
222     static void RegisterTarget(Target &T,
223                                const char *Name,
224                                const char *ShortDesc,
225                                Target::TripleMatchQualityFnTy TQualityFn,
226                                bool HasJIT = false);
227                                
228     /// RegisterTargetMachine - Register a TargetMachine implementation for the
229     /// given target.
230     /// 
231     /// Clients are responsible for ensuring that registration doesn't occur
232     /// while another thread is attempting to access the registry. Typically
233     /// this is done by initializing all targets at program startup.
234     /// 
235     /// @param T - The target being registered.
236     /// @param Fn - A function to construct a TargetMachine for the target.
237     static void RegisterTargetMachine(Target &T, 
238                                       Target::TargetMachineCtorTy Fn) {
239       // Ignore duplicate registration.
240       if (!T.TargetMachineCtorFn)
241         T.TargetMachineCtorFn = Fn;
242     }
243
244     /// RegisterAsmPrinter - Register an AsmPrinter implementation for the given
245     /// target.
246     /// 
247     /// Clients are responsible for ensuring that registration doesn't occur
248     /// while another thread is attempting to access the registry. Typically
249     /// this is done by initializing all targets at program startup.
250     ///
251     /// @param T - The target being registered.
252     /// @param Fn - A function to construct an AsmPrinter for the target.
253     static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn) {
254       // Ignore duplicate registration.
255       if (!T.AsmPrinterCtorFn)
256         T.AsmPrinterCtorFn = Fn;
257     }
258
259     /// RegisterAsmParser - Register a TargetAsmParser implementation for the
260     /// given target.
261     /// 
262     /// Clients are responsible for ensuring that registration doesn't occur
263     /// while another thread is attempting to access the registry. Typically
264     /// this is done by initializing all targets at program startup.
265     ///
266     /// @param T - The target being registered.
267     /// @param Fn - A function to construct an AsmPrinter for the target.
268     static void RegisterAsmParser(Target &T, Target::AsmParserCtorTy Fn) {
269       if (!T.AsmParserCtorFn)
270         T.AsmParserCtorFn = Fn;
271     }
272
273     /// @}
274   };
275
276
277   //===--------------------------------------------------------------------===//
278
279   /// RegisterTarget - Helper template for registering a target, for use in the
280   /// target's initialization function. Usage:
281   ///
282   ///
283   /// Target TheFooTarget; // The global target instance.
284   ///
285   /// extern "C" void LLVMInitializeFooTargetInfo() {
286   ///   RegisterTarget<Triple::foo> X(TheFooTarget, "foo", "Foo description");
287   /// }
288   template<Triple::ArchType TargetArchType = Triple::InvalidArch,
289            bool HasJIT = false>
290   struct RegisterTarget {
291     RegisterTarget(Target &T, const char *Name, const char *Desc) {
292       TargetRegistry::RegisterTarget(T, Name, Desc,
293                                      &getTripleMatchQuality,
294                                      HasJIT);
295     }
296
297     static unsigned getTripleMatchQuality(const std::string &TT) {
298       if (Triple(TT.c_str()).getArch() == TargetArchType)
299         return 20;
300       return 0;
301     }
302   };
303
304   /// RegisterTargetMachine - Helper template for registering a target machine
305   /// implementation, for use in the target machine initialization
306   /// function. Usage:
307   ///
308   /// extern "C" void LLVMInitializeFooTarget() {
309   ///   extern Target TheFooTarget;
310   ///   RegisterTargetMachine<FooTargetMachine> X(TheFooTarget);
311   /// }
312   template<class TargetMachineImpl>
313   struct RegisterTargetMachine {
314     RegisterTargetMachine(Target &T) {
315       TargetRegistry::RegisterTargetMachine(T, &Allocator);
316     }
317
318   private:
319     static TargetMachine *Allocator(const Target &T, const Module &M,
320                                     const std::string &FS) {
321       return new TargetMachineImpl(T, M, FS);
322     }
323   };
324
325   /// RegisterAsmPrinter - Helper template for registering a target specific
326   /// assembly printer, for use in the target machine initialization
327   /// function. Usage:
328   ///
329   /// extern "C" void LLVMInitializeFooAsmPrinter() {
330   ///   extern Target TheFooTarget;
331   ///   RegisterAsmPrinter<FooAsmPrinter> X(TheFooTarget);
332   /// }
333   template<class AsmPrinterImpl>
334   struct RegisterAsmPrinter {
335     RegisterAsmPrinter(Target &T) {
336       TargetRegistry::RegisterAsmPrinter(T, &Allocator);
337     }
338
339   private:
340     static FunctionPass *Allocator(formatted_raw_ostream &OS,
341                                    TargetMachine &TM,
342                                    bool Verbose) {
343       return new AsmPrinterImpl(OS, TM, TM.getTargetAsmInfo(), Verbose);
344     }
345   };
346
347   /// RegisterAsmParser - Helper template for registering a target specific asm
348   /// parser, for use in the target machine initialization function. Usage:
349   ///
350   /// extern "C" void LLVMInitializeFooAsmPrinter() {
351   ///   extern Target TheFooTarget;
352   ///   RegisterAsmPrinter<FooAsmPrinter> X(TheFooTarget);
353   /// }
354   template<class AsmParserImpl>
355   struct RegisterAsmParser {
356     RegisterAsmParser(Target &T) {
357       TargetRegistry::RegisterAsmParser(T, &Allocator);
358     }
359
360   private:
361     static TargetAsmParser *Allocator(const Target &T) {
362       return new AsmParserImpl(T);
363     }
364   };
365
366 }
367
368 #endif