ToolChains.cpp revision ec069ed8a6647d84cc3a58d46d5b2a3c9f000704
1//===--- ToolChains.cpp - ToolChain Implementations ---------------------*-===// 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 "ToolChains.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/HostInfo.h" 17#include "clang/Driver/Option.h" 18 19#include "llvm/ADT/StringExtras.h" 20#include "llvm/Support/raw_ostream.h" 21#include "llvm/System/Path.h" 22 23using namespace clang::driver; 24using namespace clang::driver::toolchains; 25 26/// Darwin_X86 - Darwin tool chain for i386 and x86_64. 27 28Darwin_X86::Darwin_X86(const HostInfo &Host, const char *Arch, 29 const char *Platform, const char *OS, 30 const unsigned (&_DarwinVersion)[3], 31 const unsigned (&_GCCVersion)[3]) 32 : ToolChain(Host, Arch, Platform, OS) 33{ 34 DarwinVersion[0] = _DarwinVersion[0]; 35 DarwinVersion[1] = _DarwinVersion[1]; 36 DarwinVersion[2] = _DarwinVersion[2]; 37 GCCVersion[0] = _GCCVersion[0]; 38 GCCVersion[1] = _GCCVersion[1]; 39 GCCVersion[2] = _GCCVersion[2]; 40 41 ToolChainDir = "i686-apple-darwin"; 42 ToolChainDir += llvm::utostr(DarwinVersion[0]); 43 ToolChainDir += "/"; 44 ToolChainDir += llvm::utostr(GCCVersion[0]); 45 ToolChainDir += '.'; 46 ToolChainDir += llvm::utostr(GCCVersion[1]); 47 ToolChainDir += '.'; 48 ToolChainDir += llvm::utostr(GCCVersion[2]); 49 50 std::string Path; 51 if (getArchName() == "x86_64") { 52 Path = getHost().getDriver().Dir; 53 Path += "/../lib/gcc/"; 54 Path += getToolChainDir(); 55 Path += "/x86_64"; 56 getFilePaths().push_back(Path); 57 58 Path = "/usr/lib/gcc/"; 59 Path += getToolChainDir(); 60 Path += "/x86_64"; 61 getFilePaths().push_back(Path); 62 } 63 64 Path = getHost().getDriver().Dir; 65 Path += "/../lib/gcc/"; 66 Path += getToolChainDir(); 67 getFilePaths().push_back(Path); 68 69 Path = "/usr/lib/gcc/"; 70 Path += getToolChainDir(); 71 getFilePaths().push_back(Path); 72 73 Path = getHost().getDriver().Dir; 74 Path += "/../libexec/gcc/"; 75 Path += getToolChainDir(); 76 getProgramPaths().push_back(Path); 77 78 Path = "/usr/libexec/gcc/"; 79 Path += getToolChainDir(); 80 getProgramPaths().push_back(Path); 81 82 Path = getHost().getDriver().Dir; 83 Path += "/../libexec"; 84 getProgramPaths().push_back(Path); 85 86 getProgramPaths().push_back(getHost().getDriver().Dir); 87} 88 89Darwin_X86::~Darwin_X86() { 90 // Free tool implementations. 91 for (llvm::DenseMap<unsigned, Tool*>::iterator 92 it = Tools.begin(), ie = Tools.end(); it != ie; ++it) 93 delete it->second; 94} 95 96std::string Darwin_X86::getMacosxVersionMin() const { 97 std::string Res; 98 llvm::raw_string_ostream OS(Res); 99 OS << "10." << DarwinVersion[0] - 4 << '.' << DarwinVersion[1]; 100 return OS.str(); 101} 102 103Tool &Darwin_X86::SelectTool(const Compilation &C, 104 const JobAction &JA) const { 105 Action::ActionClass Key; 106 if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName())) 107 Key = Action::AnalyzeJobClass; 108 else 109 Key = JA.getKind(); 110 111 Tool *&T = Tools[Key]; 112 if (!T) { 113 switch (Key) { 114 case Action::InputClass: 115 case Action::BindArchClass: 116 assert(0 && "Invalid tool kind."); 117 case Action::PreprocessJobClass: 118 T = new tools::gcc::Preprocess(*this); break; 119 case Action::PrecompileJobClass: 120 T = new tools::gcc::Precompile(*this); break; 121 case Action::AnalyzeJobClass: 122 T = new tools::Clang(*this); break; 123 case Action::CompileJobClass: 124 T = new tools::gcc::Compile(*this); break; 125 case Action::AssembleJobClass: 126 T = new tools::darwin::Assemble(*this); break; 127 case Action::LinkJobClass: 128 T = new tools::gcc::Link(*this); break; 129 case Action::LipoJobClass: 130 T = new tools::darwin::Lipo(*this); break; 131 } 132 } 133 134 return *T; 135} 136 137DerivedArgList *Darwin_X86::TranslateArgs(InputArgList &Args) const { 138 DerivedArgList *DAL = new DerivedArgList(Args, false); 139 const OptTable &Opts = getHost().getDriver().getOpts(); 140 141 // FIXME: We really want to get out of the tool chain level argument 142 // translation business, as it makes the driver functionality much 143 // more opaque. For now, we follow gcc closely solely for the 144 // purpose of easily achieving feature parity & testability. Once we 145 // have something that works, we should reevaluate each translation 146 // and try to push it down into tool specific logic. 147 148 if (!Args.hasArg(options::OPT_mmacosx_version_min_EQ, false)) { 149 const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ); 150 DAL->append(DAL->MakeJoinedArg(O, getMacosxVersionMin().c_str())); 151 } 152 153 for (ArgList::iterator it = Args.begin(), ie = Args.end(); it != ie; ++it) { 154 Arg *A = *it; 155 156 if (A->getOption().matches(options::OPT_Xarch__)) { 157 // FIXME: Canonicalize name. 158 if (getArchName() != A->getValue(Args, 0)) 159 continue; 160 161 // FIXME: The arg is leaked here, and we should have a nicer 162 // interface for this. 163 unsigned Prev, Index = Prev = A->getIndex() + 1; 164 Arg *XarchArg = Opts.ParseOneArg(Args, Index); 165 166 // If the argument parsing failed or more than one argument was 167 // consumed, the -Xarch_ argument's parameter tried to consume 168 // extra arguments. Emit an error and ignore. 169 // 170 // We also want to disallow any options which would alter the 171 // driver behavior; that isn't going to work in our model. We 172 // use isDriverOption() as an approximation, although things 173 // like -O4 are going to slip through. 174 if (!XarchArg || Index > Prev + 1 || 175 XarchArg->getOption().isDriverOption()) { 176 getHost().getDriver().Diag(clang::diag::err_drv_invalid_Xarch_argument) 177 << A->getAsString(Args); 178 continue; 179 } 180 181 A = XarchArg; 182 } 183 184 // Sob. These is strictly gcc compatible for the time being. Apple 185 // gcc translates options twice, which means that self-expanding 186 // options add duplicates. 187 options::ID id = A->getOption().getId(); 188 switch (id) { 189 default: 190 DAL->append(A); 191 break; 192 193 case options::OPT_mkernel: 194 case options::OPT_fapple_kext: 195 DAL->append(A); 196 DAL->append(DAL->MakeFlagArg(Opts.getOption(options::OPT_static))); 197 DAL->append(DAL->MakeFlagArg(Opts.getOption(options::OPT_static))); 198 break; 199 200 case options::OPT_dependency_file: 201 DAL->append(DAL->MakeSeparateArg(Opts.getOption(options::OPT_MF), 202 A->getValue(Args))); 203 break; 204 205 case options::OPT_gfull: 206 DAL->append(DAL->MakeFlagArg(Opts.getOption(options::OPT_g_Flag))); 207 DAL->append(DAL->MakeFlagArg( 208 Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols))); 209 break; 210 211 case options::OPT_gused: 212 DAL->append(DAL->MakeFlagArg(Opts.getOption(options::OPT_g_Flag))); 213 DAL->append(DAL->MakeFlagArg( 214 Opts.getOption(options::OPT_feliminate_unused_debug_symbols))); 215 break; 216 217 case options::OPT_fterminated_vtables: 218 case options::OPT_findirect_virtual_calls: 219 DAL->append(DAL->MakeFlagArg(Opts.getOption(options::OPT_fapple_kext))); 220 DAL->append(DAL->MakeFlagArg(Opts.getOption(options::OPT_static))); 221 break; 222 223 case options::OPT_shared: 224 DAL->append(DAL->MakeFlagArg(Opts.getOption(options::OPT_dynamiclib))); 225 break; 226 227 case options::OPT_fconstant_cfstrings: 228 DAL->append(DAL->MakeFlagArg( 229 Opts.getOption(options::OPT_mconstant_cfstrings))); 230 break; 231 232 case options::OPT_fno_constant_cfstrings: 233 DAL->append(DAL->MakeFlagArg( 234 Opts.getOption(options::OPT_mno_constant_cfstrings))); 235 break; 236 237 case options::OPT_Wnonportable_cfstrings: 238 DAL->append(DAL->MakeFlagArg( 239 Opts.getOption(options::OPT_mwarn_nonportable_cfstrings))); 240 break; 241 242 case options::OPT_Wno_nonportable_cfstrings: 243 DAL->append(DAL->MakeFlagArg( 244 Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings))); 245 break; 246 247 case options::OPT_fpascal_strings: 248 DAL->append(DAL->MakeFlagArg( 249 Opts.getOption(options::OPT_mpascal_strings))); 250 break; 251 252 case options::OPT_fno_pascal_strings: 253 DAL->append(DAL->MakeFlagArg( 254 Opts.getOption(options::OPT_mno_pascal_strings))); 255 break; 256 } 257 } 258 259 // FIXME: Actually, gcc always adds this, but it is filtered for 260 // duplicates somewhere. This also changes the order of things, so 261 // look it up. 262 if (getArchName() == "x86_64") 263 if (!Args.hasArg(options::OPT_m64, false)) 264 DAL->append(DAL->MakeFlagArg(Opts.getOption(options::OPT_m64))); 265 266 if (!Args.hasArg(options::OPT_mtune_EQ, false)) 267 DAL->append(DAL->MakeJoinedArg(Opts.getOption(options::OPT_mtune_EQ), 268 "core2")); 269 270 return DAL; 271} 272 273bool Darwin_X86::IsMathErrnoDefault() const { 274 return false; 275} 276 277bool Darwin_X86::IsUnwindTablesDefault() const { 278 // FIXME: Gross; we should probably have some separate target 279 // definition, possibly even reusing the one in clang. 280 return getArchName() == "x86_64"; 281} 282 283const char *Darwin_X86::GetDefaultRelocationModel() const { 284 return "pic"; 285} 286 287const char *Darwin_X86::GetForcedPicModel() const { 288 if (getArchName() == "x86_64") 289 return "pic"; 290 return 0; 291} 292 293/// Generic_GCC - A tool chain using the 'gcc' command to perform 294/// all subcommands; this relies on gcc translating the majority of 295/// command line options. 296 297Generic_GCC::Generic_GCC(const HostInfo &Host, const char *Arch, 298 const char *Platform, const char *OS) 299 : ToolChain(Host, Arch, Platform, OS) 300{ 301 std::string Path(getHost().getDriver().Dir); 302 Path += "/../libexec"; 303 getProgramPaths().push_back(Path); 304 305 getProgramPaths().push_back(getHost().getDriver().Dir); 306} 307 308Generic_GCC::~Generic_GCC() { 309 // Free tool implementations. 310 for (llvm::DenseMap<unsigned, Tool*>::iterator 311 it = Tools.begin(), ie = Tools.end(); it != ie; ++it) 312 delete it->second; 313} 314 315Tool &Generic_GCC::SelectTool(const Compilation &C, 316 const JobAction &JA) const { 317 Action::ActionClass Key; 318 if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName())) 319 Key = Action::AnalyzeJobClass; 320 else 321 Key = JA.getKind(); 322 323 Tool *&T = Tools[Key]; 324 if (!T) { 325 switch (Key) { 326 case Action::InputClass: 327 case Action::BindArchClass: 328 assert(0 && "Invalid tool kind."); 329 case Action::PreprocessJobClass: 330 T = new tools::gcc::Preprocess(*this); break; 331 case Action::PrecompileJobClass: 332 T = new tools::gcc::Precompile(*this); break; 333 case Action::AnalyzeJobClass: 334 T = new tools::Clang(*this); break; 335 case Action::CompileJobClass: 336 T = new tools::gcc::Compile(*this); break; 337 case Action::AssembleJobClass: 338 T = new tools::gcc::Assemble(*this); break; 339 case Action::LinkJobClass: 340 T = new tools::gcc::Link(*this); break; 341 342 // This is a bit ungeneric, but the only platform using a driver 343 // driver is Darwin. 344 case Action::LipoJobClass: 345 T = new tools::darwin::Lipo(*this); break; 346 } 347 } 348 349 return *T; 350} 351 352bool Generic_GCC::IsMathErrnoDefault() const { 353 return true; 354} 355 356bool Generic_GCC::IsUnwindTablesDefault() const { 357 // FIXME: Gross; we should probably have some separate target 358 // definition, possibly even reusing the one in clang. 359 return getArchName() == "x86_64"; 360} 361 362const char *Generic_GCC::GetDefaultRelocationModel() const { 363 return "static"; 364} 365 366const char *Generic_GCC::GetForcedPicModel() const { 367 return 0; 368} 369 370DerivedArgList *Generic_GCC::TranslateArgs(InputArgList &Args) const { 371 return new DerivedArgList(Args, true); 372} 373