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 23#include <cstdlib> // ::getenv 24 25using namespace clang::driver; 26using namespace clang::driver::toolchains; 27 28/// Darwin_X86 - Darwin tool chain for i386 and x86_64. 29 30Darwin_X86::Darwin_X86(const HostInfo &Host, const llvm::Triple& Triple, 31 const unsigned (&_DarwinVersion)[3], 32 const unsigned (&_GCCVersion)[3]) 33 : ToolChain(Host, Triple) { 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 llvm::raw_string_ostream(MacosxVersionMin) 42 << "10." << DarwinVersion[0] - 4 << '.' << DarwinVersion[1]; 43 44 ToolChainDir = "i686-apple-darwin"; 45 ToolChainDir += llvm::utostr(DarwinVersion[0]); 46 ToolChainDir += "/"; 47 ToolChainDir += llvm::utostr(GCCVersion[0]); 48 ToolChainDir += '.'; 49 ToolChainDir += llvm::utostr(GCCVersion[1]); 50 ToolChainDir += '.'; 51 ToolChainDir += llvm::utostr(GCCVersion[2]); 52 53 std::string Path; 54 if (getArchName() == "x86_64") { 55 Path = getHost().getDriver().Dir; 56 Path += "/../lib/gcc/"; 57 Path += getToolChainDir(); 58 Path += "/x86_64"; 59 getFilePaths().push_back(Path); 60 61 Path = "/usr/lib/gcc/"; 62 Path += getToolChainDir(); 63 Path += "/x86_64"; 64 getFilePaths().push_back(Path); 65 } 66 67 Path = getHost().getDriver().Dir; 68 Path += "/../lib/gcc/"; 69 Path += getToolChainDir(); 70 getFilePaths().push_back(Path); 71 72 Path = "/usr/lib/gcc/"; 73 Path += getToolChainDir(); 74 getFilePaths().push_back(Path); 75 76 Path = getHost().getDriver().Dir; 77 Path += "/../libexec/gcc/"; 78 Path += getToolChainDir(); 79 getProgramPaths().push_back(Path); 80 81 Path = "/usr/libexec/gcc/"; 82 Path += getToolChainDir(); 83 getProgramPaths().push_back(Path); 84 85 Path = getHost().getDriver().Dir; 86 Path += "/../libexec"; 87 getProgramPaths().push_back(Path); 88 89 getProgramPaths().push_back(getHost().getDriver().Dir); 90} 91 92Darwin_X86::~Darwin_X86() { 93 // Free tool implementations. 94 for (llvm::DenseMap<unsigned, Tool*>::iterator 95 it = Tools.begin(), ie = Tools.end(); it != ie; ++it) 96 delete it->second; 97} 98 99Tool &Darwin_X86::SelectTool(const Compilation &C, 100 const JobAction &JA) const { 101 Action::ActionClass Key; 102 if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName())) 103 Key = Action::AnalyzeJobClass; 104 else 105 Key = JA.getKind(); 106 107 Tool *&T = Tools[Key]; 108 if (!T) { 109 switch (Key) { 110 case Action::InputClass: 111 case Action::BindArchClass: 112 assert(0 && "Invalid tool kind."); 113 case Action::PreprocessJobClass: 114 T = new tools::darwin::Preprocess(*this); break; 115 case Action::AnalyzeJobClass: 116 T = new tools::Clang(*this); break; 117 case Action::PrecompileJobClass: 118 case Action::CompileJobClass: 119 T = new tools::darwin::Compile(*this); break; 120 case Action::AssembleJobClass: 121 T = new tools::darwin::Assemble(*this); break; 122 case Action::LinkJobClass: 123 T = new tools::darwin::Link(*this, MacosxVersionMin.c_str()); break; 124 case Action::LipoJobClass: 125 T = new tools::darwin::Lipo(*this); break; 126 } 127 } 128 129 return *T; 130} 131 132DerivedArgList *Darwin_X86::TranslateArgs(InputArgList &Args) const { 133 DerivedArgList *DAL = new DerivedArgList(Args, false); 134 const OptTable &Opts = getHost().getDriver().getOpts(); 135 136 // FIXME: We really want to get out of the tool chain level argument 137 // translation business, as it makes the driver functionality much 138 // more opaque. For now, we follow gcc closely solely for the 139 // purpose of easily achieving feature parity & testability. Once we 140 // have something that works, we should reevaluate each translation 141 // and try to push it down into tool specific logic. 142 143 Arg *OSXVersion = 144 Args.getLastArg(options::OPT_mmacosx_version_min_EQ, false); 145 Arg *iPhoneVersion = 146 Args.getLastArg(options::OPT_miphoneos_version_min_EQ, false); 147 if (OSXVersion && iPhoneVersion) { 148 getHost().getDriver().Diag(clang::diag::err_drv_argument_not_allowed_with) 149 << OSXVersion->getAsString(Args) 150 << iPhoneVersion->getAsString(Args); 151 } else if (!OSXVersion && !iPhoneVersion) { 152 // Chose the default version based on the arch. 153 // 154 // FIXME: This will need to be fixed when we merge in arm support. 155 156 // Look for MACOSX_DEPLOYMENT_TARGET, otherwise use the version 157 // from the host. 158 const char *Version = ::getenv("MACOSX_DEPLOYMENT_TARGET"); 159 if (!Version) 160 Version = MacosxVersionMin.c_str(); 161 const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ); 162 DAL->append(DAL->MakeJoinedArg(0, O, Version)); 163 } 164 165 for (ArgList::iterator it = Args.begin(), ie = Args.end(); it != ie; ++it) { 166 Arg *A = *it; 167 168 if (A->getOption().matches(options::OPT_Xarch__)) { 169 // FIXME: Canonicalize name. 170 if (getArchName() != A->getValue(Args, 0)) 171 continue; 172 173 // FIXME: The arg is leaked here, and we should have a nicer 174 // interface for this. 175 unsigned Prev, Index = Prev = A->getIndex() + 1; 176 Arg *XarchArg = Opts.ParseOneArg(Args, Index); 177 178 // If the argument parsing failed or more than one argument was 179 // consumed, the -Xarch_ argument's parameter tried to consume 180 // extra arguments. Emit an error and ignore. 181 // 182 // We also want to disallow any options which would alter the 183 // driver behavior; that isn't going to work in our model. We 184 // use isDriverOption() as an approximation, although things 185 // like -O4 are going to slip through. 186 if (!XarchArg || Index > Prev + 1 || 187 XarchArg->getOption().isDriverOption()) { 188 getHost().getDriver().Diag(clang::diag::err_drv_invalid_Xarch_argument) 189 << A->getAsString(Args); 190 continue; 191 } 192 193 XarchArg->setBaseArg(A); 194 A = XarchArg; 195 } 196 197 // Sob. These is strictly gcc compatible for the time being. Apple 198 // gcc translates options twice, which means that self-expanding 199 // options add duplicates. 200 options::ID id = A->getOption().getId(); 201 switch (id) { 202 default: 203 DAL->append(A); 204 break; 205 206 case options::OPT_mkernel: 207 case options::OPT_fapple_kext: 208 DAL->append(A); 209 DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_static))); 210 DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_static))); 211 break; 212 213 case options::OPT_dependency_file: 214 DAL->append(DAL->MakeSeparateArg(A, Opts.getOption(options::OPT_MF), 215 A->getValue(Args))); 216 break; 217 218 case options::OPT_gfull: 219 DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_g_Flag))); 220 DAL->append(DAL->MakeFlagArg(A, 221 Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols))); 222 break; 223 224 case options::OPT_gused: 225 DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_g_Flag))); 226 DAL->append(DAL->MakeFlagArg(A, 227 Opts.getOption(options::OPT_feliminate_unused_debug_symbols))); 228 break; 229 230 case options::OPT_fterminated_vtables: 231 case options::OPT_findirect_virtual_calls: 232 DAL->append(DAL->MakeFlagArg(A, 233 Opts.getOption(options::OPT_fapple_kext))); 234 DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_static))); 235 break; 236 237 case options::OPT_shared: 238 DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_dynamiclib))); 239 break; 240 241 case options::OPT_fconstant_cfstrings: 242 DAL->append(DAL->MakeFlagArg(A, 243 Opts.getOption(options::OPT_mconstant_cfstrings))); 244 break; 245 246 case options::OPT_fno_constant_cfstrings: 247 DAL->append(DAL->MakeFlagArg(A, 248 Opts.getOption(options::OPT_mno_constant_cfstrings))); 249 break; 250 251 case options::OPT_Wnonportable_cfstrings: 252 DAL->append(DAL->MakeFlagArg(A, 253 Opts.getOption(options::OPT_mwarn_nonportable_cfstrings))); 254 break; 255 256 case options::OPT_Wno_nonportable_cfstrings: 257 DAL->append(DAL->MakeFlagArg(A, 258 Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings))); 259 break; 260 261 case options::OPT_fpascal_strings: 262 DAL->append(DAL->MakeFlagArg(A, 263 Opts.getOption(options::OPT_mpascal_strings))); 264 break; 265 266 case options::OPT_fno_pascal_strings: 267 DAL->append(DAL->MakeFlagArg(A, 268 Opts.getOption(options::OPT_mno_pascal_strings))); 269 break; 270 } 271 } 272 273 // FIXME: Actually, gcc always adds this, but it is filtered for 274 // duplicates somewhere. This also changes the order of things, so 275 // look it up. 276 if (getArchName() == "x86_64") 277 if (!Args.hasArg(options::OPT_m64, false)) 278 DAL->append(DAL->MakeFlagArg(0, Opts.getOption(options::OPT_m64))); 279 280 if (!Args.hasArg(options::OPT_mtune_EQ, false)) 281 DAL->append(DAL->MakeJoinedArg(0, Opts.getOption(options::OPT_mtune_EQ), 282 "core2")); 283 284 return DAL; 285} 286 287bool Darwin_X86::IsMathErrnoDefault() const { 288 return false; 289} 290 291bool Darwin_X86::IsUnwindTablesDefault() const { 292 // FIXME: Gross; we should probably have some separate target 293 // definition, possibly even reusing the one in clang. 294 return getArchName() == "x86_64"; 295} 296 297const char *Darwin_X86::GetDefaultRelocationModel() const { 298 return "pic"; 299} 300 301const char *Darwin_X86::GetForcedPicModel() const { 302 if (getArchName() == "x86_64") 303 return "pic"; 304 return 0; 305} 306 307/// Generic_GCC - A tool chain using the 'gcc' command to perform 308/// all subcommands; this relies on gcc translating the majority of 309/// command line options. 310 311Generic_GCC::Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple) 312 : ToolChain(Host, Triple) 313{ 314 std::string Path(getHost().getDriver().Dir); 315 Path += "/../libexec"; 316 getProgramPaths().push_back(Path); 317 318 getProgramPaths().push_back(getHost().getDriver().Dir); 319} 320 321Generic_GCC::~Generic_GCC() { 322 // Free tool implementations. 323 for (llvm::DenseMap<unsigned, Tool*>::iterator 324 it = Tools.begin(), ie = Tools.end(); it != ie; ++it) 325 delete it->second; 326} 327 328Tool &Generic_GCC::SelectTool(const Compilation &C, 329 const JobAction &JA) const { 330 Action::ActionClass Key; 331 if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName())) 332 Key = Action::AnalyzeJobClass; 333 else 334 Key = JA.getKind(); 335 336 Tool *&T = Tools[Key]; 337 if (!T) { 338 switch (Key) { 339 case Action::InputClass: 340 case Action::BindArchClass: 341 assert(0 && "Invalid tool kind."); 342 case Action::PreprocessJobClass: 343 T = new tools::gcc::Preprocess(*this); break; 344 case Action::PrecompileJobClass: 345 T = new tools::gcc::Precompile(*this); break; 346 case Action::AnalyzeJobClass: 347 T = new tools::Clang(*this); break; 348 case Action::CompileJobClass: 349 T = new tools::gcc::Compile(*this); break; 350 case Action::AssembleJobClass: 351 T = new tools::gcc::Assemble(*this); break; 352 case Action::LinkJobClass: 353 T = new tools::gcc::Link(*this); break; 354 355 // This is a bit ungeneric, but the only platform using a driver 356 // driver is Darwin. 357 case Action::LipoJobClass: 358 T = new tools::darwin::Lipo(*this); break; 359 } 360 } 361 362 return *T; 363} 364 365bool Generic_GCC::IsMathErrnoDefault() const { 366 return true; 367} 368 369bool Generic_GCC::IsUnwindTablesDefault() const { 370 // FIXME: Gross; we should probably have some separate target 371 // definition, possibly even reusing the one in clang. 372 return getArchName() == "x86_64"; 373} 374 375const char *Generic_GCC::GetDefaultRelocationModel() const { 376 return "static"; 377} 378 379const char *Generic_GCC::GetForcedPicModel() const { 380 return 0; 381} 382 383DerivedArgList *Generic_GCC::TranslateArgs(InputArgList &Args) const { 384 return new DerivedArgList(Args, true); 385} 386
|
417/// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly. 418 419FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple, bool Lib32) 420 : Generic_GCC(Host, Triple) { 421 if (Lib32) { 422 getFilePaths().push_back(getHost().getDriver().Dir + "/../lib32"); 423 getFilePaths().push_back("/usr/lib32"); 424 } else { 425 getFilePaths().push_back(getHost().getDriver().Dir + "/../lib"); 426 getFilePaths().push_back("/usr/lib"); 427 } 428} 429 430Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA) const { 431 Action::ActionClass Key; 432 if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName())) 433 Key = Action::AnalyzeJobClass; 434 else 435 Key = JA.getKind(); 436 437 Tool *&T = Tools[Key]; 438 if (!T) { 439 switch (Key) { 440 case Action::AssembleJobClass: 441 T = new tools::freebsd::Assemble(*this); break; 442 case Action::LinkJobClass: 443 T = new tools::freebsd::Link(*this); break; 444 default: 445 T = &Generic_GCC::SelectTool(C, JA); 446 } 447 } 448 449 return *T; 450} 451 452/// Linux toolchain (very bare-bones at the moment). 453 454Linux::Linux(const HostInfo &Host, const llvm::Triple& Triple) 455 : Generic_GCC(Host, Triple) { 456 getFilePaths().push_back(getHost().getDriver().Dir + "/../lib/clang/1.0/"); 457 getFilePaths().push_back("/lib/"); 458 getFilePaths().push_back("/usr/lib/"); 459 // FIXME: Figure out some way to get gcc's libdir 460 // (e.g. /usr/lib/gcc/i486-linux-gnu/4.3/ for Ubuntu 32-bit); we need 461 // crtbegin.o/crtend.o/etc., and want static versions of various 462 // libraries. If we had our own crtbegin.o/crtend.o/etc, we could probably 463 // get away with using shared versions in /usr/lib, though. 464 // We could fall back to the approach we used for includes (a massive 465 // list), but that's messy at best. 466} 467 468/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly. 469 470DragonFly::DragonFly(const HostInfo &Host, const llvm::Triple& Triple) 471 : Generic_GCC(Host, Triple) { 472 473 // Path mangling to find libexec 474 std::string Path(getHost().getDriver().Dir); 475 476 Path += "/../libexec"; 477 getProgramPaths().push_back(Path); 478 getProgramPaths().push_back(getHost().getDriver().Dir); 479 480 getFilePaths().push_back(getHost().getDriver().Dir + "/../lib"); 481 getFilePaths().push_back("/usr/lib"); 482 getFilePaths().push_back("/usr/lib/gcc41"); 483} 484 485Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA) const { 486 Action::ActionClass Key; 487 if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName())) 488 Key = Action::AnalyzeJobClass; 489 else 490 Key = JA.getKind(); 491 492 Tool *&T = Tools[Key]; 493 if (!T) { 494 switch (Key) { 495 case Action::AssembleJobClass: 496 T = new tools::dragonfly::Assemble(*this); break; 497 case Action::LinkJobClass: 498 T = new tools::dragonfly::Link(*this); break; 499 default: 500 T = &Generic_GCC::SelectTool(C, JA); 501 } 502 } 503 504 return *T; 505}
|