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/HostInfo.h" 18 #include "clang/Driver/Options.h" 19 20 using namespace clang::driver; 21 22 ToolChain::ToolChain(const HostInfo &_Host, const llvm::Triple &_Triple) 23 : Host(_Host), Triple(_Triple) { 24 } 25 26 ToolChain::~ToolChain() { 27 } 28 29 const Driver &ToolChain::getDriver() const { 30 return Host.getDriver(); 31 } 32 33 std::string ToolChain::GetFilePath(const char *Name) const { 34 return Host.getDriver().GetFilePath(Name, *this); 35 36 } 37 38 std::string ToolChain::GetProgramPath(const char *Name, bool WantFile) const { 39 return Host.getDriver().GetProgramPath(Name, *this, WantFile); 40 } 41 42 types::ID ToolChain::LookupTypeForExtension(const char *Ext) const { 43 return types::lookupTypeForExtension(Ext); 44 } 45 46 bool ToolChain::HasNativeLLVMSupport() const { 47 return false; 48 } 49 50 /// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targetting. 51 // 52 // FIXME: tblgen this. 53 static const char *getARMTargetCPU(const ArgList &Args, 54 const llvm::Triple &Triple) { 55 // FIXME: Warn on inconsistent use of -mcpu and -march. 56 57 // If we have -mcpu=, use that. 58 if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) 59 return A->getValue(Args); 60 61 llvm::StringRef MArch; 62 if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) { 63 // Otherwise, if we have -march= choose the base CPU for that arch. 64 MArch = A->getValue(Args); 65 } else { 66 // Otherwise, use the Arch from the triple. 67 MArch = Triple.getArchName(); 68 } 69 70 if (MArch == "armv2" || MArch == "armv2a") 71 return "arm2"; 72 if (MArch == "armv3") 73 return "arm6"; 74 if (MArch == "armv3m") 75 return "arm7m"; 76 if (MArch == "armv4" || MArch == "armv4t") 77 return "arm7tdmi"; 78 if (MArch == "armv5" || MArch == "armv5t") 79 return "arm10tdmi"; 80 if (MArch == "armv5e" || MArch == "armv5te") 81 return "arm1026ejs"; 82 if (MArch == "armv5tej") 83 return "arm926ej-s"; 84 if (MArch == "armv6" || MArch == "armv6k") 85 return "arm1136jf-s"; 86 if (MArch == "armv6j") 87 return "arm1136j-s"; 88 if (MArch == "armv6z" || MArch == "armv6zk") 89 return "arm1176jzf-s"; 90 if (MArch == "armv6t2") 91 return "arm1156t2-s"; 92 if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a") 93 return "cortex-a8"; 94 if (MArch == "armv7r" || MArch == "armv7-r") 95 return "cortex-r4"; 96 if (MArch == "armv7m" || MArch == "armv7-m") 97 return "cortex-m3"; 98 if (MArch == "ep9312") 99 return "ep9312"; 100 if (MArch == "iwmmxt") 101 return "iwmmxt"; 102 if (MArch == "xscale") 103 return "xscale"; 104 if (MArch == "armv6m" || MArch == "armv6-m") 105 return "cortex-m0"; 106 107 // If all else failed, return the most base CPU LLVM supports. 108 return "arm7tdmi"; 109 } 110 111 /// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular 112 /// CPU. 113 // 114 // FIXME: This is redundant with -mcpu, why does LLVM use this. 115 // FIXME: tblgen this, or kill it! 116 static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) { 117 if (CPU == "arm7tdmi" || CPU == "arm7tdmi-s" || CPU == "arm710t" || 118 CPU == "arm720t" || CPU == "arm9" || CPU == "arm9tdmi" || 119 CPU == "arm920" || CPU == "arm920t" || CPU == "arm922t" || 120 CPU == "arm940t" || CPU == "ep9312") 121 return "v4t"; 122 123 if (CPU == "arm10tdmi" || CPU == "arm1020t") 124 return "v5"; 125 126 if (CPU == "arm9e" || CPU == "arm926ej-s" || CPU == "arm946e-s" || 127 CPU == "arm966e-s" || CPU == "arm968e-s" || CPU == "arm10e" || 128 CPU == "arm1020e" || CPU == "arm1022e" || CPU == "xscale" || 129 CPU == "iwmmxt") 130 return "v5e"; 131 132 if (CPU == "arm1136j-s" || CPU == "arm1136jf-s" || CPU == "arm1176jz-s" || 133 CPU == "arm1176jzf-s" || CPU == "mpcorenovfp" || CPU == "mpcore") 134 return "v6"; 135 136 if (CPU == "arm1156t2-s" || CPU == "arm1156t2f-s") 137 return "v6t2"; 138 139 if (CPU == "cortex-a8" || CPU == "cortex-a9") 140 return "v7"; 141 142 if (CPU == "cortex-m3") 143 return "v7m"; 144 145 if (CPU == "cortex-m0") 146 return "v6m"; 147 148 return ""; 149 } 150 151 std::string ToolChain::ComputeLLVMTriple(const ArgList &Args) const { 152 switch (getTriple().getArch()) { 153 default: 154 return getTripleString(); 155 156 case llvm::Triple::arm: 157 case llvm::Triple::thumb: { 158 // FIXME: Factor into subclasses. 159 llvm::Triple Triple = getTriple(); 160 161 // Thumb2 is the default for V7 on Darwin. 162 // 163 // FIXME: Thumb should just be another -target-feaure, not in the triple. 164 llvm::StringRef Suffix = 165 getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple)); 166 bool ThumbDefault = 167 (Suffix == "v7" && getTriple().getOS() == llvm::Triple::Darwin); 168 std::string ArchName = "arm"; 169 if (Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault)) 170 ArchName = "thumb"; 171 Triple.setArchName(ArchName + Suffix.str()); 172 173 return Triple.getTriple(); 174 } 175 } 176 } 177 178 std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args) const { 179 // Diagnose use of -mmacosx-version-min and -miphoneos-version-min on 180 // non-Darwin. 181 if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ, 182 options::OPT_miphoneos_version_min_EQ)) 183 getDriver().Diag(clang::diag::err_drv_clang_unsupported) 184 << A->getAsString(Args); 185 186 return ComputeLLVMTriple(Args); 187 } 188 189 ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ 190 if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { 191 llvm::StringRef Value = A->getValue(Args); 192 if (Value == "libc++") 193 return ToolChain::CST_Libcxx; 194 if (Value == "libstdc++") 195 return ToolChain::CST_Libstdcxx; 196 getDriver().Diag(clang::diag::err_drv_invalid_stdlib_name) 197 << A->getAsString(Args); 198 } 199 200 return ToolChain::CST_Libstdcxx; 201 } 202 203 void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args, 204 ArgStringList &CmdArgs) const { 205 CXXStdlibType Type = GetCXXStdlibType(Args); 206 207 switch (Type) { 208 case ToolChain::CST_Libcxx: 209 CmdArgs.push_back("-nostdinc++"); 210 CmdArgs.push_back("-cxx-isystem"); 211 CmdArgs.push_back("/usr/include/c++/v1"); 212 break; 213 214 case ToolChain::CST_Libstdcxx: 215 // Currently handled by the mass of goop in InitHeaderSearch. 216 break; 217 } 218 } 219 220 void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args, 221 ArgStringList &CmdArgs) const { 222 CXXStdlibType Type = GetCXXStdlibType(Args); 223 224 switch (Type) { 225 case ToolChain::CST_Libcxx: 226 CmdArgs.push_back("-lc++"); 227 break; 228 229 case ToolChain::CST_Libstdcxx: 230 CmdArgs.push_back("-lstdc++"); 231 break; 232 } 233 } 234 235 void ToolChain::AddCCKextLibArgs(const ArgList &Args, 236 ArgStringList &CmdArgs) const { 237 CmdArgs.push_back("-lcc_kext"); 238 } 239