]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/Driver/HostInfo.cpp
Update Clang sources to r73879.
[FreeBSD/FreeBSD.git] / lib / Driver / HostInfo.cpp
1 //===--- HostInfo.cpp - Host specific information -----------------------*-===//
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 #include "clang/Driver/HostInfo.h"
11
12 #include "clang/Driver/Arg.h"
13 #include "clang/Driver/ArgList.h"
14 #include "clang/Driver/Driver.h"
15 #include "clang/Driver/DriverDiagnostic.h"
16 #include "clang/Driver/Option.h"
17 #include "clang/Driver/Options.h"
18
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/Support/Compiler.h"
21
22 #include "ToolChains.h"
23
24 #include <cassert>
25  
26 using namespace clang::driver;
27
28 HostInfo::HostInfo(const Driver &D, const llvm::Triple &_Triple)
29   : TheDriver(D), Triple(_Triple)
30 {
31   
32 }
33
34 HostInfo::~HostInfo() {
35 }
36
37 namespace {
38
39 // Darwin Host Info
40
41 /// DarwinHostInfo - Darwin host information implementation.
42 class DarwinHostInfo : public HostInfo {
43   /// Darwin version of host.
44   unsigned DarwinVersion[3];
45
46   /// GCC version to use on this host.
47   unsigned GCCVersion[3];
48
49   /// Cache of tool chains we have created.
50   mutable llvm::StringMap<ToolChain *> ToolChains;
51
52 public:
53   DarwinHostInfo(const Driver &D, const llvm::Triple &Triple);
54   ~DarwinHostInfo();
55
56   virtual bool useDriverDriver() const;
57
58   virtual types::ID lookupTypeForExtension(const char *Ext) const {
59     types::ID Ty = types::lookupTypeForExtension(Ext);
60
61     // Darwin always preprocesses assembly files (unless -x is used
62     // explicitly).
63     if (Ty == types::TY_PP_Asm)
64       return types::TY_Asm;
65
66     return Ty;
67   }
68
69   virtual ToolChain *getToolChain(const ArgList &Args, 
70                                   const char *ArchName) const;
71 };
72
73 DarwinHostInfo::DarwinHostInfo(const Driver &D, const llvm::Triple& Triple)
74   : HostInfo(D, Triple) {
75   
76   assert((getArchName() == "i386" || getArchName() == "x86_64" || 
77           getArchName() == "powerpc" || getArchName() == "powerpc64" ||
78           getArchName() == "arm") &&
79          "Unknown Darwin arch.");
80
81   assert(memcmp(&getOSName()[0], "darwin", 6) == 0 &&
82          "Unknown Darwin platform.");
83   bool HadExtra;
84   if (!Driver::GetReleaseVersion(&getOSName()[6], 
85                                  DarwinVersion[0], DarwinVersion[1], 
86                                  DarwinVersion[2], HadExtra)) {
87     D.Diag(clang::diag::err_drv_invalid_darwin_version)
88       << getOSName();
89   }
90   
91   // We can only call 4.2.1 for now.
92   GCCVersion[0] = 4;
93   GCCVersion[1] = 2;
94   GCCVersion[2] = 1;
95 }
96
97 DarwinHostInfo::~DarwinHostInfo() {
98   for (llvm::StringMap<ToolChain*>::iterator
99          it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
100     delete it->second;
101 }
102
103 bool DarwinHostInfo::useDriverDriver() const { 
104   return true;
105 }
106
107 ToolChain *DarwinHostInfo::getToolChain(const ArgList &Args, 
108                                         const char *ArchName) const {
109   std::string Arch;
110   if (!ArchName) {
111     // If we aren't looking for a specific arch, infer the default architecture
112     // based on -arch and -m32/-m64 command line options.
113     if (Arg *A = Args.getLastArg(options::OPT_arch)) {
114       // The gcc driver behavior with multiple -arch flags wasn't consistent for
115       // things which rely on a default architecture. We just use the last -arch
116       // to find the default tool chain.
117       Arch = A->getValue(Args);
118       
119       // Normalize arch name; we shouldn't be doing this here.
120       //
121       // FIXME: This should be unnecessary once everything moves over to using
122       // the ID based Triple interface.
123       if (Arch == "ppc")
124         Arch = "powerpc";
125       else if (Arch == "ppc64")
126         Arch = "powerpc64";
127     } else {
128       // Otherwise default to the arch of the host.
129       Arch = getArchName();
130     }
131     ArchName = Arch.c_str();
132     
133     // Honor -m32 and -m64 when finding the default tool chain.
134     if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
135       if (Arch == "i386" || Arch == "x86_64") {
136         ArchName = (A->getOption().getId() == options::OPT_m32) ? "i386" : 
137           "x86_64";
138       } else if (Arch == "powerpc" || Arch == "powerpc64") {
139         ArchName = (A->getOption().getId() == options::OPT_m32) ? "powerpc" : 
140           "powerpc64";
141       }
142     } 
143   } else {
144     // Normalize arch name; we shouldn't be doing this here.
145     //
146     // FIXME: This should be unnecessary once everything moves over to using the
147     // ID based Triple interface.
148     if (strcmp(ArchName, "ppc") == 0)
149       ArchName = "powerpc";
150     else if (strcmp(ArchName, "ppc64") == 0)
151       ArchName = "powerpc64";
152   }
153
154   ToolChain *&TC = ToolChains[ArchName];
155   if (!TC) {
156     llvm::Triple TCTriple(getTriple());
157     TCTriple.setArchName(ArchName);
158                           
159     if (strcmp(ArchName, "i386") == 0 || strcmp(ArchName, "x86_64") == 0)
160       TC = new toolchains::Darwin_X86(*this, TCTriple,
161                                       DarwinVersion,
162                                       GCCVersion);
163     else
164       TC = new toolchains::Darwin_GCC(*this, TCTriple);
165   }
166
167   return TC;
168 }
169
170 // Unknown Host Info
171
172 /// UnknownHostInfo - Generic host information to use for unknown
173 /// hosts.
174 class UnknownHostInfo : public HostInfo {
175   /// Cache of tool chains we have created.
176   mutable llvm::StringMap<ToolChain*> ToolChains;
177
178 public:
179   UnknownHostInfo(const Driver &D, const llvm::Triple& Triple);
180   ~UnknownHostInfo();
181
182   virtual bool useDriverDriver() const;
183
184   virtual types::ID lookupTypeForExtension(const char *Ext) const {
185     return types::lookupTypeForExtension(Ext);
186   }
187
188   virtual ToolChain *getToolChain(const ArgList &Args, 
189                                   const char *ArchName) const;
190 };
191
192 UnknownHostInfo::UnknownHostInfo(const Driver &D, const llvm::Triple& Triple) 
193   : HostInfo(D, Triple) {
194 }
195
196 UnknownHostInfo::~UnknownHostInfo() {
197   for (llvm::StringMap<ToolChain*>::iterator
198          it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
199     delete it->second;
200 }
201
202 bool UnknownHostInfo::useDriverDriver() const { 
203   return false;
204 }
205
206 ToolChain *UnknownHostInfo::getToolChain(const ArgList &Args, 
207                                          const char *ArchName) const {
208   assert(!ArchName && 
209          "Unexpected arch name on platform without driver driver support.");
210   
211   // Automatically handle some instances of -m32/-m64 we know about.
212   std::string Arch = getArchName();
213   ArchName = Arch.c_str();
214   if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
215     if (Triple.getArch() == llvm::Triple::x86 ||
216         Triple.getArch() == llvm::Triple::x86_64) {
217       ArchName =
218         (A->getOption().getId() == options::OPT_m32) ? "i386" : "x86_64";
219     } else if (Triple.getArch() == llvm::Triple::ppc ||
220                Triple.getArch() == llvm::Triple::ppc64) {
221       ArchName =
222         (A->getOption().getId() == options::OPT_m32) ? "powerpc" : "powerpc64";
223     }
224   } 
225   
226   ToolChain *&TC = ToolChains[ArchName];
227   if (!TC) {
228     llvm::Triple TCTriple(getTriple());
229     TCTriple.setArchName(ArchName);
230
231     TC = new toolchains::Generic_GCC(*this, TCTriple);
232   }
233
234   return TC;
235 }
236
237 // FreeBSD Host Info
238
239 /// FreeBSDHostInfo -  FreeBSD host information implementation.
240 class FreeBSDHostInfo : public HostInfo {
241   /// Cache of tool chains we have created.
242   mutable llvm::StringMap<ToolChain*> ToolChains;
243
244 public:
245   FreeBSDHostInfo(const Driver &D, const llvm::Triple& Triple) 
246     : HostInfo(D, Triple) {}
247   ~FreeBSDHostInfo();
248
249   virtual bool useDriverDriver() const;
250
251   virtual types::ID lookupTypeForExtension(const char *Ext) const {
252     return types::lookupTypeForExtension(Ext);
253   }
254
255   virtual ToolChain *getToolChain(const ArgList &Args, 
256                                   const char *ArchName) const;
257 };
258
259 FreeBSDHostInfo::~FreeBSDHostInfo() {
260   for (llvm::StringMap<ToolChain*>::iterator
261          it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
262     delete it->second;
263 }
264
265 bool FreeBSDHostInfo::useDriverDriver() const { 
266   return false;
267 }
268
269 ToolChain *FreeBSDHostInfo::getToolChain(const ArgList &Args, 
270                                          const char *ArchName) const {
271   bool Lib32 = false;
272
273   assert(!ArchName && 
274          "Unexpected arch name on platform without driver driver support.");
275   
276   // On x86_64 we need to be able to compile 32-bits binaries as well.
277   // Compiling 64-bit binaries on i386 is not supported. We don't have a
278   // lib64.
279   std::string Arch = getArchName();
280   ArchName = Arch.c_str();
281   if (Args.hasArg(options::OPT_m32) && getArchName() == "x86_64") {
282     ArchName = "i386";
283     Lib32 = true;
284   } 
285   
286   ToolChain *&TC = ToolChains[ArchName];
287   if (!TC) {
288     llvm::Triple TCTriple(getTriple());
289     TCTriple.setArchName(ArchName);
290
291     TC = new toolchains::FreeBSD(*this, TCTriple, Lib32);
292   }
293
294   return TC;
295 }
296
297 // DragonFly Host Info
298
299 /// DragonFlyHostInfo -  DragonFly host information implementation.
300 class DragonFlyHostInfo : public HostInfo {
301   /// Cache of tool chains we have created.
302   mutable llvm::StringMap<ToolChain*> ToolChains;
303
304 public:
305   DragonFlyHostInfo(const Driver &D, const llvm::Triple& Triple)
306     : HostInfo(D, Triple) {}
307   ~DragonFlyHostInfo();
308
309   virtual bool useDriverDriver() const;
310
311   virtual types::ID lookupTypeForExtension(const char *Ext) const {
312     return types::lookupTypeForExtension(Ext);
313   }
314
315   virtual ToolChain *getToolChain(const ArgList &Args, 
316                                   const char *ArchName) const;
317 };
318
319 DragonFlyHostInfo::~DragonFlyHostInfo() {
320   for (llvm::StringMap<ToolChain*>::iterator
321          it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
322     delete it->second;
323 }
324
325 bool DragonFlyHostInfo::useDriverDriver() const { 
326   return false;
327 }
328
329 ToolChain *DragonFlyHostInfo::getToolChain(const ArgList &Args, 
330                                            const char *ArchName) const {
331   assert(!ArchName && 
332          "Unexpected arch name on platform without driver driver support.");
333
334   ToolChain *&TC = ToolChains[getArchName()];
335
336   if (!TC) {
337     llvm::Triple TCTriple(getTriple());
338     TCTriple.setArchName(getArchName());
339
340     TC = new toolchains::DragonFly(*this, TCTriple);
341   }
342
343   return TC;
344 }
345
346 // Linux Host Info
347
348 /// LinuxHostInfo -  Linux host information implementation.
349 class LinuxHostInfo : public HostInfo {
350   /// Cache of tool chains we have created.
351   mutable llvm::StringMap<ToolChain*> ToolChains;
352
353 public:
354   LinuxHostInfo(const Driver &D, const llvm::Triple& Triple)
355     : HostInfo(D, Triple) {}
356   ~LinuxHostInfo();
357
358   virtual bool useDriverDriver() const;
359
360   virtual types::ID lookupTypeForExtension(const char *Ext) const {
361     return types::lookupTypeForExtension(Ext);
362   }
363
364   virtual ToolChain *getToolChain(const ArgList &Args, 
365                                   const char *ArchName) const;
366 };
367
368 LinuxHostInfo::~LinuxHostInfo() {
369   for (llvm::StringMap<ToolChain*>::iterator
370          it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
371     delete it->second;
372 }
373
374 bool LinuxHostInfo::useDriverDriver() const { 
375   return false;
376 }
377
378 ToolChain *LinuxHostInfo::getToolChain(const ArgList &Args, 
379                                        const char *ArchName) const {
380
381   assert(!ArchName && 
382          "Unexpected arch name on platform without driver driver support.");
383
384   // Automatically handle some instances of -m32/-m64 we know about.
385   std::string Arch = getArchName();
386   ArchName = Arch.c_str();
387   if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
388     if (Triple.getArch() == llvm::Triple::x86 ||
389         Triple.getArch() == llvm::Triple::x86_64) {
390       ArchName =
391         (A->getOption().getId() == options::OPT_m32) ? "i386" : "x86_64";
392     } else if (Triple.getArch() == llvm::Triple::ppc ||
393                Triple.getArch() == llvm::Triple::ppc64) {
394       ArchName =
395         (A->getOption().getId() == options::OPT_m32) ? "powerpc" : "powerpc64";
396     }
397   }
398
399   ToolChain *&TC = ToolChains[ArchName];
400
401   if (!TC) {
402     llvm::Triple TCTriple(getTriple());
403     TCTriple.setArchName(ArchName);
404
405     TC = new toolchains::Linux(*this, TCTriple);
406   }
407
408   return TC;
409 }
410
411 }
412
413 const HostInfo *
414 clang::driver::createDarwinHostInfo(const Driver &D,
415                                     const llvm::Triple& Triple){
416   return new DarwinHostInfo(D, Triple);
417 }
418
419 const HostInfo *
420 clang::driver::createFreeBSDHostInfo(const Driver &D, 
421                                      const llvm::Triple& Triple) {
422   return new FreeBSDHostInfo(D, Triple);
423 }
424
425 const HostInfo *
426 clang::driver::createDragonFlyHostInfo(const Driver &D,
427                                        const llvm::Triple& Triple) {
428   return new DragonFlyHostInfo(D, Triple);
429 }
430
431 const HostInfo *
432 clang::driver::createLinuxHostInfo(const Driver &D,
433                                    const llvm::Triple& Triple) {
434   return new LinuxHostInfo(D, Triple);
435 }
436
437 const HostInfo *
438 clang::driver::createUnknownHostInfo(const Driver &D,
439                                      const llvm::Triple& Triple) {
440   return new UnknownHostInfo(D, Triple);
441 }