blob: 8f762095b614b2e897154d4e1b6f0565336252b9 [file] [log] [blame]
Daniel Dunbare3995642009-03-10 23:50:49 +00001//===--- 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"
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +000011
12#include "clang/Driver/Arg.h"
13#include "clang/Driver/ArgList.h"
Daniel Dunbarfc6a8992009-03-20 18:21:51 +000014#include "clang/Driver/Driver.h"
15#include "clang/Driver/DriverDiagnostic.h"
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +000016#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
Daniel Dunbar83b08eb2009-03-17 21:38:00 +000022#include "ToolChains.h"
23
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +000024#include <cassert>
Daniel Dunbare3995642009-03-10 23:50:49 +000025
26using namespace clang::driver;
27
Daniel Dunbare5049522009-03-17 20:45:45 +000028HostInfo::HostInfo(const Driver &D, const char *_Arch, const char *_Platform,
Daniel Dunbare3995642009-03-10 23:50:49 +000029 const char *_OS)
Daniel Dunbare5049522009-03-17 20:45:45 +000030 : TheDriver(D), Arch(_Arch), Platform(_Platform), OS(_OS)
Daniel Dunbare3995642009-03-10 23:50:49 +000031{
32
33}
34
35HostInfo::~HostInfo() {
36}
37
Chris Lattneraae82f12009-03-17 22:24:01 +000038namespace {
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +000039
Daniel Dunbare3995642009-03-10 23:50:49 +000040// Darwin Host Info
41
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +000042/// DarwinHostInfo - Darwin host information implementation.
43class DarwinHostInfo : public HostInfo {
44 /// Darwin version of host.
45 unsigned DarwinVersion[3];
46
47 /// GCC version to use on this host.
48 unsigned GCCVersion[3];
49
50 /// Cache of tool chains we have created.
Daniel Dunbar7e4534d2009-03-18 01:09:40 +000051 mutable llvm::StringMap<ToolChain *> ToolChains;
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +000052
53public:
Daniel Dunbare5049522009-03-17 20:45:45 +000054 DarwinHostInfo(const Driver &D, const char *Arch,
55 const char *Platform, const char *OS);
Daniel Dunbar7e4534d2009-03-18 01:09:40 +000056 ~DarwinHostInfo();
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +000057
58 virtual bool useDriverDriver() const;
59
Daniel Dunbare33bea42009-03-20 23:39:23 +000060 virtual types::ID lookupTypeForExtension(const char *Ext) const {
61 types::ID Ty = types::lookupTypeForExtension(Ext);
62
63 // Darwin always preprocesses assembly files (unless -x is used
64 // explicitly).
65 if (Ty == types::TY_PP_Asm)
66 return types::TY_Asm;
67
68 return Ty;
69 }
70
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +000071 virtual ToolChain *getToolChain(const ArgList &Args,
72 const char *ArchName) const;
73};
74
Daniel Dunbarfc6a8992009-03-20 18:21:51 +000075/// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and
76/// return the grouped values as integers. Numbers which are not
77/// provided are set to 0.
78///
79/// \return True if the entire string was parsed (9.2), or all groups
80/// were parsed (10.3.5extrastuff).
81static bool GetReleaseVersion(const char *Str, unsigned &Major,
82 unsigned &Minor, unsigned &Micro) {
83 Major = Minor = Micro = 0;
84 if (*Str == '\0')
85 return true;
86
87 char *End;
88 Major = (unsigned) strtol(Str, &End, 10);
89 if (*Str != '\0' && *End == '\0')
90 return true;
91 if (*End != '.')
92 return false;
93
94 Str = End+1;
95 Minor = (unsigned) strtol(Str, &End, 10);
96 if (*Str != '\0' && *End == '\0')
97 return true;
98 if (*End != '.')
99 return false;
100
101 Str = End+1;
102 Micro = (unsigned) strtol(Str, &End, 10);
103 return true;
104}
105
Daniel Dunbare5049522009-03-17 20:45:45 +0000106DarwinHostInfo::DarwinHostInfo(const Driver &D, const char *_Arch,
107 const char *_Platform, const char *_OS)
108 : HostInfo(D, _Arch, _Platform, _OS) {
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000109
110 assert((getArchName() == "i386" || getArchName() == "x86_64" ||
111 getArchName() == "ppc" || getArchName() == "ppc64") &&
112 "Unknown Darwin arch.");
Daniel Dunbare3995642009-03-10 23:50:49 +0000113
Daniel Dunbarfc6a8992009-03-20 18:21:51 +0000114 assert(memcmp(&getOSName()[0], "darwin", 6) == 0 &&
115 "Unknown Darwin platform.");
116 const char *Release = &getOSName()[6];
117 if (!GetReleaseVersion(Release, DarwinVersion[0], DarwinVersion[1],
118 DarwinVersion[2])) {
119 D.Diag(clang::diag::err_drv_invalid_darwin_version)
120 << Release;
121 }
Daniel Dunbare3995642009-03-10 23:50:49 +0000122
123 // We can only call 4.2.1 for now.
124 GCCVersion[0] = 4;
125 GCCVersion[1] = 2;
126 GCCVersion[2] = 1;
127}
128
Daniel Dunbar7e4534d2009-03-18 01:09:40 +0000129DarwinHostInfo::~DarwinHostInfo() {
130 for (llvm::StringMap<ToolChain*>::iterator
131 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
132 delete it->second;
133}
134
Daniel Dunbare3995642009-03-10 23:50:49 +0000135bool DarwinHostInfo::useDriverDriver() const {
136 return true;
137}
138
139ToolChain *DarwinHostInfo::getToolChain(const ArgList &Args,
140 const char *ArchName) const {
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000141 if (!ArchName) {
142 ArchName = getArchName().c_str();
143
144 // If no arch name is specified, infer it from the host and
145 // -m32/-m64.
146 if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
147 if (getArchName() == "i386" || getArchName() == "x86_64") {
148 ArchName =
149 (A->getOption().getId() == options::OPT_m32) ? "i386" : "x86_64";
150 } else if (getArchName() == "ppc" || getArchName() == "ppc64") {
151 ArchName =
152 (A->getOption().getId() == options::OPT_m32) ? "ppc" : "ppc64";
153 }
154 }
155 }
156
157 ToolChain *&TC = ToolChains[ArchName];
158 if (!TC) {
Daniel Dunbar83b08eb2009-03-17 21:38:00 +0000159 if (strcmp(ArchName, "i386") == 0 || strcmp(ArchName, "x86_64") == 0)
Daniel Dunbar8eddb3f2009-03-20 00:57:52 +0000160 TC = new toolchains::Darwin_X86(*this, ArchName,
161 getPlatformName().c_str(),
Daniel Dunbarc50b00d2009-03-23 16:15:50 +0000162 getOSName().c_str(),
163 DarwinVersion,
164 GCCVersion);
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000165 else
Daniel Dunbar8eddb3f2009-03-20 00:57:52 +0000166 TC = new toolchains::Darwin_GCC(*this, ArchName,
167 getPlatformName().c_str(),
168 getOSName().c_str());
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000169 }
170
171 return TC;
Daniel Dunbare3995642009-03-10 23:50:49 +0000172}
173
174// Unknown Host Info
175
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000176/// UnknownHostInfo - Generic host information to use for unknown
177/// hosts.
178class UnknownHostInfo : public HostInfo {
179 /// Cache of tool chains we have created.
180 mutable llvm::StringMap<ToolChain*> ToolChains;
181
182public:
Daniel Dunbare5049522009-03-17 20:45:45 +0000183 UnknownHostInfo(const Driver &D, const char *Arch,
184 const char *Platform, const char *OS);
Daniel Dunbar7e4534d2009-03-18 01:09:40 +0000185 ~UnknownHostInfo();
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000186
187 virtual bool useDriverDriver() const;
188
Daniel Dunbare33bea42009-03-20 23:39:23 +0000189 virtual types::ID lookupTypeForExtension(const char *Ext) const {
190 return types::lookupTypeForExtension(Ext);
191 }
192
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000193 virtual ToolChain *getToolChain(const ArgList &Args,
194 const char *ArchName) const;
195};
196
Daniel Dunbare5049522009-03-17 20:45:45 +0000197UnknownHostInfo::UnknownHostInfo(const Driver &D, const char *Arch,
198 const char *Platform, const char *OS)
199 : HostInfo(D, Arch, Platform, OS) {
Daniel Dunbare3995642009-03-10 23:50:49 +0000200}
201
Daniel Dunbar7e4534d2009-03-18 01:09:40 +0000202UnknownHostInfo::~UnknownHostInfo() {
203 for (llvm::StringMap<ToolChain*>::iterator
204 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
205 delete it->second;
206}
207
Daniel Dunbare3995642009-03-10 23:50:49 +0000208bool UnknownHostInfo::useDriverDriver() const {
209 return false;
210}
211
212ToolChain *UnknownHostInfo::getToolChain(const ArgList &Args,
213 const char *ArchName) const {
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000214 assert(!ArchName &&
215 "Unexpected arch name on platform without driver driver support.");
216
217 // Automatically handle some instances of -m32/-m64 we know about.
218 ArchName = getArchName().c_str();
219 if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
220 if (getArchName() == "i386" || getArchName() == "x86_64") {
221 ArchName =
222 (A->getOption().getId() == options::OPT_m32) ? "i386" : "x86_64";
223 } else if (getArchName() == "ppc" || getArchName() == "ppc64") {
224 ArchName =
225 (A->getOption().getId() == options::OPT_m32) ? "ppc" : "ppc64";
226 }
227 }
228
229 ToolChain *&TC = ToolChains[ArchName];
230 if (!TC)
Daniel Dunbar83b08eb2009-03-17 21:38:00 +0000231 TC = new toolchains::Generic_GCC(*this, ArchName,
232 getPlatformName().c_str(),
233 getOSName().c_str());
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000234
Daniel Dunbarb25c7c12009-03-18 01:39:08 +0000235 return TC;
Daniel Dunbare3995642009-03-10 23:50:49 +0000236}
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000237
238}
239
Daniel Dunbare5049522009-03-17 20:45:45 +0000240const HostInfo *clang::driver::createDarwinHostInfo(const Driver &D,
241 const char *Arch,
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000242 const char *Platform,
243 const char *OS) {
Daniel Dunbare5049522009-03-17 20:45:45 +0000244 return new DarwinHostInfo(D, Arch, Platform, OS);
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000245}
246
Daniel Dunbare5049522009-03-17 20:45:45 +0000247const HostInfo *clang::driver::createUnknownHostInfo(const Driver &D,
248 const char *Arch,
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000249 const char *Platform,
250 const char *OS) {
Daniel Dunbare5049522009-03-17 20:45:45 +0000251 return new UnknownHostInfo(D, Arch, Platform, OS);
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000252}