Triple.cpp revision fe754ab90adf114430f77f402dc6b8b5245c00f2
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/SmallString.h" 13#include "llvm/ADT/STLExtras.h" 14#include "llvm/ADT/Twine.h" 15#include <cassert> 16#include <cstring> 17using namespace llvm; 18 19// 20 21const char *Triple::getArchTypeName(ArchType Kind) { 22 switch (Kind) { 23 case InvalidArch: return "<invalid>"; 24 case UnknownArch: return "unknown"; 25 26 case alpha: return "alpha"; 27 case arm: return "arm"; 28 case bfin: return "bfin"; 29 case cellspu: return "cellspu"; 30 case mips: return "mips"; 31 case mipsel: return "mipsel"; 32 case msp430: return "msp430"; 33 case ppc64: return "powerpc64"; 34 case ppc: return "powerpc"; 35 case sparc: return "sparc"; 36 case sparcv9: return "sparcv9"; 37 case systemz: return "s390x"; 38 case tce: return "tce"; 39 case thumb: return "thumb"; 40 case x86: return "i386"; 41 case x86_64: return "x86_64"; 42 case xcore: return "xcore"; 43 case mblaze: return "mblaze"; 44 case ptx32: return "ptx32"; 45 case ptx64: return "ptx64"; 46 } 47 48 return "<invalid>"; 49} 50 51const char *Triple::getArchTypePrefix(ArchType Kind) { 52 switch (Kind) { 53 default: 54 return 0; 55 56 case alpha: return "alpha"; 57 58 case arm: 59 case thumb: return "arm"; 60 61 case bfin: return "bfin"; 62 63 case cellspu: return "spu"; 64 65 case ppc64: 66 case ppc: return "ppc"; 67 68 case mblaze: return "mblaze"; 69 70 case sparcv9: 71 case sparc: return "sparc"; 72 73 case x86: 74 case x86_64: return "x86"; 75 76 case xcore: return "xcore"; 77 78 case ptx32: return "ptx"; 79 case ptx64: return "ptx"; 80 } 81} 82 83const char *Triple::getVendorTypeName(VendorType Kind) { 84 switch (Kind) { 85 case UnknownVendor: return "unknown"; 86 87 case Apple: return "apple"; 88 case PC: return "pc"; 89 case SCEI: return "scei"; 90 } 91 92 return "<invalid>"; 93} 94 95const char *Triple::getOSTypeName(OSType Kind) { 96 switch (Kind) { 97 case UnknownOS: return "unknown"; 98 99 case AuroraUX: return "auroraux"; 100 case Cygwin: return "cygwin"; 101 case Darwin: return "darwin"; 102 case DragonFly: return "dragonfly"; 103 case FreeBSD: return "freebsd"; 104 case IOS: return "ios"; 105 case Linux: return "linux"; 106 case Lv2: return "lv2"; 107 case MacOSX: return "macosx"; 108 case MinGW32: return "mingw32"; 109 case NetBSD: return "netbsd"; 110 case OpenBSD: return "openbsd"; 111 case Psp: return "psp"; 112 case Solaris: return "solaris"; 113 case Win32: return "win32"; 114 case Haiku: return "haiku"; 115 case Minix: return "minix"; 116 } 117 118 return "<invalid>"; 119} 120 121const char *Triple::getEnvironmentTypeName(EnvironmentType Kind) { 122 switch (Kind) { 123 case UnknownEnvironment: return "unknown"; 124 case GNU: return "gnu"; 125 case GNUEABI: return "gnueabi"; 126 case EABI: return "eabi"; 127 case MachO: return "macho"; 128 } 129 130 return "<invalid>"; 131} 132 133Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { 134 if (Name == "alpha") 135 return alpha; 136 if (Name == "arm") 137 return arm; 138 if (Name == "bfin") 139 return bfin; 140 if (Name == "cellspu") 141 return cellspu; 142 if (Name == "mips") 143 return mips; 144 if (Name == "mipsel") 145 return mipsel; 146 if (Name == "msp430") 147 return msp430; 148 if (Name == "ppc64") 149 return ppc64; 150 if (Name == "ppc") 151 return ppc; 152 if (Name == "mblaze") 153 return mblaze; 154 if (Name == "sparc") 155 return sparc; 156 if (Name == "sparcv9") 157 return sparcv9; 158 if (Name == "systemz") 159 return systemz; 160 if (Name == "tce") 161 return tce; 162 if (Name == "thumb") 163 return thumb; 164 if (Name == "x86") 165 return x86; 166 if (Name == "x86-64") 167 return x86_64; 168 if (Name == "xcore") 169 return xcore; 170 if (Name == "ptx32") 171 return ptx32; 172 if (Name == "ptx64") 173 return ptx64; 174 175 return UnknownArch; 176} 177 178Triple::ArchType Triple::getArchTypeForDarwinArchName(StringRef Str) { 179 // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for 180 // archs which Darwin doesn't use. 181 182 // The matching this routine does is fairly pointless, since it is neither the 183 // complete architecture list, nor a reasonable subset. The problem is that 184 // historically the driver driver accepts this and also ties its -march= 185 // handling to the architecture name, so we need to be careful before removing 186 // support for it. 187 188 // This code must be kept in sync with Clang's Darwin specific argument 189 // translation. 190 191 if (Str == "ppc" || Str == "ppc601" || Str == "ppc603" || Str == "ppc604" || 192 Str == "ppc604e" || Str == "ppc750" || Str == "ppc7400" || 193 Str == "ppc7450" || Str == "ppc970") 194 return Triple::ppc; 195 196 if (Str == "ppc64") 197 return Triple::ppc64; 198 199 if (Str == "i386" || Str == "i486" || Str == "i486SX" || Str == "pentium" || 200 Str == "i586" || Str == "pentpro" || Str == "i686" || Str == "pentIIm3" || 201 Str == "pentIIm5" || Str == "pentium4") 202 return Triple::x86; 203 204 if (Str == "x86_64") 205 return Triple::x86_64; 206 207 // This is derived from the driver driver. 208 if (Str == "arm" || Str == "armv4t" || Str == "armv5" || Str == "xscale" || 209 Str == "armv6" || Str == "armv7") 210 return Triple::arm; 211 212 if (Str == "ptx32") 213 return Triple::ptx32; 214 if (Str == "ptx64") 215 return Triple::ptx64; 216 217 return Triple::UnknownArch; 218} 219 220// Returns architecture name that is understood by the target assembler. 221const char *Triple::getArchNameForAssembler() { 222 if (!isOSDarwin() && getVendor() != Triple::Apple) 223 return NULL; 224 225 StringRef Str = getArchName(); 226 if (Str == "i386") 227 return "i386"; 228 if (Str == "x86_64") 229 return "x86_64"; 230 if (Str == "powerpc") 231 return "ppc"; 232 if (Str == "powerpc64") 233 return "ppc64"; 234 if (Str == "mblaze" || Str == "microblaze") 235 return "mblaze"; 236 if (Str == "arm") 237 return "arm"; 238 if (Str == "armv4t" || Str == "thumbv4t") 239 return "armv4t"; 240 if (Str == "armv5" || Str == "armv5e" || Str == "thumbv5" 241 || Str == "thumbv5e") 242 return "armv5"; 243 if (Str == "armv6" || Str == "thumbv6") 244 return "armv6"; 245 if (Str == "armv7" || Str == "thumbv7") 246 return "armv7"; 247 if (Str == "ptx32") 248 return "ptx32"; 249 if (Str == "ptx64") 250 return "ptx64"; 251 return NULL; 252} 253 254// 255 256Triple::ArchType Triple::ParseArch(StringRef ArchName) { 257 if (ArchName.size() == 4 && ArchName[0] == 'i' && 258 ArchName[2] == '8' && ArchName[3] == '6' && 259 ArchName[1] - '3' < 6) // i[3-9]86 260 return x86; 261 else if (ArchName == "amd64" || ArchName == "x86_64") 262 return x86_64; 263 else if (ArchName == "bfin") 264 return bfin; 265 else if (ArchName == "powerpc") 266 return ppc; 267 else if ((ArchName == "powerpc64") || (ArchName == "ppu")) 268 return ppc64; 269 else if (ArchName == "mblaze") 270 return mblaze; 271 else if (ArchName == "arm" || 272 ArchName.startswith("armv") || 273 ArchName == "xscale") 274 return arm; 275 else if (ArchName == "thumb" || 276 ArchName.startswith("thumbv")) 277 return thumb; 278 else if (ArchName.startswith("alpha")) 279 return alpha; 280 else if (ArchName == "spu" || ArchName == "cellspu") 281 return cellspu; 282 else if (ArchName == "msp430") 283 return msp430; 284 else if (ArchName == "mips" || ArchName == "mipsallegrex") 285 return mips; 286 else if (ArchName == "mipsel" || ArchName == "mipsallegrexel" || 287 ArchName == "psp") 288 return mipsel; 289 else if (ArchName == "sparc") 290 return sparc; 291 else if (ArchName == "sparcv9") 292 return sparcv9; 293 else if (ArchName == "s390x") 294 return systemz; 295 else if (ArchName == "tce") 296 return tce; 297 else if (ArchName == "xcore") 298 return xcore; 299 else if (ArchName == "ptx32") 300 return ptx32; 301 else if (ArchName == "ptx64") 302 return ptx64; 303 else 304 return UnknownArch; 305} 306 307Triple::VendorType Triple::ParseVendor(StringRef VendorName) { 308 if (VendorName == "apple") 309 return Apple; 310 else if (VendorName == "pc") 311 return PC; 312 else if (VendorName == "scei") 313 return SCEI; 314 else 315 return UnknownVendor; 316} 317 318Triple::OSType Triple::ParseOS(StringRef OSName) { 319 if (OSName.startswith("auroraux")) 320 return AuroraUX; 321 else if (OSName.startswith("cygwin")) 322 return Cygwin; 323 else if (OSName.startswith("darwin")) 324 return Darwin; 325 else if (OSName.startswith("dragonfly")) 326 return DragonFly; 327 else if (OSName.startswith("freebsd")) 328 return FreeBSD; 329 else if (OSName.startswith("ios")) 330 return IOS; 331 else if (OSName.startswith("linux")) 332 return Linux; 333 else if (OSName.startswith("lv2")) 334 return Lv2; 335 else if (OSName.startswith("macosx")) 336 return MacOSX; 337 else if (OSName.startswith("mingw32")) 338 return MinGW32; 339 else if (OSName.startswith("netbsd")) 340 return NetBSD; 341 else if (OSName.startswith("openbsd")) 342 return OpenBSD; 343 else if (OSName.startswith("psp")) 344 return Psp; 345 else if (OSName.startswith("solaris")) 346 return Solaris; 347 else if (OSName.startswith("win32")) 348 return Win32; 349 else if (OSName.startswith("haiku")) 350 return Haiku; 351 else if (OSName.startswith("minix")) 352 return Minix; 353 else 354 return UnknownOS; 355} 356 357Triple::EnvironmentType Triple::ParseEnvironment(StringRef EnvironmentName) { 358 if (EnvironmentName.startswith("eabi")) 359 return EABI; 360 else if (EnvironmentName.startswith("gnueabi")) 361 return GNUEABI; 362 else if (EnvironmentName.startswith("gnu")) 363 return GNU; 364 else if (EnvironmentName.startswith("macho")) 365 return MachO; 366 else 367 return UnknownEnvironment; 368} 369 370void Triple::Parse() const { 371 assert(!isInitialized() && "Invalid parse call."); 372 373 Arch = ParseArch(getArchName()); 374 Vendor = ParseVendor(getVendorName()); 375 OS = ParseOS(getOSName()); 376 Environment = ParseEnvironment(getEnvironmentName()); 377 378 assert(isInitialized() && "Failed to initialize!"); 379} 380 381std::string Triple::normalize(StringRef Str) { 382 // Parse into components. 383 SmallVector<StringRef, 4> Components; 384 for (size_t First = 0, Last = 0; Last != StringRef::npos; First = Last + 1) { 385 Last = Str.find('-', First); 386 Components.push_back(Str.slice(First, Last)); 387 } 388 389 // If the first component corresponds to a known architecture, preferentially 390 // use it for the architecture. If the second component corresponds to a 391 // known vendor, preferentially use it for the vendor, etc. This avoids silly 392 // component movement when a component parses as (eg) both a valid arch and a 393 // valid os. 394 ArchType Arch = UnknownArch; 395 if (Components.size() > 0) 396 Arch = ParseArch(Components[0]); 397 VendorType Vendor = UnknownVendor; 398 if (Components.size() > 1) 399 Vendor = ParseVendor(Components[1]); 400 OSType OS = UnknownOS; 401 if (Components.size() > 2) 402 OS = ParseOS(Components[2]); 403 EnvironmentType Environment = UnknownEnvironment; 404 if (Components.size() > 3) 405 Environment = ParseEnvironment(Components[3]); 406 407 // Note which components are already in their final position. These will not 408 // be moved. 409 bool Found[4]; 410 Found[0] = Arch != UnknownArch; 411 Found[1] = Vendor != UnknownVendor; 412 Found[2] = OS != UnknownOS; 413 Found[3] = Environment != UnknownEnvironment; 414 415 // If they are not there already, permute the components into their canonical 416 // positions by seeing if they parse as a valid architecture, and if so moving 417 // the component to the architecture position etc. 418 for (unsigned Pos = 0; Pos != array_lengthof(Found); ++Pos) { 419 if (Found[Pos]) 420 continue; // Already in the canonical position. 421 422 for (unsigned Idx = 0; Idx != Components.size(); ++Idx) { 423 // Do not reparse any components that already matched. 424 if (Idx < array_lengthof(Found) && Found[Idx]) 425 continue; 426 427 // Does this component parse as valid for the target position? 428 bool Valid = false; 429 StringRef Comp = Components[Idx]; 430 switch (Pos) { 431 default: 432 assert(false && "unexpected component type!"); 433 case 0: 434 Arch = ParseArch(Comp); 435 Valid = Arch != UnknownArch; 436 break; 437 case 1: 438 Vendor = ParseVendor(Comp); 439 Valid = Vendor != UnknownVendor; 440 break; 441 case 2: 442 OS = ParseOS(Comp); 443 Valid = OS != UnknownOS; 444 break; 445 case 3: 446 Environment = ParseEnvironment(Comp); 447 Valid = Environment != UnknownEnvironment; 448 break; 449 } 450 if (!Valid) 451 continue; // Nope, try the next component. 452 453 // Move the component to the target position, pushing any non-fixed 454 // components that are in the way to the right. This tends to give 455 // good results in the common cases of a forgotten vendor component 456 // or a wrongly positioned environment. 457 if (Pos < Idx) { 458 // Insert left, pushing the existing components to the right. For 459 // example, a-b-i386 -> i386-a-b when moving i386 to the front. 460 StringRef CurrentComponent(""); // The empty component. 461 // Replace the component we are moving with an empty component. 462 std::swap(CurrentComponent, Components[Idx]); 463 // Insert the component being moved at Pos, displacing any existing 464 // components to the right. 465 for (unsigned i = Pos; !CurrentComponent.empty(); ++i) { 466 // Skip over any fixed components. 467 while (i < array_lengthof(Found) && Found[i]) ++i; 468 // Place the component at the new position, getting the component 469 // that was at this position - it will be moved right. 470 std::swap(CurrentComponent, Components[i]); 471 } 472 } else if (Pos > Idx) { 473 // Push right by inserting empty components until the component at Idx 474 // reaches the target position Pos. For example, pc-a -> -pc-a when 475 // moving pc to the second position. 476 do { 477 // Insert one empty component at Idx. 478 StringRef CurrentComponent(""); // The empty component. 479 for (unsigned i = Idx; i < Components.size();) { 480 // Place the component at the new position, getting the component 481 // that was at this position - it will be moved right. 482 std::swap(CurrentComponent, Components[i]); 483 // If it was placed on top of an empty component then we are done. 484 if (CurrentComponent.empty()) 485 break; 486 // Advance to the next component, skipping any fixed components. 487 while (++i < array_lengthof(Found) && Found[i]) 488 ; 489 } 490 // The last component was pushed off the end - append it. 491 if (!CurrentComponent.empty()) 492 Components.push_back(CurrentComponent); 493 494 // Advance Idx to the component's new position. 495 while (++Idx < array_lengthof(Found) && Found[Idx]) {} 496 } while (Idx < Pos); // Add more until the final position is reached. 497 } 498 assert(Pos < Components.size() && Components[Pos] == Comp && 499 "Component moved wrong!"); 500 Found[Pos] = true; 501 break; 502 } 503 } 504 505 // Special case logic goes here. At this point Arch, Vendor and OS have the 506 // correct values for the computed components. 507 508 // Stick the corrected components back together to form the normalized string. 509 std::string Normalized; 510 for (unsigned i = 0, e = Components.size(); i != e; ++i) { 511 if (i) Normalized += '-'; 512 Normalized += Components[i]; 513 } 514 return Normalized; 515} 516 517StringRef Triple::getArchName() const { 518 return StringRef(Data).split('-').first; // Isolate first component 519} 520 521StringRef Triple::getVendorName() const { 522 StringRef Tmp = StringRef(Data).split('-').second; // Strip first component 523 return Tmp.split('-').first; // Isolate second component 524} 525 526StringRef Triple::getOSName() const { 527 StringRef Tmp = StringRef(Data).split('-').second; // Strip first component 528 Tmp = Tmp.split('-').second; // Strip second component 529 return Tmp.split('-').first; // Isolate third component 530} 531 532StringRef Triple::getEnvironmentName() const { 533 StringRef Tmp = StringRef(Data).split('-').second; // Strip first component 534 Tmp = Tmp.split('-').second; // Strip second component 535 return Tmp.split('-').second; // Strip third component 536} 537 538StringRef Triple::getOSAndEnvironmentName() const { 539 StringRef Tmp = StringRef(Data).split('-').second; // Strip first component 540 return Tmp.split('-').second; // Strip second component 541} 542 543static unsigned EatNumber(StringRef &Str) { 544 assert(!Str.empty() && Str[0] >= '0' && Str[0] <= '9' && "Not a number"); 545 unsigned Result = 0; 546 547 do { 548 // Consume the leading digit. 549 Result = Result*10 + (Str[0] - '0'); 550 551 // Eat the digit. 552 Str = Str.substr(1); 553 } while (!Str.empty() && Str[0] >= '0' && Str[0] <= '9'); 554 555 return Result; 556} 557 558void Triple::getOSVersion(unsigned &Major, unsigned &Minor, 559 unsigned &Micro) const { 560 StringRef OSName = getOSName(); 561 562 // Assume that the OS portion of the triple starts with the canonical name. 563 StringRef OSTypeName = getOSTypeName(getOS()); 564 if (OSName.startswith(OSTypeName)) 565 OSName = OSName.substr(OSTypeName.size()); 566 567 // Any unset version defaults to 0. 568 Major = Minor = Micro = 0; 569 570 // Parse up to three components. 571 unsigned *Components[3] = { &Major, &Minor, &Micro }; 572 for (unsigned i = 0; i != 3; ++i) { 573 if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9') 574 break; 575 576 // Consume the leading number. 577 *Components[i] = EatNumber(OSName); 578 579 // Consume the separator, if present. 580 if (OSName.startswith(".")) 581 OSName = OSName.substr(1); 582 } 583} 584 585void Triple::setTriple(const Twine &Str) { 586 Data = Str.str(); 587 Arch = InvalidArch; 588} 589 590void Triple::setArch(ArchType Kind) { 591 setArchName(getArchTypeName(Kind)); 592} 593 594void Triple::setVendor(VendorType Kind) { 595 setVendorName(getVendorTypeName(Kind)); 596} 597 598void Triple::setOS(OSType Kind) { 599 setOSName(getOSTypeName(Kind)); 600} 601 602void Triple::setEnvironment(EnvironmentType Kind) { 603 setEnvironmentName(getEnvironmentTypeName(Kind)); 604} 605 606void Triple::setArchName(StringRef Str) { 607 // Work around a miscompilation bug for Twines in gcc 4.0.3. 608 SmallString<64> Triple; 609 Triple += Str; 610 Triple += "-"; 611 Triple += getVendorName(); 612 Triple += "-"; 613 Triple += getOSAndEnvironmentName(); 614 setTriple(Triple.str()); 615} 616 617void Triple::setVendorName(StringRef Str) { 618 setTriple(getArchName() + "-" + Str + "-" + getOSAndEnvironmentName()); 619} 620 621void Triple::setOSName(StringRef Str) { 622 if (hasEnvironment()) 623 setTriple(getArchName() + "-" + getVendorName() + "-" + Str + 624 "-" + getEnvironmentName()); 625 else 626 setTriple(getArchName() + "-" + getVendorName() + "-" + Str); 627} 628 629void Triple::setEnvironmentName(StringRef Str) { 630 setTriple(getArchName() + "-" + getVendorName() + "-" + getOSName() + 631 "-" + Str); 632} 633 634void Triple::setOSAndEnvironmentName(StringRef Str) { 635 setTriple(getArchName() + "-" + getVendorName() + "-" + Str); 636} 637