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 "Tools.h" 11 #include "clang/Driver/ToolChain.h" 12 #include "clang/Basic/ObjCRuntime.h" 13 #include "clang/Driver/Action.h" 14 #include "clang/Driver/Arg.h" 15 #include "clang/Driver/ArgList.h" 16 #include "clang/Driver/Driver.h" 17 #include "clang/Driver/DriverDiagnostic.h" 18 #include "clang/Driver/Option.h" 19 #include "clang/Driver/Options.h" 20 #include "llvm/ADT/StringSwitch.h" 21 #include "llvm/Support/ErrorHandling.h" 22 using namespace clang::driver; 23 using namespace clang; 24 25 ToolChain::ToolChain(const Driver &D, const llvm::Triple &T, 26 const ArgList &A) 27 : D(D), Triple(T), Args(A) { 28 } 29 30 ToolChain::~ToolChain() { 31 // Free tool implementations. 32 for (llvm::DenseMap<unsigned, Tool*>::iterator 33 it = Tools.begin(), ie = Tools.end(); it != ie; ++it) 34 delete it->second; 35 } 36 37 const Driver &ToolChain::getDriver() const { 38 return D; 39 } 40 41 bool ToolChain::useIntegratedAs() const { 42 return Args.hasFlag(options::OPT_integrated_as, 43 options::OPT_no_integrated_as, 44 IsIntegratedAssemblerDefault()); 45 } 46 47 std::string ToolChain::getDefaultUniversalArchName() const { 48 // In universal driver terms, the arch name accepted by -arch isn't exactly 49 // the same as the ones that appear in the triple. Roughly speaking, this is 50 // an inverse of the darwin::getArchTypeForDarwinArchName() function, but the 51 // only interesting special case is powerpc. 52 switch (Triple.getArch()) { 53 case llvm::Triple::ppc: 54 return "ppc"; 55 case llvm::Triple::ppc64: 56 return "ppc64"; 57 default: 58 return Triple.getArchName(); 59 } 60 } 61 62 bool ToolChain::IsUnwindTablesDefault() const { 63 return false; 64 } 65 66 Tool &ToolChain::SelectTool(const JobAction &JA) const { 67 Action::ActionClass Key; 68 if (getDriver().ShouldUseClangCompiler(JA)) 69 Key = Action::AnalyzeJobClass; 70 else 71 Key = JA.getKind(); 72 73 Tool *&T = Tools[Key]; 74 if (T) 75 return *T; 76 77 if (getDriver().ShouldUseClangCompiler(JA)) 78 T = new tools::Clang(*this); 79 else 80 T = constructTool(Key); 81 82 return *T; 83 } 84 85 std::string ToolChain::GetFilePath(const char *Name) const { 86 return D.GetFilePath(Name, *this); 87 88 } 89 90 std::string ToolChain::GetProgramPath(const char *Name) const { 91 return D.GetProgramPath(Name, *this); 92 } 93 94 types::ID ToolChain::LookupTypeForExtension(const char *Ext) const { 95 return types::lookupTypeForExtension(Ext); 96 } 97 98 bool ToolChain::HasNativeLLVMSupport() const { 99 return false; 100 } 101 102 ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const { 103 return ObjCRuntime(isNonFragile ? ObjCRuntime::GNUstep : ObjCRuntime::GCC, 104 VersionTuple()); 105 } 106 107 /// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. 108 // 109 // FIXME: tblgen this. 110 static const char *getARMTargetCPU(const ArgList &Args, 111 const llvm::Triple &Triple) { 112 // For Darwin targets, the -arch option (which is translated to a 113 // corresponding -march option) should determine the architecture 114 // (and the Mach-O slice) regardless of any -mcpu options. 115 if (!Triple.isOSDarwin()) { 116 // FIXME: Warn on inconsistent use of -mcpu and -march. 117 // If we have -mcpu=, use that. 118 if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) 119 return A->getValue(); 120 } 121 122 StringRef MArch; 123 if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) { 124 // Otherwise, if we have -march= choose the base CPU for that arch. 125 MArch = A->getValue(); 126 } else { 127 // Otherwise, use the Arch from the triple. 128 MArch = Triple.getArchName(); 129 } 130 131 return llvm::StringSwitch<const char *>(MArch) 132 .Cases("armv2", "armv2a","arm2") 133 .Case("armv3", "arm6") 134 .Case("armv3m", "arm7m") 135 .Cases("armv4", "armv4t", "arm7tdmi") 136 .Cases("armv5", "armv5t", "arm10tdmi") 137 .Cases("armv5e", "armv5te", "arm1026ejs") 138 .Case("armv5tej", "arm926ej-s") 139 .Cases("armv6", "armv6k", "arm1136jf-s") 140 .Case("armv6j", "arm1136j-s") 141 .Cases("armv6z", "armv6zk", "arm1176jzf-s") 142 .Case("armv6t2", "arm1156t2-s") 143 .Cases("armv6m", "armv6-m", "cortex-m0") 144 .Cases("armv7", "armv7a", "armv7-a", "cortex-a8") 145 .Cases("armv7l", "armv7-l", "cortex-a8") 146 .Cases("armv7f", "armv7-f", "cortex-a9-mp") 147 .Cases("armv7s", "armv7-s", "swift") 148 .Cases("armv7r", "armv7-r", "cortex-r4") 149 .Cases("armv7m", "armv7-m", "cortex-m3") 150 .Cases("armv7em", "armv7e-m", "cortex-m4") 151 .Case("ep9312", "ep9312") 152 .Case("iwmmxt", "iwmmxt") 153 .Case("xscale", "xscale") 154 // If all else failed, return the most base CPU LLVM supports. 155 .Default("arm7tdmi"); 156 } 157 158 /// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular 159 /// CPU. 160 // 161 // FIXME: This is redundant with -mcpu, why does LLVM use this. 162 // FIXME: tblgen this, or kill it! 163 static const char *getLLVMArchSuffixForARM(StringRef CPU) { 164 return llvm::StringSwitch<const char *>(CPU) 165 .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t") 166 .Cases("arm720t", "arm9", "arm9tdmi", "v4t") 167 .Cases("arm920", "arm920t", "arm922t", "v4t") 168 .Cases("arm940t", "ep9312","v4t") 169 .Cases("arm10tdmi", "arm1020t", "v5") 170 .Cases("arm9e", "arm926ej-s", "arm946e-s", "v5e") 171 .Cases("arm966e-s", "arm968e-s", "arm10e", "v5e") 172 .Cases("arm1020e", "arm1022e", "xscale", "iwmmxt", "v5e") 173 .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "v6") 174 .Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6") 175 .Cases("arm1156t2-s", "arm1156t2f-s", "v6t2") 176 .Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7") 177 .Cases("cortex-a9", "cortex-a15", "v7") 178 .Case("cortex-r5", "v7r") 179 .Case("cortex-m0", "v6m") 180 .Case("cortex-m3", "v7m") 181 .Case("cortex-m4", "v7em") 182 .Case("cortex-a9-mp", "v7f") 183 .Case("swift", "v7s") 184 .Default(""); 185 } 186 187 std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, 188 types::ID InputType) const { 189 switch (getTriple().getArch()) { 190 default: 191 return getTripleString(); 192 193 case llvm::Triple::arm: 194 case llvm::Triple::thumb: { 195 // FIXME: Factor into subclasses. 196 llvm::Triple Triple = getTriple(); 197 198 // Thumb2 is the default for V7 on Darwin. 199 // 200 // FIXME: Thumb should just be another -target-feaure, not in the triple. 201 StringRef Suffix = 202 getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple)); 203 bool ThumbDefault = Suffix.startswith("v6m") || 204 (Suffix.startswith("v7") && getTriple().isOSDarwin()); 205 std::string ArchName = "arm"; 206 207 // Assembly files should start in ARM mode. 208 if (InputType != types::TY_PP_Asm && 209 Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault)) 210 ArchName = "thumb"; 211 Triple.setArchName(ArchName + Suffix.str()); 212 213 return Triple.getTriple(); 214 } 215 } 216 } 217 218 std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args, 219 types::ID InputType) const { 220 // Diagnose use of Darwin OS deployment target arguments on non-Darwin. 221 if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ, 222 options::OPT_miphoneos_version_min_EQ, 223 options::OPT_mios_simulator_version_min_EQ)) 224 getDriver().Diag(diag::err_drv_clang_unsupported) 225 << A->getAsString(Args); 226 227 return ComputeLLVMTriple(Args, InputType); 228 } 229 230 void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 231 ArgStringList &CC1Args) const { 232 // Each toolchain should provide the appropriate include flags. 233 } 234 235 void ToolChain::addClangTargetOptions(const ArgList &DriverArgs, 236 ArgStringList &CC1Args) const { 237 } 238 239 ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType( 240 const ArgList &Args) const 241 { 242 if (Arg *A = Args.getLastArg(options::OPT_rtlib_EQ)) { 243 StringRef Value = A->getValue(); 244 if (Value == "compiler-rt") 245 return ToolChain::RLT_CompilerRT; 246 if (Value == "libgcc") 247 return ToolChain::RLT_Libgcc; 248 getDriver().Diag(diag::err_drv_invalid_rtlib_name) 249 << A->getAsString(Args); 250 } 251 252 return GetDefaultRuntimeLibType(); 253 } 254 255 ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ 256 if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { 257 StringRef Value = A->getValue(); 258 if (Value == "libc++") 259 return ToolChain::CST_Libcxx; 260 if (Value == "libstdc++") 261 return ToolChain::CST_Libstdcxx; 262 getDriver().Diag(diag::err_drv_invalid_stdlib_name) 263 << A->getAsString(Args); 264 } 265 266 return ToolChain::CST_Libstdcxx; 267 } 268 269 /// \brief Utility function to add a system include directory to CC1 arguments. 270 /*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs, 271 ArgStringList &CC1Args, 272 const Twine &Path) { 273 CC1Args.push_back("-internal-isystem"); 274 CC1Args.push_back(DriverArgs.MakeArgString(Path)); 275 } 276 277 /// \brief Utility function to add a system include directory with extern "C" 278 /// semantics to CC1 arguments. 279 /// 280 /// Note that this should be used rarely, and only for directories that 281 /// historically and for legacy reasons are treated as having implicit extern 282 /// "C" semantics. These semantics are *ignored* by and large today, but its 283 /// important to preserve the preprocessor changes resulting from the 284 /// classification. 285 /*static*/ void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs, 286 ArgStringList &CC1Args, 287 const Twine &Path) { 288 CC1Args.push_back("-internal-externc-isystem"); 289 CC1Args.push_back(DriverArgs.MakeArgString(Path)); 290 } 291 292 /// \brief Utility function to add a list of system include directories to CC1. 293 /*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs, 294 ArgStringList &CC1Args, 295 ArrayRef<StringRef> Paths) { 296 for (ArrayRef<StringRef>::iterator I = Paths.begin(), E = Paths.end(); 297 I != E; ++I) { 298 CC1Args.push_back("-internal-isystem"); 299 CC1Args.push_back(DriverArgs.MakeArgString(*I)); 300 } 301 } 302 303 void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, 304 ArgStringList &CC1Args) const { 305 // Header search paths should be handled by each of the subclasses. 306 // Historically, they have not been, and instead have been handled inside of 307 // the CC1-layer frontend. As the logic is hoisted out, this generic function 308 // will slowly stop being called. 309 // 310 // While it is being called, replicate a bit of a hack to propagate the 311 // '-stdlib=' flag down to CC1 so that it can in turn customize the C++ 312 // header search paths with it. Once all systems are overriding this 313 // function, the CC1 flag and this line can be removed. 314 DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ); 315 } 316 317 void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args, 318 ArgStringList &CmdArgs) const { 319 CXXStdlibType Type = GetCXXStdlibType(Args); 320 321 switch (Type) { 322 case ToolChain::CST_Libcxx: 323 CmdArgs.push_back("-lc++"); 324 break; 325 326 case ToolChain::CST_Libstdcxx: 327 CmdArgs.push_back("-lstdc++"); 328 break; 329 } 330 } 331 332 void ToolChain::AddCCKextLibArgs(const ArgList &Args, 333 ArgStringList &CmdArgs) const { 334 CmdArgs.push_back("-lcc_kext"); 335 } 336 337 bool ToolChain::AddFastMathRuntimeIfAvailable(const ArgList &Args, 338 ArgStringList &CmdArgs) const { 339 // Check if -ffast-math or -funsafe-math is enabled. 340 Arg *A = Args.getLastArg(options::OPT_ffast_math, 341 options::OPT_fno_fast_math, 342 options::OPT_funsafe_math_optimizations, 343 options::OPT_fno_unsafe_math_optimizations); 344 345 if (!A || A->getOption().getID() == options::OPT_fno_fast_math || 346 A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations) 347 return false; 348 349 // If crtfastmath.o exists add it to the arguments. 350 std::string Path = GetFilePath("crtfastmath.o"); 351 if (Path == "crtfastmath.o") // Not found. 352 return false; 353 354 CmdArgs.push_back(Args.MakeArgString(Path)); 355 return true; 356 } 357