blob: 8c24a3c707b830ac5351536ef8b72f75b370974e [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(),
162 getOSName().c_str());
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000163 else
Daniel Dunbar8eddb3f2009-03-20 00:57:52 +0000164 TC = new toolchains::Darwin_GCC(*this, ArchName,
165 getPlatformName().c_str(),
166 getOSName().c_str());
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000167 }
168
169 return TC;
Daniel Dunbare3995642009-03-10 23:50:49 +0000170}
171
172// Unknown Host Info
173
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000174/// UnknownHostInfo - Generic host information to use for unknown
175/// hosts.
176class UnknownHostInfo : public HostInfo {
177 /// Cache of tool chains we have created.
178 mutable llvm::StringMap<ToolChain*> ToolChains;
179
180public:
Daniel Dunbare5049522009-03-17 20:45:45 +0000181 UnknownHostInfo(const Driver &D, const char *Arch,
182 const char *Platform, const char *OS);
Daniel Dunbar7e4534d2009-03-18 01:09:40 +0000183 ~UnknownHostInfo();
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000184
185 virtual bool useDriverDriver() const;
186
Daniel Dunbare33bea42009-03-20 23:39:23 +0000187 virtual types::ID lookupTypeForExtension(const char *Ext) const {
188 return types::lookupTypeForExtension(Ext);
189 }
190
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000191 virtual ToolChain *getToolChain(const ArgList &Args,
192 const char *ArchName) const;
193};
194
Daniel Dunbare5049522009-03-17 20:45:45 +0000195UnknownHostInfo::UnknownHostInfo(const Driver &D, const char *Arch,
196 const char *Platform, const char *OS)
197 : HostInfo(D, Arch, Platform, OS) {
Daniel Dunbare3995642009-03-10 23:50:49 +0000198}
199
Daniel Dunbar7e4534d2009-03-18 01:09:40 +0000200UnknownHostInfo::~UnknownHostInfo() {
201 for (llvm::StringMap<ToolChain*>::iterator
202 it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
203 delete it->second;
204}
205
Daniel Dunbare3995642009-03-10 23:50:49 +0000206bool UnknownHostInfo::useDriverDriver() const {
207 return false;
208}
209
210ToolChain *UnknownHostInfo::getToolChain(const ArgList &Args,
211 const char *ArchName) const {
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000212 assert(!ArchName &&
213 "Unexpected arch name on platform without driver driver support.");
214
215 // Automatically handle some instances of -m32/-m64 we know about.
216 ArchName = getArchName().c_str();
217 if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
218 if (getArchName() == "i386" || getArchName() == "x86_64") {
219 ArchName =
220 (A->getOption().getId() == options::OPT_m32) ? "i386" : "x86_64";
221 } else if (getArchName() == "ppc" || getArchName() == "ppc64") {
222 ArchName =
223 (A->getOption().getId() == options::OPT_m32) ? "ppc" : "ppc64";
224 }
225 }
226
227 ToolChain *&TC = ToolChains[ArchName];
228 if (!TC)
Daniel Dunbar83b08eb2009-03-17 21:38:00 +0000229 TC = new toolchains::Generic_GCC(*this, ArchName,
230 getPlatformName().c_str(),
231 getOSName().c_str());
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000232
Daniel Dunbarb25c7c12009-03-18 01:39:08 +0000233 return TC;
Daniel Dunbare3995642009-03-10 23:50:49 +0000234}
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000235
236}
237
Daniel Dunbare5049522009-03-17 20:45:45 +0000238const HostInfo *clang::driver::createDarwinHostInfo(const Driver &D,
239 const char *Arch,
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000240 const char *Platform,
241 const char *OS) {
Daniel Dunbare5049522009-03-17 20:45:45 +0000242 return new DarwinHostInfo(D, Arch, Platform, OS);
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000243}
244
Daniel Dunbare5049522009-03-17 20:45:45 +0000245const HostInfo *clang::driver::createUnknownHostInfo(const Driver &D,
246 const char *Arch,
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000247 const char *Platform,
248 const char *OS) {
Daniel Dunbare5049522009-03-17 20:45:45 +0000249 return new UnknownHostInfo(D, Arch, Platform, OS);
Daniel Dunbar1fd6c4b2009-03-17 19:00:50 +0000250}