1 //===--- Triple.cpp - Target triple helper class --------------------------===// 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 "llvm/ADT/Triple.h" 11 12 #include "llvm/ADT/Twine.h" 13 #include <cassert> 14 #include <cstring> 15 using namespace llvm; 16 17 // 18 19 const char *Triple::getArchTypeName(ArchType Kind) { 20 switch (Kind) { 21 case InvalidArch: return "<invalid>"; 22 case UnknownArch: return "unknown"; 23 24 case alpha: return "alpha"; 25 case arm: return "arm"; 26 case bfin: return "bfin"; 27 case cellspu: return "cellspu"; 28 case mips: return "mips"; 29 case mipsel: return "mipsel"; 30 case msp430: return "msp430"; 31 case pic16: return "pic16"; 32 case ppc64: return "powerpc64"; 33 case ppc: return "powerpc"; 34 case sparc: return "sparc"; 35 case systemz: return "s390x"; 36 case tce: return "tce"; 37 case thumb: return "thumb"; 38 case x86: return "i386"; 39 case x86_64: return "x86_64"; 40 case xcore: return "xcore"; 41 } 42 43 return "<invalid>"; 44 } 45 46 const char *Triple::getArchTypePrefix(ArchType Kind) { 47 switch (Kind) { 48 default: 49 return 0; 50 51 case alpha: return "alpha"; 52 53 case arm: 54 case thumb: return "arm"; 55 56 case bfin: return "bfin"; 57 58 case cellspu: return "spu"; 59 60 case ppc64: 61 case ppc: return "ppc"; 62 63 case sparc: return "sparc"; 64 65 case x86: 66 case x86_64: return "x86"; 67 case xcore: return "xcore"; 68 } 69 } 70 71 const char *Triple::getVendorTypeName(VendorType Kind) { 72 switch (Kind) { 73 case UnknownVendor: return "unknown"; 74 75 case Apple: return "apple"; 76 case PC: return "pc"; 77 } 78 79 return "<invalid>"; 80 } 81 82 const char *Triple::getOSTypeName(OSType Kind) { 83 switch (Kind) { 84 case UnknownOS: return "unknown"; 85 86 case AuroraUX: return "auroraux"; 87 case Cygwin: return "cygwin"; 88 case Darwin: return "darwin"; 89 case DragonFly: return "dragonfly"; 90 case FreeBSD: return "freebsd"; 91 case Linux: return "linux"; 92 case MinGW32: return "mingw32"; 93 case MinGW64: return "mingw64"; 94 case NetBSD: return "netbsd"; 95 case OpenBSD: return "openbsd"; 96 case Solaris: return "solaris"; 97 case Win32: return "win32"; 98 } 99 100 return "<invalid>"; 101 } 102 103 Triple::ArchType Triple::getArchTypeForLLVMName(const StringRef &Name) { 104 if (Name == "alpha") 105 return alpha; 106 if (Name == "arm") 107 return arm; 108 if (Name == "bfin") 109 return bfin; 110 if (Name == "cellspu") 111 return cellspu; 112 if (Name == "mips") 113 return mips; 114 if (Name == "mipsel") 115 return mipsel; 116 if (Name == "msp430") 117 return msp430; 118 if (Name == "pic16") 119 return pic16; 120 if (Name == "ppc64") 121 return ppc64; 122 if (Name == "ppc") 123 return ppc; 124 if (Name == "sparc") 125 return sparc; 126 if (Name == "systemz") 127 return systemz; 128 if (Name == "tce") 129 return tce; 130 if (Name == "thumb") 131 return thumb; 132 if (Name == "x86") 133 return x86; 134 if (Name == "x86-64") 135 return x86_64; 136 if (Name == "xcore") 137 return xcore; 138 139 return UnknownArch; 140 } 141 142 Triple::ArchType Triple::getArchTypeForDarwinArchName(const StringRef &Str) { 143 // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for 144 // archs which Darwin doesn't use. 145 146 // The matching this routine does is fairly pointless, since it is neither the 147 // complete architecture list, nor a reasonable subset. The problem is that 148 // historically the driver driver accepts this and also ties its -march= 149 // handling to the architecture name, so we need to be careful before removing 150 // support for it. 151 152 // This code must be kept in sync with Clang's Darwin specific argument 153 // translation. 154 155 if (Str == "ppc" || Str == "ppc601" || Str == "ppc603" || Str == "ppc604" || 156 Str == "ppc604e" || Str == "ppc750" || Str == "ppc7400" || 157 Str == "ppc7450" || Str == "ppc970") 158 return Triple::ppc; 159 160 if (Str == "ppc64") 161 return Triple::ppc64; 162 163 if (Str == "i386" || Str == "i486" || Str == "i486SX" || Str == "pentium" || 164 Str == "i586" || Str == "pentpro" || Str == "i686" || Str == "pentIIm3" || 165 Str == "pentIIm5" || Str == "pentium4") 166 return Triple::x86; 167 168 if (Str == "x86_64") 169 return Triple::x86_64; 170 171 // This is derived from the driver driver. 172 if (Str == "arm" || Str == "armv4t" || Str == "armv5" || Str == "xscale" || 173 Str == "armv6" || Str == "armv7") 174 return Triple::arm; 175 176 return Triple::UnknownArch; 177 } 178 179 // 180 181 void Triple::Parse() const { 182 assert(!isInitialized() && "Invalid parse call."); 183 184 StringRef ArchName = getArchName(); 185 StringRef VendorName = getVendorName(); 186 StringRef OSName = getOSName(); 187 188 if (ArchName.size() == 4 && ArchName[0] == 'i' && 189 ArchName[2] == '8' && ArchName[3] == '6' && 190 ArchName[1] - '3' < 6) // i[3-9]86 191 Arch = x86; 192 else if (ArchName == "amd64" || ArchName == "x86_64") 193 Arch = x86_64; 194 else if (ArchName == "bfin") 195 Arch = bfin; 196 else if (ArchName == "pic16") 197 Arch = pic16; 198 else if (ArchName == "powerpc") 199 Arch = ppc; 200 else if (ArchName == "powerpc64") 201 Arch = ppc64; 202 else if (ArchName == "arm" || 203 ArchName.startswith("armv") || 204 ArchName == "xscale") 205 Arch = arm; 206 else if (ArchName == "thumb" || 207 ArchName.startswith("thumbv")) 208 Arch = thumb; 209 else if (ArchName.startswith("alpha")) 210 Arch = alpha; 211 else if (ArchName == "spu" || ArchName == "cellspu") 212 Arch = cellspu; 213 else if (ArchName == "msp430") 214 Arch = msp430; 215 else if (ArchName == "mips" || ArchName == "mipsallegrex") 216 Arch = mips; 217 else if (ArchName == "mipsel" || ArchName == "mipsallegrexel" || 218 ArchName == "psp") 219 Arch = mipsel; 220 else if (ArchName == "sparc") 221 Arch = sparc; 222 else if (ArchName == "s390x") 223 Arch = systemz; 224 else if (ArchName == "tce") 225 Arch = tce; 226 else if (ArchName == "xcore") 227 Arch = xcore; 228 else 229 Arch = UnknownArch; 230 231 232 // Handle some exceptional cases where the OS / environment components are 233 // stuck into the vendor field. 234 if (StringRef(getTriple()).count('-') == 1) { 235 StringRef VendorName = getVendorName(); 236 237 if (VendorName.startswith("mingw32")) { // 'i386-mingw32', etc. 238 Vendor = PC; 239 OS = MinGW32; 240 return; 241 } 242 243 // arm-elf is another example, but we don't currently parse anything about 244 // the environment. 245 } 246 247 if (VendorName == "apple") 248 Vendor = Apple; 249 else if (VendorName == "pc") 250 Vendor = PC; 251 else 252 Vendor = UnknownVendor; 253 254 if (OSName.startswith("auroraux")) 255 OS = AuroraUX; 256 else if (OSName.startswith("cygwin")) 257 OS = Cygwin; 258 else if (OSName.startswith("darwin")) 259 OS = Darwin; 260 else if (OSName.startswith("dragonfly")) 261 OS = DragonFly; 262 else if (OSName.startswith("freebsd")) 263 OS = FreeBSD; 264 else if (OSName.startswith("linux")) 265 OS = Linux; 266 else if (OSName.startswith("mingw32")) 267 OS = MinGW32; 268 else if (OSName.startswith("mingw64")) 269 OS = MinGW64; 270 else if (OSName.startswith("netbsd")) 271 OS = NetBSD; 272 else if (OSName.startswith("openbsd")) 273 OS = OpenBSD; 274 else if (OSName.startswith("solaris")) 275 OS = Solaris; 276 else if (OSName.startswith("win32")) 277 OS = Win32; 278 else 279 OS = UnknownOS; 280 281 assert(isInitialized() && "Failed to initialize!"); 282 } 283 284 StringRef Triple::getArchName() const { 285 return StringRef(Data).split('-').first; // Isolate first component 286 } 287 288 StringRef Triple::getVendorName() const { 289 StringRef Tmp = StringRef(Data).split('-').second; // Strip first component 290 return Tmp.split('-').first; // Isolate second component 291 } 292 293 StringRef Triple::getOSName() const { 294 StringRef Tmp = StringRef(Data).split('-').second; // Strip first component 295 Tmp = Tmp.split('-').second; // Strip second component 296 return Tmp.split('-').first; // Isolate third component 297 } 298 299 StringRef Triple::getEnvironmentName() const { 300 StringRef Tmp = StringRef(Data).split('-').second; // Strip first component 301 Tmp = Tmp.split('-').second; // Strip second component 302 return Tmp.split('-').second; // Strip third component 303 } 304 305 StringRef Triple::getOSAndEnvironmentName() const { 306 StringRef Tmp = StringRef(Data).split('-').second; // Strip first component 307 return Tmp.split('-').second; // Strip second component 308 } 309 310 static unsigned EatNumber(StringRef &Str) { 311 assert(!Str.empty() && Str[0] >= '0' && Str[0] <= '9' && "Not a number"); 312 unsigned Result = Str[0]-'0'; 313 314 // Eat the digit. 315 Str = Str.substr(1); 316 317 // Handle "darwin11". 318 if (Result == 1 && !Str.empty() && Str[0] >= '0' && Str[0] <= '9') { 319 Result = Result*10 + (Str[0] - '0'); 320 // Eat the digit. 321 Str = Str.substr(1); 322 } 323 324 return Result; 325 } 326 327 /// getDarwinNumber - Parse the 'darwin number' out of the specific target 328 /// triple. For example, if we have darwin8.5 return 8,5,0. If any entry is 329 /// not defined, return 0's. This requires that the triple have an OSType of 330 /// darwin before it is called. 331 void Triple::getDarwinNumber(unsigned &Maj, unsigned &Min, 332 unsigned &Revision) const { 333 assert(getOS() == Darwin && "Not a darwin target triple!"); 334 StringRef OSName = getOSName(); 335 assert(OSName.startswith("darwin") && "Unknown darwin target triple!"); 336 337 // Strip off "darwin". 338 OSName = OSName.substr(6); 339 340 Maj = Min = Revision = 0; 341 342 if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9') 343 return; 344 345 // The major version is the first digit. 346 Maj = EatNumber(OSName); 347 if (OSName.empty()) return; 348 349 // Handle minor version: 10.4.9 -> darwin8.9. 350 if (OSName[0] != '.') 351 return; 352 353 // Eat the '.'. 354 OSName = OSName.substr(1); 355 356 if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9') 357 return; 358 359 Min = EatNumber(OSName); 360 if (OSName.empty()) return; 361 362 // Handle revision darwin8.9.1 363 if (OSName[0] != '.') 364 return; 365 366 // Eat the '.'. 367 OSName = OSName.substr(1); 368 369 if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9') 370 return; 371 372 Revision = EatNumber(OSName); 373 } 374 375 void Triple::setTriple(const Twine &Str) { 376 Data = Str.str(); 377 Arch = InvalidArch; 378 } 379 380 void Triple::setArch(ArchType Kind) { 381 setArchName(getArchTypeName(Kind)); 382 } 383 384 void Triple::setVendor(VendorType Kind) { 385 setVendorName(getVendorTypeName(Kind)); 386 } 387 388 void Triple::setOS(OSType Kind) { 389 setOSName(getOSTypeName(Kind)); 390 } 391 392 void Triple::setArchName(const StringRef &Str) { 393 setTriple(Str + "-" + getVendorName() + "-" + getOSAndEnvironmentName()); 394 } 395 396 void Triple::setVendorName(const StringRef &Str) { 397 setTriple(getArchName() + "-" + Str + "-" + getOSAndEnvironmentName()); 398 } 399 400 void Triple::setOSName(const StringRef &Str) { 401 if (hasEnvironment()) 402 setTriple(getArchName() + "-" + getVendorName() + "-" + Str + 403 "-" + getEnvironmentName()); 404 else 405 setTriple(getArchName() + "-" + getVendorName() + "-" + Str); 406 } 407 408 void Triple::setEnvironmentName(const StringRef &Str) { 409 setTriple(getArchName() + "-" + getVendorName() + "-" + getOSName() + 410 "-" + Str); 411 } 412 413 void Triple::setOSAndEnvironmentName(const StringRef &Str) { 414 setTriple(getArchName() + "-" + getVendorName() + "-" + Str); 415 } 416