Host.cpp revision b9548d8ee30f880a237ea46430478b95f2ef4772
1//===-- Host.cpp - Implement OS Host Concept --------------------*- C++ -*-===// 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// This header file implements the operating system Host concept. 11// 12//===----------------------------------------------------------------------===// 13 14#include "llvm/Support/Host.h" 15#include "llvm/ADT/SmallVector.h" 16#include "llvm/ADT/StringRef.h" 17#include "llvm/ADT/StringSwitch.h" 18#include "llvm/ADT/Triple.h" 19#include "llvm/Config/config.h" 20#include "llvm/Support/DataStream.h" 21#include "llvm/Support/Debug.h" 22#include "llvm/Support/raw_ostream.h" 23#include <string.h> 24 25// Include the platform-specific parts of this class. 26#ifdef LLVM_ON_UNIX 27#include "Unix/Host.inc" 28#endif 29#ifdef LLVM_ON_WIN32 30#include "Windows/Host.inc" 31#endif 32#ifdef _MSC_VER 33#include <intrin.h> 34#endif 35#if defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__)) 36#include <mach/mach.h> 37#include <mach/mach_host.h> 38#include <mach/host_info.h> 39#include <mach/machine.h> 40#endif 41 42//===----------------------------------------------------------------------===// 43// 44// Implementations of the CPU detection routines 45// 46//===----------------------------------------------------------------------===// 47 48using namespace llvm; 49 50#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)\ 51 || defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) 52 53/// GetX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in the 54/// specified arguments. If we can't run cpuid on the host, return true. 55static bool GetX86CpuIDAndInfo(unsigned value, unsigned *rEAX, 56 unsigned *rEBX, unsigned *rECX, unsigned *rEDX) { 57#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) 58 #if defined(__GNUC__) 59 // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. 60 asm ("movq\t%%rbx, %%rsi\n\t" 61 "cpuid\n\t" 62 "xchgq\t%%rbx, %%rsi\n\t" 63 : "=a" (*rEAX), 64 "=S" (*rEBX), 65 "=c" (*rECX), 66 "=d" (*rEDX) 67 : "a" (value)); 68 return false; 69 #elif defined(_MSC_VER) 70 int registers[4]; 71 __cpuid(registers, value); 72 *rEAX = registers[0]; 73 *rEBX = registers[1]; 74 *rECX = registers[2]; 75 *rEDX = registers[3]; 76 return false; 77 #else 78 return true; 79 #endif 80#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86) 81 #if defined(__GNUC__) 82 asm ("movl\t%%ebx, %%esi\n\t" 83 "cpuid\n\t" 84 "xchgl\t%%ebx, %%esi\n\t" 85 : "=a" (*rEAX), 86 "=S" (*rEBX), 87 "=c" (*rECX), 88 "=d" (*rEDX) 89 : "a" (value)); 90 return false; 91 #elif defined(_MSC_VER) 92 __asm { 93 mov eax,value 94 cpuid 95 mov esi,rEAX 96 mov dword ptr [esi],eax 97 mov esi,rEBX 98 mov dword ptr [esi],ebx 99 mov esi,rECX 100 mov dword ptr [esi],ecx 101 mov esi,rEDX 102 mov dword ptr [esi],edx 103 } 104 return false; 105// pedantic #else returns to appease -Wunreachable-code (so we don't generate 106// postprocessed code that looks like "return true; return false;") 107 #else 108 return true; 109 #endif 110#else 111 return true; 112#endif 113} 114 115static bool OSHasAVXSupport() { 116#if defined(__GNUC__) 117 // Check xgetbv; this uses a .byte sequence instead of the instruction 118 // directly because older assemblers do not include support for xgetbv and 119 // there is no easy way to conditionally compile based on the assembler used. 120 int rEAX, rEDX; 121 __asm__ (".byte 0x0f, 0x01, 0xd0" : "=a" (rEAX), "=d" (rEDX) : "c" (0)); 122#elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK) 123 unsigned long long rEAX = _xgetbv(_XCR_XFEATURE_ENABLED_MASK); 124#else 125 int rEAX = 0; // Ensures we return false 126#endif 127 return (rEAX & 6) == 6; 128} 129 130static void DetectX86FamilyModel(unsigned EAX, unsigned &Family, 131 unsigned &Model) { 132 Family = (EAX >> 8) & 0xf; // Bits 8 - 11 133 Model = (EAX >> 4) & 0xf; // Bits 4 - 7 134 if (Family == 6 || Family == 0xf) { 135 if (Family == 0xf) 136 // Examine extended family ID if family ID is F. 137 Family += (EAX >> 20) & 0xff; // Bits 20 - 27 138 // Examine extended model ID if family ID is 6 or F. 139 Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19 140 } 141} 142 143std::string sys::getHostCPUName() { 144 unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; 145 if (GetX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX)) 146 return "generic"; 147 unsigned Family = 0; 148 unsigned Model = 0; 149 DetectX86FamilyModel(EAX, Family, Model); 150 151 bool HasSSE3 = (ECX & 0x1); 152 // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV 153 // indicates that the AVX registers will be saved and restored on context 154 // switch, then we have full AVX support. 155 const unsigned AVXBits = (1 << 27) | (1 << 28); 156 bool HasAVX = ((ECX & AVXBits) == AVXBits) && OSHasAVXSupport(); 157 GetX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); 158 bool Em64T = (EDX >> 29) & 0x1; 159 160 union { 161 unsigned u[3]; 162 char c[12]; 163 } text; 164 165 GetX86CpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1); 166 if (memcmp(text.c, "GenuineIntel", 12) == 0) { 167 switch (Family) { 168 case 3: 169 return "i386"; 170 case 4: 171 switch (Model) { 172 case 0: // Intel486 DX processors 173 case 1: // Intel486 DX processors 174 case 2: // Intel486 SX processors 175 case 3: // Intel487 processors, IntelDX2 OverDrive processors, 176 // IntelDX2 processors 177 case 4: // Intel486 SL processor 178 case 5: // IntelSX2 processors 179 case 7: // Write-Back Enhanced IntelDX2 processors 180 case 8: // IntelDX4 OverDrive processors, IntelDX4 processors 181 default: return "i486"; 182 } 183 case 5: 184 switch (Model) { 185 case 1: // Pentium OverDrive processor for Pentium processor (60, 66), 186 // Pentium processors (60, 66) 187 case 2: // Pentium OverDrive processor for Pentium processor (75, 90, 188 // 100, 120, 133), Pentium processors (75, 90, 100, 120, 133, 189 // 150, 166, 200) 190 case 3: // Pentium OverDrive processors for Intel486 processor-based 191 // systems 192 return "pentium"; 193 194 case 4: // Pentium OverDrive processor with MMX technology for Pentium 195 // processor (75, 90, 100, 120, 133), Pentium processor with 196 // MMX technology (166, 200) 197 return "pentium-mmx"; 198 199 default: return "pentium"; 200 } 201 case 6: 202 switch (Model) { 203 case 1: // Pentium Pro processor 204 return "pentiumpro"; 205 206 case 3: // Intel Pentium II OverDrive processor, Pentium II processor, 207 // model 03 208 case 5: // Pentium II processor, model 05, Pentium II Xeon processor, 209 // model 05, and Intel Celeron processor, model 05 210 case 6: // Celeron processor, model 06 211 return "pentium2"; 212 213 case 7: // Pentium III processor, model 07, and Pentium III Xeon 214 // processor, model 07 215 case 8: // Pentium III processor, model 08, Pentium III Xeon processor, 216 // model 08, and Celeron processor, model 08 217 case 10: // Pentium III Xeon processor, model 0Ah 218 case 11: // Pentium III processor, model 0Bh 219 return "pentium3"; 220 221 case 9: // Intel Pentium M processor, Intel Celeron M processor model 09. 222 case 13: // Intel Pentium M processor, Intel Celeron M processor, model 223 // 0Dh. All processors are manufactured using the 90 nm process. 224 return "pentium-m"; 225 226 case 14: // Intel Core Duo processor, Intel Core Solo processor, model 227 // 0Eh. All processors are manufactured using the 65 nm process. 228 return "yonah"; 229 230 case 15: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile 231 // processor, Intel Core 2 Quad processor, Intel Core 2 Quad 232 // mobile processor, Intel Core 2 Extreme processor, Intel 233 // Pentium Dual-Core processor, Intel Xeon processor, model 234 // 0Fh. All processors are manufactured using the 65 nm process. 235 case 22: // Intel Celeron processor model 16h. All processors are 236 // manufactured using the 65 nm process 237 return "core2"; 238 239 case 21: // Intel EP80579 Integrated Processor and Intel EP80579 240 // Integrated Processor with Intel QuickAssist Technology 241 return "i686"; // FIXME: ??? 242 243 case 23: // Intel Core 2 Extreme processor, Intel Xeon processor, model 244 // 17h. All processors are manufactured using the 45 nm process. 245 // 246 // 45nm: Penryn , Wolfdale, Yorkfield (XE) 247 return "penryn"; 248 249 case 26: // Intel Core i7 processor and Intel Xeon processor. All 250 // processors are manufactured using the 45 nm process. 251 case 29: // Intel Xeon processor MP. All processors are manufactured using 252 // the 45 nm process. 253 case 30: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz. 254 // As found in a Summer 2010 model iMac. 255 case 37: // Intel Core i7, laptop version. 256 case 44: // Intel Core i7 processor and Intel Xeon processor. All 257 // processors are manufactured using the 32 nm process. 258 case 46: // Nehalem EX 259 case 47: // Westmere EX 260 return "corei7"; 261 262 // SandyBridge: 263 case 42: // Intel Core i7 processor. All processors are manufactured 264 // using the 32 nm process. 265 case 45: 266 // Not all Sandy Bridge processors support AVX (such as the Pentium 267 // versions instead of the i7 versions). 268 return HasAVX ? "corei7-avx" : "corei7"; 269 270 // Ivy Bridge: 271 case 58: 272 // Not all Ivy Bridge processors support AVX (such as the Pentium 273 // versions instead of the i7 versions). 274 return HasAVX ? "core-avx-i" : "corei7"; 275 276 case 28: // Most 45 nm Intel Atom processors 277 case 38: // 45 nm Atom Lincroft 278 case 39: // 32 nm Atom Medfield 279 case 53: // 32 nm Atom Midview 280 case 54: // 32 nm Atom Midview 281 return "atom"; 282 283 default: return (Em64T) ? "x86-64" : "i686"; 284 } 285 case 15: { 286 switch (Model) { 287 case 0: // Pentium 4 processor, Intel Xeon processor. All processors are 288 // model 00h and manufactured using the 0.18 micron process. 289 case 1: // Pentium 4 processor, Intel Xeon processor, Intel Xeon 290 // processor MP, and Intel Celeron processor. All processors are 291 // model 01h and manufactured using the 0.18 micron process. 292 case 2: // Pentium 4 processor, Mobile Intel Pentium 4 processor - M, 293 // Intel Xeon processor, Intel Xeon processor MP, Intel Celeron 294 // processor, and Mobile Intel Celeron processor. All processors 295 // are model 02h and manufactured using the 0.13 micron process. 296 return (Em64T) ? "x86-64" : "pentium4"; 297 298 case 3: // Pentium 4 processor, Intel Xeon processor, Intel Celeron D 299 // processor. All processors are model 03h and manufactured using 300 // the 90 nm process. 301 case 4: // Pentium 4 processor, Pentium 4 processor Extreme Edition, 302 // Pentium D processor, Intel Xeon processor, Intel Xeon 303 // processor MP, Intel Celeron D processor. All processors are 304 // model 04h and manufactured using the 90 nm process. 305 case 6: // Pentium 4 processor, Pentium D processor, Pentium processor 306 // Extreme Edition, Intel Xeon processor, Intel Xeon processor 307 // MP, Intel Celeron D processor. All processors are model 06h 308 // and manufactured using the 65 nm process. 309 return (Em64T) ? "nocona" : "prescott"; 310 311 default: 312 return (Em64T) ? "x86-64" : "pentium4"; 313 } 314 } 315 316 default: 317 return "generic"; 318 } 319 } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) { 320 // FIXME: this poorly matches the generated SubtargetFeatureKV table. There 321 // appears to be no way to generate the wide variety of AMD-specific targets 322 // from the information returned from CPUID. 323 switch (Family) { 324 case 4: 325 return "i486"; 326 case 5: 327 switch (Model) { 328 case 6: 329 case 7: return "k6"; 330 case 8: return "k6-2"; 331 case 9: 332 case 13: return "k6-3"; 333 case 10: return "geode"; 334 default: return "pentium"; 335 } 336 case 6: 337 switch (Model) { 338 case 4: return "athlon-tbird"; 339 case 6: 340 case 7: 341 case 8: return "athlon-mp"; 342 case 10: return "athlon-xp"; 343 default: return "athlon"; 344 } 345 case 15: 346 if (HasSSE3) 347 return "k8-sse3"; 348 switch (Model) { 349 case 1: return "opteron"; 350 case 5: return "athlon-fx"; // also opteron 351 default: return "athlon64"; 352 } 353 case 16: 354 return "amdfam10"; 355 case 20: 356 return "btver1"; 357 case 21: 358 if (!HasAVX) // If the OS doesn't support AVX provide a sane fallback. 359 return "btver1"; 360 if (Model > 15 && Model <= 31) 361 return "bdver2"; 362 return "bdver1"; 363 case 22: 364 if (!HasAVX) // If the OS doesn't support AVX provide a sane fallback. 365 return "btver1"; 366 return "btver2"; 367 default: 368 return "generic"; 369 } 370 } 371 return "generic"; 372} 373#elif defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__)) 374std::string sys::getHostCPUName() { 375 host_basic_info_data_t hostInfo; 376 mach_msg_type_number_t infoCount; 377 378 infoCount = HOST_BASIC_INFO_COUNT; 379 host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, 380 &infoCount); 381 382 if (hostInfo.cpu_type != CPU_TYPE_POWERPC) return "generic"; 383 384 switch(hostInfo.cpu_subtype) { 385 case CPU_SUBTYPE_POWERPC_601: return "601"; 386 case CPU_SUBTYPE_POWERPC_602: return "602"; 387 case CPU_SUBTYPE_POWERPC_603: return "603"; 388 case CPU_SUBTYPE_POWERPC_603e: return "603e"; 389 case CPU_SUBTYPE_POWERPC_603ev: return "603ev"; 390 case CPU_SUBTYPE_POWERPC_604: return "604"; 391 case CPU_SUBTYPE_POWERPC_604e: return "604e"; 392 case CPU_SUBTYPE_POWERPC_620: return "620"; 393 case CPU_SUBTYPE_POWERPC_750: return "750"; 394 case CPU_SUBTYPE_POWERPC_7400: return "7400"; 395 case CPU_SUBTYPE_POWERPC_7450: return "7450"; 396 case CPU_SUBTYPE_POWERPC_970: return "970"; 397 default: ; 398 } 399 400 return "generic"; 401} 402#elif defined(__linux__) && (defined(__ppc__) || defined(__powerpc__)) 403std::string sys::getHostCPUName() { 404 // Access to the Processor Version Register (PVR) on PowerPC is privileged, 405 // and so we must use an operating-system interface to determine the current 406 // processor type. On Linux, this is exposed through the /proc/cpuinfo file. 407 const char *generic = "generic"; 408 409 // Note: We cannot mmap /proc/cpuinfo here and then process the resulting 410 // memory buffer because the 'file' has 0 size (it can be read from only 411 // as a stream). 412 413 std::string Err; 414 DataStreamer *DS = getDataFileStreamer("/proc/cpuinfo", &Err); 415 if (!DS) { 416 DEBUG(dbgs() << "Unable to open /proc/cpuinfo: " << Err << "\n"); 417 return generic; 418 } 419 420 // The cpu line is second (after the 'processor: 0' line), so if this 421 // buffer is too small then something has changed (or is wrong). 422 char buffer[1024]; 423 size_t CPUInfoSize = DS->GetBytes((unsigned char*) buffer, sizeof(buffer)); 424 delete DS; 425 426 const char *CPUInfoStart = buffer; 427 const char *CPUInfoEnd = buffer + CPUInfoSize; 428 429 const char *CIP = CPUInfoStart; 430 431 const char *CPUStart = 0; 432 size_t CPULen = 0; 433 434 // We need to find the first line which starts with cpu, spaces, and a colon. 435 // After the colon, there may be some additional spaces and then the cpu type. 436 while (CIP < CPUInfoEnd && CPUStart == 0) { 437 if (CIP < CPUInfoEnd && *CIP == '\n') 438 ++CIP; 439 440 if (CIP < CPUInfoEnd && *CIP == 'c') { 441 ++CIP; 442 if (CIP < CPUInfoEnd && *CIP == 'p') { 443 ++CIP; 444 if (CIP < CPUInfoEnd && *CIP == 'u') { 445 ++CIP; 446 while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t')) 447 ++CIP; 448 449 if (CIP < CPUInfoEnd && *CIP == ':') { 450 ++CIP; 451 while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t')) 452 ++CIP; 453 454 if (CIP < CPUInfoEnd) { 455 CPUStart = CIP; 456 while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' && 457 *CIP != ',' && *CIP != '\n')) 458 ++CIP; 459 CPULen = CIP - CPUStart; 460 } 461 } 462 } 463 } 464 } 465 466 if (CPUStart == 0) 467 while (CIP < CPUInfoEnd && *CIP != '\n') 468 ++CIP; 469 } 470 471 if (CPUStart == 0) 472 return generic; 473 474 return StringSwitch<const char *>(StringRef(CPUStart, CPULen)) 475 .Case("604e", "604e") 476 .Case("604", "604") 477 .Case("7400", "7400") 478 .Case("7410", "7400") 479 .Case("7447", "7400") 480 .Case("7455", "7450") 481 .Case("G4", "g4") 482 .Case("POWER4", "970") 483 .Case("PPC970FX", "970") 484 .Case("PPC970MP", "970") 485 .Case("G5", "g5") 486 .Case("POWER5", "g5") 487 .Case("A2", "a2") 488 .Case("POWER6", "pwr6") 489 .Case("POWER7", "pwr7") 490 .Default(generic); 491} 492#elif defined(__linux__) && defined(__arm__) 493std::string sys::getHostCPUName() { 494 // The cpuid register on arm is not accessible from user space. On Linux, 495 // it is exposed through the /proc/cpuinfo file. 496 // Note: We cannot mmap /proc/cpuinfo here and then process the resulting 497 // memory buffer because the 'file' has 0 size (it can be read from only 498 // as a stream). 499 500 std::string Err; 501 DataStreamer *DS = getDataFileStreamer("/proc/cpuinfo", &Err); 502 if (!DS) { 503 DEBUG(dbgs() << "Unable to open /proc/cpuinfo: " << Err << "\n"); 504 return "generic"; 505 } 506 507 // Read 1024 bytes from /proc/cpuinfo, which should contain the CPU part line 508 // in all cases. 509 char buffer[1024]; 510 size_t CPUInfoSize = DS->GetBytes((unsigned char*) buffer, sizeof(buffer)); 511 delete DS; 512 513 StringRef Str(buffer, CPUInfoSize); 514 515 SmallVector<StringRef, 32> Lines; 516 Str.split(Lines, "\n"); 517 518 // Look for the CPU implementer line. 519 StringRef Implementer; 520 for (unsigned I = 0, E = Lines.size(); I != E; ++I) 521 if (Lines[I].startswith("CPU implementer")) 522 Implementer = Lines[I].substr(15).ltrim("\t :"); 523 524 if (Implementer == "0x41") // ARM Ltd. 525 // Look for the CPU part line. 526 for (unsigned I = 0, E = Lines.size(); I != E; ++I) 527 if (Lines[I].startswith("CPU part")) 528 // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The 529 // values correspond to the "Part number" in the CP15/c0 register. The 530 // contents are specified in the various processor manuals. 531 return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :")) 532 .Case("0x926", "arm926ej-s") 533 .Case("0xb02", "mpcore") 534 .Case("0xb36", "arm1136j-s") 535 .Case("0xb56", "arm1156t2-s") 536 .Case("0xb76", "arm1176jz-s") 537 .Case("0xc08", "cortex-a8") 538 .Case("0xc09", "cortex-a9") 539 .Case("0xc0f", "cortex-a15") 540 .Case("0xc20", "cortex-m0") 541 .Case("0xc23", "cortex-m3") 542 .Case("0xc24", "cortex-m4") 543 .Default("generic"); 544 545 return "generic"; 546} 547#else 548std::string sys::getHostCPUName() { 549 return "generic"; 550} 551#endif 552 553#if defined(__linux__) && defined(__arm__) 554bool sys::getHostCPUFeatures(StringMap<bool> &Features) { 555 std::string Err; 556 DataStreamer *DS = getDataFileStreamer("/proc/cpuinfo", &Err); 557 if (!DS) { 558 DEBUG(dbgs() << "Unable to open /proc/cpuinfo: " << Err << "\n"); 559 return false; 560 } 561 562 // Read 1024 bytes from /proc/cpuinfo, which should contain the Features line 563 // in all cases. 564 char buffer[1024]; 565 size_t CPUInfoSize = DS->GetBytes((unsigned char*) buffer, sizeof(buffer)); 566 delete DS; 567 568 StringRef Str(buffer, CPUInfoSize); 569 570 SmallVector<StringRef, 32> Lines; 571 Str.split(Lines, "\n"); 572 573 // Look for the CPU implementer line. 574 StringRef Implementer; 575 for (unsigned I = 0, E = Lines.size(); I != E; ++I) 576 if (Lines[I].startswith("CPU implementer")) 577 Implementer = Lines[I].substr(15).ltrim("\t :"); 578 579 if (Implementer == "0x41") { // ARM Ltd. 580 SmallVector<StringRef, 32> CPUFeatures; 581 582 // Look for the CPU features. 583 for (unsigned I = 0, E = Lines.size(); I != E; ++I) 584 if (Lines[I].startswith("Features")) { 585 Lines[I].split(CPUFeatures, " "); 586 break; 587 } 588 589 for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) { 590 StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I]) 591 .Case("half", "fp16") 592 .Case("neon", "neon") 593 .Case("vfpv3", "vfp3") 594 .Case("vfpv3d16", "d16") 595 .Case("vfpv4", "vfp4") 596 .Case("idiva", "hwdiv-arm") 597 .Case("idivt", "hwdiv") 598 .Default(""); 599 600 if (LLVMFeatureStr != "") 601 Features.GetOrCreateValue(LLVMFeatureStr).setValue(true); 602 } 603 604 return true; 605 } 606 607 return false; 608} 609#else 610bool sys::getHostCPUFeatures(StringMap<bool> &Features){ 611 return false; 612} 613#endif 614 615std::string sys::getProcessTriple() { 616 Triple PT(LLVM_HOSTTRIPLE); 617 618 if (sizeof(void *) == 8 && PT.isArch32Bit()) 619 PT = PT.get64BitArchVariant(); 620 if (sizeof(void *) == 4 && PT.isArch64Bit()) 621 PT = PT.get32BitArchVariant(); 622 623 return PT.str(); 624} 625