ToolChain.cpp revision 30660a898545416f0fea2d717f16f75640001e38
1//===--- ToolChain.cpp - Collections of tools for one platform ------------===// 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/ToolChain.h" 11 12#include "clang/Driver/Action.h" 13#include "clang/Driver/Arg.h" 14#include "clang/Driver/ArgList.h" 15#include "clang/Driver/Driver.h" 16#include "clang/Driver/DriverDiagnostic.h" 17#include "clang/Driver/ObjCRuntime.h" 18#include "clang/Driver/Options.h" 19#include "llvm/Support/ErrorHandling.h" 20using namespace clang::driver; 21using namespace clang; 22 23ToolChain::ToolChain(const Driver &D, const llvm::Triple &T) 24 : D(D), Triple(T) { 25} 26 27ToolChain::~ToolChain() { 28} 29 30const Driver &ToolChain::getDriver() const { 31 return D; 32} 33 34std::string ToolChain::GetFilePath(const char *Name) const { 35 return D.GetFilePath(Name, *this); 36 37} 38 39std::string ToolChain::GetProgramPath(const char *Name, bool WantFile) const { 40 return D.GetProgramPath(Name, *this, WantFile); 41} 42 43types::ID ToolChain::LookupTypeForExtension(const char *Ext) const { 44 return types::lookupTypeForExtension(Ext); 45} 46 47bool ToolChain::HasNativeLLVMSupport() const { 48 return false; 49} 50 51void ToolChain::configureObjCRuntime(ObjCRuntime &runtime) const { 52 switch (runtime.getKind()) { 53 case ObjCRuntime::NeXT: 54 // Assume a minimal NeXT runtime. 55 runtime.HasARC = false; 56 runtime.HasWeak = false; 57 runtime.HasSubscripting = false; 58 runtime.HasTerminate = false; 59 return; 60 61 case ObjCRuntime::GNU: 62 // Assume a maximal GNU runtime. 63 runtime.HasARC = true; 64 runtime.HasWeak = true; 65 runtime.HasSubscripting = false; // to be added 66 runtime.HasTerminate = false; // to be added 67 return; 68 } 69 llvm_unreachable("invalid runtime kind!"); 70} 71 72/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. 73// 74// FIXME: tblgen this. 75static const char *getARMTargetCPU(const ArgList &Args, 76 const llvm::Triple &Triple) { 77 // FIXME: Warn on inconsistent use of -mcpu and -march. 78 79 // If we have -mcpu=, use that. 80 if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) 81 return A->getValue(Args); 82 83 StringRef MArch; 84 if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) { 85 // Otherwise, if we have -march= choose the base CPU for that arch. 86 MArch = A->getValue(Args); 87 } else { 88 // Otherwise, use the Arch from the triple. 89 MArch = Triple.getArchName(); 90 } 91 92 if (MArch == "armv2" || MArch == "armv2a") 93 return "arm2"; 94 if (MArch == "armv3") 95 return "arm6"; 96 if (MArch == "armv3m") 97 return "arm7m"; 98 if (MArch == "armv4" || MArch == "armv4t") 99 return "arm7tdmi"; 100 if (MArch == "armv5" || MArch == "armv5t") 101 return "arm10tdmi"; 102 if (MArch == "armv5e" || MArch == "armv5te") 103 return "arm1026ejs"; 104 if (MArch == "armv5tej") 105 return "arm926ej-s"; 106 if (MArch == "armv6" || MArch == "armv6k") 107 return "arm1136jf-s"; 108 if (MArch == "armv6j") 109 return "arm1136j-s"; 110 if (MArch == "armv6z" || MArch == "armv6zk") 111 return "arm1176jzf-s"; 112 if (MArch == "armv6t2") 113 return "arm1156t2-s"; 114 if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a") 115 return "cortex-a8"; 116 if (MArch == "armv7r" || MArch == "armv7-r") 117 return "cortex-r4"; 118 if (MArch == "armv7m" || MArch == "armv7-m") 119 return "cortex-m3"; 120 if (MArch == "ep9312") 121 return "ep9312"; 122 if (MArch == "iwmmxt") 123 return "iwmmxt"; 124 if (MArch == "xscale") 125 return "xscale"; 126 if (MArch == "armv6m" || MArch == "armv6-m") 127 return "cortex-m0"; 128 129 // If all else failed, return the most base CPU LLVM supports. 130 return "arm7tdmi"; 131} 132 133/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular 134/// CPU. 135// 136// FIXME: This is redundant with -mcpu, why does LLVM use this. 137// FIXME: tblgen this, or kill it! 138static const char *getLLVMArchSuffixForARM(StringRef CPU) { 139 if (CPU == "arm7tdmi" || CPU == "arm7tdmi-s" || CPU == "arm710t" || 140 CPU == "arm720t" || CPU == "arm9" || CPU == "arm9tdmi" || 141 CPU == "arm920" || CPU == "arm920t" || CPU == "arm922t" || 142 CPU == "arm940t" || CPU == "ep9312") 143 return "v4t"; 144 145 if (CPU == "arm10tdmi" || CPU == "arm1020t") 146 return "v5"; 147 148 if (CPU == "arm9e" || CPU == "arm926ej-s" || CPU == "arm946e-s" || 149 CPU == "arm966e-s" || CPU == "arm968e-s" || CPU == "arm10e" || 150 CPU == "arm1020e" || CPU == "arm1022e" || CPU == "xscale" || 151 CPU == "iwmmxt") 152 return "v5e"; 153 154 if (CPU == "arm1136j-s" || CPU == "arm1136jf-s" || CPU == "arm1176jz-s" || 155 CPU == "arm1176jzf-s" || CPU == "mpcorenovfp" || CPU == "mpcore") 156 return "v6"; 157 158 if (CPU == "arm1156t2-s" || CPU == "arm1156t2f-s") 159 return "v6t2"; 160 161 if (CPU == "cortex-a8" || CPU == "cortex-a9") 162 return "v7"; 163 164 if (CPU == "cortex-m3") 165 return "v7m"; 166 167 if (CPU == "cortex-m0") 168 return "v6m"; 169 170 return ""; 171} 172 173std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, 174 types::ID InputType) const { 175 switch (getTriple().getArch()) { 176 default: 177 return getTripleString(); 178 179 case llvm::Triple::arm: 180 case llvm::Triple::thumb: { 181 // FIXME: Factor into subclasses. 182 llvm::Triple Triple = getTriple(); 183 184 // Thumb2 is the default for V7 on Darwin. 185 // 186 // FIXME: Thumb should just be another -target-feaure, not in the triple. 187 StringRef Suffix = 188 getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple)); 189 bool ThumbDefault = (Suffix == "v7" && getTriple().isOSDarwin()); 190 std::string ArchName = "arm"; 191 192 // Assembly files should start in ARM mode. 193 if (InputType != types::TY_PP_Asm && 194 Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault)) 195 ArchName = "thumb"; 196 Triple.setArchName(ArchName + Suffix.str()); 197 198 return Triple.getTriple(); 199 } 200 } 201} 202 203std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args, 204 types::ID InputType) const { 205 // Diagnose use of Darwin OS deployment target arguments on non-Darwin. 206 if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ, 207 options::OPT_miphoneos_version_min_EQ, 208 options::OPT_mios_simulator_version_min_EQ)) 209 getDriver().Diag(diag::err_drv_clang_unsupported) 210 << A->getAsString(Args); 211 212 return ComputeLLVMTriple(Args, InputType); 213} 214 215void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 216 ArgStringList &CC1Args) const { 217 // Each toolchain should provide the appropriate include flags. 218} 219 220ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType( 221 const ArgList &Args) const 222{ 223 if (Arg *A = Args.getLastArg(options::OPT_rtlib_EQ)) { 224 StringRef Value = A->getValue(Args); 225 if (Value == "compiler-rt") 226 return ToolChain::RLT_CompilerRT; 227 if (Value == "libgcc") 228 return ToolChain::RLT_Libgcc; 229 getDriver().Diag(diag::err_drv_invalid_rtlib_name) 230 << A->getAsString(Args); 231 } 232 233 return GetDefaultRuntimeLibType(); 234} 235 236ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ 237 if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { 238 StringRef Value = A->getValue(Args); 239 if (Value == "libc++") 240 return ToolChain::CST_Libcxx; 241 if (Value == "libstdc++") 242 return ToolChain::CST_Libstdcxx; 243 getDriver().Diag(diag::err_drv_invalid_stdlib_name) 244 << A->getAsString(Args); 245 } 246 247 return ToolChain::CST_Libstdcxx; 248} 249 250/// \brief Utility function to add a system include directory to CC1 arguments. 251/*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs, 252 ArgStringList &CC1Args, 253 const Twine &Path) { 254 CC1Args.push_back("-internal-isystem"); 255 CC1Args.push_back(DriverArgs.MakeArgString(Path)); 256} 257 258/// \brief Utility function to add a system include directory with extern "C" 259/// semantics to CC1 arguments. 260/// 261/// Note that this should be used rarely, and only for directories that 262/// historically and for legacy reasons are treated as having implicit extern 263/// "C" semantics. These semantics are *ignored* by and large today, but its 264/// important to preserve the preprocessor changes resulting from the 265/// classification. 266/*static*/ void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs, 267 ArgStringList &CC1Args, 268 const Twine &Path) { 269 CC1Args.push_back("-internal-externc-isystem"); 270 CC1Args.push_back(DriverArgs.MakeArgString(Path)); 271} 272 273/// \brief Utility function to add a list of system include directories to CC1. 274/*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs, 275 ArgStringList &CC1Args, 276 ArrayRef<StringRef> Paths) { 277 for (ArrayRef<StringRef>::iterator I = Paths.begin(), E = Paths.end(); 278 I != E; ++I) { 279 CC1Args.push_back("-internal-isystem"); 280 CC1Args.push_back(DriverArgs.MakeArgString(*I)); 281 } 282} 283 284void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, 285 ArgStringList &CC1Args) const { 286 // Header search paths should be handled by each of the subclasses. 287 // Historically, they have not been, and instead have been handled inside of 288 // the CC1-layer frontend. As the logic is hoisted out, this generic function 289 // will slowly stop being called. 290 // 291 // While it is being called, replicate a bit of a hack to propagate the 292 // '-stdlib=' flag down to CC1 so that it can in turn customize the C++ 293 // header search paths with it. Once all systems are overriding this 294 // function, the CC1 flag and this line can be removed. 295 DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ); 296} 297 298void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args, 299 ArgStringList &CmdArgs) const { 300 CXXStdlibType Type = GetCXXStdlibType(Args); 301 302 switch (Type) { 303 case ToolChain::CST_Libcxx: 304 CmdArgs.push_back("-lc++"); 305 break; 306 307 case ToolChain::CST_Libstdcxx: 308 CmdArgs.push_back("-lstdc++"); 309 break; 310 } 311} 312 313void ToolChain::AddCCKextLibArgs(const ArgList &Args, 314 ArgStringList &CmdArgs) const { 315 CmdArgs.push_back("-lcc_kext"); 316} 317